diff options
Diffstat (limited to 'omegalib/omega/src/hull.cc')
-rw-r--r-- | omegalib/omega/src/hull.cc | 1489 |
1 files changed, 0 insertions, 1489 deletions
diff --git a/omegalib/omega/src/hull.cc b/omegalib/omega/src/hull.cc deleted file mode 100644 index f1b0601..0000000 --- a/omegalib/omega/src/hull.cc +++ /dev/null @@ -1,1489 +0,0 @@ -/***************************************************************************** - Copyright (C) 1994-2000 University of Maryland - Copyright (C) 2008 University of Southern California - Copyright (C) 2009-2010 University of Utah - All Rights Reserved. - - Purpose: - Various hull calculations. - - Notes: - - History: - 06/15/09 ConvexRepresentation, Chun Chen - 11/25/09 RectHull, Chun Chen -*****************************************************************************/ - -#include <omega.h> -#include <omega/farkas.h> -#include <omega/hull.h> -#include <basic/Bag.h> -#include <basic/Map.h> -#include <basic/omega_error.h> -#include <list> -#include <vector> -#include <set> - -namespace omega { - -int hull_debug = 0; - -Relation ConvexHull(NOT_CONST Relation &R) { - Relation S = Approximate(consume_and_regurgitate(R)); - if (!S.is_upper_bound_satisfiable()) - return S; - if (S.has_single_conjunct()) - return S; - return Farkas(Farkas(S,Basic_Farkas), Convex_Combination_Farkas); -} - -Relation DecoupledConvexHull(NOT_CONST Relation &R) { - Relation S = Approximate(consume_and_regurgitate(R)); - if (!S.is_upper_bound_satisfiable()) - return S; - if (S.has_single_conjunct()) - return S; - return Farkas(Farkas(S,Decoupled_Farkas), Convex_Combination_Farkas); -} - -Relation AffineHull(NOT_CONST Relation &R) { - Relation S = Approximate(consume_and_regurgitate(R)); - if (!S.is_upper_bound_satisfiable()) - return S; - return Farkas(Farkas(S,Basic_Farkas), Affine_Combination_Farkas); -} - -Relation LinearHull(NOT_CONST Relation &R) { - Relation S = Approximate(consume_and_regurgitate(R)); - if (!S.is_upper_bound_satisfiable()) - return S; - return Farkas(Farkas(S,Basic_Farkas), Linear_Combination_Farkas); -} - -Relation ConicHull(NOT_CONST Relation &R) { - Relation S = Approximate(consume_and_regurgitate(R)); - if (!S.is_upper_bound_satisfiable()) - return S; - return Farkas(Farkas(S,Basic_Farkas), Positive_Combination_Farkas); -} - - -Relation FastTightHull(NOT_CONST Relation &input_R, NOT_CONST Relation &input_H) { - Relation R = Approximate(consume_and_regurgitate(input_R)); - Relation H = Approximate(consume_and_regurgitate(input_H)); - - if (hull_debug) { - fprintf(DebugFile,"[ Computing FastTightHull of:\n"); - R.prefix_print(DebugFile); - fprintf(DebugFile,"given known hull of:\n"); - H.prefix_print(DebugFile); - } - - if (!H.has_single_conjunct()) { - if (hull_debug) - fprintf(DebugFile, "] bailing out of FastTightHull, known hull not convex\n"); - return H; - } - - if (!H.is_obvious_tautology()) { - R = Gist(R,copy(H)); - R.simplify(1,0); - } - - if (R.has_single_conjunct()) { - R = Intersection(R,H); - if (hull_debug) { - fprintf(DebugFile, "] quick easy answer to FastTightHull\n"); - R.prefix_print(DebugFile); - } - return R; - } - if (R.has_local(coefficient_of_constant_term)) { - if (hull_debug) { - fprintf(DebugFile, "] Can't handle recursive application of Farkas lemma\n"); - } - return H; - } - - if (hull_debug) { - fprintf(DebugFile,"Gist of R given H is:\n"); - R.prefix_print(DebugFile); - } - - if (1) { - Set<Variable_ID> vars; - int conjuncts = 0; - for (DNF_Iterator s(R.query_DNF()); s.live(); s.next()) { - conjuncts++; - for (Variable_ID_Iterator v(*((*s)->variables())); v.live(); v++) { - bool found = false; - for (EQ_Iterator eq = (*s)->EQs(); eq.live(); eq.next()) - if ((*eq).get_coef(*v) != 0) { - if (!found) vars.insert(*v); - found = true; - break; - } - if (!found) - for (GEQ_Iterator geq = (*s)->GEQs(); geq.live(); geq.next()) - if ((*geq).get_coef(*v) != 0) { - if (!found) vars.insert(*v); - found = true; - break; - } - } - } - - - // We now know which variables appear in R - if (hull_debug) { - fprintf(DebugFile,"Variables we need a better hull on are: "); - foreach(v,Variable_ID,vars, - fprintf(DebugFile," %s",v->char_name())); - fprintf(DebugFile,"\n"); - } - Conjunct *c = H.single_conjunct(); - int total=0; - int copied = 0; - for (EQ_Iterator eq = c->EQs(); eq.live(); eq.next()) { - total++; - foreach(v,Variable_ID,vars, - if ((*eq).get_coef(v) != 0) { - R.and_with_EQ(*eq); - copied++; - break; // out of variable loop - } - ); - } - for (GEQ_Iterator geq = c->GEQs(); geq.live(); geq.next()) { - total++; - foreach(v,Variable_ID,vars, - if ((*geq).get_coef(v) != 0) { - R.and_with_GEQ(*geq); - copied++; - break; // out of variable loop - } - ); - } - if (copied < total) { - R = Approximate(R); - - if (hull_debug) { - fprintf(DebugFile,"Decomposed relation, copied only %d of %d constraints\n",copied,total); - fprintf(DebugFile,"Original R:\n"); - R.prefix_print(DebugFile); - fprintf(DebugFile,"Known hull:\n"); - H.prefix_print(DebugFile); - fprintf(DebugFile,"New R:\n"); - R.prefix_print(DebugFile); - } - } - } - - Relation F = Farkas(copy(R), Basic_Farkas, true); - if (hull_debug) - fprintf(DebugFile,"Farkas Difficulty = " coef_fmt "\n", farkasDifficulty); - if (farkasDifficulty > 260) { - if (hull_debug) { - fprintf(DebugFile, "] bailing out, farkas is way too complex\n"); - fprintf(DebugFile,"Farkas:\n"); - F.prefix_print(DebugFile); - } - return H; - } - else if (farkasDifficulty > 130) { - // Bail out - if (hull_debug) { - fprintf(DebugFile, coef_fmt " non-zeros in original farkas\n", farkasDifficulty); - } - Relation tmp = Farkas(R, Decoupled_Farkas, true); - - if (hull_debug) { - fprintf(DebugFile, coef_fmt " non-zeros in decoupled farkas\n", farkasDifficulty); - } - if (farkasDifficulty > 260) { - if (hull_debug) { - fprintf(DebugFile, "] bailing out, farkas is way too complex\n"); - fprintf(DebugFile,"Farkas:\n"); - F.prefix_print(DebugFile); - } - return H; - } - else { - if (farkasDifficulty > 130) - R = Intersection(H, Farkas(tmp, Affine_Combination_Farkas, true)); - else R = Intersection(H, - Intersection(Farkas(tmp, Convex_Combination_Farkas, true), - Farkas(F, Affine_Combination_Farkas, true))); - if (hull_debug) { - fprintf(DebugFile, "] bailing out, farkas is too complex, using affine hull\n"); - fprintf(DebugFile,"Farkas:\n"); - F.prefix_print(DebugFile); - fprintf(DebugFile,"Affine hull:\n"); - R.prefix_print(DebugFile); - } - return R; - } - } - - R = Intersection(H, Farkas(F, Convex_Combination_Farkas, true)); - if (hull_debug) { - fprintf(DebugFile, "] Result of FastTightHull:\n"); - R.prefix_print(DebugFile); - } - return R; -} - - - -namespace { - bool parallel(const GEQ_Handle &g1, const GEQ_Handle &g2) { - for(Constr_Vars_Iter cvi(g1, false); cvi; cvi++) { - coef_t c1 = (*cvi).coef; - coef_t c2 = g2.get_coef((*cvi).var); - if (c1 != c2) return false; - } - { - for(Constr_Vars_Iter cvi(g2, false); cvi; cvi++) { - coef_t c1 = g1.get_coef((*cvi).var); - coef_t c2 = (*cvi).coef; - if (c1 != c2) return false; - } - } - return true; - } - - - bool hull(const EQ_Handle &e, const GEQ_Handle &g, coef_t &hull) { - int sign = 0; - for(Constr_Vars_Iter cvi(e, false); cvi; cvi++) { - coef_t c1 = (*cvi).coef; - coef_t c2 = g.get_coef((*cvi).var); - if (sign == 0) sign = (c1*c2>=0?1:-1); - if (sign*c1 != c2) return false; - } - assert(sign != 0); - { - for(Constr_Vars_Iter cvi(g, false); cvi; cvi++) { - coef_t c1 = e.get_coef((*cvi).var); - coef_t c2 = (*cvi).coef; - if (sign*c1 != c2) return false; - } - } - hull = max(sign * e.get_const(), g.get_const()); - if (hull_debug) { - fprintf(DebugFile,"Hull of:\n %s\n", e.print_to_string().c_str()); - fprintf(DebugFile," %s\n", g.print_to_string().c_str()); - fprintf(DebugFile,"is " coef_fmt "\n\n",hull); - } - return true; - } - - bool eq(const EQ_Handle &e1, const EQ_Handle &e2) { - int sign = 0; - for(Constr_Vars_Iter cvi(e1, false); cvi; cvi++) { - coef_t c1 = (*cvi).coef; - coef_t c2 = e2.get_coef((*cvi).var); - if (sign == 0) sign = (c1*c2>=0?1:-1); - if (sign*c1 != c2) return false; - } - assert(sign != 0); - { - for(Constr_Vars_Iter cvi(e2, false); cvi; cvi++) { - coef_t c1 = e1.get_coef((*cvi).var); - coef_t c2 = (*cvi).coef; - if (sign*c1 != c2) return false; - } - } - return sign * e1.get_const() == e2.get_const(); - } -} - - -// This function is deprecated!!! -Relation QuickHull(Relation &R) { - Tuple<Relation> Rs(1); - Rs[1] = R; - return QuickHull(Rs); -} - - -// This function is deprecated!!! -Relation QuickHull(Tuple<Relation> &Rs) { - assert(!Rs.empty()); - - // if (Rs.size() == 1) return Rs[1]; - - Tuple<Relation> l_Rs; - for (int i = 1; i <= Rs.size(); i++) - for (DNF_Iterator c(Rs[i].query_DNF()); c; c++) { - Relation r = Relation(Rs[i], c.curr()); - l_Rs.append(Approximate(r)); - } - - if (l_Rs.size() == 1) - return l_Rs[1]; - - Relation result = Relation::True(Rs[1]); - result.copy_names(Rs[1]); - - use_ugly_names++; - - if (hull_debug > 1) - for (int i = 1; i <= l_Rs.size(); i++) { - fprintf(DebugFile,"#%d \n",i); - l_Rs[i].prefix_print(DebugFile); - } - - -// Relation R = copy(Rs[1]); -// for (int i = 2; i <= Rs.size(); i++) -// R = Union(R,copy(Rs[i])); - -// #if 0 -// if (!R.is_set()) { -// if (R.n_inp() == R.n_out()) { -// Relation AC = DeltasToRelation(Hull(Deltas(copy(R), -// min(R.n_inp(),R.n_out()))), -// R.n_inp(),R.n_out()); -// Relation dH = Hull(Domain(copy(R)),false); -// Relation rH = Hull(Range(copy(R)),false); -// result = Intersection(AC,Cross_Product(dH,rH)); -// } -// else { -// Relation dH = Hull(Domain(copy(R)),false); -// Relation rH = Hull(Range(copy(R)),false); -// result = Cross_Product(dH,rH); -// assert(Must_Be_Subset(copy(R),copy(result))); -// } -// } - -// #endif - - Conjunct *first; - l_Rs[1] = EQs_to_GEQs(l_Rs[1]); - first = l_Rs[1].single_conjunct(); - for (GEQ_Iterator candidate(first->GEQs()); candidate.live(); candidate.next()) { - coef_t maxConstantTerm = (*candidate).get_const(); - bool found = true; - if (hull_debug > 1) { - fprintf(DebugFile,"searching for bound on:\n %s\n", (*candidate).print_to_string().c_str()); - } - for (int i = 2; i <= l_Rs.size(); i++) { - Conjunct *other = l_Rs[i].single_conjunct(); - bool found_for_i = false; - for (GEQ_Iterator target(other->GEQs()); target.live(); target.next()) { - if (hull_debug > 2) { - fprintf(DebugFile,"candidate:\n %s\n", (*candidate).print_to_string().c_str()); - fprintf(DebugFile,"target:\n %s\n", (*target).print_to_string().c_str()); - } - if (parallel(*candidate,*target)) { - if (hull_debug > 1) - fprintf(DebugFile,"Found bound:\n %s\n", (*target).print_to_string().c_str()); - maxConstantTerm = max(maxConstantTerm,(*target).get_const()); - found_for_i = true; - break; - } - } - if (!found_for_i) { - for (EQ_Iterator target_e(other->EQs()); target_e.live(); target_e.next()) { - coef_t h; - if (hull(*target_e,*candidate,h)) { - if (hull_debug > 1) - fprintf(DebugFile,"Found bound of " coef_fmt ":\n %s\n", h, (*target_e).print_to_string().c_str()); - maxConstantTerm = max(maxConstantTerm,h); - found_for_i = true; - break; - } - }; - if (!found_for_i) { - if (hull_debug > 1) { - fprintf(DebugFile,"No bound found in:\n"); - fprintf(DebugFile, "%s", l_Rs[i].print_with_subs_to_string().c_str()); - } - //if nothing found - found = false; - break; - } - } - } - - if (found) { - GEQ_Handle h = result.and_with_GEQ(); - copy_constraint(h,*candidate); - if (hull_debug > 1) - fprintf(DebugFile,"Setting constant term to " coef_fmt " in\n %s\n", maxConstantTerm, h.print_to_string().c_str()); - h.update_const(maxConstantTerm - (*candidate).get_const()); - if (hull_debug > 1) - fprintf(DebugFile,"Updated constraint is\n %s\n", h.print_to_string().c_str()); - } - } - - - for (EQ_Iterator candidate_eq(first->EQs()); candidate_eq.live(); candidate_eq.next()) { - bool found = true; - for (int i = 2; i <= l_Rs.size(); i++) { - Conjunct *C = l_Rs[i].single_conjunct(); - bool found_for_i = false; - - for (EQ_Iterator target(C->EQs()); target.live(); target.next()) { - if (eq(*candidate_eq,*target)) { - found_for_i = true; - break; - } - } - if (!found_for_i) { - //if nothing found - found = false; - break; - } - } - - if (found) { - EQ_Handle h = result.and_with_EQ(); - copy_constraint(h,*candidate_eq); - if (hull_debug > 1) - fprintf(DebugFile,"Adding eq constraint: %s\n", h.print_to_string().c_str()); - } - } - - use_ugly_names--; - if (hull_debug > 1) { - fprintf(DebugFile,"quick hull is of:"); - result.print_with_subs(DebugFile); - } - return result; -} - - -// Relation Hull2(Tuple<Relation> &Rs, Tuple<int> &active) { -// assert(Rs.size() == active.size() && Rs.size() > 0); - -// Tuple<Relation> l_Rs; -// for (int i = 1; i <= Rs.size(); i++) -// if (active[i]) -// l_Rs.append(copy(Rs[i])); - -// if (l_Rs.size() == 0) -// return Relation::False(Rs[1]); - -// try { -// Relation r = l_Rs[1]; -// for (int i = 2; i <= l_Rs.size(); i++) { -// r = Union(r, copy(l_Rs[i])); -// r.simplify(); -// } - -// // Relation F = Farkas(r, Basic_Farkas, true); -// // if (farkasDifficulty >= 500) -// // throw std::overflow_error("loop convex hull too complicated."); -// // F = Farkas(F, Convex_Combination_Farkas, true); -// return Farkas(Farkas(r, Basic_Farkas, true), Convex_Combination_Farkas, true); -// } -// catch (std::overflow_error) { -// return QuickHull(l_Rs); -// } -// } - - -namespace { - void printRs(Tuple<Relation> &Rs) { - fprintf(DebugFile,"Rs:\n"); - for (int i = 1; i <= Rs.size(); i++) - fprintf(DebugFile,"#%d : %s\n",i, - Rs[i].print_with_subs_to_string().c_str()); - } -} - -Relation BetterHull(Tuple<Relation> &Rs, bool stridesAllowed, bool checkSubsets, - NOT_CONST Relation &input_knownHull = Relation::Null()) { - Relation knownHull = consume_and_regurgitate(input_knownHull); - static int OMEGA_WHINGE = -1; - if (OMEGA_WHINGE < 0) { - OMEGA_WHINGE = getenv("OMEGA_WHINGE") ? atoi(getenv("OMEGA_WHINGE")) : 0; - } - assert(!Rs.empty()); - if (Rs.size() == 1) { - if (stridesAllowed) return Rs[1]; - else return Approximate(Rs[1]); - } - - if (checkSubsets) { - Tuple<bool> live(Rs.size()); - if (hull_debug) { - fprintf(DebugFile,"Checking subsets in hull computation:\n"); - printRs(Rs); - } - int i; - for(i=1;i <=Rs.size(); i++) live[i] = true; - for(i=1;i <=Rs.size(); i++) - for(int j=1;j <=Rs.size(); j++) if (i != j && live[j]) { - if (hull_debug) fprintf(DebugFile,"checking %d Is_Obvious_Subset %d\n",i,j); - if (Is_Obvious_Subset(copy(Rs[i]),copy(Rs[j]))) { - if (hull_debug) fprintf(DebugFile,"yes...\n"); - live[i] = false; - break; - } - } - for(i=1;i <=Rs.size(); i++) if (!live[i]) { - if (i < Rs.size()) { - Rs[i] = Rs[Rs.size()]; - live[i] = live[Rs.size()]; - } - Rs[Rs.size()] = Relation(); - Rs.delete_last(); - i--; - } - } - Relation hull; - if (hull_debug) { - fprintf(DebugFile,"Better Hull:\n"); - printRs(Rs); - fprintf(DebugFile,"known hull: %s\n", knownHull.print_with_subs_to_string().c_str()); - } - if (knownHull.is_null()) hull = QuickHull(Rs); - else hull = Intersection(QuickHull(Rs),knownHull); - // for (int i = 1; i <= Rs.size(); i++) - // hull = RectHull(Union(hull, copy(Rs[i]))); - // hull = Intersection(hull, knownHull); - hull.simplify(); - if (hull_debug) { - fprintf(DebugFile,"quick hull: %s\n", hull.print_with_subs_to_string().c_str()); - } - - Relation orig = Relation::False(Rs[1]); - int i; - for (i = 1; i <= Rs.size(); i++) - orig = Union(orig,copy(Rs[i])); - - orig.simplify(); - - for (i = 1; i <= Rs.size(); i++) { - if (!hull.is_obvious_tautology()) Rs[i] = Gist(Rs[i],copy(hull)); - Rs[i].simplify(); - if (Rs[i].is_obvious_tautology()) return hull; - if (Rs[i].has_single_conjunct()) { - Rs[i] = EQs_to_GEQs(Rs[i]); - if (hull_debug) { - fprintf(DebugFile,"Checking for hull constraints in:\n %s\n", Rs[i].print_with_subs_to_string().c_str()); - } - Conjunct *c = Rs[i].single_conjunct(); - for (GEQ_Iterator g(c->GEQs()); g.live(); g.next()) { - Relation tmp = Relation::True(Rs[i]); - tmp.and_with_GEQ(*g); - if (!Difference(copy(orig),tmp).is_upper_bound_satisfiable()) - hull.and_with_GEQ(*g); - } - for (EQ_Iterator e(c->EQs()); e.live(); e.next()) { - Relation tmp = Relation::True(Rs[i]); - tmp.and_with_EQ(*e); - if (!Difference(copy(orig),tmp).is_upper_bound_satisfiable()) - hull.and_with_EQ(*e); - } - } - } - - hull = FastTightHull(orig,hull); - assert(hull.has_single_conjunct()); - - if (stridesAllowed) return hull; - else return Approximate(hull); - -} - - - -Relation Hull(NOT_CONST Relation &S, - bool stridesAllowed, - int effort, - NOT_CONST Relation &knownHull) { - Relation R = consume_and_regurgitate(S); - R.simplify(1,0); - if (!R.is_upper_bound_satisfiable()) return R; - Tuple<Relation> Rs; - for (DNF_Iterator c(R.query_DNF()); c.live(); ) { - Rs.append(Relation(R,c.curr())); - c.next(); - } - if (effort == 1) - return BetterHull(Rs,stridesAllowed,false,knownHull); - else - return QuickHull(Rs); -} - - - -Relation Hull(Tuple<Relation> &Rs, - Tuple<int> &validMask, - int effort, - bool stridesAllowed, - NOT_CONST Relation &knownHull) { - // Use relation of index i only when validMask[i] != 0 - Tuple<Relation> Rs2; - for(int i = 1; i <= Rs.size(); i++) { - if (validMask[i]) { - Rs[i].simplify(); - for (DNF_Iterator c(Rs[i].query_DNF()); c.live(); ) { - Rs2.append(Relation(Rs[i],c.curr())); - c.next(); - } - } - } - assert(effort == 0 || effort == 1); - if (effort == 1) - return BetterHull(Rs2,stridesAllowed,true,knownHull); - else - return QuickHull(Rs2); -} - - -// This function is deprecated!!! -Relation CheckForConvexRepresentation(NOT_CONST Relation &R_In) { - Relation R = consume_and_regurgitate(R_In); - Relation h = Hull(copy(R)); - if (!Difference(copy(h),copy(R)).is_upper_bound_satisfiable()) - return h; - else - return R; -} - -// This function is deprecated!!! -Relation CheckForConvexPairs(NOT_CONST Relation &S) { - Relation R = consume_and_regurgitate(S); - Relation hull = FastTightHull(copy(R),Relation::True(R)); - R.simplify(1,0); - if (!R.is_upper_bound_satisfiable() || R.number_of_conjuncts() < 2) return R; - Tuple<Relation> Rs; - for (DNF_Iterator c(R.query_DNF()); c.live(); ) { - Rs.append(Relation(R,c.curr())); - c.next(); - } - - bool *dead = new bool[Rs.size()+1]; - int i; - for(i = 1; i<=Rs.size();i++) dead[i] = false; - - for(i = 1; i<=Rs.size();i++) - if (!dead[i]) - for(int j = i+1; j<=Rs.size();j++) if (!dead[j]) { - if (hull_debug) { - fprintf(DebugFile,"Comparing #%d and %d\n",i,j); - } - Relation U = Union(copy(Rs[i]),copy(Rs[j])); - Relation H_ij = FastTightHull(copy(U),copy(hull)); - if (!Difference(copy(H_ij),U).is_upper_bound_satisfiable()) { - Rs[i] = H_ij; - dead[j] = true; - if (hull_debug) { - fprintf(DebugFile,"Combined them\n"); - } - } - } - i = 1; - while(i<=Rs.size() && dead[i]) i++; - assert(i<=Rs.size()); - R = Rs[i]; - i++; - for(; i<=Rs.size();i++) - if (!dead[i]) - R = Union(R,Rs[i]); - delete []dead; - return R; -} - -// -// Supporting functions for ConvexRepresentation -// -namespace { -struct Interval { - std::list<std::pair<Relation, Relation> >::iterator pos; - coef_t lb; - coef_t ub; - bool change; - coef_t modulo; - Interval(std::list<std::pair<Relation, Relation> >::iterator pos_, coef_t lb_, coef_t ub_): - pos(pos_), lb(lb_), ub(ub_) {} - friend bool operator<(const Interval &a, const Interval &b); -}; - -bool operator<(const Interval &a, const Interval &b) { - return a.lb < b.lb; -} - -struct Modulo_Interval { - coef_t modulo; - coef_t start; - coef_t size; - Modulo_Interval(coef_t modulo_, coef_t start_, coef_t size_): - modulo(modulo_), start(start_), size(size_) {} - friend bool operator<(const Interval &a, const Interval &b); -}; - -bool operator<(const Modulo_Interval &a, const Modulo_Interval &b) { - if (a.modulo == b.modulo) { - if (a.start == b.start) - return a.size < b.size; - else - return a.start < b.start; - } - else - return a.modulo < b.modulo; -} - -void merge_intervals(std::list<Interval> &intervals, coef_t modulo, std::list<std::pair<Relation, Relation> > &Rs, std::list<std::pair<Relation, Relation> >::iterator orig) { - // normalize intervals - for (std::list<Interval>::iterator i = intervals.begin(); i != intervals.end(); i++) { - (*i).modulo = modulo; - (*i).change = false; - if ((*i).ub - (*i).lb + 1>= modulo) { - (*i).lb = 0; - (*i).ub = modulo - 1; - } - else if ((*i).ub < 0 || (*i).lb >= modulo) { - coef_t range = (*i).ub - (*i).lb; - (*i).lb = int_mod((*i).lb, modulo); - (*i).ub = (*i).lb + range; - } - } - - intervals.sort(); - - // merge neighboring intervals - std::list<Interval>::iterator p = intervals.begin(); - while (p != intervals.end()) { - std::list<Interval>::iterator q = p; - q++; - while (q != intervals.end()) { - if ((*p).ub + 1 >= (*q).lb) { - Relation hull = ConvexHull(Union(copy((*(*p).pos).first), copy((*(*q).pos).first))); - Relation remainder = Difference(Difference(copy(hull), copy((*(*p).pos).first)), copy((*(*q).pos).first)); - if (!remainder.is_upper_bound_satisfiable()) { - if ((*q).pos == orig) - std::swap((*p).pos, (*q).pos); - (*(*p).pos).first = hull; - (*p).ub = max((*p).ub, (*q).ub); - (*p).change = true; - Rs.erase((*q).pos); - q = intervals.erase(q); - } - else - break; - } - else - break; - } - - bool p_moved = false; - q = p; - q++; - while (q != intervals.end()) { - if ((*q).ub >= modulo && int_mod((*q).ub, modulo) + 1 >= (*p).lb) { - Relation hull = ConvexHull(Union(copy((*(*p).pos).first), copy((*(*q).pos).first))); - Relation remainder = Difference(Difference(copy(hull), copy((*(*p).pos).first)), copy((*(*q).pos).first)); - if (!remainder.is_upper_bound_satisfiable()) { - if ((*p).pos == orig) - std::swap((*p).pos, (*q).pos); - (*(*q).pos).first = hull; - coef_t t = (*p).ub - int_mod((*q).ub, modulo); - if (t > 0) - (*q).ub = (*q).ub + t; - (*q).change = true; - Rs.erase((*p).pos); - p = intervals.erase(p); - p_moved = true; - break; - } - else - q++; - } - else - q++; - } - - if (!p_moved) - p++; - } - - // merge by reducing the strengh of modulo - std::list<Modulo_Interval> modulo_intervals; - coef_t max_distance = modulo/2; - for (std::list<Interval>::iterator p = intervals.begin(); p != intervals.end(); p++) { - if ((*p).lb >= max_distance) - break; - - coef_t size = (*p).ub - (*p).lb; - - std::list<Interval>::iterator q = p; - q++; - while (q != intervals.end()) { - coef_t distance = (*q).lb - (*p).lb; - if (distance > max_distance) - break; - - if ((*q).ub - (*q).lb != size || int_mod(modulo, distance) != 0) { - q++; - continue; - } - - int num_reduced = 0; - coef_t looking_for = int_mod((*p).lb, distance); - for (std::list<Interval>::iterator k = intervals.begin(); k != intervals.end(); k++) { - if ((*k).lb == looking_for && (*k).ub - (*k).lb == size) { - num_reduced++; - looking_for += distance; - if (looking_for >= modulo) - break; - } - else if ((*k).lb <= looking_for && (*k).ub >= looking_for + size) { - looking_for += distance; - if (looking_for >= modulo) - break; - } - else if ((*k).lb > looking_for) - break; - } - - if (looking_for >= modulo && num_reduced > 1) - modulo_intervals.push_back(Modulo_Interval(distance, int_mod((*p).lb, distance), size)); - - q++; - } - } - - modulo_intervals.sort(); - - // remove redundant reduced-strength intervals - std::list<Modulo_Interval>::iterator p2 = modulo_intervals.begin(); - while (p2 != modulo_intervals.end()) { - std::list<Modulo_Interval>::iterator q2 = p2; - q2++; - while (q2 != modulo_intervals.end()) { - if ((*p2).modulo == (*q2).modulo && (*p2).start == (*q2).start) - q2 = modulo_intervals.erase(q2); - else if (int_mod((*q2).modulo, (*p2).modulo) == 0 && - (*p2).start == int_mod((*q2).start, (*p2).modulo) && - (*p2).size >= (*q2).size) - q2 = modulo_intervals.erase(q2); - else - q2++; - } - p2++; - } - - // replace original intervals with new reduced-strength ones - for (std::list<Modulo_Interval>::iterator i = modulo_intervals.begin(); i != modulo_intervals.end(); i++) { - std::vector<Relation *> candidates; - int num_replaced = 0; - for (std::list<Interval>::iterator j = intervals.begin(); j != intervals.end(); j++) - if (int_mod((*j).modulo, (*i).modulo) == 0 && - (*j).ub - (*j).lb >= (*i).size && - (int_mod((*j).lb, (*i).modulo) == (*i).start || - int_mod((*j).ub, (*i).modulo) == (*i).start + (*i).size)) { - candidates.push_back(&((*(*j).pos).first)); - if (int_mod((*j).lb, (*i).modulo) == (*i).start && - (*j).ub - (*j).lb == (*i).size) - num_replaced++; - } - if (num_replaced <= 1) - continue; - - Relation R = copy(*candidates[0]); - for (size_t k = 1; k < candidates.size(); k++) - R = Union(R, copy(*candidates[k])); - Relation hull = ConvexHull(copy(R)); - Relation remainder = Difference(copy(hull), copy(R)); - if (!remainder.is_upper_bound_satisfiable()) { - std::list<Interval>::iterator replaced_one = intervals.end(); - for (std::list<Interval>::iterator j = intervals.begin(); j != intervals.end();) - if (int_mod((*j).modulo, (*i).modulo) == 0 && - (*j).ub - (*j).lb >= (*i).size && - (int_mod((*j).lb, (*i).modulo) == (*i).start || - int_mod((*j).ub, (*i).modulo) == (*i).start + (*i).size)) { - if (int_mod((*j).lb, (*i).modulo) == (*i).start && - (*j).ub - (*j).lb == (*i).size) { - if (replaced_one == intervals.end()) { - (*(*j).pos).first = hull; - (*j).lb = int_mod((*j).lb, (*i).modulo); - (*j).ub = int_mod((*j).ub, (*i).modulo); - (*j).modulo = (*i).modulo; - (*j).change = true; - replaced_one = j; - j++; - } - else { - if ((*j).pos == orig) { - std::swap((*replaced_one).pos, (*j).pos); - (*(*replaced_one).pos).first = (*(*j).pos).first; - } - Rs.erase((*j).pos); - j = intervals.erase(j); - } - } - else { - if (int_mod((*j).lb, (*i).modulo) == (*i).start) - (*j).lb = (*j).lb + (*i).size + 1; - else - (*j).ub = (*j).ub - (*i).size - 1; - (*j).change = true; - j++; - } - } - else - j++; - } - } -} -} // namespace - - -// -// Simplify a union of sets/relations to a minimal (may not be -// optimal) number of convex regions. It intends to replace -// CheckForConvexRepresentation and CheckForConvexPairs functions. -// -Relation ConvexRepresentation(NOT_CONST Relation &R) { - Relation l_R = copy(R); - if (!l_R.is_upper_bound_satisfiable() || l_R.number_of_conjuncts() < 2) - return R; - - // separate each conjunct into smooth convex region and holes - std::list<std::pair<Relation, Relation> > Rs; // pair(smooth region, hole condition) - for (DNF_Iterator c(l_R.query_DNF()); c.live(); c++) { - Relation r1 = Relation(l_R, c.curr()); - Relation r2 = Approximate(copy(r1)); - r1 = Gist(r1, copy(r2)); - Rs.push_back(std::make_pair(r2, r1)); - } - - try { - bool change = true; - while (change) { - change = false; - - std::list<std::pair<Relation, Relation> >::iterator i = Rs.begin(); - while (i != Rs.end()) { - // find regions with identical hole conditions to merge - { - std::list<std::pair<Relation, Relation> >::iterator j = i; - j++; - while (j != Rs.end()) { - if (!Difference(copy((*i).second), copy((*j).second)).is_upper_bound_satisfiable() && - !Difference(copy((*j).second), copy((*i).second)).is_upper_bound_satisfiable()) { - if (Must_Be_Subset(copy((*j).first), copy((*i).first))) { - j = Rs.erase(j); - } - else if (Must_Be_Subset(copy((*i).first), copy((*j).first))) { - (*i).first = (*j).first; - j = Rs.erase(j); - change = true; - } - else { - Relation r; - bool already_use_recthull = false; - try { - // chun's debug - // throw std::runtime_error("dfdf"); - - r = ConvexHull(Union(copy((*i).first), copy((*j).first))); - } - catch (const std::overflow_error &e) { - r = RectHull(Union(copy((*i).first), copy((*j).first))); - already_use_recthull = true; - } - retry_recthull: - Relation r2 = Difference(Difference(copy(r), copy((*i).first)), copy((*j).first)); - if (!r2.is_upper_bound_satisfiable()) { // convex hull is tight - (*i).first = r; - j = Rs.erase(j); - change = true; - } - else { - if (!already_use_recthull) { - r = RectHull(Union(copy((*i).first), copy((*j).first))); - already_use_recthull = true; - goto retry_recthull; - } - else - j++; - } - } - } - else - j++; - } - } - - // find identical smooth regions as candidates for hole merge - std::list<std::list<std::pair<Relation, Relation> >::iterator> s; - for (std::list<std::pair<Relation, Relation> >::iterator j = Rs.begin(); j != Rs.end(); j++) - if (j != i) { - if (!Intersection(Difference(copy((*i).first), copy((*j).first)), copy((*j).second)).is_upper_bound_satisfiable() && - !Intersection(Difference(copy((*j).first), copy((*i).first)), copy((*i).second)).is_upper_bound_satisfiable()) - s.push_back(j); - } - - if (s.size() != 0) { - // convert hole condition c1*x1+c2*x2+... = c*alpha+d to a pair of inequalities - (*i).second = EQs_to_GEQs((*i).second, false); - - // find potential wildcards that can be used for hole conditions - std::set<Variable_ID> nonsingle_wild; - for (EQ_Iterator ei((*i).second.single_conjunct()); ei; ei++) - if ((*ei).has_wildcards()) - for (Constr_Vars_Iter cvi(*ei, true); cvi; cvi++) - nonsingle_wild.insert(cvi.curr_var()); - for (GEQ_Iterator gei((*i).second.single_conjunct()); gei; gei++) - if ((*gei).has_wildcards()) { - Constr_Vars_Iter cvi(*gei, true); - Constr_Vars_Iter cvi2 = cvi; - cvi2++; - if (cvi2) { - nonsingle_wild.insert(cvi.curr_var()); - for (; cvi2; cvi2++) - nonsingle_wild.insert(cvi2.curr_var()); - } - } - - // find hole condition in c*alpha+d1<=c1*x1+c2*x2+...<=c*alpha+d2 format - for (GEQ_Iterator gei((*i).second.single_conjunct()); gei; gei++) - if ((*gei).has_wildcards()) { - coef_t c; - Variable_ID v; - { - Constr_Vars_Iter cvi(*gei, true); - v = cvi.curr_var(); - c = cvi.curr_coef(); - if (c < 0 || nonsingle_wild.find(v) != nonsingle_wild.end()) - continue; - } - - coef_t lb = posInfinity; - for (GEQ_Iterator gei2((*i).second.single_conjunct()); gei2; gei2++) { - if (!(*gei2 == *gei) && (*gei2).get_coef(v) != 0) { - if (lb != posInfinity) { - nonsingle_wild.insert(v); - break; - } - - bool match = true; - for (Constr_Vars_Iter cvi2(*gei); cvi2; cvi2++) - if (cvi2.curr_coef() != -((*gei2).get_coef(cvi2.curr_var()))) { - match = false; - break; - } - if (match) - for (Constr_Vars_Iter cvi2(*gei2); cvi2; cvi2++) - if (cvi2.curr_coef() != -((*gei).get_coef(cvi2.curr_var()))) { - match = false; - break; - } - if (!match) { - nonsingle_wild.insert(v); - break; - } - - lb = -(*gei2).get_const(); - } - } - - if (nonsingle_wild.find(v) != nonsingle_wild.end()) - continue; - - Relation stride_cond = Relation::True((*i).second); - F_Exists *f_exists = stride_cond.and_with_and()->add_exists(); - Variable_ID e = f_exists->declare(); - F_And *f_root = f_exists->add_and(); - GEQ_Handle h1 = f_root->add_GEQ(); - GEQ_Handle h2 = f_root->add_GEQ(); - for (Constr_Vars_Iter cvi2(*gei); cvi2; cvi2++) { - Variable_ID v = cvi2.curr_var(); - switch (v->kind()) { - case Wildcard_Var: - h1.update_coef(e, cvi2.curr_coef()); - h2.update_coef(e, -cvi2.curr_coef()); - break; - case Global_Var: { - Global_Var_ID g = v->get_global_var(); - Variable_ID v2; - if (g->arity() == 0) - v2 = stride_cond.get_local(g); - else - v2 = stride_cond.get_local(g, v->function_of()); - h1.update_coef(v2, cvi2.curr_coef()); - h2.update_coef(v2, -cvi2.curr_coef()); - break; - } - default: - h1.update_coef(v, cvi2.curr_coef()); - h2.update_coef(v, -cvi2.curr_coef()); - } - } - h1.update_const((*gei).get_const()); - h2.update_const(-lb); - - stride_cond.simplify(); - Relation other_cond = Gist(copy((*i).second), copy(stride_cond)); - - // find regions with potential mergeable stride condition with this one - std::list<Interval> intervals; - intervals.push_back(Interval(i, lb, (*gei).get_const())); - - for (std::list<std::list<std::pair<Relation, Relation> >::iterator>::iterator j = s.begin(); j != s.end(); j++) - if (Must_Be_Subset(copy((**j).second), copy(other_cond))) { - Relation stride_cond2 = Gist(copy((**j).second), copy(other_cond)); - - // interval can be removed - if (stride_cond2.is_obvious_tautology()) { - intervals.push_back(Interval(*j, 0, c-1)); - continue; - } - - stride_cond2 = EQs_to_GEQs(stride_cond2, false); - coef_t lb, ub; - GEQ_Iterator gei2(stride_cond2.single_conjunct()); - coef_t sign = 0; - for (Constr_Vars_Iter cvi(*gei2, true); cvi; cvi++) - if (sign != 0) { - sign = 0; - break; - } - else if (cvi.curr_coef() == c) - sign = 1; - else if (cvi.curr_coef() == -c) - sign = -1; - else { - sign = 0; - break; - } - if (sign == 0) - continue; - - bool match = true; - for (Constr_Vars_Iter cvi(*gei2); cvi; cvi++) { - Variable_ID v = cvi.curr_var(); - if (v->kind() == Wildcard_Var) - continue; - else if (v->kind() == Global_Var) { - Global_Var_ID g = v->get_global_var(); - if (g->arity() == 0) - v = (*i).second.get_local(g); - else - v = (*i).second.get_local(g, v->function_of()); - } - - if (cvi.curr_coef() != sign * (*gei).get_coef(v)) { - match = false; - break; - } - } - if (!match) - continue; - - for (Constr_Vars_Iter cvi(*gei); cvi; cvi++) { - Variable_ID v = cvi.curr_var(); - if (v->kind() == Wildcard_Var) - continue; - else if (v->kind() == Global_Var) { - Global_Var_ID g = v->get_global_var(); - if (g->arity() == 0) - v = stride_cond2.get_local(g); - else - v = stride_cond2.get_local(g, v->function_of()); - } - - if (cvi.curr_coef() != sign * (*gei2).get_coef(v)) { - match = false; - break; - } - } - if (!match) - continue; - if (sign > 0) - ub = (*gei2).get_const(); - else - lb = -(*gei2).get_const(); - - gei2++; - if (!gei2) - continue; - - coef_t sign2 = 0; - for (Constr_Vars_Iter cvi(*gei2, true); cvi; cvi++) - if (sign2 != 0) { - sign2 = 0; - break; - } - else if (cvi.curr_coef() == c) - sign2 = 1; - else if (cvi.curr_coef() == -c) - sign2 = -1; - else { - sign2 = 0; - break; - } - if (sign2 != -sign) - continue; - - for (Constr_Vars_Iter cvi(*gei2); cvi; cvi++) { - Variable_ID v = cvi.curr_var(); - if (v->kind() == Wildcard_Var) - continue; - else if (v->kind() == Global_Var) { - Global_Var_ID g = v->get_global_var(); - if (g->arity() == 0) - v = (*i).second.get_local(g); - else - v = (*i).second.get_local(g, v->function_of()); - } - - if (cvi.curr_coef() != sign2 * (*gei).get_coef(v)) { - match = false; - break; - } - } - if (!match) - continue; - - for (Constr_Vars_Iter cvi(*gei); cvi; cvi++) { - Variable_ID v = cvi.curr_var(); - if (v->kind() == Wildcard_Var) - continue; - else if (v->kind() == Global_Var) { - Global_Var_ID g = v->get_global_var(); - if (g->arity() == 0) - v = stride_cond2.get_local(g); - else - v = stride_cond2.get_local(g, v->function_of()); - } - - if (cvi.curr_coef() != sign2 * (*gei2).get_coef(v)) { - match = false; - break; - } - } - if (!match) - continue; - if (sign2 > 0) - ub = (*gei2).get_const(); - else - lb = -(*gei2).get_const(); - - gei2++; - if (gei2) - continue; - - intervals.push_back(Interval(*j, lb, ub)); - } - - merge_intervals(intervals, c, Rs, i); - - // make current region the last one being updated - bool invalid = false; - for (std::list<Interval>::iterator ii = intervals.begin(); ii != intervals.end(); ii++) - if ((*ii).change && (*ii).pos == i) { - invalid = true; - intervals.push_back(*ii); - intervals.erase(ii); - break; - } - - // update hole condition for each region - for (std::list<Interval>::iterator ii = intervals.begin(); ii != intervals.end(); ii++) - if ((*ii).change) { - change = true; - - if ((*ii).ub - (*ii).lb + 1 >= (*ii).modulo) - (*(*ii).pos).second = copy(other_cond); - else { - Relation stride_cond = Relation::True((*i).second); - F_Exists *f_exists = stride_cond.and_with_and()->add_exists(); - Variable_ID e = f_exists->declare(); - F_And *f_root = f_exists->add_and(); - GEQ_Handle h1 = f_root->add_GEQ(); - GEQ_Handle h2 = f_root->add_GEQ(); - for (Constr_Vars_Iter cvi2(*gei); cvi2; cvi2++) { - Variable_ID v = cvi2.curr_var(); - switch (v->kind()) { - case Wildcard_Var: - h1.update_coef(e, (*ii).modulo); - h2.update_coef(e, -(*ii).modulo); - break; - case Global_Var: { - Global_Var_ID g = v->get_global_var(); - Variable_ID v2; - if (g->arity() == 0) - v2 = stride_cond.get_local(g); - else - v2 = stride_cond.get_local(g, v->function_of()); - h1.update_coef(v2, cvi2.curr_coef()); - h2.update_coef(v2, -cvi2.curr_coef()); - break; - } - default: - h1.update_coef(v, cvi2.curr_coef()); - h2.update_coef(v, -cvi2.curr_coef()); - } - } - h1.update_const((*ii).ub); - h2.update_const(-(*ii).lb); - - (*(*ii).pos).second = Intersection(copy(other_cond), stride_cond); - (*(*ii).pos).second.simplify(); - } - } - - if (invalid) - break; - } - } - i++; - } - } - } - catch (const presburger_error &e) { - throw e; - } - - Relation R2 = Relation::False(l_R); - for (std::list<std::pair<Relation, Relation> >::iterator i = Rs.begin(); i != Rs.end(); i++) - R2 = Union(R2, Intersection((*i).first, (*i).second)); - R2.simplify(0, 1); - - return R2; -} - - -// -// Use gist and value range to calculate a quick rectangular hull. It -// intends to replace all hull calculations (QuickHull, BetterHull, -// FastTightHull) beyond the method of ConvexHull (dual -// representations). In the future, it will support max(...)-like -// upper bound. So RectHull complements ConvexHull in two ways: first -// for relations that ConvexHull gets too complicated, second for -// relations where different conjuncts have different symbolic upper -// bounds. -// -Relation RectHull(NOT_CONST Relation &Rel) { - Relation R = Approximate(consume_and_regurgitate(Rel)); - if (!R.is_upper_bound_satisfiable()) - return R; - if (R.has_single_conjunct()) - return R; - - std::vector<std::string> input_names(R.n_inp()); - for (int i = 1; i <= R.n_inp(); i++) - input_names[i-1] = R.input_var(i)->name(); - std::vector<std::string> output_names(R.n_out()); - for (int i = 1; i <= R.n_out(); i++) - output_names[i-1] = R.output_var(i)->name(); - - DNF_Iterator c(R.query_DNF()); - Relation r = Relation(R, c.curr()); - c++; - std::vector<std::pair<coef_t, coef_t> > bounds1(R.n_inp()); - std::vector<std::pair<coef_t, coef_t> > bounds2(R.n_out()); - { - Relation t = Project_Sym(copy(r)); - t.simplify(); - for (int i = 1; i <= R.n_inp(); i++) { - Tuple<Variable_ID> v; - for (int j = 1; j <= R.n_inp(); j++) - if (j != i) - v.append(r.input_var(j)); - for (int j = 1; j <= R.n_out(); j++) - v.append(r.output_var(j)); - Relation t2 = Project(copy(t), v); - t2.query_variable_bounds(t2.input_var(i), bounds1[i-1].first, bounds1[i-1].second); - } - for (int i = 1; i <= R.n_out(); i++) { - Tuple<Variable_ID> v; - for (int j = 1; j <= R.n_out(); j++) - if (j != i) - v.append(r.output_var(j)); - for (int j = 1; j <= R.n_inp(); j++) - v.append(r.input_var(j)); - Relation t2 = Project(copy(t), v); - t2.query_variable_bounds(t2.output_var(i), bounds2[i-1].first, bounds2[i-1].second); - } - } - - while (c.live()) { - Relation r2 = Relation(R, c.curr()); - c++; - Relation x = Gist(copy(r), Gist(copy(r), copy(r2), 1), 1); - if (Difference(copy(r2), copy(x)).is_upper_bound_satisfiable()) - x = Relation::True(R); - Relation y = Gist(copy(r2), Gist(copy(r2), copy(r), 1), 1); - if (Difference(copy(r), copy(y)).is_upper_bound_satisfiable()) - y = Relation::True(R); - r = Intersection(x, y); - - { - Relation t = Project_Sym(copy(r2)); - t.simplify(); - for (int i = 1; i <= R.n_inp(); i++) { - Tuple<Variable_ID> v; - for (int j = 1; j <= R.n_inp(); j++) - if (j != i) - v.append(r2.input_var(j)); - for (int j = 1; j <= R.n_out(); j++) - v.append(r2.output_var(j)); - Relation t2 = Project(copy(t), v); - coef_t lbound, ubound; - t2.query_variable_bounds(t2.input_var(i), lbound, ubound); - bounds1[i-1].first = min(bounds1[i-1].first, lbound); - bounds1[i-1].second = max(bounds1[i-1].second, ubound); - } - for (int i = 1; i <= R.n_out(); i++) { - Tuple<Variable_ID> v; - for (int j = 1; j <= R.n_out(); j++) - if (j != i) - v.append(r2.output_var(j)); - for (int j = 1; j <= R.n_inp(); j++) - v.append(r2.input_var(j)); - Relation t2 = Project(copy(t), v); - coef_t lbound, ubound; - t2.query_variable_bounds(t2.output_var(i), lbound, ubound); - bounds2[i-1].first = min(bounds2[i-1].first, lbound); - bounds2[i-1].second = max(bounds2[i-1].second, ubound); - } - } - - Relation r3(R.n_inp(), R.n_out()); - F_And *f_root = r3.add_and(); - for (int i = 1; i <= R.n_inp(); i++) { - if (bounds1[i-1].first != -posInfinity) { - GEQ_Handle h = f_root->add_GEQ(); - h.update_coef(r3.input_var(i), 1); - h.update_const(-bounds1[i-1].first); - } - if (bounds1[i-1].second != posInfinity) { - GEQ_Handle h = f_root->add_GEQ(); - h.update_coef(r3.input_var(i), -1); - h.update_const(bounds1[i-1].second); - } - } - for (int i = 1; i <= R.n_out(); i++) { - if (bounds2[i-1].first != -posInfinity) { - GEQ_Handle h = f_root->add_GEQ(); - h.update_coef(r3.output_var(i), 1); - h.update_const(-bounds2[i-1].first); - } - if (bounds2[i-1].second != posInfinity) { - GEQ_Handle h = f_root->add_GEQ(); - h.update_coef(r3.output_var(i), -1); - h.update_const(bounds2[i-1].second); - } - } - r = Intersection(r, r3); - r.simplify(); - } - - for (int i = 1; i <= r.n_inp(); i++) - r.name_input_var(i, input_names[i-1]); - for (int i = 1; i <= r.n_out(); i++) - r.name_output_var(i, output_names[i-1]); - r.setup_names(); - return r; -} - -} // namespace |