* ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
*/
+#include <isl_ctx_private.h>
#include "isl_map_private.h"
#include <isl/seq.h>
#include "isl_tab.h"
* The strategy used for obtaining a feasible solution is different
* from the one used in isl_tab.c. In particular, in isl_tab.c,
* upon finding a constraint that is not yet satisfied, we pivot
- * in a row that increases the constant term of row holding the
+ * in a row that increases the constant term of the row holding the
* constraint, making sure the sample solution remains feasible
* for all the constraints it already satisfied.
* Here, we always pivot in the row holding the constraint,
* then the initial sample value may be chosen equal to zero.
* However, we will not make this assumption. Instead, we apply
* the "big parameter" trick. Any variable x is then not directly
- * used in the tableau, but instead it its represented by another
+ * used in the tableau, but instead it is represented by another
* variable x' = M + x, where M is an arbitrarily large (positive)
* value. x' is therefore always non-negative, whatever the value of x.
* Taking as initial sample value x' = 0 corresponds to x = -M,
return -1;
}
+/* Check whether the invariant that all columns are lexico-positive
+ * is satisfied. This function is not called from the current code
+ * but is useful during debugging.
+ */
+static void check_lexpos(struct isl_tab *tab)
+{
+ unsigned off = 2 + tab->M;
+ int col;
+ int var;
+ int row;
+
+ for (col = tab->n_dead; col < tab->n_col; ++col) {
+ if (tab->col_var[col] >= 0 &&
+ (tab->col_var[col] < tab->n_param ||
+ tab->col_var[col] >= tab->n_var - tab->n_div))
+ continue;
+ for (var = tab->n_param; var < tab->n_var - tab->n_div; ++var) {
+ if (!tab->var[var].is_row) {
+ if (tab->var[var].index == col)
+ break;
+ else
+ continue;
+ }
+ row = tab->var[var].index;
+ if (isl_int_is_zero(tab->mat->row[row][off + col]))
+ continue;
+ if (isl_int_is_pos(tab->mat->row[row][off + col]))
+ break;
+ fprintf(stderr, "lexneg column %d (row %d)\n",
+ col, row);
+ }
+ if (var >= tab->n_var - tab->n_div)
+ fprintf(stderr, "zero column %d\n", col);
+ }
+}
+
/* Resolve all known or obviously violated constraints through pivoting.
* In particular, as long as we can find any violated constraint, we
* look for a pivoting column that would result in the lexicographically
} else if (!tab->con[r2].is_row) {
if (isl_tab_kill_col(tab, tab->con[r2].index) < 0)
goto error;
- } else if (isl_int_is_zero(tab->mat->row[tab->con[r1].index][1])) {
- unsigned off = 2 + tab->M;
- int i;
- int row = tab->con[r1].index;
- i = isl_seq_first_non_zero(tab->mat->row[row]+off+tab->n_dead,
- tab->n_col - tab->n_dead);
- if (i != -1) {
- if (isl_tab_pivot(tab, row, tab->n_dead + i) < 0)
- goto error;
- if (isl_tab_kill_col(tab, tab->n_dead + i) < 0)
- goto error;
- }
}
if (tab->bmap) {
return get_div(tab, context, div);
}
+/* Add a div specified by "div" to the context tableau and return
+ * 1 if the div is obviously non-negative.
+ * context_tab_add_div will always return 1, because all variables
+ * in a isl_context_lex tableau are non-negative.
+ * However, if we are using a big parameter in the context, then this only
+ * reflects the non-negativity of the variable used to _encode_ the
+ * div, i.e., div' = M + div, so we can't draw any conclusions.
+ */
static int context_lex_add_div(struct isl_context *context, struct isl_vec *div)
{
struct isl_context_lex *clex = (struct isl_context_lex *)context;
- return context_tab_add_div(clex->tab, div,
+ int nonneg;
+ nonneg = context_tab_add_div(clex->tab, div,
context_lex_add_ineq_wrap, context);
+ if (nonneg < 0)
+ return -1;
+ if (clex->tab->M)
+ return 0;
+ return nonneg;
}
static int context_lex_detect_equalities(struct isl_context *context,
*
* a x >= -u >= -b_i(p)
*
- * Moreover, m = min_i(b_i(p)) satisfied the constraints on u and can
+ * Moreover, m = min_i(b_i(p)) satisfies the constraints on u and can
* therefore be plugged into the solution.
*/
static __isl_give isl_map *basic_map_partial_lexopt_symm(
isl_assert(bmap->ctx,
isl_basic_map_compatible_domain(bmap, dom), goto error);
+ if (isl_basic_set_dim(dom, isl_dim_all) == 0)
+ return basic_map_partial_lexopt(bmap, dom, empty, max);
+
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);