summaryrefslogtreecommitdiff
path: root/omegalib/omega/src/pres_conj.cc
diff options
context:
space:
mode:
authorTuowen Zhao <ztuowen@gmail.com>2016-09-19 21:14:58 +0000
committerTuowen Zhao <ztuowen@gmail.com>2016-09-19 21:14:58 +0000
commit210f77d2c32f14d2e99577fd3c9842bb19d47e50 (patch)
tree5edb327c919b8309e301c3440fb6668a0075c8ef /omegalib/omega/src/pres_conj.cc
parenta66ce5cd670c4d3c0dc449720f5bc45dd4c281b8 (diff)
downloadchill-210f77d2c32f14d2e99577fd3c9842bb19d47e50.tar.gz
chill-210f77d2c32f14d2e99577fd3c9842bb19d47e50.tar.bz2
chill-210f77d2c32f14d2e99577fd3c9842bb19d47e50.zip
Moved most modules into lib
Diffstat (limited to 'omegalib/omega/src/pres_conj.cc')
-rw-r--r--omegalib/omega/src/pres_conj.cc1460
1 files changed, 0 insertions, 1460 deletions
diff --git a/omegalib/omega/src/pres_conj.cc b/omegalib/omega/src/pres_conj.cc
deleted file mode 100644
index f3f458d..0000000
--- a/omegalib/omega/src/pres_conj.cc
+++ /dev/null
@@ -1,1460 +0,0 @@
-/*****************************************************************************
- Copyright (C) 1994-2000 the Omega Project Team
- Copyright (C) 2005-2011 Chun Chen
- All Rights Reserved.
-
- Purpose:
- class Conjunct.
-
- Notes:
-
- History:
-*****************************************************************************/
-
-#include <omega/omega_core/oc.h>
-#include <omega/pres_conj.h>
-#include <omega/pres_cmpr.h>
-#include <omega/Relation.h>
-#include <omega/omega_i.h>
-#include <set>
-
-namespace omega {
-
-int NR_CONJUNCTS, MAX_CONJUNCTS;
-
-/*
- * Make a new wildcard variable, return WC number.
- * Should be static to this file, but must be a friend of conjunct.
- */
-int new_WC(Conjunct *nc, Problem *) {
- Variable_ID wc = nc->declare();
- int wc_no = nc->map_to_column(wc);
- return(wc_no);
-}
-
-
-const char* get_var_name(unsigned int col, void * void_conj) {
-#if defined PRINT_COLUMN_NUMBERS
- static char scum[512];
-#endif
- Conjunct *c = (Conjunct *) void_conj;
- if (col == 0)
- return 0;
- Variable_ID v = c->mappedVars[col];
- assert(v!=0);
-#if defined PRINT_COLUMN_NUMBERS
- strcpy(scum, v->char_name());
- sprintf(scum + strlen(scum), "(%d)", col);
- return scum;
-#endif
- return v->char_name();
-}
-
-void Conjunct::promise_that_ub_solutions_exist(Relation &R) {
-#ifndef NDEBUG
- Relation verify=Relation(R, this);
- assert(verify.is_upper_bound_satisfiable());
-#endif
- verified = true;
-}
-
-
-int Conjunct::max_ufs_arity_of_set() {
- int ma = 0, a;
- for (Variable_ID_Iterator v(mappedVars); v; v++)
- if ((*v)->kind() == Global_Var && (*v)->function_of() == Set_Tuple
- && query_variable_used(*v)) {
- a = (*v)->get_global_var()->arity();
- if (a > ma)
- ma = a;
- }
- return ma;
-}
-
-
-int Conjunct::max_ufs_arity_of_in() {
- int ma = 0, a;
- for (Variable_ID_Iterator v(mappedVars); v; v++)
- if ((*v)->kind() == Global_Var && (*v)->function_of() == Input_Tuple
- && query_variable_used(*v)) {
- a = (*v)->get_global_var()->arity();
- if (a > ma)
- ma = a;
- }
- return ma;
-}
-
-
-int Conjunct::max_ufs_arity_of_out() {
- int ma = 0, a;
- for (Variable_ID_Iterator v(mappedVars); v; v++)
- if ((*v)->kind() == Global_Var && (*v)->function_of() == Output_Tuple
- && query_variable_used(*v)) {
- a = (*v)->get_global_var()->arity();
- if (a > ma)
- ma = a;
- }
- return ma;
-}
-
-
-bool Conjunct::is_unknown() const {
- assert(problem || comp_problem);
- return !exact && ((problem && problem->nEQs==0 && problem->nGEQs==0) ||
- (comp_problem && comp_problem->no_constraints()));
-}
-
-
-/*
- * Remove black constraints from the problem.
- * Make all the remaining red constraints black.
- */
-void Conjunct::rm_color_constrs() {
- int geqs = 0, eqs = 0;
-
- possible_leading_0s = -1;
- guaranteed_leading_0s = -1;
- leading_dir = 0;
-
- for(int i=0; i<problem->nGEQs; i++) {
- if(problem->GEQs[i].color) {
- if(geqs!=i)
- eqnncpy(&problem->GEQs[geqs], &problem->GEQs[i], problem->nVars);
- problem->GEQs[geqs].color = EQ_BLACK;
- geqs++;
- }
- }
- problem->nGEQs = geqs;
-
- for(int i=0; i<problem->nEQs; i++) {
- if(problem->EQs[i].color) {
- if(eqs!=i)
- eqnncpy(&problem->EQs[eqs], &problem->EQs[i], problem->nVars);
- problem->EQs[eqs].color = EQ_BLACK;
- eqs++;
- }
- }
- problem->nEQs = eqs;
-}
-
-
-
-//
-// Conjunct constructors.
-//
-Conjunct::Conjunct() :
- F_Declaration(NULL, NULL),
- mappedVars(0),
- n_open_constraints(0),
- cols_ordered(false),
- simplified(false),
- verified(false),
- guaranteed_leading_0s(-1),
- possible_leading_0s(-1),
- leading_dir(0),
- exact(true),
- r_constrs(0) {
- NR_CONJUNCTS++;
- if (NR_CONJUNCTS>MAX_CONJUNCTS) MAX_CONJUNCTS = NR_CONJUNCTS;
- problem = new Problem;
- comp_problem = NULL;
- problem->get_var_name = get_var_name;
- problem->getVarNameArgs = (void *) this;
-}
-
-
-Conjunct::Conjunct(Formula *f, Rel_Body *r) :
- F_Declaration(f,r),
- mappedVars(0),
- n_open_constraints(0),
- cols_ordered(false),
- simplified(false),
- verified(false),
- guaranteed_leading_0s(-1),
- possible_leading_0s(-1),
- leading_dir(0),
- exact(true),
- r_constrs(0) {
- NR_CONJUNCTS++;
- if (NR_CONJUNCTS>MAX_CONJUNCTS) MAX_CONJUNCTS = NR_CONJUNCTS;
- problem = new Problem;
- comp_problem = NULL;
- problem->get_var_name = get_var_name;
- problem->getVarNameArgs = (void *) this ;
-}
-
-void internal_copy_conjunct(Conjunct* to, Conjunct* fr);
-
-//
-// Copy Conjunct.
-//
-Conjunct* Conjunct::copy_conj_diff_relation(Formula *parent, Rel_Body *rel_body) {
- Conjunct *new_conj;
- if(problem && comp_problem==NULL) {
- new_conj = new Conjunct(parent, rel_body);
- internal_copy_conjunct(new_conj, this);
- }
- else if (problem==NULL && comp_problem) {
- /* copy compressed conjunct */
- assert(0 && "copy compressed conjunct");
- new_conj = 0;
- }
- else {
- assert(0 && "problem == NULL");
- new_conj = 0;
- }
- return new_conj;
-}
-
-
-void internal_copy_conjunct(Conjunct* to, Conjunct* fr) {
- copy_conj_header(to, fr);
-
- //
- // We repeat part of what is done by copy_conj_header(to, fr) by
- // calling Problem::operator=(const Problem &).
- // copy_conj_header should go away, but there is some code that still needs
- // it in negate_conj.
- //
- to->r_constrs = fr->r_constrs;
- to->simplified = fr->simplified;
- to->verified = fr->verified;
- to->guaranteed_leading_0s = fr->guaranteed_leading_0s;
- to->possible_leading_0s = fr->possible_leading_0s;
- to->leading_dir = fr->leading_dir;
- // the following duplicates some work of the "copy_conj_header" brain damage
- *to->problem = *fr->problem;
- to->problem->getVarNameArgs = (void *)to; // important
-}
-
-
-//
-// Copy Conjunct variable declarations
-// and problem parameters but not problem itself.
-//
-void copy_conj_header(Conjunct* to, Conjunct* fr) {
- free_var_decls(to->myLocals); to->myLocals.clear();
-
- copy_var_decls(to->myLocals, fr->myLocals);
- to->mappedVars = fr->mappedVars;
- to->remap();
- reset_remap_field(fr->myLocals);
-
- to->cols_ordered = fr->cols_ordered;
- to->r_constrs = fr->r_constrs;
- to->simplified = fr->simplified;
- to->verified = fr->verified;
- to->guaranteed_leading_0s = fr->guaranteed_leading_0s;
- to->possible_leading_0s = fr->possible_leading_0s;
- to->leading_dir = fr->leading_dir;
- to->n_open_constraints = fr->n_open_constraints;
- to->exact=fr->exact;
-
- Problem *fp = fr->problem;
- Problem *tp = to->problem;
- tp->nVars = fp->nVars;
- tp->safeVars = fp->safeVars;
- tp->variablesInitialized = fp->variablesInitialized;
- tp->variablesFreed = fp->variablesFreed;
- for(int i=1; i<=maxVars; i++) { // only need nVars of var
- tp->forwardingAddress[i] = fp->forwardingAddress[i];
- tp->var[i] = fp->var[i];
- }
- to->problem->get_var_name = get_var_name;
- to->problem->getVarNameArgs = (void *)to ;
-}
-
-
-void Conjunct::reverse_leading_dir_info() {
- leading_dir *= -1;
-}
-
-
-void Conjunct::enforce_leading_info(int guaranteed, int possible, int dir) {
- skip_finalization_check++;
- guaranteed_leading_0s = guaranteed;
-
- int d = min(relation()->n_inp(),relation()->n_out());
-
- assert(0 <= guaranteed);
- assert(guaranteed <= possible);
- assert(possible <= d);
-
- for(int i = 1; i <= guaranteed; i++) {
- EQ_Handle e = add_EQ();
- e.update_coef_during_simplify(input_var(i), -1);
- e.update_coef_during_simplify(output_var(i), 1);
- e.finalize();
- }
-
-
- if (guaranteed == possible && guaranteed >= 0 && possible+1 <= d && dir) {
- GEQ_Handle g = add_GEQ();
- if (dir > 0) {
- g.update_coef_during_simplify(input_var(possible+1), -1);
- g.update_coef_during_simplify(output_var(possible+1), 1);
- }
- else {
- g.update_coef_during_simplify(input_var(possible+1), 1);
- g.update_coef_during_simplify(output_var(possible+1), -1);
- }
- g.update_const_during_simplify(-1);
- g.finalize();
- possible_leading_0s = possible;
- leading_dir = dir;
- }
- else {
- possible_leading_0s = d;
- leading_dir = 0;
- }
-
- skip_finalization_check--;
-#if ! defined NDEBUG
- assert_leading_info();
-#endif
-}
-
-
-void Conjunct::invalidate_leading_info(int changed) {
- if (changed == -1) {
- guaranteed_leading_0s = possible_leading_0s = -1;
- leading_dir = 0;
- }
- else {
- int d = min(relation()->n_inp(), relation()->n_out());
- assert(1 <= changed && changed <= d);
- if (possible_leading_0s == changed -1) {
- possible_leading_0s = d;
- }
- guaranteed_leading_0s = min(guaranteed_leading_0s,changed-1);
- }
-#if ! defined NDEBUG
- assert_leading_info();
-#endif
-}
-
-
-int Conjunct::leading_dir_valid_and_known() {
- if (relation()->is_set()) {
- return 0;
- }
- // if we know leading dir, we can rule out extra possible 0's
- assert(leading_dir == 0 ||
- possible_leading_0s == guaranteed_leading_0s);
-
- return (possible_leading_0s == guaranteed_leading_0s &&
- possible_leading_0s >= 0 &&
- possible_leading_0s < min(relation()->n_inp(),relation()->n_out())
- && leading_dir);
-}
-
-
-#if ! defined NDEBUG
-void Conjunct::assert_leading_info() {
- if (relation()->is_set()) {
- return;
- }
-
- int d = min(relation()->n_inp(), relation()->n_out());
-
- if ( guaranteed_leading_0s == -1
- && guaranteed_leading_0s == possible_leading_0s)
- assert(leading_dir == 0);
-
- if(leading_dir != 0 &&
- possible_leading_0s != guaranteed_leading_0s) {
- use_ugly_names++;
- prefix_print(DebugFile);
- use_ugly_names--;
- }
-
- assert(leading_dir == 0 || possible_leading_0s == guaranteed_leading_0s);
-
- assert(possible_leading_0s <= d && guaranteed_leading_0s <= d);
-
- assert(possible_leading_0s == -1 || guaranteed_leading_0s <= possible_leading_0s);
-
- // check that there must be "guaranteed_leading_0s" 0s
- int carried_level;
- for (carried_level = 1; carried_level <= guaranteed_leading_0s; carried_level++) {
- Variable_ID in = input_var(carried_level),
- out = output_var(carried_level);
- coef_t lb, ub;
- bool guar;
- query_difference(out, in, lb, ub, guar);
- if (lb != 0 && ub != 0) {
- // probably "query_difference" is just approximate
- // add the negation of leading_dir and assert that
- // the result is unsatisfiable;
- // add in > out (in-out-1>=0) and assert unsatisfiable.
-
- Conjunct *test = copy_conj_same_relation();
- test->problem->turnRedBlack();
- skip_finalization_check++;
-
- GEQ_Handle g = test->add_GEQ();
- g.update_coef_during_simplify(in, -1);
- g.update_coef_during_simplify(out, 1);
- g.update_const_during_simplify(-1);
- g.finalize();
- assert(!simplify_conj(test, true, 0, 0));
- // test was deleted by simplify_conj, as it was FALSE
-
- test = copy_conj_same_relation();
- test->problem->turnRedBlack();
- g = test->add_GEQ();
- g.update_coef_during_simplify(in, 1);
- g.update_coef_during_simplify(out, -1);
- g.update_const_during_simplify(-1);
- g.finalize();
- assert(!simplify_conj(test, true, 0, 0));
- // test was deleted by simplify_conj, as it was FALSE
-
- skip_finalization_check--;
- }
- }
-
- carried_level = possible_leading_0s+1;
-
- // check that there can't be another
- if (guaranteed_leading_0s == possible_leading_0s
- && possible_leading_0s >= 0 &&
- carried_level <= min(relation()->n_inp(), relation()->n_out())) {
- Variable_ID in = input_var(carried_level),
- out = output_var(carried_level);
- coef_t lb, ub;
- bool guar;
- query_difference(out, in, lb, ub, guar);
- if (lb <= 0 && ub >= 0) {
- // probably "query_difference" is just approximate
- // add a 0 and see if its satisfiable
-
- Conjunct *test = copy_conj_same_relation();
- test->problem->turnRedBlack();
- skip_finalization_check++;
-
- EQ_Handle e = test->add_EQ();
- e.update_coef_during_simplify(in, -1);
- e.update_coef_during_simplify(out, 1);
- e.finalize();
- assert(!simplify_conj(test, true, 0, 0));
- // test was deleted by simplify_conj, as it was FALSE
-
- skip_finalization_check--;
- }
- }
-
- // check leading direction info
- if (leading_dir_valid_and_known()) {
- Variable_ID in = input_var(guaranteed_leading_0s+1),
- out = output_var(guaranteed_leading_0s+1);
- coef_t lb, ub;
- bool guar;
- query_difference(out, in, lb, ub, guar);
- if ((leading_dir < 0 && ub >= 0) ||
- (leading_dir > 0 && lb <= 0)) {
- // probably "query_difference" is just approximate
- // add the negation of leading_dir and assert that
- // the result is unsatisfiable;
- // eg for leading_dir = +1 (in must be < out),
- // add in >= out (in-out>=0) and assert unsatisfiable.
-
- Conjunct *test = copy_conj_same_relation();
- test->problem->turnRedBlack();
- skip_finalization_check++;
-
- GEQ_Handle g = test->add_GEQ();
- g.update_coef_during_simplify(in, leading_dir);
- g.update_coef_during_simplify(out, -leading_dir);
- g.finalize();
-
- assert(!simplify_conj(test, true, 0, 0));
- // test was deleted by simplify_conj, as it was FALSE
-
- skip_finalization_check--;
- }
- }
-}
-#endif
-
-
-Variable_ID Conjunct::declare(Const_String s) {
- return do_declare(s, Wildcard_Var);
-}
-
-Variable_ID Conjunct::declare() {
- return do_declare(Const_String(), Wildcard_Var);
-}
-
-Variable_ID Conjunct::declare(Variable_ID v) {
- return do_declare(v->base_name, Wildcard_Var);
-}
-
-Conjunct* Conjunct::really_conjunct() {
- return this;
-}
-
-
-Variable_ID_Tuple* Conjunct::variables() {
- return &mappedVars;
-}
-
-Stride_Handle Conjunct::add_stride(int step, int preserves_level) {
- assert_not_finalized();
- Variable_ID wild = declare();
- int c;
- c = problem->newEQ();
- simplified = false;
- verified = false;
- if (! preserves_level) {
- if (leading_dir == 0)
- possible_leading_0s = -1;
- // otherwise we must still have leading_dir, and thus no more 0's
- }
- problem->EQs[c].color = EQ_BLACK;
- eqnnzero(&problem->EQs[c],problem->nVars);
- n_open_constraints++;
- EQ_Handle h = EQ_Handle(this, c);
- h.update_coef(wild,step);
- return h;
-}
-
-// This should only be used to copy constraints from simplified relations,
-// i.e. there are no quantified variables in c except wildcards.
-EQ_Handle Conjunct::add_EQ(const Constraint_Handle &c, int /*preserves_level, currently unused*/) {
- EQ_Handle e = add_EQ();
- copy_constraint(e,c);
- return e;
-}
-
-
-EQ_Handle Conjunct::add_EQ(int preserves_level) {
- assert_not_finalized();
- int c;
- c = problem->newEQ();
- simplified = false;
- verified = false;
- if (!preserves_level) {
- if (leading_dir == 0)
- possible_leading_0s = -1;
- // otherwise we must still have leading_dir, and thus no more 0's
- }
- problem->EQs[c].color = EQ_BLACK;
- eqnnzero(&problem->EQs[c],problem->nVars);
- n_open_constraints++;
- return EQ_Handle(this, c);
-}
-
-
-// This should only be used to copy constraints from simplified relations,
-// i.e. there are no quantified variables in c except wildcards.
-GEQ_Handle Conjunct::add_GEQ(const Constraint_Handle &c, int /*preserves_level, currently unused */) {
- GEQ_Handle g = add_GEQ();
- copy_constraint(g,c);
- return g;
-}
-
-
-GEQ_Handle Conjunct::add_GEQ(int preserves_level) {
- assert_not_finalized();
- int c;
- c = problem->newGEQ();
- simplified = false;
- verified = false;
- if (!preserves_level) {
- if (leading_dir == 0)
- possible_leading_0s = -1;
- // otherwise we must still have leading_dir, and thus no more 0's
- }
- problem->GEQs[c].color = EQ_BLACK;
- eqnnzero(&problem->GEQs[c],problem->nVars);
- n_open_constraints++;
- return GEQ_Handle(this, c);
-}
-
-
-Conjunct *Conjunct::find_available_conjunct() {
- return this;
-}
-
-
-bool Conjunct::can_add_child() {
- return false;
-}
-
-
-void Conjunct::combine_columns() {
- int nvars = mappedVars.size(),i,j,k;
-
- for(i=1; i<=nvars; i++)
- for(j=i+1; j<=nvars; j++) {
- // If they are the same, copy into the higher numbered column.
- // That way we won't have problems with already-merged columns later
- assert(i != j);
- if(mappedVars[i] == mappedVars[j]) {
- if (pres_debug)
- fprintf(DebugFile, "combine_col:Actually combined %d,%d\n",
- j,i);
- for(k=0; k<problem->nEQs; k++)
- problem->EQs[k].coef[j] += problem->EQs[k].coef[i];
- for(k=0; k<problem->nGEQs; k++)
- problem->GEQs[k].coef[j] += problem->GEQs[k].coef[i];
- zero_column(problem, i, 0, 0, problem->nEQs, problem->nGEQs);
- // Create a wildcard w/no constraints. temporary measure,
- // so we don't have to shuffle columns
- Variable_ID zero_var = declare();
- mappedVars[i] = zero_var;
- break;
- }
- }
-}
-
-
-void Conjunct::finalize() {
-// Debugging version of finalize; copy the conjunct and free the old one,
-// so that purify will catch accesses to finalized constraints
-// assert(n_open_constraints == 0);
-// Conjunct *C = this->copy();
-// parent().replace_child(this, C);
-// delete this;
-}
-
-Conjunct::~Conjunct() {
- NR_CONJUNCTS--;
- delete problem;
- delete comp_problem;
-}
-
-
-//
-// Cost = # of terms in DNF when negated
-// or CantBeNegated if too bad (i.e. bad wildcards)
-// or AvoidNegating if it would be inexact
-//
-// Also check pres_legal_negations --
-// If set to any_negation, just return the number
-// If set to one_geq_or_stride, return CantBeNegated if c > 1
-// If set to one_geq_or_eq, return CantBeNegated if not a single geq or eq
-//
-
-int Conjunct::cost() {
- int c;
- int i;
- int wc_no;
- int wc_j = 0; // initialize to shut up the compiler
-
- // cost 1 per GEQ, and if 1 GEQ has wildcards, +2 for each of them
-
- c = problem->nGEQs;
- for(i=0; i<problem->nGEQs; i++) {
- wc_no = 0;
- for(int j=1; j<=problem->nVars; j++) if(problem->GEQs[i].coef[j]!=0) {
- Variable_ID v = mappedVars[j];
- if(v->kind()==Wildcard_Var) {
- wc_no++;
- c+=2;
- wc_j = j;
- }
- }
- if (wc_no > 1) return CantBeNegated;
- }
-
- for(i=0; i<problem->nEQs; i++) {
- wc_no = 0;
- for(int j=1; j<=problem->nVars; j++) if(problem->EQs[i].coef[j]!=0) {
- Variable_ID v = mappedVars[j];
- if(v->kind()==Wildcard_Var) {
- wc_no++;
- wc_j = j;
- }
- }
-
- if (wc_no == 0) // no wildcards
- c+=2;
- else if (wc_no == 1) { // one wildcard - maybe we can negate it
- int i2;
- for(i2=0; i2<problem->nEQs; i2++)
- if(i != i2 && problem->EQs[i2].coef[wc_j]!=0) break;
- if (i2 >= problem->nEQs) // Stride constraint
- c++;
- else // We are not ready to handle this
- return CantBeNegated;
- }
- else // Multiple wildcards
- return CantBeNegated;
- }
- if (!exact) return AvoidNegating;
-
- if (pres_legal_negations == any_negation) {
- return c;
- }
- else {
- // single GEQ ok either way as long as no wildcards
- // (we might be able to handle wildcards, but I haven't thought about it)
- if (problem->nEQs==0 && problem->nGEQs<=1) {
- if (c>1) { // the GEQ had a wildcard -- I'm not ready to go here.
- if (pres_debug > 0) {
- fprintf(DebugFile,
- "Refusing to negate a GEQ with wildcard(s)"
- " under restricted_negation; "
- "It may be possible to fix this.\n");
- }
- return CantBeNegated;
- }
- return c;
- }
- else if (problem->nEQs==1 && problem->nGEQs==0) {
- assert(c == 1 || c == 2);
-
- if (pres_legal_negations == one_geq_or_stride) {
- if (c == 1)
- return c; // stride constraint is ok
- else {
- if (pres_debug > 0) {
- fprintf(DebugFile, "Refusing to negate a non-stride EQ under current pres_legal_negations.\n");
- }
- return CantBeNegated;
- }
- }
- else {
- assert(pres_legal_negations == one_geq_or_eq);
- return c;
- }
- }
- else {
- if (pres_debug > 0) {
- fprintf(DebugFile, "Refusing to negate multiple constraints under current pres_legal_negations.\n");
- }
- return CantBeNegated;
- }
- }
-}
-
-
-//
-// Merge CONJ1 & CONJ2 -> CONJ.
-// Action: MERGE_REGULAR or MERGE_COMPOSE: regular merge.
-// MERGE_GIST make constraints from conj2 red, i.e.
-// Gist Conj2 given Conj1 (T.S. comment).
-// Reorder columns as we go.
-// Merge the columns for identical variables.
-// We assume we know nothing about the ordering of conj1, conj2.
-//
-// Does not consume its arguments
-//
-// Optional 4th argument gives the relation for the result - if
-// null, conj1 and conj2 must have the same relation, which will
-// be used for the result
-//
-// The only members of conj1 and conj2 that are used are: problem,
-// mappedVars and declare(), and the leading_0s/leading_dir members
-// and exact.
-//
-// NOTE: variables that are shared between conjuncts are necessarily
-// declared above, not here; so we can simply create columns for the
-// locals of each conj after doing the protected vars.
-//
-Conjunct* merge_conjs(Conjunct* conj1, Conjunct* conj2,
- Merge_Action action, Rel_Body *body) {
- // body must be set unless both conjuncts are from the same relation
- assert(body || conj1->relation() == conj2->relation());
-
- if (body == conj1->relation() && body == conj2->relation())
- body = 0; // we test this later to see if there is a new body
-
- Conjunct *conj3 = new Conjunct(NULL, body ? body : conj2->relation());
- Problem *p1 = conj1->problem;
- Problem *p2 = conj2->problem;
- Problem *p3 = conj3->problem;
- int i;
-
- if (action != MERGE_COMPOSE) {
- conj1->assert_leading_info();
- conj2->assert_leading_info();
- }
-
- if(pres_debug>=2) {
- use_ugly_names++;
- fprintf(DebugFile, ">>> Merge conjuncts: Merging%s:\n",
- (action == MERGE_GIST ? " for gist" :
- (action == MERGE_COMPOSE ? " for composition" : "")));
- conj1->prefix_print(DebugFile);
- conj2->prefix_print(DebugFile);
- fprintf(DebugFile, "\n");
- use_ugly_names--;
- }
-
-
-
- switch(action) {
- case MERGE_REGULAR:
- case MERGE_COMPOSE:
- conj3->exact=conj1->exact && conj2->exact;
- break;
- case MERGE_GIST:
- conj3->exact=conj2->exact;
- break;
- }
-
- if (action == MERGE_COMPOSE) {
- conj3->guaranteed_leading_0s=min(conj1->guaranteed_leading_0s,
- conj2->guaranteed_leading_0s);
- conj3->possible_leading_0s=min((unsigned int) conj1->possible_leading_0s,
- (unsigned int) conj2->possible_leading_0s);
-
- assert( conj3->guaranteed_leading_0s <= conj3->possible_leading_0s);
-
- // investigate leading_dir - not well tested code
- if (conj1->guaranteed_leading_0s<0 || conj2->guaranteed_leading_0s<0) {
- conj3->leading_dir = 0;
- }
- else if (conj1->guaranteed_leading_0s == conj2->guaranteed_leading_0s)
- if (conj1->leading_dir == conj2->leading_dir)
- conj3->leading_dir = conj1->leading_dir;
- else
- conj3->leading_dir = 0;
- else if (conj1->guaranteed_leading_0s < conj2->guaranteed_leading_0s) {
- conj3->leading_dir = conj1->leading_dir;
- }
- else { // (conj1->guaranteed_leading_0s > conj2->guaranteed_leading_0s)
- conj3->leading_dir = conj2->leading_dir;
- }
-
- if (conj3->leading_dir == 0)
- conj3->possible_leading_0s = min(conj3->relation()->n_inp(),
- conj3->relation()->n_out());
-
- assert(conj3->guaranteed_leading_0s <= conj3->possible_leading_0s);
- assert(conj3->guaranteed_leading_0s == conj3->possible_leading_0s
- || !conj3->leading_dir);
- }
- else if (!body) { // if body is set, who knows what leading 0's mean?
- assert(action == MERGE_REGULAR || action == MERGE_GIST);
-
- int feasable = 1;
-
- int redAndBlackGuarLeadingZeros = max(conj1->guaranteed_leading_0s,
- conj2->guaranteed_leading_0s);
- if (action == MERGE_REGULAR)
- conj3->guaranteed_leading_0s= redAndBlackGuarLeadingZeros;
- else conj3->guaranteed_leading_0s=conj1->guaranteed_leading_0s;
-
- conj3->possible_leading_0s=min((unsigned)conj1->possible_leading_0s,
- (unsigned)conj2->possible_leading_0s);
- if (conj3->possible_leading_0s < redAndBlackGuarLeadingZeros)
- feasable = 0;
- else if (conj3->guaranteed_leading_0s == -1
- || conj3->possible_leading_0s > redAndBlackGuarLeadingZeros)
- conj3->leading_dir = 0;
- else {
- if (conj1->guaranteed_leading_0s == conj2->guaranteed_leading_0s)
- if (!conj1->leading_dir_valid_and_known())
- conj3->leading_dir = conj2->leading_dir;
- else if (!conj2->leading_dir_valid_and_known())
- conj3->leading_dir = conj1->leading_dir;
- else if (conj1->leading_dir * conj2->leading_dir > 0)
- conj3->leading_dir = conj1->leading_dir; // 1,2 same dir
- else
- feasable = 0; // 1 and 2 go in opposite directions
- else if (conj3->possible_leading_0s != conj3->guaranteed_leading_0s)
- conj3->leading_dir = 0;
- else if (conj1->guaranteed_leading_0s<conj2->guaranteed_leading_0s) {
- assert(!conj1->leading_dir_valid_and_known());
- conj3->leading_dir = conj2->leading_dir;
- }
- else {
- assert(!conj2->leading_dir_valid_and_known());
- conj3->leading_dir = conj1->leading_dir;
- }
- }
-
- if (!feasable) {
- if(pres_debug>=2)
- fprintf(DebugFile, ">>> Merge conjuncts: quick check proves FALSE.\n");
-
- // return 0 = 1
-
- int e = p3->newEQ();
- p3->EQs[e].color = EQ_BLACK;
- p3->EQs[e].touched = 1;
- p3->EQs[e].key = 0;
- p3->EQs[e].coef[0] = 1;
-
- // Make sure these don't blow later assertions
- conj3->possible_leading_0s = conj3->guaranteed_leading_0s = -1;
- conj3->leading_dir = 0;
-
- return conj3;
- }
- }
- else { // provided "body" argument but not composing, leading 0s meaningless
- conj3->guaranteed_leading_0s = conj3->possible_leading_0s = -1;
- conj3->leading_dir = 0;
- }
-
- // initialize omega stuff
-
- for(i=0; i<p1->nGEQs+p2->nGEQs; i++) {
- int e = p3->newGEQ();
- assert(e == i);
- p3->GEQs[e].color = EQ_BLACK;
- p3->GEQs[e].touched = 1;
- p3->GEQs[e].key = 0;
- }
- for(i=0; i<p1->nEQs+p2->nEQs; i++) {
- int e = p3->newEQ();
- assert(e == i);
- p3->EQs[e].color = EQ_BLACK;
- p3->EQs[e].touched = 1;
- p3->EQs[e].key = 0;
- }
-
- assert(p3->nGEQs == p1->nGEQs + p2->nGEQs);
- assert(p3->nEQs == p1->nEQs + p2->nEQs);
-
- // flag constraints from second constraint as red, if necessary
- if (action == MERGE_GIST) {
- for(i=0; i<p2->nEQs; i++) {
- p3->EQs[i+p1->nEQs].color = EQ_RED;
- }
- for(i=0; i<p2->nGEQs; i++) {
- p3->GEQs[i+p1->nGEQs].color = EQ_RED;
- }
- }
-
- // copy constant column
- copy_column(p3, 0, p1, 0, 0, 0);
- copy_column(p3, 0, p2, 0, p1->nEQs, p1->nGEQs);
-
- // copy protected variables column from conj1
- int new_col = 1;
- Variable_Iterator VI(conj1->mappedVars);
- for(i=1; VI; VI++, i++) {
- Variable_ID v = *VI;
- if(v->kind() != Wildcard_Var) {
- conj3->mappedVars.append(v);
- int fr_ix = i;
- copy_column(p3, new_col, p1, fr_ix, 0, 0);
- zero_column(p3, new_col, p1->nEQs, p1->nGEQs,
- p2->nEQs, p2->nGEQs);
- new_col++;
- }
- }
-
- // copy protected variables column from conj2,
- // checking if conj3 already has this variable from conj1
- for(i=1; i <= conj2->mappedVars.size(); i++) {
- Variable_ID v = conj2->mappedVars[i];
- if(v->kind() != Wildcard_Var) {
- int to_ix = conj3->mappedVars.index(v);
- int fr_ix = i;
- if(to_ix > 0) {
- // use old column
- copy_column(p3, to_ix, p2, fr_ix, p1->nEQs, p1->nGEQs);
- }
- else {
- // create new column
- conj3->mappedVars.append(v);
- zero_column(p3, new_col, 0, 0, p1->nEQs, p1->nGEQs);
- copy_column(p3, new_col, p2, fr_ix, p1->nEQs, p1->nGEQs);
- new_col++;
- }
- }
- }
-
- p3->safeVars = new_col-1;
-
- // copy wildcards from conj1
- for(i=1; i <= conj1->mappedVars.size(); i++) {
- Variable_ID v = conj1->mappedVars[i];
- if(v->kind() == Wildcard_Var) {
- Variable_ID nv = conj3->declare(v);
- conj3->mappedVars.append(nv);
- int fr_ix = i;
- copy_column(p3, new_col, p1, fr_ix, 0, 0);
- zero_column(p3, new_col, p1->nEQs, p1->nGEQs,
- p2->nEQs, p2->nGEQs);
- new_col++;
- }
- }
-
- // copy wildcards from conj2
- for(i=1; i <= conj2->mappedVars.size(); i++) {
- Variable_ID v = conj2->mappedVars[i];
- if(v->kind() == Wildcard_Var) {
- Variable_ID nv = conj3->declare(v);
- conj3->mappedVars.append(nv);
- int fr_ix = i;
- zero_column(p3, new_col, 0, 0, p1->nEQs, p1->nGEQs);
- copy_column(p3, new_col, p2, fr_ix, p1->nEQs, p1->nGEQs);
- new_col++;
- }
- }
-
- p3->nVars = new_col-1;
- checkVars(p3->nVars);
- p3->variablesInitialized = 1;
- for(i=1; i<=p3->nVars; i++)
- p3->var[i] = p3->forwardingAddress[i] = i;
-
- conj3->cols_ordered = true;
- conj3->simplified = false;
- conj3->verified = false;
-
- if(pres_debug>=2) {
- use_ugly_names++;
- fprintf(DebugFile, ">>> Merge conjuncts: result is:\n");
- conj3->prefix_print(DebugFile);
- fprintf(DebugFile, "\n");
- use_ugly_names--;
- }
-
- conj3->assert_leading_info();
-
- return conj3;
-}
-
-
-
-
-//
-// Reorder variables by swapping.
-// cols_ordered is just a hint that thorough check needs to be done.
-// Sets _safeVars.
-//
-void Conjunct::reorder() {
- if(!cols_ordered) {
- int var_no = mappedVars.size();
- int first_wild = 1;
- int last_prot = var_no;
- while(first_wild < last_prot) {
- for(; first_wild<=var_no && mappedVars[first_wild]->kind()!=Wildcard_Var;
- first_wild++) ;
- for(; last_prot>=1 && mappedVars[last_prot]->kind()==Wildcard_Var;
- last_prot--) ;
- if(first_wild < last_prot) {
- problem->swapVars(first_wild, last_prot);
- problem->variablesInitialized = false;
- Var_Decl *t = mappedVars[first_wild];
- mappedVars[first_wild] = mappedVars[last_prot];
- mappedVars[last_prot] = t;
- if(pres_debug) {
- fprintf(DebugFile, "<<<OrderConjCols>>>: swapped var-s %d and %d\n", first_wild, last_prot);
- }
- }
- }
-
- int safe_vars;
- for(safe_vars=0;
- safe_vars<var_no && mappedVars[safe_vars+1]->kind()!=Wildcard_Var;
- safe_vars++) ;
-
-#if ! defined NDEBUG
- for(int s = safe_vars ; s<var_no ; s++ ) {
- assert(mappedVars[s+1]->kind() == Wildcard_Var);
- }
-#endif
-
- problem->safeVars = safe_vars;
- cols_ordered = true;
- }
-}
-
-
-
-// Wherever possible, move function symbols to input tuple.
-// This ensures that if in == out, red F(in) = x is redundant
-// with black F(out) = x
-
-void Conjunct::move_UFS_to_input() {
- if (guaranteed_leading_0s > 0) {
- std::set<Global_Var_ID> already_done;
- int remapped = 0;
- skip_finalization_check++;
- Rel_Body *body = relation();
-
- assert(body);
-
- for (Variable_ID_Iterator func(*body->global_decls()); func; func++) {
- Global_Var_ID f = (*func)->get_global_var();
- if (f->arity() <= guaranteed_leading_0s)
- if (already_done.find(f) == already_done.end() &&
- body->has_local(f, Input_Tuple) &&
- body->has_local(f, Output_Tuple)) {
- already_done.insert(f);
-
- // equatE f(in) = f(out)
- Variable_ID f_in = body->get_local(f, Input_Tuple);
- Variable_ID f_out = body->get_local(f, Output_Tuple);
- if (f_in != f_out) {
- EQ_Handle e = add_EQ(1);
-
- e.update_coef_during_simplify(f_in, -1);
- e.update_coef_during_simplify(f_out, 1);
-
- f_out->remap = f_in;
- remapped = 1;
- }
- }
- }
-
- if (remapped) {
- remap();
- combine_columns();
- reset_remap_field(*body->global_decls());
- remapped = 0;
- }
-
- skip_finalization_check--;
- }
-}
-
-
-
-
-
-//
-// Simplify CONJ.
-// Return TRUE if there are solutions, FALSE -- no solutions.
-//
-int simplify_conj(Conjunct* conj, int ver_sim, int simplificationEffort, int color) {
- if (conj->verified
- && simplificationEffort <= conj->r_constrs
- && (conj->simplified || simplificationEffort < 0)
- && !color) {
- if(pres_debug) {
- fprintf(DebugFile, "$$$ Redundant simplify_conj ignored (%d,%d,%d)\n",ver_sim,simplificationEffort,color);
- conj->prefix_print(DebugFile);
- }
- return 1;
- }
-
- if (simplificationEffort < 0) simplificationEffort = 0;
- conj->move_UFS_to_input();
- conj->reorder();
-
- Problem *p = conj->problem;
-
- use_ugly_names++;
-
- int i;
- for(i=0; i<p->nGEQs; i++) {
- p->GEQs[i].touched = 1;
- }
- for(i=0; i<p->nEQs; i++) {
- p->EQs[i].touched = 1;
- }
-
- if(pres_debug) {
- fprintf(DebugFile, "$$$ simplify_conj (%d,%d,%d)[\n",ver_sim,simplificationEffort,color);
- conj->prefix_print(DebugFile);
- }
-
- assert(conj->cols_ordered);
-
- int ret_code;
- assert(p == conj->problem);
- if(!color) {
- ret_code = conj->simplifyProblem(ver_sim && ! conj->verified,0,simplificationEffort);
- }
- else {
- ret_code = conj->redSimplifyProblem(simplificationEffort,1);
- ret_code = (ret_code==redFalse ? 0 : 1);
- }
- assert(p->nSUBs==0);
-
- if(ret_code == 0) {
- if(pres_debug)
- fprintf(DebugFile, "] $$$ simplify_conj : false\n\n");
- delete conj;
- use_ugly_names--;
- return(false);
- }
-
-
- //
- // mappedVars is mapping from columns to Variable_IDs.
- // Recompute mappedVars for problem returned from ip.c
- //
- Variable_ID_Tuple new_mapped(0); // This is expanded by "append"
- for (i=1; i<=p->safeVars; i++) {
- // what is now in column i used to be in column p->var[i]
- Variable_ID v = conj->mappedVars[p->var[i]];
- assert(v->kind() != Wildcard_Var);
- new_mapped.append(v);
- }
-
- /* Redeclare all wildcards that weren't eliminated. */
- free_var_decls(conj->myLocals); conj->myLocals.clear();
-
- conj->mappedVars = new_mapped;
- for (i = p->safeVars+1; i<=p->nVars; i++) {
- Variable_ID v = conj->declare();
- conj->mappedVars.append(v);
- }
-
- // reset var and forwarding address if desired.
- p->variablesInitialized = 1;
- for(i=1; i<=conj->problem->nVars; i++)
- conj->problem->var[i] = conj->problem->forwardingAddress[i] = i;
-
- if(pres_debug) {
- fprintf(DebugFile, "] $$$ simplify_conj\n");
- conj->prefix_print(DebugFile);
- fprintf(DebugFile, "\n");
- }
-
-
- use_ugly_names--;
- conj->simplified = true;
- conj->setup_anonymous_wildcard_names();
-
- return(true);
-}
-
-
-int Conjunct::rank() {
- Conjunct *C = this->copy_conj_same_relation();
- C->reorder();
- C->ordered_elimination(C->relation()->global_decls()->size());
- int C_rank = 0;
- for(Variable_Iterator vi = C->mappedVars; vi; vi++)
- if(C->find_column(*vi) > 0) C_rank++;
- delete C;
- return C_rank;
-
-}
-
-
-void Conjunct::query_difference(Variable_ID v1, Variable_ID v2, coef_t &lowerBound, coef_t &upperBound, bool &guaranteed) {
- int c1 = get_column(v1);
- int c2 = get_column(v2);
- assert(c1 && c2);
- problem->query_difference(c1, c2, lowerBound, upperBound, guaranteed);
-}
-
-
-void Conjunct::query_variable_bounds(Variable_ID v, coef_t &lowerBound, coef_t &upperBound) {
- int c = get_column(v);
- assert (c);
- problem->query_variable_bounds(c, &lowerBound, &upperBound);
-}
-
-coef_t Conjunct::query_variable_mod(Variable_ID v, coef_t factor) {
- int c = get_column(v);
- assert(c);
- return problem->query_variable_mod(c, factor);
-}
-
-bool Conjunct::query_variable_used(Variable_ID v) {
- for (GEQ_Iterator g = GEQs(); g.live(); g.next()) {
- if ((*g).get_coef(v)) return true;
- }
- for (EQ_Iterator e = EQs(); e.live(); e.next()) {
- if ((*e).get_coef(v)) return true;
- }
- return false;
-}
-
-
-int Conjunct::simplifyProblem(int verify, int subs, int redundantElimination) {
- if (verified) verify = 0;
- int result = problem->simplifyProblem(verify, subs, redundantElimination);
- if (result == false && !exact)
- exact=true;
- assert(!(verified && verify && result == false));
- if (verify && result) verified = true;
- else if (!result) verified = false;
- return result;
-}
-
-
-// not as confident about this one as the previous:
-int Conjunct::redSimplifyProblem(int effort, int computeGist) {
- redCheck result = problem->redSimplifyProblem(effort, computeGist);
- if (result == redFalse && !exact)
- exact=true;
- return result;
-}
-
-
-//
-// Add given list of wildcards S to this Conjunct.
-// Clears argument. (That's very important, otherwise those var_id's get freed)
-// Push_exists takes responsibility for reusing or deleting Var_ID's;
-// here we reuse them. Must also empty out the Tuple when finished (joins).
-void Conjunct::push_exists(Variable_ID_Tuple &S) {
- for(Tuple_Iterator<Variable_ID> VI(S); VI; VI++) {
- (*VI)->var_kind = Wildcard_Var;
- }
- myLocals.join(S); // Sets S to be empty.
- cols_ordered = false;
- simplified = false;
-}
-
-
-Conjunct *Formula::add_conjunct() {
- assert_not_finalized();
- assert(can_add_child());
- Conjunct *f = new Conjunct(this, myRelation);
- myChildren.append(f);
- return f;
-}
-
-// Compress/uncompress functions
-
-bool Conjunct::is_compressed() {
- if(problem!=NULL && comp_problem==NULL) {
- return false;
- }
- else if(problem==NULL && comp_problem!=NULL) {
- return true;
- }
- else {
- assert(0 && "Conjunct::is_compressed: bad conjunct");
- return false;
- }
-}
-
-
-void Conjunct::compress() {
- if(!is_compressed()) { // compress
- comp_problem = new Comp_Problem(problem);
- delete problem;
- problem = NULL;
- }
-}
-
-
-void Conjunct::uncompress() {
- if(is_compressed()) {
- problem = comp_problem->UncompressProblem();
- delete comp_problem;
- comp_problem = NULL;
- }
-}
-
-
-Comp_Problem::Comp_Problem(Problem *problem) :
- _nVars(problem->nVars),
- _safeVars(problem->safeVars),
- _get_var_name(problem->get_var_name),
- _getVarNameArgs(problem->getVarNameArgs),
- eqs(&problem->EQs[0],problem->nEQs,problem->nVars),
- geqs(&problem->GEQs[0],problem->nGEQs,problem->nVars) {
-}
-
-Comp_Constraints::Comp_Constraints(eqn *constrs, int no_constrs, int no_vars) :
- n_constrs(no_constrs),
- n_vars(no_vars) {
- coefs = new coef_t[(n_vars+1)*n_constrs];
- int e, v;
- for(e=0; e<n_constrs; e++) {
- for(v=0; v<=n_vars; v++) {
- coefs[coef_index(e,v)] = constrs[e].coef[v];
- }
- }
-}
-
-
-Comp_Constraints::~Comp_Constraints() {
- delete coefs;
-}
-
-
-Problem *Comp_Problem::UncompressProblem() {
- Problem *p = new Problem(eqs.n_constraints(), geqs.n_constraints());
- p->get_var_name = get_var_name;
- p->getVarNameArgs = _getVarNameArgs;
- p->nVars = _nVars;
- p->safeVars = _safeVars;
- for(int i=1; i<=p->nVars; i++) {
- p->forwardingAddress[i] = i;
- p->var[i] = i;
- }
- eqs.UncompressConstr(&p->EQs[0], p->nEQs);
- geqs.UncompressConstr(&p->GEQs[0], p->nGEQs);
- return p;
-}
-
-void Comp_Constraints::UncompressConstr(eqn *constrs, short &pn_constrs) {
- int e, v;
- for(e=0; e<n_constrs; e++) {
- eqnnzero(&constrs[e], 0);
- for(v=0; v<=n_vars; v++) {
- constrs[e].coef[v] = coefs[coef_index(e,v)];
- }
- constrs[e].touched = 1;
- }
- pn_constrs = n_constrs;
-}
-
-
-void Conjunct::convertEQstoGEQs(bool excludeStrides) {
- simplify_conj(this,true,1,EQ_BLACK); // don't remember why I want to comment this statement out with reason "will cause inconsistency between Conjunct::mappedVars and Problem::nVars", 06/09/2009 by chun
- problem->convertEQstoGEQs(excludeStrides);
-}
-
-
-void Conjunct::calculate_dimensions(Relation &R, int &ndim_all, int &ndim_domain) {
-
- Conjunct * c = this;
- Relation rc=Relation(R, c);
-
- if(relation_debug) {
- fprintf(DebugFile,"{{{\nIn Conjunct::calculate_dimensions:\n");
- rc.prefix_print(DebugFile);
- }
-
- rc=Approximate(rc);
- Relation rd=rc;
-
- if(relation_debug) {
- fprintf(DebugFile,"Conjunct::calculate_dimensions: Approximated as:\n");
- rc.prefix_print(DebugFile);
- }
-
- // skip_set_checks++;
-
- Conjunct * rc_conj=rc.single_conjunct();
- ndim_all=rc.n_inp()+rc.n_out();
- ndim_all-=rc_conj->n_EQs();
-
- rc = Project_On_Sym(rc);
- rc.simplify();
-
- if(relation_debug) {
- fprintf(DebugFile, "Conjunct::calculate_dimensions: after project_on_sym\n");
- rc.prefix_print(DebugFile);
- }
-
- int n_eq_sym = 1000;
- for (DNF_Iterator s(rc.query_DNF()); s.live(); s.next())
- n_eq_sym = min(n_eq_sym, s.curr()->n_EQs());
- ndim_all+=n_eq_sym;
- // skip_set_checks--;
-
- if (R.is_set())
- ndim_domain = ndim_all;
- else {
- /* get dimensions for the domain (broadcasting) */
-
- rd=Domain(rd);
- rd.simplify();
-
- if(relation_debug) {
- fprintf(DebugFile,"Domain is:\n");
- rd.prefix_print(DebugFile);
- }
-
- rc_conj=rd.single_conjunct();
- ndim_domain=rd.n_set()-rc_conj->n_EQs()+n_eq_sym;
- }
-
- if(relation_debug) {
- fprintf(DebugFile,"n_eq_sym=%d \n",n_eq_sym);
- fprintf(DebugFile,"Dimensions: all=%d domain=%d\n}}}\n", ndim_all,ndim_domain);
- }
-}
-
-} // namespace