1 1.1 mrg /* 2 1.1 mrg * Copyright 2008-2009 Katholieke Universiteit Leuven 3 1.1 mrg * 4 1.1 mrg * Use of this software is governed by the MIT license 5 1.1 mrg * 6 1.1 mrg * Written by Sven Verdoolaege, K.U.Leuven, Departement 7 1.1 mrg * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium 8 1.1 mrg */ 9 1.1 mrg 10 1.1 mrg #include <isl_ctx_private.h> 11 1.1 mrg #include <isl_map_private.h> 12 1.1 mrg #include "isl_sample.h" 13 1.1 mrg #include <isl/vec.h> 14 1.1 mrg #include <isl/mat.h> 15 1.1 mrg #include <isl_seq.h> 16 1.1 mrg #include "isl_equalities.h" 17 1.1 mrg #include "isl_tab.h" 18 1.1 mrg #include "isl_basis_reduction.h" 19 1.1 mrg #include <isl_factorization.h> 20 1.1 mrg #include <isl_point_private.h> 21 1.1 mrg #include <isl_options_private.h> 22 1.1 mrg #include <isl_vec_private.h> 23 1.1 mrg 24 1.1 mrg #include <bset_from_bmap.c> 25 1.1 mrg #include <set_to_map.c> 26 1.1 mrg 27 1.1 mrg static __isl_give isl_vec *isl_basic_set_sample_bounded( 28 1.1 mrg __isl_take isl_basic_set *bset); 29 1.1 mrg 30 1.1 mrg static __isl_give isl_vec *empty_sample(__isl_take isl_basic_set *bset) 31 1.1 mrg { 32 1.1 mrg struct isl_vec *vec; 33 1.1 mrg 34 1.1 mrg vec = isl_vec_alloc(bset->ctx, 0); 35 1.1 mrg isl_basic_set_free(bset); 36 1.1 mrg return vec; 37 1.1 mrg } 38 1.1 mrg 39 1.1 mrg /* Construct a zero sample of the same dimension as bset. 40 1.1 mrg * As a special case, if bset is zero-dimensional, this 41 1.1 mrg * function creates a zero-dimensional sample point. 42 1.1 mrg */ 43 1.1 mrg static __isl_give isl_vec *zero_sample(__isl_take isl_basic_set *bset) 44 1.1 mrg { 45 1.1 mrg isl_size dim; 46 1.1 mrg struct isl_vec *sample; 47 1.1 mrg 48 1.1 mrg dim = isl_basic_set_dim(bset, isl_dim_all); 49 1.1 mrg if (dim < 0) 50 1.1 mrg goto error; 51 1.1 mrg sample = isl_vec_alloc(bset->ctx, 1 + dim); 52 1.1 mrg if (sample) { 53 1.1 mrg isl_int_set_si(sample->el[0], 1); 54 1.1 mrg isl_seq_clr(sample->el + 1, dim); 55 1.1 mrg } 56 1.1 mrg isl_basic_set_free(bset); 57 1.1 mrg return sample; 58 1.1 mrg error: 59 1.1 mrg isl_basic_set_free(bset); 60 1.1 mrg return NULL; 61 1.1 mrg } 62 1.1 mrg 63 1.1 mrg static __isl_give isl_vec *interval_sample(__isl_take isl_basic_set *bset) 64 1.1 mrg { 65 1.1 mrg int i; 66 1.1 mrg isl_int t; 67 1.1 mrg struct isl_vec *sample; 68 1.1 mrg 69 1.1 mrg bset = isl_basic_set_simplify(bset); 70 1.1 mrg if (!bset) 71 1.1 mrg return NULL; 72 1.1 mrg if (isl_basic_set_plain_is_empty(bset)) 73 1.1 mrg return empty_sample(bset); 74 1.1 mrg if (bset->n_eq == 0 && bset->n_ineq == 0) 75 1.1 mrg return zero_sample(bset); 76 1.1 mrg 77 1.1 mrg sample = isl_vec_alloc(bset->ctx, 2); 78 1.1 mrg if (!sample) 79 1.1 mrg goto error; 80 1.1 mrg if (!bset) 81 1.1 mrg return NULL; 82 1.1 mrg isl_int_set_si(sample->block.data[0], 1); 83 1.1 mrg 84 1.1 mrg if (bset->n_eq > 0) { 85 1.1 mrg isl_assert(bset->ctx, bset->n_eq == 1, goto error); 86 1.1 mrg isl_assert(bset->ctx, bset->n_ineq == 0, goto error); 87 1.1 mrg if (isl_int_is_one(bset->eq[0][1])) 88 1.1 mrg isl_int_neg(sample->el[1], bset->eq[0][0]); 89 1.1 mrg else { 90 1.1 mrg isl_assert(bset->ctx, isl_int_is_negone(bset->eq[0][1]), 91 1.1 mrg goto error); 92 1.1 mrg isl_int_set(sample->el[1], bset->eq[0][0]); 93 1.1 mrg } 94 1.1 mrg isl_basic_set_free(bset); 95 1.1 mrg return sample; 96 1.1 mrg } 97 1.1 mrg 98 1.1 mrg isl_int_init(t); 99 1.1 mrg if (isl_int_is_one(bset->ineq[0][1])) 100 1.1 mrg isl_int_neg(sample->block.data[1], bset->ineq[0][0]); 101 1.1 mrg else 102 1.1 mrg isl_int_set(sample->block.data[1], bset->ineq[0][0]); 103 1.1 mrg for (i = 1; i < bset->n_ineq; ++i) { 104 1.1 mrg isl_seq_inner_product(sample->block.data, 105 1.1 mrg bset->ineq[i], 2, &t); 106 1.1 mrg if (isl_int_is_neg(t)) 107 1.1 mrg break; 108 1.1 mrg } 109 1.1 mrg isl_int_clear(t); 110 1.1 mrg if (i < bset->n_ineq) { 111 1.1 mrg isl_vec_free(sample); 112 1.1 mrg return empty_sample(bset); 113 1.1 mrg } 114 1.1 mrg 115 1.1 mrg isl_basic_set_free(bset); 116 1.1 mrg return sample; 117 1.1 mrg error: 118 1.1 mrg isl_basic_set_free(bset); 119 1.1 mrg isl_vec_free(sample); 120 1.1 mrg return NULL; 121 1.1 mrg } 122 1.1 mrg 123 1.1 mrg /* Find a sample integer point, if any, in bset, which is known 124 1.1 mrg * to have equalities. If bset contains no integer points, then 125 1.1 mrg * return a zero-length vector. 126 1.1 mrg * We simply remove the known equalities, compute a sample 127 1.1 mrg * in the resulting bset, using the specified recurse function, 128 1.1 mrg * and then transform the sample back to the original space. 129 1.1 mrg */ 130 1.1 mrg static __isl_give isl_vec *sample_eq(__isl_take isl_basic_set *bset, 131 1.1 mrg __isl_give isl_vec *(*recurse)(__isl_take isl_basic_set *)) 132 1.1 mrg { 133 1.1 mrg struct isl_mat *T; 134 1.1 mrg struct isl_vec *sample; 135 1.1 mrg 136 1.1 mrg if (!bset) 137 1.1 mrg return NULL; 138 1.1 mrg 139 1.1 mrg bset = isl_basic_set_remove_equalities(bset, &T, NULL); 140 1.1 mrg sample = recurse(bset); 141 1.1 mrg if (!sample || sample->size == 0) 142 1.1 mrg isl_mat_free(T); 143 1.1 mrg else 144 1.1 mrg sample = isl_mat_vec_product(T, sample); 145 1.1 mrg return sample; 146 1.1 mrg } 147 1.1 mrg 148 1.1 mrg /* Return a matrix containing the equalities of the tableau 149 1.1 mrg * in constraint form. The tableau is assumed to have 150 1.1 mrg * an associated bset that has been kept up-to-date. 151 1.1 mrg */ 152 1.1 mrg static struct isl_mat *tab_equalities(struct isl_tab *tab) 153 1.1 mrg { 154 1.1 mrg int i, j; 155 1.1 mrg int n_eq; 156 1.1 mrg struct isl_mat *eq; 157 1.1 mrg struct isl_basic_set *bset; 158 1.1 mrg 159 1.1 mrg if (!tab) 160 1.1 mrg return NULL; 161 1.1 mrg 162 1.1 mrg bset = isl_tab_peek_bset(tab); 163 1.1 mrg isl_assert(tab->mat->ctx, bset, return NULL); 164 1.1 mrg 165 1.1 mrg n_eq = tab->n_var - tab->n_col + tab->n_dead; 166 1.1 mrg if (tab->empty || n_eq == 0) 167 1.1 mrg return isl_mat_alloc(tab->mat->ctx, 0, tab->n_var); 168 1.1 mrg if (n_eq == tab->n_var) 169 1.1 mrg return isl_mat_identity(tab->mat->ctx, tab->n_var); 170 1.1 mrg 171 1.1 mrg eq = isl_mat_alloc(tab->mat->ctx, n_eq, tab->n_var); 172 1.1 mrg if (!eq) 173 1.1 mrg return NULL; 174 1.1 mrg for (i = 0, j = 0; i < tab->n_con; ++i) { 175 1.1 mrg if (tab->con[i].is_row) 176 1.1 mrg continue; 177 1.1 mrg if (tab->con[i].index >= 0 && tab->con[i].index >= tab->n_dead) 178 1.1 mrg continue; 179 1.1 mrg if (i < bset->n_eq) 180 1.1 mrg isl_seq_cpy(eq->row[j], bset->eq[i] + 1, tab->n_var); 181 1.1 mrg else 182 1.1 mrg isl_seq_cpy(eq->row[j], 183 1.1 mrg bset->ineq[i - bset->n_eq] + 1, tab->n_var); 184 1.1 mrg ++j; 185 1.1 mrg } 186 1.1 mrg isl_assert(bset->ctx, j == n_eq, goto error); 187 1.1 mrg return eq; 188 1.1 mrg error: 189 1.1 mrg isl_mat_free(eq); 190 1.1 mrg return NULL; 191 1.1 mrg } 192 1.1 mrg 193 1.1 mrg /* Compute and return an initial basis for the bounded tableau "tab". 194 1.1 mrg * 195 1.1 mrg * If the tableau is either full-dimensional or zero-dimensional, 196 1.1 mrg * the we simply return an identity matrix. 197 1.1 mrg * Otherwise, we construct a basis whose first directions correspond 198 1.1 mrg * to equalities. 199 1.1 mrg */ 200 1.1 mrg static struct isl_mat *initial_basis(struct isl_tab *tab) 201 1.1 mrg { 202 1.1 mrg int n_eq; 203 1.1 mrg struct isl_mat *eq; 204 1.1 mrg struct isl_mat *Q; 205 1.1 mrg 206 1.1 mrg tab->n_unbounded = 0; 207 1.1 mrg tab->n_zero = n_eq = tab->n_var - tab->n_col + tab->n_dead; 208 1.1 mrg if (tab->empty || n_eq == 0 || n_eq == tab->n_var) 209 1.1 mrg return isl_mat_identity(tab->mat->ctx, 1 + tab->n_var); 210 1.1 mrg 211 1.1 mrg eq = tab_equalities(tab); 212 1.1 mrg eq = isl_mat_left_hermite(eq, 0, NULL, &Q); 213 1.1 mrg if (!eq) 214 1.1 mrg return NULL; 215 1.1 mrg isl_mat_free(eq); 216 1.1 mrg 217 1.1 mrg Q = isl_mat_lin_to_aff(Q); 218 1.1 mrg return Q; 219 1.1 mrg } 220 1.1 mrg 221 1.1 mrg /* Compute the minimum of the current ("level") basis row over "tab" 222 1.1 mrg * and store the result in position "level" of "min". 223 1.1 mrg * 224 1.1 mrg * This function assumes that at least one more row and at least 225 1.1 mrg * one more element in the constraint array are available in the tableau. 226 1.1 mrg */ 227 1.1 mrg static enum isl_lp_result compute_min(isl_ctx *ctx, struct isl_tab *tab, 228 1.1 mrg __isl_keep isl_vec *min, int level) 229 1.1 mrg { 230 1.1 mrg return isl_tab_min(tab, tab->basis->row[1 + level], 231 1.1 mrg ctx->one, &min->el[level], NULL, 0); 232 1.1 mrg } 233 1.1 mrg 234 1.1 mrg /* Compute the maximum of the current ("level") basis row over "tab" 235 1.1 mrg * and store the result in position "level" of "max". 236 1.1 mrg * 237 1.1 mrg * This function assumes that at least one more row and at least 238 1.1 mrg * one more element in the constraint array are available in the tableau. 239 1.1 mrg */ 240 1.1 mrg static enum isl_lp_result compute_max(isl_ctx *ctx, struct isl_tab *tab, 241 1.1 mrg __isl_keep isl_vec *max, int level) 242 1.1 mrg { 243 1.1 mrg enum isl_lp_result res; 244 1.1 mrg unsigned dim = tab->n_var; 245 1.1 mrg 246 1.1 mrg isl_seq_neg(tab->basis->row[1 + level] + 1, 247 1.1 mrg tab->basis->row[1 + level] + 1, dim); 248 1.1 mrg res = isl_tab_min(tab, tab->basis->row[1 + level], 249 1.1 mrg ctx->one, &max->el[level], NULL, 0); 250 1.1 mrg isl_seq_neg(tab->basis->row[1 + level] + 1, 251 1.1 mrg tab->basis->row[1 + level] + 1, dim); 252 1.1 mrg isl_int_neg(max->el[level], max->el[level]); 253 1.1 mrg 254 1.1 mrg return res; 255 1.1 mrg } 256 1.1 mrg 257 1.1 mrg /* Perform a greedy search for an integer point in the set represented 258 1.1 mrg * by "tab", given that the minimal rational value (rounded up to the 259 1.1 mrg * nearest integer) at "level" is smaller than the maximal rational 260 1.1 mrg * value (rounded down to the nearest integer). 261 1.1 mrg * 262 1.1 mrg * Return 1 if we have found an integer point (if tab->n_unbounded > 0 263 1.1 mrg * then we may have only found integer values for the bounded dimensions 264 1.1 mrg * and it is the responsibility of the caller to extend this solution 265 1.1 mrg * to the unbounded dimensions). 266 1.1 mrg * Return 0 if greedy search did not result in a solution. 267 1.1 mrg * Return -1 if some error occurred. 268 1.1 mrg * 269 1.1 mrg * We assign a value half-way between the minimum and the maximum 270 1.1 mrg * to the current dimension and check if the minimal value of the 271 1.1 mrg * next dimension is still smaller than (or equal) to the maximal value. 272 1.1 mrg * We continue this process until either 273 1.1 mrg * - the minimal value (rounded up) is greater than the maximal value 274 1.1 mrg * (rounded down). In this case, greedy search has failed. 275 1.1 mrg * - we have exhausted all bounded dimensions, meaning that we have 276 1.1 mrg * found a solution. 277 1.1 mrg * - the sample value of the tableau is integral. 278 1.1 mrg * - some error has occurred. 279 1.1 mrg */ 280 1.1 mrg static int greedy_search(isl_ctx *ctx, struct isl_tab *tab, 281 1.1 mrg __isl_keep isl_vec *min, __isl_keep isl_vec *max, int level) 282 1.1 mrg { 283 1.1 mrg struct isl_tab_undo *snap; 284 1.1 mrg enum isl_lp_result res; 285 1.1 mrg 286 1.1 mrg snap = isl_tab_snap(tab); 287 1.1 mrg 288 1.1 mrg do { 289 1.1 mrg isl_int_add(tab->basis->row[1 + level][0], 290 1.1 mrg min->el[level], max->el[level]); 291 1.1 mrg isl_int_fdiv_q_ui(tab->basis->row[1 + level][0], 292 1.1 mrg tab->basis->row[1 + level][0], 2); 293 1.1 mrg isl_int_neg(tab->basis->row[1 + level][0], 294 1.1 mrg tab->basis->row[1 + level][0]); 295 1.1 mrg if (isl_tab_add_valid_eq(tab, tab->basis->row[1 + level]) < 0) 296 1.1 mrg return -1; 297 1.1 mrg isl_int_set_si(tab->basis->row[1 + level][0], 0); 298 1.1 mrg 299 1.1 mrg if (++level >= tab->n_var - tab->n_unbounded) 300 1.1 mrg return 1; 301 1.1 mrg if (isl_tab_sample_is_integer(tab)) 302 1.1 mrg return 1; 303 1.1 mrg 304 1.1 mrg res = compute_min(ctx, tab, min, level); 305 1.1 mrg if (res == isl_lp_error) 306 1.1 mrg return -1; 307 1.1 mrg if (res != isl_lp_ok) 308 1.1 mrg isl_die(ctx, isl_error_internal, 309 1.1 mrg "expecting bounded rational solution", 310 1.1 mrg return -1); 311 1.1 mrg res = compute_max(ctx, tab, max, level); 312 1.1 mrg if (res == isl_lp_error) 313 1.1 mrg return -1; 314 1.1 mrg if (res != isl_lp_ok) 315 1.1 mrg isl_die(ctx, isl_error_internal, 316 1.1 mrg "expecting bounded rational solution", 317 1.1 mrg return -1); 318 1.1 mrg } while (isl_int_le(min->el[level], max->el[level])); 319 1.1 mrg 320 1.1 mrg if (isl_tab_rollback(tab, snap) < 0) 321 1.1 mrg return -1; 322 1.1 mrg 323 1.1 mrg return 0; 324 1.1 mrg } 325 1.1 mrg 326 1.1 mrg /* Given a tableau representing a set, find and return 327 1.1 mrg * an integer point in the set, if there is any. 328 1.1 mrg * 329 1.1 mrg * We perform a depth first search 330 1.1 mrg * for an integer point, by scanning all possible values in the range 331 1.1 mrg * attained by a basis vector, where an initial basis may have been set 332 1.1 mrg * by the calling function. Otherwise an initial basis that exploits 333 1.1 mrg * the equalities in the tableau is created. 334 1.1 mrg * tab->n_zero is currently ignored and is clobbered by this function. 335 1.1 mrg * 336 1.1 mrg * The tableau is allowed to have unbounded direction, but then 337 1.1 mrg * the calling function needs to set an initial basis, with the 338 1.1 mrg * unbounded directions last and with tab->n_unbounded set 339 1.1 mrg * to the number of unbounded directions. 340 1.1 mrg * Furthermore, the calling functions needs to add shifted copies 341 1.1 mrg * of all constraints involving unbounded directions to ensure 342 1.1 mrg * that any feasible rational value in these directions can be rounded 343 1.1 mrg * up to yield a feasible integer value. 344 1.1 mrg * In particular, let B define the given basis x' = B x 345 1.1 mrg * and let T be the inverse of B, i.e., X = T x'. 346 1.1 mrg * Let a x + c >= 0 be a constraint of the set represented by the tableau, 347 1.1 mrg * or a T x' + c >= 0 in terms of the given basis. Assume that 348 1.1 mrg * the bounded directions have an integer value, then we can safely 349 1.1 mrg * round up the values for the unbounded directions if we make sure 350 1.1 mrg * that x' not only satisfies the original constraint, but also 351 1.1 mrg * the constraint "a T x' + c + s >= 0" with s the sum of all 352 1.1 mrg * negative values in the last n_unbounded entries of "a T". 353 1.1 mrg * The calling function therefore needs to add the constraint 354 1.1 mrg * a x + c + s >= 0. The current function then scans the first 355 1.1 mrg * directions for an integer value and once those have been found, 356 1.1 mrg * it can compute "T ceil(B x)" to yield an integer point in the set. 357 1.1 mrg * Note that during the search, the first rows of B may be changed 358 1.1 mrg * by a basis reduction, but the last n_unbounded rows of B remain 359 1.1 mrg * unaltered and are also not mixed into the first rows. 360 1.1 mrg * 361 1.1 mrg * The search is implemented iteratively. "level" identifies the current 362 1.1 mrg * basis vector. "init" is true if we want the first value at the current 363 1.1 mrg * level and false if we want the next value. 364 1.1 mrg * 365 1.1 mrg * At the start of each level, we first check if we can find a solution 366 1.1 mrg * using greedy search. If not, we continue with the exhaustive search. 367 1.1 mrg * 368 1.1 mrg * The initial basis is the identity matrix. If the range in some direction 369 1.1 mrg * contains more than one integer value, we perform basis reduction based 370 1.1 mrg * on the value of ctx->opt->gbr 371 1.1 mrg * - ISL_GBR_NEVER: never perform basis reduction 372 1.1 mrg * - ISL_GBR_ONCE: only perform basis reduction the first 373 1.1 mrg * time such a range is encountered 374 1.1 mrg * - ISL_GBR_ALWAYS: always perform basis reduction when 375 1.1 mrg * such a range is encountered 376 1.1 mrg * 377 1.1 mrg * When ctx->opt->gbr is set to ISL_GBR_ALWAYS, then we allow the basis 378 1.1 mrg * reduction computation to return early. That is, as soon as it 379 1.1 mrg * finds a reasonable first direction. 380 1.1 mrg */ 381 1.1 mrg __isl_give isl_vec *isl_tab_sample(struct isl_tab *tab) 382 1.1 mrg { 383 1.1 mrg unsigned dim; 384 1.1 mrg unsigned gbr; 385 1.1 mrg struct isl_ctx *ctx; 386 1.1 mrg struct isl_vec *sample; 387 1.1 mrg struct isl_vec *min; 388 1.1 mrg struct isl_vec *max; 389 1.1 mrg enum isl_lp_result res; 390 1.1 mrg int level; 391 1.1 mrg int init; 392 1.1 mrg int reduced; 393 1.1 mrg struct isl_tab_undo **snap; 394 1.1 mrg 395 1.1 mrg if (!tab) 396 1.1 mrg return NULL; 397 1.1 mrg if (tab->empty) 398 1.1 mrg return isl_vec_alloc(tab->mat->ctx, 0); 399 1.1 mrg 400 1.1 mrg if (!tab->basis) 401 1.1 mrg tab->basis = initial_basis(tab); 402 1.1 mrg if (!tab->basis) 403 1.1 mrg return NULL; 404 1.1 mrg isl_assert(tab->mat->ctx, tab->basis->n_row == tab->n_var + 1, 405 1.1 mrg return NULL); 406 1.1 mrg isl_assert(tab->mat->ctx, tab->basis->n_col == tab->n_var + 1, 407 1.1 mrg return NULL); 408 1.1 mrg 409 1.1 mrg ctx = tab->mat->ctx; 410 1.1 mrg dim = tab->n_var; 411 1.1 mrg gbr = ctx->opt->gbr; 412 1.1 mrg 413 1.1 mrg if (tab->n_unbounded == tab->n_var) { 414 1.1 mrg sample = isl_tab_get_sample_value(tab); 415 1.1 mrg sample = isl_mat_vec_product(isl_mat_copy(tab->basis), sample); 416 1.1 mrg sample = isl_vec_ceil(sample); 417 1.1 mrg sample = isl_mat_vec_inverse_product(isl_mat_copy(tab->basis), 418 1.1 mrg sample); 419 1.1 mrg return sample; 420 1.1 mrg } 421 1.1 mrg 422 1.1 mrg if (isl_tab_extend_cons(tab, dim + 1) < 0) 423 1.1 mrg return NULL; 424 1.1 mrg 425 1.1 mrg min = isl_vec_alloc(ctx, dim); 426 1.1 mrg max = isl_vec_alloc(ctx, dim); 427 1.1 mrg snap = isl_alloc_array(ctx, struct isl_tab_undo *, dim); 428 1.1 mrg 429 1.1 mrg if (!min || !max || !snap) 430 1.1 mrg goto error; 431 1.1 mrg 432 1.1 mrg level = 0; 433 1.1 mrg init = 1; 434 1.1 mrg reduced = 0; 435 1.1 mrg 436 1.1 mrg while (level >= 0) { 437 1.1 mrg if (init) { 438 1.1 mrg int choice; 439 1.1 mrg 440 1.1 mrg res = compute_min(ctx, tab, min, level); 441 1.1 mrg if (res == isl_lp_error) 442 1.1 mrg goto error; 443 1.1 mrg if (res != isl_lp_ok) 444 1.1 mrg isl_die(ctx, isl_error_internal, 445 1.1 mrg "expecting bounded rational solution", 446 1.1 mrg goto error); 447 1.1 mrg if (isl_tab_sample_is_integer(tab)) 448 1.1 mrg break; 449 1.1 mrg res = compute_max(ctx, tab, max, level); 450 1.1 mrg if (res == isl_lp_error) 451 1.1 mrg goto error; 452 1.1 mrg if (res != isl_lp_ok) 453 1.1 mrg isl_die(ctx, isl_error_internal, 454 1.1 mrg "expecting bounded rational solution", 455 1.1 mrg goto error); 456 1.1 mrg if (isl_tab_sample_is_integer(tab)) 457 1.1 mrg break; 458 1.1 mrg choice = isl_int_lt(min->el[level], max->el[level]); 459 1.1 mrg if (choice) { 460 1.1 mrg int g; 461 1.1 mrg g = greedy_search(ctx, tab, min, max, level); 462 1.1 mrg if (g < 0) 463 1.1 mrg goto error; 464 1.1 mrg if (g) 465 1.1 mrg break; 466 1.1 mrg } 467 1.1 mrg if (!reduced && choice && 468 1.1 mrg ctx->opt->gbr != ISL_GBR_NEVER) { 469 1.1 mrg unsigned gbr_only_first; 470 1.1 mrg if (ctx->opt->gbr == ISL_GBR_ONCE) 471 1.1 mrg ctx->opt->gbr = ISL_GBR_NEVER; 472 1.1 mrg tab->n_zero = level; 473 1.1 mrg gbr_only_first = ctx->opt->gbr_only_first; 474 1.1 mrg ctx->opt->gbr_only_first = 475 1.1 mrg ctx->opt->gbr == ISL_GBR_ALWAYS; 476 1.1 mrg tab = isl_tab_compute_reduced_basis(tab); 477 1.1 mrg ctx->opt->gbr_only_first = gbr_only_first; 478 1.1 mrg if (!tab || !tab->basis) 479 1.1 mrg goto error; 480 1.1 mrg reduced = 1; 481 1.1 mrg continue; 482 1.1 mrg } 483 1.1 mrg reduced = 0; 484 1.1 mrg snap[level] = isl_tab_snap(tab); 485 1.1 mrg } else 486 1.1 mrg isl_int_add_ui(min->el[level], min->el[level], 1); 487 1.1 mrg 488 1.1 mrg if (isl_int_gt(min->el[level], max->el[level])) { 489 1.1 mrg level--; 490 1.1 mrg init = 0; 491 1.1 mrg if (level >= 0) 492 1.1 mrg if (isl_tab_rollback(tab, snap[level]) < 0) 493 1.1 mrg goto error; 494 1.1 mrg continue; 495 1.1 mrg } 496 1.1 mrg isl_int_neg(tab->basis->row[1 + level][0], min->el[level]); 497 1.1 mrg if (isl_tab_add_valid_eq(tab, tab->basis->row[1 + level]) < 0) 498 1.1 mrg goto error; 499 1.1 mrg isl_int_set_si(tab->basis->row[1 + level][0], 0); 500 1.1 mrg if (level + tab->n_unbounded < dim - 1) { 501 1.1 mrg ++level; 502 1.1 mrg init = 1; 503 1.1 mrg continue; 504 1.1 mrg } 505 1.1 mrg break; 506 1.1 mrg } 507 1.1 mrg 508 1.1 mrg if (level >= 0) { 509 1.1 mrg sample = isl_tab_get_sample_value(tab); 510 1.1 mrg if (!sample) 511 1.1 mrg goto error; 512 1.1 mrg if (tab->n_unbounded && !isl_int_is_one(sample->el[0])) { 513 1.1 mrg sample = isl_mat_vec_product(isl_mat_copy(tab->basis), 514 1.1 mrg sample); 515 1.1 mrg sample = isl_vec_ceil(sample); 516 1.1 mrg sample = isl_mat_vec_inverse_product( 517 1.1 mrg isl_mat_copy(tab->basis), sample); 518 1.1 mrg } 519 1.1 mrg } else 520 1.1 mrg sample = isl_vec_alloc(ctx, 0); 521 1.1 mrg 522 1.1 mrg ctx->opt->gbr = gbr; 523 1.1 mrg isl_vec_free(min); 524 1.1 mrg isl_vec_free(max); 525 1.1 mrg free(snap); 526 1.1 mrg return sample; 527 1.1 mrg error: 528 1.1 mrg ctx->opt->gbr = gbr; 529 1.1 mrg isl_vec_free(min); 530 1.1 mrg isl_vec_free(max); 531 1.1 mrg free(snap); 532 1.1 mrg return NULL; 533 1.1 mrg } 534 1.1 mrg 535 1.1 mrg static __isl_give isl_vec *sample_bounded(__isl_take isl_basic_set *bset); 536 1.1 mrg 537 1.1 mrg /* Internal data for factored_sample. 538 1.1 mrg * "sample" collects the sample and may get reset to a zero-length vector 539 1.1 mrg * signaling the absence of a sample vector. 540 1.1 mrg * "pos" is the position of the contribution of the next factor. 541 1.1 mrg */ 542 1.1 mrg struct isl_factored_sample_data { 543 1.1 mrg isl_vec *sample; 544 1.1 mrg int pos; 545 1.1 mrg }; 546 1.1 mrg 547 1.1 mrg /* isl_factorizer_every_factor_basic_set callback that extends 548 1.1 mrg * the sample in data->sample with the contribution 549 1.1 mrg * of the factor "bset". 550 1.1 mrg * If "bset" turns out to be empty, then the product is empty too and 551 1.1 mrg * no further factors need to be considered. 552 1.1 mrg */ 553 1.1 mrg static isl_bool factor_sample(__isl_keep isl_basic_set *bset, void *user) 554 1.1 mrg { 555 1.1 mrg struct isl_factored_sample_data *data = user; 556 1.1 mrg isl_vec *sample; 557 1.1 mrg isl_size n; 558 1.1 mrg 559 1.1 mrg n = isl_basic_set_dim(bset, isl_dim_set); 560 1.1 mrg if (n < 0) 561 1.1 mrg return isl_bool_error; 562 1.1 mrg 563 1.1 mrg sample = sample_bounded(isl_basic_set_copy(bset)); 564 1.1 mrg if (!sample) 565 1.1 mrg return isl_bool_error; 566 1.1 mrg if (sample->size == 0) { 567 1.1 mrg isl_vec_free(data->sample); 568 1.1 mrg data->sample = sample; 569 1.1 mrg return isl_bool_false; 570 1.1 mrg } 571 1.1 mrg isl_seq_cpy(data->sample->el + data->pos, sample->el + 1, n); 572 1.1 mrg isl_vec_free(sample); 573 1.1 mrg data->pos += n; 574 1.1 mrg 575 1.1 mrg return isl_bool_true; 576 1.1 mrg } 577 1.1 mrg 578 1.1 mrg /* Compute a sample point of the given basic set, based on the given, 579 1.1 mrg * non-trivial factorization. 580 1.1 mrg */ 581 1.1 mrg static __isl_give isl_vec *factored_sample(__isl_take isl_basic_set *bset, 582 1.1 mrg __isl_take isl_factorizer *f) 583 1.1 mrg { 584 1.1 mrg struct isl_factored_sample_data data = { NULL }; 585 1.1 mrg isl_ctx *ctx; 586 1.1 mrg isl_size total; 587 1.1 mrg isl_bool every; 588 1.1 mrg 589 1.1 mrg ctx = isl_basic_set_get_ctx(bset); 590 1.1 mrg total = isl_basic_set_dim(bset, isl_dim_all); 591 1.1 mrg if (!ctx || total < 0) 592 1.1 mrg goto error; 593 1.1 mrg 594 1.1 mrg data.sample = isl_vec_alloc(ctx, 1 + total); 595 1.1 mrg if (!data.sample) 596 1.1 mrg goto error; 597 1.1 mrg isl_int_set_si(data.sample->el[0], 1); 598 1.1 mrg data.pos = 1; 599 1.1 mrg 600 1.1 mrg every = isl_factorizer_every_factor_basic_set(f, &factor_sample, &data); 601 1.1 mrg if (every < 0) { 602 1.1 mrg data.sample = isl_vec_free(data.sample); 603 1.1 mrg } else if (every) { 604 1.1 mrg isl_morph *morph; 605 1.1 mrg 606 1.1 mrg morph = isl_morph_inverse(isl_morph_copy(f->morph)); 607 1.1 mrg data.sample = isl_morph_vec(morph, data.sample); 608 1.1 mrg } 609 1.1 mrg 610 1.1 mrg isl_basic_set_free(bset); 611 1.1 mrg isl_factorizer_free(f); 612 1.1 mrg return data.sample; 613 1.1 mrg error: 614 1.1 mrg isl_basic_set_free(bset); 615 1.1 mrg isl_factorizer_free(f); 616 1.1 mrg isl_vec_free(data.sample); 617 1.1 mrg return NULL; 618 1.1 mrg } 619 1.1 mrg 620 1.1 mrg /* Given a basic set that is known to be bounded, find and return 621 1.1 mrg * an integer point in the basic set, if there is any. 622 1.1 mrg * 623 1.1 mrg * After handling some trivial cases, we construct a tableau 624 1.1 mrg * and then use isl_tab_sample to find a sample, passing it 625 1.1 mrg * the identity matrix as initial basis. 626 1.1 mrg */ 627 1.1 mrg static __isl_give isl_vec *sample_bounded(__isl_take isl_basic_set *bset) 628 1.1 mrg { 629 1.1 mrg isl_size dim; 630 1.1 mrg struct isl_vec *sample; 631 1.1 mrg struct isl_tab *tab = NULL; 632 1.1 mrg isl_factorizer *f; 633 1.1 mrg 634 1.1 mrg if (!bset) 635 1.1 mrg return NULL; 636 1.1 mrg 637 1.1 mrg if (isl_basic_set_plain_is_empty(bset)) 638 1.1 mrg return empty_sample(bset); 639 1.1 mrg 640 1.1 mrg dim = isl_basic_set_dim(bset, isl_dim_all); 641 1.1 mrg if (dim < 0) 642 1.1 mrg bset = isl_basic_set_free(bset); 643 1.1 mrg if (dim == 0) 644 1.1 mrg return zero_sample(bset); 645 1.1 mrg if (dim == 1) 646 1.1 mrg return interval_sample(bset); 647 1.1 mrg if (bset->n_eq > 0) 648 1.1 mrg return sample_eq(bset, sample_bounded); 649 1.1 mrg 650 1.1 mrg f = isl_basic_set_factorizer(bset); 651 1.1 mrg if (!f) 652 1.1 mrg goto error; 653 1.1 mrg if (f->n_group != 0) 654 1.1 mrg return factored_sample(bset, f); 655 1.1 mrg isl_factorizer_free(f); 656 1.1 mrg 657 1.1 mrg tab = isl_tab_from_basic_set(bset, 1); 658 1.1 mrg if (tab && tab->empty) { 659 1.1 mrg isl_tab_free(tab); 660 1.1 mrg ISL_F_SET(bset, ISL_BASIC_SET_EMPTY); 661 1.1 mrg sample = isl_vec_alloc(isl_basic_set_get_ctx(bset), 0); 662 1.1 mrg isl_basic_set_free(bset); 663 1.1 mrg return sample; 664 1.1 mrg } 665 1.1 mrg 666 1.1 mrg if (!ISL_F_ISSET(bset, ISL_BASIC_SET_NO_IMPLICIT)) 667 1.1 mrg if (isl_tab_detect_implicit_equalities(tab) < 0) 668 1.1 mrg goto error; 669 1.1 mrg 670 1.1 mrg sample = isl_tab_sample(tab); 671 1.1 mrg if (!sample) 672 1.1 mrg goto error; 673 1.1 mrg 674 1.1 mrg if (sample->size > 0) { 675 1.1 mrg isl_vec_free(bset->sample); 676 1.1 mrg bset->sample = isl_vec_copy(sample); 677 1.1 mrg } 678 1.1 mrg 679 1.1 mrg isl_basic_set_free(bset); 680 1.1 mrg isl_tab_free(tab); 681 1.1 mrg return sample; 682 1.1 mrg error: 683 1.1 mrg isl_basic_set_free(bset); 684 1.1 mrg isl_tab_free(tab); 685 1.1 mrg return NULL; 686 1.1 mrg } 687 1.1 mrg 688 1.1 mrg /* Given a basic set "bset" and a value "sample" for the first coordinates 689 1.1 mrg * of bset, plug in these values and drop the corresponding coordinates. 690 1.1 mrg * 691 1.1 mrg * We do this by computing the preimage of the transformation 692 1.1 mrg * 693 1.1 mrg * [ 1 0 ] 694 1.1 mrg * x = [ s 0 ] x' 695 1.1 mrg * [ 0 I ] 696 1.1 mrg * 697 1.1 mrg * where [1 s] is the sample value and I is the identity matrix of the 698 1.1 mrg * appropriate dimension. 699 1.1 mrg */ 700 1.1 mrg static __isl_give isl_basic_set *plug_in(__isl_take isl_basic_set *bset, 701 1.1 mrg __isl_take isl_vec *sample) 702 1.1 mrg { 703 1.1 mrg int i; 704 1.1 mrg isl_size total; 705 1.1 mrg struct isl_mat *T; 706 1.1 mrg 707 1.1 mrg total = isl_basic_set_dim(bset, isl_dim_all); 708 1.1 mrg if (total < 0 || !sample) 709 1.1 mrg goto error; 710 1.1 mrg 711 1.1 mrg T = isl_mat_alloc(bset->ctx, 1 + total, 1 + total - (sample->size - 1)); 712 1.1 mrg if (!T) 713 1.1 mrg goto error; 714 1.1 mrg 715 1.1 mrg for (i = 0; i < sample->size; ++i) { 716 1.1 mrg isl_int_set(T->row[i][0], sample->el[i]); 717 1.1 mrg isl_seq_clr(T->row[i] + 1, T->n_col - 1); 718 1.1 mrg } 719 1.1 mrg for (i = 0; i < T->n_col - 1; ++i) { 720 1.1 mrg isl_seq_clr(T->row[sample->size + i], T->n_col); 721 1.1 mrg isl_int_set_si(T->row[sample->size + i][1 + i], 1); 722 1.1 mrg } 723 1.1 mrg isl_vec_free(sample); 724 1.1 mrg 725 1.1 mrg bset = isl_basic_set_preimage(bset, T); 726 1.1 mrg return bset; 727 1.1 mrg error: 728 1.1 mrg isl_basic_set_free(bset); 729 1.1 mrg isl_vec_free(sample); 730 1.1 mrg return NULL; 731 1.1 mrg } 732 1.1 mrg 733 1.1 mrg /* Given a basic set "bset", return any (possibly non-integer) point 734 1.1 mrg * in the basic set. 735 1.1 mrg */ 736 1.1 mrg static __isl_give isl_vec *rational_sample(__isl_take isl_basic_set *bset) 737 1.1 mrg { 738 1.1 mrg struct isl_tab *tab; 739 1.1 mrg struct isl_vec *sample; 740 1.1 mrg 741 1.1 mrg if (!bset) 742 1.1 mrg return NULL; 743 1.1 mrg 744 1.1 mrg tab = isl_tab_from_basic_set(bset, 0); 745 1.1 mrg sample = isl_tab_get_sample_value(tab); 746 1.1 mrg isl_tab_free(tab); 747 1.1 mrg 748 1.1 mrg isl_basic_set_free(bset); 749 1.1 mrg 750 1.1 mrg return sample; 751 1.1 mrg } 752 1.1 mrg 753 1.1 mrg /* Given a linear cone "cone" and a rational point "vec", 754 1.1 mrg * construct a polyhedron with shifted copies of the constraints in "cone", 755 1.1 mrg * i.e., a polyhedron with "cone" as its recession cone, such that each 756 1.1 mrg * point x in this polyhedron is such that the unit box positioned at x 757 1.1 mrg * lies entirely inside the affine cone 'vec + cone'. 758 1.1 mrg * Any rational point in this polyhedron may therefore be rounded up 759 1.1 mrg * to yield an integer point that lies inside said affine cone. 760 1.1 mrg * 761 1.1 mrg * Denote the constraints of cone by "<a_i, x> >= 0" and the rational 762 1.1 mrg * point "vec" by v/d. 763 1.1 mrg * Let b_i = <a_i, v>. Then the affine cone 'vec + cone' is given 764 1.1 mrg * by <a_i, x> - b/d >= 0. 765 1.1 mrg * The polyhedron <a_i, x> - ceil{b/d} >= 0 is a subset of this affine cone. 766 1.1 mrg * We prefer this polyhedron over the actual affine cone because it doesn't 767 1.1 mrg * require a scaling of the constraints. 768 1.1 mrg * If each of the vertices of the unit cube positioned at x lies inside 769 1.1 mrg * this polyhedron, then the whole unit cube at x lies inside the affine cone. 770 1.1 mrg * We therefore impose that x' = x + \sum e_i, for any selection of unit 771 1.1 mrg * vectors lies inside the polyhedron, i.e., 772 1.1 mrg * 773 1.1 mrg * <a_i, x'> - ceil{b/d} = <a_i, x> + sum a_i - ceil{b/d} >= 0 774 1.1 mrg * 775 1.1 mrg * The most stringent of these constraints is the one that selects 776 1.1 mrg * all negative a_i, so the polyhedron we are looking for has constraints 777 1.1 mrg * 778 1.1 mrg * <a_i, x> + sum_{a_i < 0} a_i - ceil{b/d} >= 0 779 1.1 mrg * 780 1.1 mrg * Note that if cone were known to have only non-negative rays 781 1.1 mrg * (which can be accomplished by a unimodular transformation), 782 1.1 mrg * then we would only have to check the points x' = x + e_i 783 1.1 mrg * and we only have to add the smallest negative a_i (if any) 784 1.1 mrg * instead of the sum of all negative a_i. 785 1.1 mrg */ 786 1.1 mrg static __isl_give isl_basic_set *shift_cone(__isl_take isl_basic_set *cone, 787 1.1 mrg __isl_take isl_vec *vec) 788 1.1 mrg { 789 1.1 mrg int i, j, k; 790 1.1 mrg isl_size total; 791 1.1 mrg 792 1.1 mrg struct isl_basic_set *shift = NULL; 793 1.1 mrg 794 1.1 mrg total = isl_basic_set_dim(cone, isl_dim_all); 795 1.1 mrg if (total < 0 || !vec) 796 1.1 mrg goto error; 797 1.1 mrg 798 1.1 mrg isl_assert(cone->ctx, cone->n_eq == 0, goto error); 799 1.1 mrg 800 1.1 mrg shift = isl_basic_set_alloc_space(isl_basic_set_get_space(cone), 801 1.1 mrg 0, 0, cone->n_ineq); 802 1.1 mrg 803 1.1 mrg for (i = 0; i < cone->n_ineq; ++i) { 804 1.1 mrg k = isl_basic_set_alloc_inequality(shift); 805 1.1 mrg if (k < 0) 806 1.1 mrg goto error; 807 1.1 mrg isl_seq_cpy(shift->ineq[k] + 1, cone->ineq[i] + 1, total); 808 1.1 mrg isl_seq_inner_product(shift->ineq[k] + 1, vec->el + 1, total, 809 1.1 mrg &shift->ineq[k][0]); 810 1.1 mrg isl_int_cdiv_q(shift->ineq[k][0], 811 1.1 mrg shift->ineq[k][0], vec->el[0]); 812 1.1 mrg isl_int_neg(shift->ineq[k][0], shift->ineq[k][0]); 813 1.1 mrg for (j = 0; j < total; ++j) { 814 1.1 mrg if (isl_int_is_nonneg(shift->ineq[k][1 + j])) 815 1.1 mrg continue; 816 1.1 mrg isl_int_add(shift->ineq[k][0], 817 1.1 mrg shift->ineq[k][0], shift->ineq[k][1 + j]); 818 1.1 mrg } 819 1.1 mrg } 820 1.1 mrg 821 1.1 mrg isl_basic_set_free(cone); 822 1.1 mrg isl_vec_free(vec); 823 1.1 mrg 824 1.1 mrg return isl_basic_set_finalize(shift); 825 1.1 mrg error: 826 1.1 mrg isl_basic_set_free(shift); 827 1.1 mrg isl_basic_set_free(cone); 828 1.1 mrg isl_vec_free(vec); 829 1.1 mrg return NULL; 830 1.1 mrg } 831 1.1 mrg 832 1.1 mrg /* Given a rational point vec in a (transformed) basic set, 833 1.1 mrg * such that cone is the recession cone of the original basic set, 834 1.1 mrg * "round up" the rational point to an integer point. 835 1.1 mrg * 836 1.1 mrg * We first check if the rational point just happens to be integer. 837 1.1 mrg * If not, we transform the cone in the same way as the basic set, 838 1.1 mrg * pick a point x in this cone shifted to the rational point such that 839 1.1 mrg * the whole unit cube at x is also inside this affine cone. 840 1.1 mrg * Then we simply round up the coordinates of x and return the 841 1.1 mrg * resulting integer point. 842 1.1 mrg */ 843 1.1 mrg static __isl_give isl_vec *round_up_in_cone(__isl_take isl_vec *vec, 844 1.1 mrg __isl_take isl_basic_set *cone, __isl_take isl_mat *U) 845 1.1 mrg { 846 1.1 mrg isl_size total; 847 1.1 mrg 848 1.1 mrg if (!vec || !cone || !U) 849 1.1 mrg goto error; 850 1.1 mrg 851 1.1 mrg isl_assert(vec->ctx, vec->size != 0, goto error); 852 1.1 mrg if (isl_int_is_one(vec->el[0])) { 853 1.1 mrg isl_mat_free(U); 854 1.1 mrg isl_basic_set_free(cone); 855 1.1 mrg return vec; 856 1.1 mrg } 857 1.1 mrg 858 1.1 mrg total = isl_basic_set_dim(cone, isl_dim_all); 859 1.1 mrg if (total < 0) 860 1.1 mrg goto error; 861 1.1 mrg cone = isl_basic_set_preimage(cone, U); 862 1.1 mrg cone = isl_basic_set_remove_dims(cone, isl_dim_set, 863 1.1 mrg 0, total - (vec->size - 1)); 864 1.1 mrg 865 1.1 mrg cone = shift_cone(cone, vec); 866 1.1 mrg 867 1.1 mrg vec = rational_sample(cone); 868 1.1 mrg vec = isl_vec_ceil(vec); 869 1.1 mrg return vec; 870 1.1 mrg error: 871 1.1 mrg isl_mat_free(U); 872 1.1 mrg isl_vec_free(vec); 873 1.1 mrg isl_basic_set_free(cone); 874 1.1 mrg return NULL; 875 1.1 mrg } 876 1.1 mrg 877 1.1 mrg /* Concatenate two integer vectors, i.e., two vectors with denominator 878 1.1 mrg * (stored in element 0) equal to 1. 879 1.1 mrg */ 880 1.1 mrg static __isl_give isl_vec *vec_concat(__isl_take isl_vec *vec1, 881 1.1 mrg __isl_take isl_vec *vec2) 882 1.1 mrg { 883 1.1 mrg struct isl_vec *vec; 884 1.1 mrg 885 1.1 mrg if (!vec1 || !vec2) 886 1.1 mrg goto error; 887 1.1 mrg isl_assert(vec1->ctx, vec1->size > 0, goto error); 888 1.1 mrg isl_assert(vec2->ctx, vec2->size > 0, goto error); 889 1.1 mrg isl_assert(vec1->ctx, isl_int_is_one(vec1->el[0]), goto error); 890 1.1 mrg isl_assert(vec2->ctx, isl_int_is_one(vec2->el[0]), goto error); 891 1.1 mrg 892 1.1 mrg vec = isl_vec_alloc(vec1->ctx, vec1->size + vec2->size - 1); 893 1.1 mrg if (!vec) 894 1.1 mrg goto error; 895 1.1 mrg 896 1.1 mrg isl_seq_cpy(vec->el, vec1->el, vec1->size); 897 1.1 mrg isl_seq_cpy(vec->el + vec1->size, vec2->el + 1, vec2->size - 1); 898 1.1 mrg 899 1.1 mrg isl_vec_free(vec1); 900 1.1 mrg isl_vec_free(vec2); 901 1.1 mrg 902 1.1 mrg return vec; 903 1.1 mrg error: 904 1.1 mrg isl_vec_free(vec1); 905 1.1 mrg isl_vec_free(vec2); 906 1.1 mrg return NULL; 907 1.1 mrg } 908 1.1 mrg 909 1.1 mrg /* Give a basic set "bset" with recession cone "cone", compute and 910 1.1 mrg * return an integer point in bset, if any. 911 1.1 mrg * 912 1.1 mrg * If the recession cone is full-dimensional, then we know that 913 1.1 mrg * bset contains an infinite number of integer points and it is 914 1.1 mrg * fairly easy to pick one of them. 915 1.1 mrg * If the recession cone is not full-dimensional, then we first 916 1.1 mrg * transform bset such that the bounded directions appear as 917 1.1 mrg * the first dimensions of the transformed basic set. 918 1.1 mrg * We do this by using a unimodular transformation that transforms 919 1.1 mrg * the equalities in the recession cone to equalities on the first 920 1.1 mrg * dimensions. 921 1.1 mrg * 922 1.1 mrg * The transformed set is then projected onto its bounded dimensions. 923 1.1 mrg * Note that to compute this projection, we can simply drop all constraints 924 1.1 mrg * involving any of the unbounded dimensions since these constraints 925 1.1 mrg * cannot be combined to produce a constraint on the bounded dimensions. 926 1.1 mrg * To see this, assume that there is such a combination of constraints 927 1.1 mrg * that produces a constraint on the bounded dimensions. This means 928 1.1 mrg * that some combination of the unbounded dimensions has both an upper 929 1.1 mrg * bound and a lower bound in terms of the bounded dimensions, but then 930 1.1 mrg * this combination would be a bounded direction too and would have been 931 1.1 mrg * transformed into a bounded dimensions. 932 1.1 mrg * 933 1.1 mrg * We then compute a sample value in the bounded dimensions. 934 1.1 mrg * If no such value can be found, then the original set did not contain 935 1.1 mrg * any integer points and we are done. 936 1.1 mrg * Otherwise, we plug in the value we found in the bounded dimensions, 937 1.1 mrg * project out these bounded dimensions and end up with a set with 938 1.1 mrg * a full-dimensional recession cone. 939 1.1 mrg * A sample point in this set is computed by "rounding up" any 940 1.1 mrg * rational point in the set. 941 1.1 mrg * 942 1.1 mrg * The sample points in the bounded and unbounded dimensions are 943 1.1 mrg * then combined into a single sample point and transformed back 944 1.1 mrg * to the original space. 945 1.1 mrg */ 946 1.1 mrg __isl_give isl_vec *isl_basic_set_sample_with_cone( 947 1.1 mrg __isl_take isl_basic_set *bset, __isl_take isl_basic_set *cone) 948 1.1 mrg { 949 1.1 mrg isl_size total; 950 1.1 mrg unsigned cone_dim; 951 1.1 mrg struct isl_mat *M, *U; 952 1.1 mrg struct isl_vec *sample; 953 1.1 mrg struct isl_vec *cone_sample; 954 1.1 mrg struct isl_ctx *ctx; 955 1.1 mrg struct isl_basic_set *bounded; 956 1.1 mrg 957 1.1 mrg total = isl_basic_set_dim(cone, isl_dim_all); 958 1.1 mrg if (!bset || total < 0) 959 1.1 mrg goto error; 960 1.1 mrg 961 1.1 mrg ctx = isl_basic_set_get_ctx(bset); 962 1.1 mrg cone_dim = total - cone->n_eq; 963 1.1 mrg 964 1.1 mrg M = isl_mat_sub_alloc6(ctx, cone->eq, 0, cone->n_eq, 1, total); 965 1.1 mrg M = isl_mat_left_hermite(M, 0, &U, NULL); 966 1.1 mrg if (!M) 967 1.1 mrg goto error; 968 1.1 mrg isl_mat_free(M); 969 1.1 mrg 970 1.1 mrg U = isl_mat_lin_to_aff(U); 971 1.1 mrg bset = isl_basic_set_preimage(bset, isl_mat_copy(U)); 972 1.1 mrg 973 1.1 mrg bounded = isl_basic_set_copy(bset); 974 1.1 mrg bounded = isl_basic_set_drop_constraints_involving(bounded, 975 1.1 mrg total - cone_dim, cone_dim); 976 1.1 mrg bounded = isl_basic_set_drop_dims(bounded, total - cone_dim, cone_dim); 977 1.1 mrg sample = sample_bounded(bounded); 978 1.1 mrg if (!sample || sample->size == 0) { 979 1.1 mrg isl_basic_set_free(bset); 980 1.1 mrg isl_basic_set_free(cone); 981 1.1 mrg isl_mat_free(U); 982 1.1 mrg return sample; 983 1.1 mrg } 984 1.1 mrg bset = plug_in(bset, isl_vec_copy(sample)); 985 1.1 mrg cone_sample = rational_sample(bset); 986 1.1 mrg cone_sample = round_up_in_cone(cone_sample, cone, isl_mat_copy(U)); 987 1.1 mrg sample = vec_concat(sample, cone_sample); 988 1.1 mrg sample = isl_mat_vec_product(U, sample); 989 1.1 mrg return sample; 990 1.1 mrg error: 991 1.1 mrg isl_basic_set_free(cone); 992 1.1 mrg isl_basic_set_free(bset); 993 1.1 mrg return NULL; 994 1.1 mrg } 995 1.1 mrg 996 1.1 mrg static void vec_sum_of_neg(__isl_keep isl_vec *v, isl_int *s) 997 1.1 mrg { 998 1.1 mrg int i; 999 1.1 mrg 1000 1.1 mrg isl_int_set_si(*s, 0); 1001 1.1 mrg 1002 1.1 mrg for (i = 0; i < v->size; ++i) 1003 1.1 mrg if (isl_int_is_neg(v->el[i])) 1004 1.1 mrg isl_int_add(*s, *s, v->el[i]); 1005 1.1 mrg } 1006 1.1 mrg 1007 1.1 mrg /* Given a tableau "tab", a tableau "tab_cone" that corresponds 1008 1.1 mrg * to the recession cone and the inverse of a new basis U = inv(B), 1009 1.1 mrg * with the unbounded directions in B last, 1010 1.1 mrg * add constraints to "tab" that ensure any rational value 1011 1.1 mrg * in the unbounded directions can be rounded up to an integer value. 1012 1.1 mrg * 1013 1.1 mrg * The new basis is given by x' = B x, i.e., x = U x'. 1014 1.1 mrg * For any rational value of the last tab->n_unbounded coordinates 1015 1.1 mrg * in the update tableau, the value that is obtained by rounding 1016 1.1 mrg * up this value should be contained in the original tableau. 1017 1.1 mrg * For any constraint "a x + c >= 0", we therefore need to add 1018 1.1 mrg * a constraint "a x + c + s >= 0", with s the sum of all negative 1019 1.1 mrg * entries in the last elements of "a U". 1020 1.1 mrg * 1021 1.1 mrg * Since we are not interested in the first entries of any of the "a U", 1022 1.1 mrg * we first drop the columns of U that correpond to bounded directions. 1023 1.1 mrg */ 1024 1.1 mrg static int tab_shift_cone(struct isl_tab *tab, 1025 1.1 mrg struct isl_tab *tab_cone, struct isl_mat *U) 1026 1.1 mrg { 1027 1.1 mrg int i; 1028 1.1 mrg isl_int v; 1029 1.1 mrg struct isl_basic_set *bset = NULL; 1030 1.1 mrg 1031 1.1 mrg if (tab && tab->n_unbounded == 0) { 1032 1.1 mrg isl_mat_free(U); 1033 1.1 mrg return 0; 1034 1.1 mrg } 1035 1.1 mrg isl_int_init(v); 1036 1.1 mrg if (!tab || !tab_cone || !U) 1037 1.1 mrg goto error; 1038 1.1 mrg bset = isl_tab_peek_bset(tab_cone); 1039 1.1 mrg U = isl_mat_drop_cols(U, 0, tab->n_var - tab->n_unbounded); 1040 1.1 mrg for (i = 0; i < bset->n_ineq; ++i) { 1041 1.1 mrg int ok; 1042 1.1 mrg struct isl_vec *row = NULL; 1043 1.1 mrg if (isl_tab_is_equality(tab_cone, tab_cone->n_eq + i)) 1044 1.1 mrg continue; 1045 1.1 mrg row = isl_vec_alloc(bset->ctx, tab_cone->n_var); 1046 1.1 mrg if (!row) 1047 1.1 mrg goto error; 1048 1.1 mrg isl_seq_cpy(row->el, bset->ineq[i] + 1, tab_cone->n_var); 1049 1.1 mrg row = isl_vec_mat_product(row, isl_mat_copy(U)); 1050 1.1 mrg if (!row) 1051 1.1 mrg goto error; 1052 1.1 mrg vec_sum_of_neg(row, &v); 1053 1.1 mrg isl_vec_free(row); 1054 1.1 mrg if (isl_int_is_zero(v)) 1055 1.1 mrg continue; 1056 1.1 mrg if (isl_tab_extend_cons(tab, 1) < 0) 1057 1.1 mrg goto error; 1058 1.1 mrg isl_int_add(bset->ineq[i][0], bset->ineq[i][0], v); 1059 1.1 mrg ok = isl_tab_add_ineq(tab, bset->ineq[i]) >= 0; 1060 1.1 mrg isl_int_sub(bset->ineq[i][0], bset->ineq[i][0], v); 1061 1.1 mrg if (!ok) 1062 1.1 mrg goto error; 1063 1.1 mrg } 1064 1.1 mrg 1065 1.1 mrg isl_mat_free(U); 1066 1.1 mrg isl_int_clear(v); 1067 1.1 mrg return 0; 1068 1.1 mrg error: 1069 1.1 mrg isl_mat_free(U); 1070 1.1 mrg isl_int_clear(v); 1071 1.1 mrg return -1; 1072 1.1 mrg } 1073 1.1 mrg 1074 1.1 mrg /* Compute and return an initial basis for the possibly 1075 1.1 mrg * unbounded tableau "tab". "tab_cone" is a tableau 1076 1.1 mrg * for the corresponding recession cone. 1077 1.1 mrg * Additionally, add constraints to "tab" that ensure 1078 1.1 mrg * that any rational value for the unbounded directions 1079 1.1 mrg * can be rounded up to an integer value. 1080 1.1 mrg * 1081 1.1 mrg * If the tableau is bounded, i.e., if the recession cone 1082 1.1 mrg * is zero-dimensional, then we just use inital_basis. 1083 1.1 mrg * Otherwise, we construct a basis whose first directions 1084 1.1 mrg * correspond to equalities, followed by bounded directions, 1085 1.1 mrg * i.e., equalities in the recession cone. 1086 1.1 mrg * The remaining directions are then unbounded. 1087 1.1 mrg */ 1088 1.1 mrg int isl_tab_set_initial_basis_with_cone(struct isl_tab *tab, 1089 1.1 mrg struct isl_tab *tab_cone) 1090 1.1 mrg { 1091 1.1 mrg struct isl_mat *eq; 1092 1.1 mrg struct isl_mat *cone_eq; 1093 1.1 mrg struct isl_mat *U, *Q; 1094 1.1 mrg 1095 1.1 mrg if (!tab || !tab_cone) 1096 1.1 mrg return -1; 1097 1.1 mrg 1098 1.1 mrg if (tab_cone->n_col == tab_cone->n_dead) { 1099 1.1 mrg tab->basis = initial_basis(tab); 1100 1.1 mrg return tab->basis ? 0 : -1; 1101 1.1 mrg } 1102 1.1 mrg 1103 1.1 mrg eq = tab_equalities(tab); 1104 1.1 mrg if (!eq) 1105 1.1 mrg return -1; 1106 1.1 mrg tab->n_zero = eq->n_row; 1107 1.1 mrg cone_eq = tab_equalities(tab_cone); 1108 1.1 mrg eq = isl_mat_concat(eq, cone_eq); 1109 1.1 mrg if (!eq) 1110 1.1 mrg return -1; 1111 1.1 mrg tab->n_unbounded = tab->n_var - (eq->n_row - tab->n_zero); 1112 1.1 mrg eq = isl_mat_left_hermite(eq, 0, &U, &Q); 1113 1.1 mrg if (!eq) 1114 1.1 mrg return -1; 1115 1.1 mrg isl_mat_free(eq); 1116 1.1 mrg tab->basis = isl_mat_lin_to_aff(Q); 1117 1.1 mrg if (tab_shift_cone(tab, tab_cone, U) < 0) 1118 1.1 mrg return -1; 1119 1.1 mrg if (!tab->basis) 1120 1.1 mrg return -1; 1121 1.1 mrg return 0; 1122 1.1 mrg } 1123 1.1 mrg 1124 1.1 mrg /* Compute and return a sample point in bset using generalized basis 1125 1.1 mrg * reduction. We first check if the input set has a non-trivial 1126 1.1 mrg * recession cone. If so, we perform some extra preprocessing in 1127 1.1 mrg * sample_with_cone. Otherwise, we directly perform generalized basis 1128 1.1 mrg * reduction. 1129 1.1 mrg */ 1130 1.1 mrg static __isl_give isl_vec *gbr_sample(__isl_take isl_basic_set *bset) 1131 1.1 mrg { 1132 1.1 mrg isl_size dim; 1133 1.1 mrg struct isl_basic_set *cone; 1134 1.1 mrg 1135 1.1 mrg dim = isl_basic_set_dim(bset, isl_dim_all); 1136 1.1 mrg if (dim < 0) 1137 1.1 mrg goto error; 1138 1.1 mrg 1139 1.1 mrg cone = isl_basic_set_recession_cone(isl_basic_set_copy(bset)); 1140 1.1 mrg if (!cone) 1141 1.1 mrg goto error; 1142 1.1 mrg 1143 1.1 mrg if (cone->n_eq < dim) 1144 1.1 mrg return isl_basic_set_sample_with_cone(bset, cone); 1145 1.1 mrg 1146 1.1 mrg isl_basic_set_free(cone); 1147 1.1 mrg return sample_bounded(bset); 1148 1.1 mrg error: 1149 1.1 mrg isl_basic_set_free(bset); 1150 1.1 mrg return NULL; 1151 1.1 mrg } 1152 1.1 mrg 1153 1.1 mrg static __isl_give isl_vec *basic_set_sample(__isl_take isl_basic_set *bset, 1154 1.1 mrg int bounded) 1155 1.1 mrg { 1156 1.1 mrg isl_size dim; 1157 1.1 mrg if (!bset) 1158 1.1 mrg return NULL; 1159 1.1 mrg 1160 1.1 mrg if (isl_basic_set_plain_is_empty(bset)) 1161 1.1 mrg return empty_sample(bset); 1162 1.1 mrg 1163 1.1 mrg dim = isl_basic_set_dim(bset, isl_dim_set); 1164 1.1 mrg if (dim < 0 || 1165 1.1 mrg isl_basic_set_check_no_params(bset) < 0 || 1166 1.1 mrg isl_basic_set_check_no_locals(bset) < 0) 1167 1.1 mrg goto error; 1168 1.1 mrg 1169 1.1 mrg if (bset->sample && bset->sample->size == 1 + dim) { 1170 1.1 mrg int contains = isl_basic_set_contains(bset, bset->sample); 1171 1.1 mrg if (contains < 0) 1172 1.1 mrg goto error; 1173 1.1 mrg if (contains) { 1174 1.1 mrg struct isl_vec *sample = isl_vec_copy(bset->sample); 1175 1.1 mrg isl_basic_set_free(bset); 1176 1.1 mrg return sample; 1177 1.1 mrg } 1178 1.1 mrg } 1179 1.1 mrg isl_vec_free(bset->sample); 1180 1.1 mrg bset->sample = NULL; 1181 1.1 mrg 1182 1.1 mrg if (bset->n_eq > 0) 1183 1.1 mrg return sample_eq(bset, bounded ? isl_basic_set_sample_bounded 1184 1.1 mrg : isl_basic_set_sample_vec); 1185 1.1 mrg if (dim == 0) 1186 1.1 mrg return zero_sample(bset); 1187 1.1 mrg if (dim == 1) 1188 1.1 mrg return interval_sample(bset); 1189 1.1 mrg 1190 1.1 mrg return bounded ? sample_bounded(bset) : gbr_sample(bset); 1191 1.1 mrg error: 1192 1.1 mrg isl_basic_set_free(bset); 1193 1.1 mrg return NULL; 1194 1.1 mrg } 1195 1.1 mrg 1196 1.1 mrg __isl_give isl_vec *isl_basic_set_sample_vec(__isl_take isl_basic_set *bset) 1197 1.1 mrg { 1198 1.1 mrg return basic_set_sample(bset, 0); 1199 1.1 mrg } 1200 1.1 mrg 1201 1.1 mrg /* Compute an integer sample in "bset", where the caller guarantees 1202 1.1 mrg * that "bset" is bounded. 1203 1.1 mrg */ 1204 1.1 mrg __isl_give isl_vec *isl_basic_set_sample_bounded(__isl_take isl_basic_set *bset) 1205 1.1 mrg { 1206 1.1 mrg return basic_set_sample(bset, 1); 1207 1.1 mrg } 1208 1.1 mrg 1209 1.1 mrg __isl_give isl_basic_set *isl_basic_set_from_vec(__isl_take isl_vec *vec) 1210 1.1 mrg { 1211 1.1 mrg int i; 1212 1.1 mrg int k; 1213 1.1 mrg struct isl_basic_set *bset = NULL; 1214 1.1 mrg struct isl_ctx *ctx; 1215 1.1 mrg isl_size dim; 1216 1.1 mrg 1217 1.1 mrg if (!vec) 1218 1.1 mrg return NULL; 1219 1.1 mrg ctx = vec->ctx; 1220 1.1 mrg isl_assert(ctx, vec->size != 0, goto error); 1221 1.1 mrg 1222 1.1 mrg bset = isl_basic_set_alloc(ctx, 0, vec->size - 1, 0, vec->size - 1, 0); 1223 1.1 mrg dim = isl_basic_set_dim(bset, isl_dim_set); 1224 1.1 mrg if (dim < 0) 1225 1.1 mrg goto error; 1226 1.1 mrg for (i = dim - 1; i >= 0; --i) { 1227 1.1 mrg k = isl_basic_set_alloc_equality(bset); 1228 1.1 mrg if (k < 0) 1229 1.1 mrg goto error; 1230 1.1 mrg isl_seq_clr(bset->eq[k], 1 + dim); 1231 1.1 mrg isl_int_neg(bset->eq[k][0], vec->el[1 + i]); 1232 1.1 mrg isl_int_set(bset->eq[k][1 + i], vec->el[0]); 1233 1.1 mrg } 1234 1.1 mrg bset->sample = vec; 1235 1.1 mrg 1236 1.1 mrg return bset; 1237 1.1 mrg error: 1238 1.1 mrg isl_basic_set_free(bset); 1239 1.1 mrg isl_vec_free(vec); 1240 1.1 mrg return NULL; 1241 1.1 mrg } 1242 1.1 mrg 1243 1.1 mrg __isl_give isl_basic_map *isl_basic_map_sample(__isl_take isl_basic_map *bmap) 1244 1.1 mrg { 1245 1.1 mrg struct isl_basic_set *bset; 1246 1.1 mrg struct isl_vec *sample_vec; 1247 1.1 mrg 1248 1.1 mrg bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap)); 1249 1.1 mrg sample_vec = isl_basic_set_sample_vec(bset); 1250 1.1 mrg if (!sample_vec) 1251 1.1 mrg goto error; 1252 1.1 mrg if (sample_vec->size == 0) { 1253 1.1 mrg isl_vec_free(sample_vec); 1254 1.1 mrg return isl_basic_map_set_to_empty(bmap); 1255 1.1 mrg } 1256 1.1 mrg isl_vec_free(bmap->sample); 1257 1.1 mrg bmap->sample = isl_vec_copy(sample_vec); 1258 1.1 mrg bset = isl_basic_set_from_vec(sample_vec); 1259 1.1 mrg return isl_basic_map_overlying_set(bset, bmap); 1260 1.1 mrg error: 1261 1.1 mrg isl_basic_map_free(bmap); 1262 1.1 mrg return NULL; 1263 1.1 mrg } 1264 1.1 mrg 1265 1.1 mrg __isl_give isl_basic_set *isl_basic_set_sample(__isl_take isl_basic_set *bset) 1266 1.1 mrg { 1267 1.1 mrg return isl_basic_map_sample(bset); 1268 1.1 mrg } 1269 1.1 mrg 1270 1.1 mrg __isl_give isl_basic_map *isl_map_sample(__isl_take isl_map *map) 1271 1.1 mrg { 1272 1.1 mrg int i; 1273 1.1 mrg isl_basic_map *sample = NULL; 1274 1.1 mrg 1275 1.1 mrg if (!map) 1276 1.1 mrg goto error; 1277 1.1 mrg 1278 1.1 mrg for (i = 0; i < map->n; ++i) { 1279 1.1 mrg sample = isl_basic_map_sample(isl_basic_map_copy(map->p[i])); 1280 1.1 mrg if (!sample) 1281 1.1 mrg goto error; 1282 1.1 mrg if (!ISL_F_ISSET(sample, ISL_BASIC_MAP_EMPTY)) 1283 1.1 mrg break; 1284 1.1 mrg isl_basic_map_free(sample); 1285 1.1 mrg } 1286 1.1 mrg if (i == map->n) 1287 1.1 mrg sample = isl_basic_map_empty(isl_map_get_space(map)); 1288 1.1 mrg isl_map_free(map); 1289 1.1 mrg return sample; 1290 1.1 mrg error: 1291 1.1 mrg isl_map_free(map); 1292 1.1 mrg return NULL; 1293 1.1 mrg } 1294 1.1 mrg 1295 1.1 mrg __isl_give isl_basic_set *isl_set_sample(__isl_take isl_set *set) 1296 1.1 mrg { 1297 1.1 mrg return bset_from_bmap(isl_map_sample(set_to_map(set))); 1298 1.1 mrg } 1299 1.1 mrg 1300 1.1 mrg __isl_give isl_point *isl_basic_set_sample_point(__isl_take isl_basic_set *bset) 1301 1.1 mrg { 1302 1.1 mrg isl_vec *vec; 1303 1.1 mrg isl_space *space; 1304 1.1 mrg 1305 1.1 mrg space = isl_basic_set_get_space(bset); 1306 1.1 mrg bset = isl_basic_set_underlying_set(bset); 1307 1.1 mrg vec = isl_basic_set_sample_vec(bset); 1308 1.1 mrg 1309 1.1 mrg return isl_point_alloc(space, vec); 1310 1.1 mrg } 1311 1.1 mrg 1312 1.1 mrg __isl_give isl_point *isl_set_sample_point(__isl_take isl_set *set) 1313 1.1 mrg { 1314 1.1 mrg int i; 1315 1.1 mrg isl_point *pnt; 1316 1.1 mrg 1317 1.1 mrg if (!set) 1318 1.1 mrg return NULL; 1319 1.1 mrg 1320 1.1 mrg for (i = 0; i < set->n; ++i) { 1321 1.1 mrg pnt = isl_basic_set_sample_point(isl_basic_set_copy(set->p[i])); 1322 1.1 mrg if (!pnt) 1323 1.1 mrg goto error; 1324 1.1 mrg if (!isl_point_is_void(pnt)) 1325 1.1 mrg break; 1326 1.1 mrg isl_point_free(pnt); 1327 1.1 mrg } 1328 1.1 mrg if (i == set->n) 1329 1.1 mrg pnt = isl_point_void(isl_set_get_space(set)); 1330 1.1 mrg 1331 1.1 mrg isl_set_free(set); 1332 1.1 mrg return pnt; 1333 1.1 mrg error: 1334 1.1 mrg isl_set_free(set); 1335 1.1 mrg return NULL; 1336 1.1 mrg } 1337