diff options
author | Tuowen Zhao <ztuowen@gmail.com> | 2016-09-18 15:45:13 +0000 |
---|---|---|
committer | Tuowen Zhao <ztuowen@gmail.com> | 2016-09-18 15:45:13 +0000 |
commit | 2fce43d484e4148ae858f410d51dcd9951d34374 (patch) | |
tree | 80c204799cd38349b3bb209d4d37962b11aa6222 /omegalib/omega_lib/src/closure.cc | |
parent | f433eae7a1408cca20f3b72fb4c136d9b62de3b8 (diff) | |
download | chill-2fce43d484e4148ae858f410d51dcd9951d34374.tar.gz chill-2fce43d484e4148ae858f410d51dcd9951d34374.tar.bz2 chill-2fce43d484e4148ae858f410d51dcd9951d34374.zip |
remove include & rename
Diffstat (limited to 'omegalib/omega_lib/src/closure.cc')
-rw-r--r-- | omegalib/omega_lib/src/closure.cc | 2100 |
1 files changed, 0 insertions, 2100 deletions
diff --git a/omegalib/omega_lib/src/closure.cc b/omegalib/omega_lib/src/closure.cc deleted file mode 100644 index 416a3e7..0000000 --- a/omegalib/omega_lib/src/closure.cc +++ /dev/null @@ -1,2100 +0,0 @@ -/***************************************************************************** - Copyright (C) 1994-2000 the Omega Project Team - Copyright (C) 2005-2011 Chun Chen - Copyright (C) 2009-2011 West Pomeranian University of Technology, Szczecin - All Rights Reserved. - - Purpose: - All calculations of closure are now here. - - Notes: - Related paper: - - "Transitive closure of infinite graphs and its applications", - Wayne Kelly, William Pugh, Evan Rosser and Tatiana Shpeisman, IJPP 1996. - - "Computing the Transitive Closure of a Union of Affine Integer Tuple - Relations", Anna Beletska, Denis Barthou, Wlodzimierz Bielecki and - Albert Cohen, COCOA 2009. - - "An Iterative Algorithm of Computing the Transitive Closure of a Union - of Parameterized Affine Integer Tuple Relations", Bielecki Wlodzimierz, - Klimek Tomasz, Palkowski Marek and Anna Beletska, COCOA 2010. - - History: - 12/27/09 move ConicClosure here, Chun Chen - 01/19/11 new closure algorithms, Klimek Tomzsz - 02/02/11 move VennDiagramFrom here, Chun Chen -*****************************************************************************/ - -#include <typeinfo> -#include <assert.h> -#include <omega.h> -#include <omega/hull.h> -#include <basic/Iterator.h> -#include <basic/List.h> -#include <basic/SimpleList.h> - -namespace omega { - -void InvestigateClosure(Relation r, Relation r_closure, Relation bounds); -void print_given_bounds(const Relation & R1, NOT_CONST Relation& input_Bounds); -#define printConjunctClosure (closure_presburger_debug & 0x1) -#define detailedClosureDebug (closure_presburger_debug & 0x2) - - -#ifdef TC_STATS -extern int clock_diff(); -extern void start_clock(); -FILE *statsfile; -int singles, totals=0; -#endif - -int closure_presburger_debug = 0; - - -Relation VennDiagramForm(NOT_CONST Relation &Context_In, - Tuple<Relation> &Rs, - int next, - bool anyPositives, - int weight) { - Relation Context = consume_and_regurgitate(Context_In); - if (hull_debug) { - fprintf(DebugFile,"[VennDiagramForm, next = %d, anyPositives = %d, weight = %d \n", next,anyPositives,weight); - fprintf(DebugFile,"context:\n"); - Context.prefix_print(DebugFile); - } - if (anyPositives && weight > 3) { - Context.simplify(); - if (!Context.is_upper_bound_satisfiable()) { - if (hull_debug) - fprintf(DebugFile,"] not satisfiable\n"); - return Context; - } - weight = 0; - } - if (next > Rs.size()) { - if (!anyPositives) { - if (hull_debug) - fprintf(DebugFile,"] no positives\n"); - return Relation::False(Context); - } - Context.simplify(); - if (hull_debug) { - fprintf(DebugFile,"] answer is:\n"); - Context.prefix_print(DebugFile); - } - return Context; - } - Relation Pos = VennDiagramForm(Intersection(copy(Context),copy(Rs[next])), - Rs, - next+1, - true, - weight+2); - Relation Neg = VennDiagramForm(Difference(Context,copy(Rs[next])), - Rs, - next+1, - anyPositives, - weight+1); - if (hull_debug) { - fprintf(DebugFile,"] VennDiagramForm\n"); - fprintf(DebugFile,"pos part:\n"); - Pos.prefix_print(DebugFile); - fprintf(DebugFile,"neg part:\n"); - Neg.prefix_print(DebugFile); - } - return Union(Pos,Neg); -} - - -Relation VennDiagramForm(Tuple<Relation> &Rs, NOT_CONST Relation &Context_In) { - Relation Context = consume_and_regurgitate(Context_In); - if (Context.is_null()) Context = Relation::True(Rs[1]); - if (hull_debug) { - fprintf(DebugFile,"Starting computation of VennDiagramForm\n"); - fprintf(DebugFile,"Context:\n"); - Context.prefix_print(DebugFile); - for(int i = 1; i <= Rs.size(); i++) { - fprintf(DebugFile,"#%d:\n",i); - Rs[i].prefix_print(DebugFile); - } - } - return VennDiagramForm(Context,Rs,1,false,0); -} - -Relation VennDiagramForm(NOT_CONST Relation &R_In, NOT_CONST Relation &Context_In) { - Relation R = consume_and_regurgitate(R_In); - Relation Context = consume_and_regurgitate(Context_In); - Tuple<Relation> Rs; - for (DNF_Iterator c(R.query_DNF()); c.live(); ) { - Rs.append(Relation(R,c.curr())); - c.next(); - } - return VennDiagramForm(Rs,Context); -} - - -Relation ConicClosure (NOT_CONST Relation &R) { - int n = R.n_inp(); - if (n != R.n_out()) - throw std::invalid_argument("conic closure must have the same input arity and output arity"); - - return DeltasToRelation(ConicHull(Deltas(R)), n, n); -} - - -bool is_lex_forward(Relation R) { - if(R.n_inp() != R.n_out()) { - fprintf(stderr, "relation has wrong inputs/outpts\n"); - exit(1); - } - Relation forw(R.n_inp(), R.n_out()); - F_Or * o = forw.add_or(); - for(int a = 1; a <= forw.n_inp(); a++) { - F_And * andd = o->add_and(); - GEQ_Handle g = andd->add_GEQ(); - g.update_coef(input_var(a), -1); - g.update_coef(output_var(a), 1); - g.update_const(1); - for(int b = 1; b < a; b++) { - EQ_Handle e = andd->add_EQ(); - e.update_coef(input_var(a),1); - e.update_coef(output_var(a),-1); - } - } - Relation test = Difference(R, forw); - return !test.is_upper_bound_satisfiable(); -} - - -static Relation compose_n(NOT_CONST Relation &input_r, int n) { - Relation r = consume_and_regurgitate(input_r); - if (n == 1) - return r; - else - return Composition(r, compose_n(copy(r), n-1)); -} /* compose_n */ - - - - -Relation approx_closure(NOT_CONST Relation &input_r, int n) { - Relation r = consume_and_regurgitate(input_r); - Relation r_closure; - - r_closure=r; - int i; - for(i=2; i<=n; i++) - r_closure=Union(r_closure,compose_n(copy(r), n)); - r_closure = Union(r_closure, Relation::Unknown(r_closure)); - - return r_closure; -} /* approx_closure */ - - -static bool is_closure_itself(NOT_CONST Relation &r) { - return Must_Be_Subset(Composition(copy(r),copy(r)),copy(r)); -} - - -/***** - * get a D form of the Relation (single conjunct). - * D = {[ i_1,i_2,...,i_m] -> [j_1, j_2, ..., j_m ] : - * (forall p, 1<= p <= m) L_p <= j_p - i_p <= U_p && - * j_p - i_p == M_p alpha_p}; - * Right now only wildcards that are in stride constraints are treated. - *****/ - -Relation get_D_form (Relation & R) { - Relation D(R.n_inp(), R.n_out()); - - R.make_level_carried_to(R.n_inp()); - assert(R.has_single_conjunct()); - int n_zero=0; - for (DNF_Iterator d(R.query_DNF()); d.live(); d.next()) - n_zero=d.curr()->query_guaranteed_leading_0s(); - - Relation Diff=Deltas(copy(R)); - - if (detailedClosureDebug) { - fprintf(DebugFile, "The relation projected onto differencies is:\n"); - Diff.print_with_subs(DebugFile); - } - - - /* now form D */ - - int i; - coef_t l,u; - F_And * N = D.add_and(); - GEQ_Handle g; - for (i=1; i<=Diff.n_set(); i++) { - Diff.query_variable_bounds(Diff.set_var(i), l,u); -/* if (i== n_zero+1 && l==negInfinity) - l=1; */ - if (l!=negInfinity) { - g=N->add_GEQ(); - g.update_coef(D.input_var(i),-1); - g.update_coef(D.output_var(i),1); - g.update_const(-l); - g.finalize(); - } - if (u!=posInfinity) { - g=N->add_GEQ(); - g.update_coef(D.input_var(i),1); - g.update_coef(D.output_var(i),-1); - g.update_const(u); - g.finalize(); - } - } - - /* add all stride constrains if they do exist */ - - Conjunct *c = Diff.single_conjunct(); - - if (c->locals().size()>0) {// there are local variables - // now go through all the equalities - - coef_t coef=0; - int pos=0; - for (EQ_Iterator eq = c->EQs(); eq.live(); eq.next()) { - // constraint is in stride form if it has 2 vars, - // one of which is wildcard. Count number if vars and wildcard vars - int nwild=0,nvar=0; - - for (Constr_Vars_Iter cvi(*eq, false); cvi; cvi++) { - if ((*cvi).var->kind() == Global_Var) - continue; - else if ((*cvi).var->kind() == Wildcard_Var) { - coef=(*cvi).coef; - nwild++; - } - else - pos=(*cvi).var->get_position(); - nvar++; - } - if (nvar==2 && nwild==1) { //stride constraint - EQ_Handle e=N->add_stride(coef); - e.update_coef(D.input_var(pos),-1); - e.update_coef(D.output_var(pos),1); - e.finalize(); - } - } - } // end search of stride constrains - - D.finalize(); - D.simplify(); - return D; -} /* end get_D_form */ - -/**** - * get relation A x A describing a region of domain and range: - * A=Hull(Domain(R), Range(R)) intersection IterationSpace - * returns cross product A x A - ***/ - -Relation form_region(const Relation &R, const Relation& IterationSpace) { - Relation H=Union(Domain(copy(R)), Range(copy(R))); - H.simplify(1,1); - H = EQs_to_GEQs(H); - H=Hull(H); - Relation A=Intersection(H, copy(IterationSpace)); - Relation A1=A; - return Cross_Product(A,A1); -} - -Relation form_region1(const Relation &R, const Relation& IterationSpace) { - Relation Dom=Intersection(Domain(copy(R)), copy(IterationSpace)); - Relation Ran=Intersection(Range(copy(R)), copy(IterationSpace)); - return Cross_Product(Dom,Ran); -} - - -/**** - * Check if we can use D instead of R - * i.e. D intersection (A cross A) is Must_Be_Subset of R - ***/ - -bool isD_OK(Relation &R, Relation &D, Relation &AxA) { - Relation B=Intersection(copy(D), copy(AxA)); - B.simplify(); - - if (detailedClosureDebug) { - fprintf(DebugFile, "Intersection of D and AxA is:\n"); - B.print_with_subs(DebugFile); - } - assert (Must_Be_Subset(copy(R),copy(B))); - - return Must_Be_Subset(B, copy(R)); -} - - - -/**** - * check if the constraint is a stride one. Here we say that an equality - * constraint is a stride constraint if it has exatly one wildcard. - * The function returns number of the wildcards in the constraint. - * So if we know that constraint is from the relation in D form, then - * it cannot have more than 1 wildcard variables, and the result of - * this functions can be treated as bool. - ***/ - -static int is_stride(const EQ_Handle &eq) { - int n=0; - - for (Constr_Vars_Iter cvi(eq,true); cvi; cvi++) - n++; - - return n; -} - - - -/***** - * check if the constraint is in the form i_k' - i_k comp_op c - * return v - the number of the var and the type of the comp_op: - * 1 - >, -1 - <, 0 - not in the right form - * if this is equality constraint in the right form any 1 or -1 can be - * returned - ******/ - -static coef_t is_constraint_in_D_form(Relation &r, const Constraint_Handle &h, int &v) { - v=-1; - coef_t c_out = 0; - for (int i = 1; i <= r.n_inp(); i++) { - coef_t c_in = h.get_coef(r.input_var(i)); - if (c_in) { - if (v!=-1) - return 0; - v=i; - c_out = h.get_coef(r.output_var(i)); - - // special case for modular constraint -- by chun 04/02/2009 - if (h.has_wildcards() && typeid(h) == typeid(EQ_Handle)) { - coef_t g = 0; - for (Constr_Vars_Iter cvi(h, true); cvi; cvi++) - g = gcd(g, abs(cvi.curr_coef())); - c_in = int_mod_hat(c_in, g); - c_out = int_mod_hat(c_out, g); - - if (g == 2) { - if (c_in * c_out == 1) { - c_out = -1; - } - else - return 0; - } - else if (c_in * c_out != -1) - return 0; - } - // other cases - else if (c_in * c_out != -1) - return 0; - } - } - return c_out; -} - - -/*** - * Check if relation is in the D form - * D = {[ i_1,i_2,...,i_m] -> [j_1, j_2, ..., j_m ] : - * (forall p, 1<= p <= m) L_p <= j_p - i_p <= U_p && - * j_p - i_p == M_p alpha_p}; - * Right now we do not check for multiple stride constraints for one var. - * Probably they cannot exist in simplified conjunct - * This function will be used in assertions - *****/ - -bool is_in_D_form(Relation & D) { - /* check that D has one conjunct */ - - if (! D.has_single_conjunct()) - return false; - - Conjunct * c=D.single_conjunct(); - - if (D.global_decls()->size() != 0) // there are symbolic vars - return false; - - if (D.n_inp() != D.n_out()) - return false; - - int n=D.n_inp(); - - Tuple<int> bl(n), bu(n); - - for (int i=1; i<= n; i++) - bl[i]=bu[i]=0; - - int v; - coef_t res; - - for (EQ_Iterator eq = c->EQs(); eq.live(); eq.next()) { - if ((res=is_constraint_in_D_form(D,*eq,v))==0) - return false; - int n_wild=is_stride(*eq); - if (n_wild>=2) - return false; - if (n_wild==0) { // not stride constraint - if (bl[v] || bu[v]) - return false; - bl[v]=bu[v]=1; - } - } - - for (GEQ_Iterator geq = c->GEQs(); geq.live(); geq.next()) { - if ((res=is_constraint_in_D_form(D,*geq,v))==0) - return false; - if ((res>0 && bl[v]) || (res<0 && bu[v])) - return false; - if (res>0) - bl[v]=1; - else - bu[v]=1; - } - - return true; -} - - -#define get_D_plus_form(R) (get_D_closure(R,1)) -#define get_D_star_form(R) (get_D_closure(R,0)) - -/**** - * Get D+ or D* from the relation that is in D form - * To get D+ calculate: - * D+= {[i1, i2 .. i_m] -> {j1, j2, ..., j_m]: - * exists s s.t. s>=1 and - * (forall p, 1<= p <= m) L_p * s<= j_p - i_p <= U_p*s && - * j_p - i_p == M_p alpha_p}; - * To get D* calculate almost the same relation but s>=0. - * Parameter n is 1 for getting D+ and 0 for D* - ****/ - - -Relation get_D_closure(Relation & D, int n) { - assert (is_in_D_form(D)); - assert(n==0 || n==1); - - Conjunct *c=D.single_conjunct(); - - Relation R(D.n_inp(), D.n_out()); - - F_Exists * ex = R.add_exists(); - Variable_ID s = ex->declare("s"); - F_And * N = ex->add_and(); - - /* add s>=1 or s>=0 */ - - GEQ_Handle geq= N->add_GEQ(); - geq.update_coef(s,1); - geq.update_const(-n); - geq.finalize(); - - - /* copy and modify all the EQs */ - - for (EQ_Iterator j= c->EQs(); j.live(); j.next()) { - EQ_Handle eq=N->add_EQ(); - copy_constraint(eq, *j); - - // if it's stride constraint do not change it - - if (!is_stride(*j)) { - /* eq is j_k -i_k = c, replace c buy s*c */ - - eq.update_coef(s, (*j).get_const()); - eq.update_const(-(*j).get_const()); - } - eq.finalize(); - } - - /* copy and modify all the GEQs */ - - for (GEQ_Iterator gi= c->GEQs(); gi.live(); gi.next()) { - geq=N->add_GEQ(); - copy_constraint(geq, *gi); - - /* geq is j_k -i_k >=c or i_k-j_k >=c, replace c buy s*c */ - - geq.update_coef(s,(*gi).get_const()); - geq.update_const(-(*gi).get_const()); - geq.finalize(); - } - - R.finalize(); - - if (detailedClosureDebug) { - fprintf(DebugFile, "Simplified D%c is:\n", n==1?'+':'*'); - R.print_with_subs(DebugFile); - } - - return R; -} - - -/*** - * Check if we can easily calculate the D* (D* will be convex). - * We can calculate D* if all differences have both lower and upper - * bounds to be non -/+ infinity - ***/ - - -bool can_get_D_star_form(Relation &D) { - assert(is_in_D_form(D)); - Conjunct *c=D.single_conjunct(); - - int n=D.n_inp(); - Tuple<int> bl(n), bu(n); - int i; - - for (i=1; i<=n; i++) - bl[i]=bu[i]=0; - - for (EQ_Iterator eq = c->EQs(); eq.live(); eq.next()) { - // do not check stride constraints - if (!is_stride(*eq)) { - for (i=1; i<=n; i++) { - if ((*eq).get_coef(D.input_var(i)) !=0 ) - bl[i]=bu[i]=1; - } - } - } - - - for (GEQ_Iterator geq = c->GEQs(); geq.live(); geq.next()) { - for (i=1; i<=n; i++) { - coef_t k; - if ((k=(*geq).get_coef(D.input_var(i))) != 0) { - if (k>0) - bu[i]=1; - else - bl[i]=1; - } - } - } - - for (i=1; i<=n; i++) - if (!bl[i] || !bu[i]) - return false; - - return true; -} - - - -/***** - * Check whether the relation intersect with identity or not - ****/ - -bool does_intersect_with_identity(Relation &R) { - assert (R.n_inp() == R.n_out()); - - Relation I=Identity(R.n_inp()); - Relation C=Intersection(I, copy(R)); - return C.is_upper_bound_satisfiable(); -} - -bool does_include_identity(Relation &R) { - Relation I=Identity(R.n_inp()); - return Must_Be_Subset(I, copy(R)); -} - -/***** - * Bill's closure: check if it is possible to calculate transitive closure - * of the relation using the Bill's algorithm. - * Return the transitive closure relation if it is possible and null relation - * otherwise - ****/ - -bool Bill_closure(Relation &R, Relation& IterationSpace, Relation & R_plus, Relation & R_star) { -#ifdef TC_STATS - fprintf(statsfile,"start bill closure\n"); -#endif - - if (does_include_identity(R)) - return false; - - if (detailedClosureDebug) { - fprintf(DebugFile, "\nApplying Bill's method to calculate transitive closure\n"); - } - - // get D and AxA - Relation D=get_D_form(R); - - - if (detailedClosureDebug) { - fprintf(DebugFile,"\n D form for the relation:\n"); - D.print_with_subs(DebugFile); - } - - Relation AxA=form_region1(R, IterationSpace); - - if (detailedClosureDebug) { - fprintf(DebugFile, "\n AxA for the relation:\n"); - AxA.print_with_subs(DebugFile); - } - - // compute R_+ - - R_plus=Intersection(get_D_plus_form(D), copy(AxA)); - - if (detailedClosureDebug) { - fprintf(DebugFile, "\nR_+= D+ intersection AxA is:\n"); - R_plus.print_with_subs(DebugFile); - } - - // compute R_* - R_star=Intersection(get_D_star_form(D), form_region(R,IterationSpace)); - - if (detailedClosureDebug) { - fprintf(DebugFile, "\nR_*= D* intersection AxA is:\n"); - R_star.print_with_subs(DebugFile); - } - -/* Check that R_+ is acyclic. - Given the way we constructed R_+, R_+=(R_+)+. - As a result it's enough to verify that R_+ intersection I = 0, - to prove that R_+ is acyclic. -*/ - - if (does_intersect_with_identity(R_plus)) { - if (detailedClosureDebug) { - fprintf(DebugFile,"R_+ is not acyclic.\n"); - } - return false; - } - - //Check R_+ - R is Must_Be_Subset of R o R_+ - - if (!Must_Be_Subset(Difference(copy(R_plus), copy(R)), Composition(copy(R), copy(R_plus)))) { -#if defined(TC_STATS) - fprintf(statsfile, "R_+ -R is not a Must_Be_Subset of R o R_+\n"); - fprintf(statsfile, "Bill Method is not applicable\n"); -#endif - return false; - } - if (detailedClosureDebug) { - fprintf(DebugFile, "R_+ -R is a Must_Be_Subset of R o R_+ - good\n"); - } - -// if we are here than all tests worked, and R_+ is transitive closure -// of R. - -#if defined(TC_STATS) - fprintf(statsfile,"\nAll three tests succeeded -- exact closure found\n"); - fprintf(statsfile, "Transitive closure is R_+\n"); -#endif -// assert(isD_OK(R,D,AxA)); - return true; -} - - -/********************************************************************** - * print the relation given the bounds on the iteration space - * If the bounds are unknown (Bounds is Null), then just print relation - * itself - ****/ - -void print_given_bounds( const Relation& R1, NOT_CONST Relation& input_Bounds) { - Relation & Bounds = (Relation &)input_Bounds; - Relation r; - if (Bounds.is_null()) - r=R1; - else - r = Gist(copy(R1),copy(Bounds),1); - r.print_with_subs(DebugFile); -} - -/********************************************************************** - * Investigate closure: - * checks if the copmuted approximation on the Transitive closure - * is upper and lower bound. If it's both - it's exact. - * This function doesn't return any value. It's just prints a lot - * of debug output - * INPUT: - * r - relation - * r_closure - approximation on r+. - * F - iteration space - **********************************************************************/ - -void InvestigateClosure(Relation r, Relation r_closure, Relation F) { - Relation r3; - bool LB_res, UB_res; - - if (!F.is_null()) - F=Cross_Product(copy(F),copy(F)); - - fprintf(DebugFile, "\n\n--->investigating the closure of the relation:\n"); - print_given_bounds(r,F); - - fprintf(DebugFile, "\nComputed closure is:\n"); - print_given_bounds(r_closure,F); - - r3=Composition(copy(r),copy(r_closure)); - r3.simplify(1,1); - - r3=Union(r3,Composition(copy(r_closure),copy(r))); - r3.simplify(1,1); - - r3=Union(r3,copy(r)); - r3.simplify(1,1); - - Relation remainder = Difference(copy(r3),copy(r_closure)); - - if (!F.is_null()) { - r3=Gist(r3,F,1); - } - r3.simplify(1,1); - - if (!F.is_null()) { - r_closure=Gist(r_closure,F,1); - } - r_closure.simplify(1,1); - - LB_res= Must_Be_Subset(copy(r_closure),copy(r3)); - - UB_res=Must_Be_Subset(copy(r3),copy(r_closure)); - - fprintf(DebugFile,"\nThe results of checking closure (gist) are:\n"); - fprintf(DebugFile,"LB - %s, UB - %s\n", LB_res?"YES":"NO", UB_res?"YES":"NO"); - - if (!UB_res) { - remainder.simplify(2,2); - fprintf(DebugFile,"Dependences not included include:\n"); - print_given_bounds(remainder,F); - } -} - - - -/**** - * Transitive closure of the relation containing single conjunct - ****/ - -bool ConjunctTransitiveClosure (NOT_CONST Relation & input_R, Relation & IterationSpace, Relation & R_plus, Relation & R_star) { - Relation R = consume_and_regurgitate(input_R); - assert(R.has_single_conjunct()); - - if (printConjunctClosure) { - fprintf(DebugFile,"\nTaking closure of the single conjunct: [\n"); - R.print_with_subs(DebugFile); - } -#ifdef TC_STATS - fprintf(statsfile,"start conjuncttransitiveclosure\n"); - singles++; -#endif - - if (is_closure_itself(copy(R))) { -#ifdef TC_STATS - fprintf(statsfile, "Relation is closure itself\n"); -#endif - int ndim_all, ndim_domain; - R.dimensions(ndim_all,ndim_domain); - if (ndim_all == ndim_domain +1) { - Relation ispace = Cross_Product(Domain(copy(R)),Range(copy(R))); - Relation R_zero = Intersection(copy(ispace),Identity(R.n_inp())); - R_star = Hull(Union(copy(R),R_zero),true,1,ispace); - R_plus=R; - if (printConjunctClosure) { - fprintf(DebugFile, "\n] For this relation R+=R\n"); - fprintf(DebugFile,"R*:\n"); - R_star.print_with_subs(DebugFile); - } - return true; - } - else { - R_star=R; - R_plus=R; - if (printConjunctClosure) { - fprintf(DebugFile, "\n] For this relation R+=R, not appropriate for R*\n"); - } - return false; - } - } - else { - bool done=false; - if (!IterationSpace.is_null()) { -// Bill's closure requires the information about Iteration Space. -// So if IterationSpace is NULL, i.e. unknown( e.g. when calling from parser, -// we do not do Bill's closure - - done = Bill_closure(R, IterationSpace, R_plus, R_star); -#ifdef TC_STATS - fprintf(statsfile,"Bill closure is %sapplicable\n",done?"":"not "); -#endif - if (printConjunctClosure) { - if (!done) - fprintf(DebugFile, "Bill's closure is not applicable\n"); - else { - fprintf(DebugFile, "Bill's closure is applicable\n"); - fprintf (DebugFile, " For R:\n"); - R.print_with_subs(DebugFile); - fprintf(DebugFile, "R+ is:\n"); - R_plus.print_with_subs(DebugFile); - fprintf(DebugFile, "R* is:\n"); - R_star.print_with_subs(DebugFile); - fprintf(DebugFile, "\n"); - InvestigateClosure(R, R_plus, IterationSpace); - } - } - } - if (done) { - if (printConjunctClosure) { - fprintf(DebugFile, "]\n"); - } - return true; - } - else { - // do and check approximate closure (several compositions) - R_plus = approx_closure(copy(R), 2); -#ifdef TC_STATS - fprintf(statsfile,"Approximating closure with 2 compositions\n"); -#endif - if (printConjunctClosure) { - fprintf(DebugFile, "Doing approximate closure\n"); - InvestigateClosure(R, R_plus, IterationSpace); - } - } //end else (!done after Bill Closure or Iteration space is NULL) - - if (printConjunctClosure) { - fprintf(DebugFile, "]\n"); - } - } - return false; -} - - -/********************************************************************* - * try to get conjunct transitive closure. - * it we can get it easy get it, return true. - * if not - return false - ********************************************************************/ - - -bool TryConjunctTransitiveClosure (NOT_CONST Relation & input_R, Relation & IterationSpace, Relation & R_plus) { - Relation R = consume_and_regurgitate(input_R); - assert(R.has_single_conjunct()); -#ifdef TC_STATS - fprintf(statsfile,"start tryconjuncttransitiveclosure\n"); - singles++; -#endif - - if (printConjunctClosure) { - fprintf(DebugFile,"\nTrying to take closure of the single conjunct: [\n"); - R.print_with_subs(DebugFile); - } - - if (is_closure_itself(copy(R))) { -#ifdef TC_STATS - fprintf(statsfile, "Relation is closure itself, leave alone (try)\n"); -#endif - if (printConjunctClosure) - fprintf(DebugFile, "\n ]The relation is closure itself. Leave it alone\n"); - return false; - } - else { - bool done; - assert(!IterationSpace.is_null()); - Relation R_star; - done = Bill_closure(R, IterationSpace, R_plus, R_star); -#ifdef TC_STATS - fprintf(statsfile, "Bill closure is %sapplicable (try)\n", done?"":"NOT "); -#endif - if (printConjunctClosure) { - if (!done) - fprintf(DebugFile, "]Bill's closure is not applicable\n"); - else { - fprintf(DebugFile, "]Bill's closure is applicable\n"); - fprintf (DebugFile, " For R:\n"); - R.print_with_subs(DebugFile); - fprintf(DebugFile, "R+ is:\n"); - R_plus.print_with_subs(DebugFile); - fprintf(DebugFile, "R* is:\n"); - R_star.print_with_subs(DebugFile); - fprintf(DebugFile, "\n"); - InvestigateClosure(R, R_plus, IterationSpace); - } - } - return done; - } - //return false; -} - - -bool Equal (const Relation & r1, const Relation & r2) { - bool res=Must_Be_Subset (copy(r1), copy(r2)); - if (!res) - return false; - return Must_Be_Subset (copy(r2),copy(r1)); -} - - -void appendClausesToList(Simple_List<Relation> &L, Relation &R) { - R.make_level_carried_to(R.n_inp()); - R.simplify(2,2); - for(int depth = R.n_inp(); depth >= -1; depth--) - for (DNF_Iterator d(R.query_DNF()); d.live(); d.next()) - if (d.curr()->query_guaranteed_leading_0s() == depth) { - L.append(Relation(R, d.curr())); - } -} - -void printRelationList(Simple_List<Relation> &L) { - for (Simple_List_Iterator<Relation> li(L); li.live(); li.next()) { - li.curr().print_with_subs(DebugFile); - } -} - -/**** - * Transitive closure of the relation containing multiple conjuncts - * New (Bill's) version - ***/ - -Relation TransitiveClosure0(NOT_CONST Relation &input_r, int maxExpansion, NOT_CONST Relation & input_IterationSpace) { - Relation r = consume_and_regurgitate(input_r); - Relation IterationSpace = consume_and_regurgitate(input_IterationSpace); - - if (closure_presburger_debug) - fprintf(DebugFile, "\n\n[Transitive closure\n\n"); - - Relation result; - -#ifdef TC_STATS -#define TC_RUNS 1 - int in_conj = copy(r).query_DNF()->length(); - totals++; - fprintf(statsfile,"%d closure run\n", totals); - if(is_in_D_form(copy(r))) - fprintf(statsfile, "Relation initially in D form\n"); - else - fprintf(statsfile, "Relation initially NOT in D form\n"); - if(is_lex_forward(copy(r))) - fprintf(statsfile, "Relation is initially lex forw\n"); - else - fprintf(statsfile, "Relation is NOT initially lex forw\n"); - start_clock(); - for(int tc_loop = 1; tc_loop <= TC_RUNS; tc_loop++) { - singles = 0; -#endif - - assert(!r.is_null()); - assert(r.n_inp() == r.n_out()); - - if (r.max_ufs_arity() > 0) { - assert(r.max_ufs_arity() == 0 && "Can't take transitive closure with UFS yet."); - - fprintf(stderr, "Can't take transitive closure with UFS yet."); - exit(1); - } - - r.simplify(2,2); - if (!r.is_upper_bound_satisfiable()) { -#ifdef TC_STATS - int totalTime = clock_diff(); - fprintf(statsfile, "Relation is unsatisfiable\n"); - fprintf(statsfile, "input conj: %d output conj: %d #singe conj closures: %d time: %d\n", - in_conj, copy(result).query_DNF()->length(), - singles, - totalTime/TC_RUNS); -#endif - - - if (closure_presburger_debug) - fprintf(DebugFile, "]TC : relation is false\n"); - return r; - } - - IterationSpace = Hull(Union(Domain(copy(r)),Range(copy(r))), true, 1, IterationSpace); - - if (detailedClosureDebug) { - fprintf(DebugFile, "r is:\n"); - r.print_with_subs(DebugFile); - fprintf(DebugFile, "IS is:\n"); - IterationSpace.print_with_subs(DebugFile); - } - Relation dom = Domain(copy(r)); - dom.simplify(2,1); - Relation rng = Range(copy(r)); - rng.simplify(2,1); - Relation AC = ConicClosure(Restrict_Range(Restrict_Domain(copy(r),copy(rng)),copy(dom))); - Relation UB = Union(copy(r),Join(copy(r),Join(AC,copy(r)))); - UB.simplify(2,1); - - if (detailedClosureDebug) { - fprintf(DebugFile, "UB is:\n"); - UB.print_with_subs(DebugFile); - } - result = Relation::False(r); - Simple_List<Relation> firstChoice,secondChoice; - - r.simplify(2,2); - - Relation test = Difference(copy(r),Composition(copy(r),copy(r))); - test.simplify(2,2); - if (r.number_of_conjuncts() > test.number_of_conjuncts()) { - Relation test2 = Union(copy(test),Composition(copy(test),copy(test))); - test2.simplify(2,2); - if (Must_Be_Subset(copy(r),copy(test2))) r = test; - else if (detailedClosureDebug) { - fprintf(DebugFile, "Transitive reduction not possible:\n"); - fprintf(DebugFile, "R is:\n"); - r.print_with_subs(DebugFile); - fprintf(DebugFile, "test2 is:\n"); - test2.print_with_subs(DebugFile); - } - } - - r.make_level_carried_to(r.n_inp()); - if (detailedClosureDebug) { - fprintf(DebugFile, "r is:\n"); - r.print_with_subs(DebugFile); - } - for(int depth = r.n_inp(); depth >= -1; depth--) - for (DNF_Iterator d(r.query_DNF()); d.live(); d.next()) - if (d.curr()->query_guaranteed_leading_0s() == depth) { - Relation C(r, d.curr()); - firstChoice.append(C); - } - - bool first_conj=true; - for (Simple_List_Iterator<Relation> sli(firstChoice); sli; sli++) { - if (first_conj) - first_conj=false; - else { - Relation C_plus; - bool change=TryConjunctTransitiveClosure( - copy(sli.curr()), IterationSpace, C_plus); - if (change) - sli.curr()=C_plus; - } - } - - //compute closure - int maxClauses = 3+firstChoice.size()*(1+maxExpansion); - - int resultConjuncts = 0; - int numFails = 0; - bool resultInexact = false; - while (!firstChoice.empty() || !secondChoice.empty()) { - Relation R_plus, R_star; - - if (detailedClosureDebug) { - fprintf(DebugFile,"Main loop of TC:\n"); - if (!firstChoice.empty()) { - fprintf(DebugFile,"First choice:\n"); - printRelationList(firstChoice); - } - if (!secondChoice.empty()) { - fprintf(DebugFile,"Second choice:\n"); - printRelationList(secondChoice); - } - } - - Relation R; - if (!firstChoice.empty()) - R = firstChoice.remove_front(); - else R = secondChoice.remove_front(); - - if (detailedClosureDebug) { - fprintf(DebugFile, "Working with conjunct:\n"); - R.print_with_subs(DebugFile); - } - - bool known=ConjunctTransitiveClosure(copy(R),IterationSpace, R_plus, R_star); - - if (!known && numFails < firstChoice.size()) { - numFails++; - firstChoice.append(R); - if (detailedClosureDebug) { - fprintf(DebugFile, "\nTry another conjunct, R is not suitable\n"); - R.print_with_subs(DebugFile); - } - continue; - } - - - if (detailedClosureDebug) { - fprintf(DebugFile,"\nR+ is:\n"); - R_plus.print_with_subs(DebugFile); - if (known) { - fprintf(DebugFile, "Known R? is :\n"); - R_star.print_with_subs(DebugFile); - } - else - fprintf(DebugFile, "The R* for this relation is not calculated\n"); - } - - Relation R_z; - if (known) { - R_z=Difference(copy(R_star),copy(R_plus)); - known = R_z.is_upper_bound_satisfiable(); - if (known) { - int d = R.single_conjunct()->query_guaranteed_leading_0s(); - R_z.make_level_carried_to(min(R.n_inp(),d+1)); - if (R_z.query_DNF()->length() > 1) known = false; - if (detailedClosureDebug) { - fprintf(DebugFile, "\nForced R_Z to be level carried at level %d\n",min(R.n_inp(),d+1)); - } - } - if (detailedClosureDebug) { - if (known) { - fprintf(DebugFile, "\nDifference between R? and R+ is:\n"); - R_z.print_with_subs(DebugFile); - } - else - fprintf(DebugFile, "\nR_z is unusable\n"); - } - } - else R_z = Relation::False(r); - - if (!known) - numFails++; - else numFails = 0; - if (!known && numFails <= firstChoice.size()) { - firstChoice.append(R); - if (detailedClosureDebug) { - fprintf(DebugFile, "\nTry another conjunct, Rz is avaiable for R:\n"); - R.print_with_subs(DebugFile); - } - continue; - } - - //make N empty list - Relation N = Relation::False(r); - - //append R+ to T - result = Union(result, copy(R_plus)); - resultConjuncts++; - - int expansion = maxClauses - (resultConjuncts + 2*firstChoice.size() + secondChoice.size()); - if (expansion < 0) expansion = 0; - if (detailedClosureDebug) { - fprintf(DebugFile,"Max clauses = %d\n",maxClauses); - fprintf(DebugFile,"result conjuncts = %d\n",resultConjuncts); - fprintf(DebugFile,"firstChoice's = %d\n",firstChoice.size()); - fprintf(DebugFile,"secondChoice's = %d\n",secondChoice.size()); - fprintf(DebugFile,"Allowed expansion is %d\n",expansion); - } - - bool firstPart=true; - if (!known && expansion == 0) { - if (detailedClosureDebug) { - fprintf(DebugFile,"Expansion = 0, R? unknown, skipping composition\n"); - } - if (!resultInexact && detailedClosureDebug) fprintf(DebugFile,"RESULT BECOMES INEXACT 1\n"); - resultInexact = true; - } - else - for (Simple_List_Iterator<Relation> s(firstChoice); - firstPart? - (s.live()?true: - (s = Simple_List_Iterator<Relation>(secondChoice), - firstPart = false, - s.live())) - :s.live(); - s.next()) { - assert(s.live()); - Relation C=(s.curr()); - if (detailedClosureDebug) { - fprintf(DebugFile, "\nComposing chosen conjunct with C:\n"); - C.print_with_subs(DebugFile); - } - - if (!known) { - if (detailedClosureDebug) { - fprintf(DebugFile, "\nR? is unknown! No debug info here yet\n"); - } - Relation C1=Composition(copy(C), copy(R_plus)); - if (detailedClosureDebug) { - fprintf(DebugFile, "\nGenerating \n"); - C1.print_with_subs(DebugFile); - } - C1.simplify(); - Relation newStuff = - Difference( - Difference(copy(C1),copy(C)), - copy(R_plus)); - newStuff.simplify(); - if (detailedClosureDebug) { - fprintf(DebugFile, "New Stuff:\n"); - newStuff.print_with_subs(DebugFile); - } - bool C1_contains_new_stuff = newStuff.is_upper_bound_satisfiable(); - if (C1_contains_new_stuff) { - if (newStuff.has_single_conjunct()) - C1 = newStuff; - if (expansion) { - N = Union(N,copy(C1)); - expansion--; - } - else { - if (!resultInexact && detailedClosureDebug) fprintf(DebugFile,"RESULT BECOMES INEXACT 2\n"); - resultInexact = true; - break; - } - } - else C1 = Relation::False(C1); - - Relation C2(Composition(copy(R_plus),copy(C))); - if (detailedClosureDebug) { - fprintf(DebugFile, "\nGenerating \n"); - C2.print_with_subs(DebugFile); - } - newStuff = - Difference( - Difference( - Difference(copy(C2),copy(C)), - copy(C1)), - copy(R_plus)); - newStuff.simplify(); - if (detailedClosureDebug) { - fprintf(DebugFile, "New Stuff:\n"); - newStuff.print_with_subs(DebugFile); - } - if (newStuff.is_upper_bound_satisfiable()) { - if (newStuff.has_single_conjunct()) - C2 = newStuff; - if (expansion) { - N = Union(N,copy(C2)); - expansion--; - } - else { - if (!resultInexact && detailedClosureDebug) fprintf(DebugFile,"RESULT BECOMES INEXACT 3\n"); - resultInexact = true; - break; - } - } - else C2 = Relation::False(C2); - - if (C1_contains_new_stuff) { - Relation C3(Composition(copy(R_plus),copy(C1))); - if (detailedClosureDebug) { - fprintf(DebugFile, "\nGenerating \n"); - C3.print_with_subs(DebugFile); - } - newStuff = - Difference( - Difference( - Difference( - Difference(copy(C3),copy(C)), - copy(C1)), - copy(C2)), - copy(R_plus)); - newStuff.simplify(); - if (detailedClosureDebug) { - fprintf(DebugFile, "New Stuff:\n"); - newStuff.print_with_subs(DebugFile); - } - if (newStuff.is_upper_bound_satisfiable()) { - if (newStuff.has_single_conjunct()) - C3 = newStuff; - if (expansion) { - N = Union(N,C3); - expansion--; - } - else { - if (!resultInexact && detailedClosureDebug) fprintf(DebugFile,"RESULT BECOMES INEXACT 4\n"); - resultInexact = true; - break; - } - } - } - - } - else { - Relation C_Rz(Composition(copy(C),copy(R_z))); - if (detailedClosureDebug) { - fprintf(DebugFile, "C o Rz is:\n"); - C_Rz.print_with_subs(DebugFile); - } - - Relation Rz_C_Rz(Composition(copy(R_z),copy(C_Rz))); - if (detailedClosureDebug) { - fprintf(DebugFile, "\nRz o C o Rz is:\n"); - Rz_C_Rz.print_with_subs(DebugFile); - } - - if (Equal(C,Rz_C_Rz)) { -#if defined(TC_STATS) - fprintf(statsfile,"weak test selects C?\n"); -#endif - Relation tmp = Composition(C,copy(R_star)); - tmp.simplify(); - Relation tmp2 = Composition(copy(R_star),copy(tmp)); - tmp2.simplify(); - if (Must_Be_Subset(copy(tmp2),copy(tmp))) - *s = tmp; - else - *s = tmp2; - if (detailedClosureDebug) { - fprintf(DebugFile,"\nC is equal to Rz o C o Rz so R? o C o R? replaces C\n"); - fprintf(DebugFile, "R? o C o R? is:\n"); - (*s).print_with_subs(DebugFile); - } - } - else { -#if defined(TC_STATS) - fprintf(statsfile,"weak test fails\n"); -#endif - if (Equal(C, C_Rz)) { - *s=Composition(copy(C),copy(R_star)); - Relation p(Composition(copy(R_plus), copy(*s))); - p.simplify(); - if (detailedClosureDebug) { - fprintf(DebugFile, "\nC is equal to C o Rz, so C o Rz replaces C\n"); - fprintf (DebugFile, "C o R? is:\n"); - (*s).print_with_subs(DebugFile); - fprintf (DebugFile, "R+ o C o R? is added to list N. It's :\n"); - p.print_with_subs(DebugFile); - } - if (!Is_Obvious_Subset(copy(p),copy(R_plus)) - && !Is_Obvious_Subset(copy(p),copy(C))) { - if (expansion) { - p.simplify(2,2); - expansion--; - } - else { - if (!resultInexact && detailedClosureDebug) fprintf(DebugFile,"RESULT BECOMES INEXACT 5\n"); - resultInexact = true; - break; - } - } - } - else { - Relation Rz_C(Composition(copy(R_z),copy(C))); - - if (Equal(C,Rz_C)) { - *s=Composition(copy(R_star),copy(C)); - Relation Rstar_C_Rplus(Composition(copy(*s),copy(R_plus))); - Rstar_C_Rplus.simplify(); - if (detailedClosureDebug) { - fprintf(DebugFile, "\nC is equal to Rz o C , so R? o C replaces C\n"); - fprintf (DebugFile, "R? o C is:\n"); - (*s).print_with_subs(DebugFile); - fprintf (DebugFile, "R+ o C is added to list N. It's :\n"); - Rstar_C_Rplus.print_with_subs(DebugFile); - } - if (!Is_Obvious_Subset(copy(Rstar_C_Rplus),copy(R_plus)) - && !Is_Obvious_Subset(copy(Rstar_C_Rplus),copy(C))) { - if (expansion) - N = Union(N,Rstar_C_Rplus); - else { - if (!resultInexact && detailedClosureDebug) fprintf(DebugFile,"RESULT BECOMES INEXACT 6\n"); - resultInexact = true; - break; - } - } - } - else { - if (detailedClosureDebug) { - fprintf(DebugFile, "\nHave to handle it the hard way\n"); - } - Relation C1=Composition(copy(C), copy(R_plus)); - C1.simplify(); - if (!Is_Obvious_Subset(copy(C1),copy(R_plus)) - && !Is_Obvious_Subset(copy(C1),copy(C))) { - if (expansion) { - N = Union(N,copy(C1)); - expansion--; - } - else { - if (!resultInexact && detailedClosureDebug) fprintf(DebugFile,"RESULT BECOMES INEXACT 7\n"); - resultInexact = true; - break; - } - } - - Relation C2(Composition(copy(R_plus),copy(C))); - C2.simplify(); - if (!Is_Obvious_Subset(copy(C2),copy(R_plus)) - && !Is_Obvious_Subset(copy(C2),copy(C))) { - if (expansion) { - N = Union(N,C2); - expansion--; - } - else { - if (!resultInexact && detailedClosureDebug) { - fprintf(DebugFile,"RESULT BECOMES INEXACT 8\n"); - fprintf(DebugFile,"Have to discard:\n"); - C2.print_with_subs(DebugFile); - } - resultInexact = true; - break; - } - } - Relation C3(Composition(copy(R_plus),C1)); - C3.simplify(); - if (!Is_Obvious_Subset(copy(C3),copy(R_plus)) && !Is_Obvious_Subset(copy(C3),copy(C))) { - if (expansion) { - N = Union(N,C3); - expansion--; - } - else { - if (!resultInexact && detailedClosureDebug) - fprintf(DebugFile,"RESULT BECOMES INEXACT 9\n"); - resultInexact = true; - break; - } - } - } - } - } - } - } - - //now we processed the first conjunct. - if (detailedClosureDebug) { - N.simplify(2,2); - fprintf(DebugFile, "\nNew conjuncts:\n"); - N.print_with_subs(DebugFile); - } - - N.simplify(2,2); - appendClausesToList(secondChoice,N); - } - - //Did we do all conjuncts? If not, make T be inexact - result.copy_names(r); - - result.simplify(2,2); - - if (!result.is_exact()) { - result = Lower_Bound(result); - resultInexact = true; - } - if (resultInexact) { - Relation test(Composition(copy(result),copy(result))); - test.simplify(2,2); - if (detailedClosureDebug) { - fprintf(DebugFile, "\nResult is:\n"); - result.print_with_subs(DebugFile); - fprintf(DebugFile, "\nResult composed with itself is:\n"); - test.print_with_subs(DebugFile); - } - if (!Must_Be_Subset(test,copy(result))) { - result = Union(result,Intersection(UB, Relation::Unknown(result))); - } - } - -#ifdef TC_STATS - { - Relation rcopy = result; - Relation test2(Composition(copy(rcopy),copy(rcopy))); - test2.simplify(2,2); - test2.remove_disjunction_with_unknown(); - rcopy.remove_disjunction_with_unknown(); - if (detailedClosureDebug) { - fprintf(DebugFile, "\nResult is:\n"); - rcopy.print_with_subs(DebugFile); - fprintf(DebugFile, "\nResult composed with itself is:\n"); - test2.print_with_subs(DebugFile); - } - if (!Must_Be_Subset(test2,copy(rcopy))) { - fprintf(statsfile,"multi TC result is inexact\n"); - } - else - fprintf(statsfile,"TC result is exact%s\n", (resultInexact || !rcopy.is_exact())?" despite perceived inexactness":""); - } -#endif - -#ifdef TC_STATS - } - int totalTime = clock_diff(); - fprintf(statsfile, "input conj: %d output conj: %d #singe conj closures: %d time: %d\n", - in_conj, copy(result).query_DNF()->length(), - singles, - totalTime/TC_RUNS); -#endif - - if (closure_presburger_debug || detailedClosureDebug) { - if (detailedClosureDebug) { - fprintf(DebugFile, "\nThe transitive closure is :\n"); - result.print_with_subs(DebugFile); - } - fprintf(DebugFile, "\n\n] END Transitive closure\n\n"); - } - return result; -} - - -Relation TransitiveClosure(NOT_CONST Relation &input_r, - int maxExpansion, - NOT_CONST Relation & input_IterationSpace) { - Relation r = consume_and_regurgitate(input_r); - Relation IterationSpace = consume_and_regurgitate(input_IterationSpace); - if (r.is_null()) - return r; - if (r.n_out() == 0) - throw std::invalid_argument("transitive closure does not apply to set"); - if (r.n_inp() != r.n_out()) - throw std::invalid_argument("transitive closure must has the same input and output arity"); - - if (closure_presburger_debug) { - fprintf(DebugFile,"\nComputing Transitive closure of:\n"); - r.print_with_subs(DebugFile); - fprintf(DebugFile,"\nIteration space is:\n"); - IterationSpace.print_with_subs(DebugFile); - } - if (!r.is_upper_bound_satisfiable()) { - if (closure_presburger_debug) - fprintf(DebugFile, "]TC : relation is false\n"); - return r; - } - - Relation UB = DeltasToRelation(ConicHull(Project_Sym(Deltas(copy(r)))), - r.n_inp(),r.n_out()); - if (closure_presburger_debug) { - fprintf(DebugFile,"UB is:\n"); - UB.print_with_subs(DebugFile); - } - - Relation conditions = Restrict_Domain(copy(UB),Domain(copy(r))); - conditions.simplify(); - if (closure_presburger_debug) { - fprintf(DebugFile,"Forward reachable is:\n"); - conditions.print_with_subs(DebugFile); - } - conditions = Composition(Inverse(copy(UB)),conditions); - conditions.simplify(); - if (closure_presburger_debug) { - fprintf(DebugFile,"Backward/forward reachable is:\n"); - conditions.print_with_subs(DebugFile); - } - conditions = Range(conditions); - conditions.simplify(); - // conditions = Approximate(conditions); - // conditions.simplify(); - conditions = VennDiagramForm(conditions); - conditions.simplify(); - - if (closure_presburger_debug) { - fprintf(DebugFile,"Condition regions are:\n"); - conditions.print_with_subs(DebugFile); - } - - if (conditions.is_obvious_tautology()) { - return TransitiveClosure0(r, maxExpansion, IterationSpace); - } - else { - Relation answer = Relation::False(r); - answer.copy_names(r); - answer.setup_names(); - - for (DNF_Iterator c(conditions.query_DNF()); c.live(); c.next()) { - Relation tmp = Relation(conditions, c.curr()); - if (closure_presburger_debug) { - fprintf(DebugFile,"\nComputing Transitive closure:\n"); - fprintf(DebugFile,"\nRegion:\n"); - tmp.prefix_print(DebugFile); - } - - Relation tmp3 = Restrict_Domain(copy(r),tmp); - tmp3.simplify(2,2); - if (closure_presburger_debug) { - fprintf(DebugFile,"\nRelation:\n"); - tmp3.prefix_print(DebugFile); - } - - answer = Union(answer, TransitiveClosure0(tmp3, maxExpansion,copy(IterationSpace))); - } - return answer; - } -} - - -/* ********************************* */ -/* Function check if relation */ -/* belong to d-form or */ -/* uniform relaion class */ -/* ********************************* */ - -Relation is_DForm_or_Uniform(NOT_CONST Relation &r){ - - Relation s = consume_and_regurgitate(r); - Relation Rtmp, Rdelta, delta; - - delta = Deltas(copy(s)); - Rdelta = DeltasToRelation(copy(delta), s.n_inp(), s.n_out()); - Rtmp = DeltasToRelation(Project_Sym(delta), s.n_inp(), s.n_out()); - - Rtmp = Restrict_Domain(Rtmp, Domain(copy(Rdelta))); - Rtmp = Restrict_Range(Rtmp, Range(Rdelta)); - - Rdelta = copy(Rtmp); - - Rtmp = Restrict_Domain(Rtmp, Domain(copy(s))); - Rtmp = Restrict_Range(Rtmp, Range(copy(s))); - - if (Must_Be_Subset( copy(Rtmp), copy(s)) && \ - Must_Be_Subset(copy(s), copy(Rtmp))) { - Rtmp = Relation::Null(); - } - else { - Rtmp = Rdelta = Relation::Null(); - } - - return Rdelta; - } - - - - /* ********************************* */ - /* Get a conjunction for */ - /* a given number from set */ - /* of relations */ - /* ********************************* */ - -Relation getConjunctionNr(NOT_CONST Relation &r, int conjNr) { - - Relation s = consume_and_regurgitate(r); - int i = 1; - - for (DNF_Iterator c(s.query_DNF()); c; c++,i++) { - if ( i == conjNr ) { - return Relation(s, c.curr()); - } - } - - return Relation::False(s.n_inp(), s.n_out()); - - } - - -/* ********************************* */ -/* Get a common region for */ -/* a given set of relations */ -/* ********************************* */ - -Relation getCommonRegion( NOT_CONST Relation &r, const long* relTab, const long relCount) { - - Relation s = consume_and_regurgitate(r); - Relation commonRegion, Rcurr; - long i = 0; - - Rcurr = getConjunctionNr( copy(s), relTab[0]); - commonRegion = Union(Domain(copy(Rcurr)), Range(copy(Rcurr))); - - for( i=1; i < relCount; i++ ){ - Rcurr = getConjunctionNr( copy(s), relTab[i]); - commonRegion = Intersection( commonRegion, Union( Domain(copy(Rcurr)), Range(copy(Rcurr))) ); - } - - return commonRegion; - } - - -/* ********************************* */ -/* Get a set of relations */ -/* ********************************* */ - -Relation getRelationsSet( NOT_CONST Relation &r, const long* relTab, const long relCount) { - - Relation s = consume_and_regurgitate(r); - Relation R = Relation::False(s.n_inp(), s.n_out()); - long i = 0; - - for( i=0; i < relCount; i++ ){ - R = Union( R, getConjunctionNr( copy(s), relTab[i]) ); - } - - return R; - } - - -/* ********************************* */ -/* Get a set of relations */ -/* from a common region */ -/* ********************************* */ - -Relation relationsOnCommonRegion( NOT_CONST Relation &r, NOT_CONST Relation ®ion ) { - - Relation set = consume_and_regurgitate(r); - Relation reg = consume_and_regurgitate(region); - Relation R = Relation::True(set.n_inp(), set.n_out()); - - R = Restrict_Domain(R, copy(reg)); - R.simplify(2,1); - R = Restrict_Range(R, reg); - R.simplify(2,1); - - R = Intersection(R, set); - - return R; - - } - - -Relation compose_N(NOT_CONST Relation &input_r) { - Relation r = consume_and_regurgitate(input_r); - Relation powerR, powerR2; - - r = Union(r, Identity(r.n_inp())); - powerR = copy(r); - - for(;;){ - if (powerR.number_of_conjuncts() > 50) { - powerR = Relation::Null(); - return powerR; - } - - powerR2 = Composition(copy(powerR), copy(r)); - powerR2.simplify(2,1); - - if (Must_Be_Subset( copy(powerR2), copy(powerR))) { - powerR2 = Relation::Null(); - return powerR; - } - - powerR = Relation::Null(); - powerR = copy(powerR2); - powerR2 = Relation::Null(); - } -} - - -/****************************** */ -/* Check exactness of R+ */ -/* */ -/* Tomasz Klimek 05-06-2010 */ -/****************************** */ - -bool checkExactness(NOT_CONST Relation &r, NOT_CONST Relation &rplus){ - - -Relation s1 = consume_and_regurgitate(r); -Relation s2 = consume_and_regurgitate(rplus); -Relation R; - -R = Composition(copy(s1), copy(s2)); -R = Union(s1, R); - - if( Must_Be_Subset(copy(s2), copy(R)) && \ - Must_Be_Subset(copy(R), copy(s2))) { - R = Relation::Null(); - s1 = Relation::Null(); - return true; - } - - R = Relation::Null(); - s1 = Relation::Null(); - - return false; - -} - -/************************************** */ -/* Calculate approximation of R* */ -/* */ -/* Tomasz Klimek 05-06-2010 */ -/************************************** */ - - -Relation ApproxClosure(NOT_CONST Relation &r) { - - Relation s = consume_and_regurgitate(r); - Relation R = Relation::False(s.n_inp(), s.n_out()); - Relation tc = Identity(s.n_inp()); - Relation Rtmp; - - - for (DNF_Iterator c(s.query_DNF()); c; c++) { - Rtmp = Hull(Project_Sym(Deltas(Relation(s, c.curr()))), false, 1, Relation::Null()); - R = Union(R, TransitiveClosure(DeltasToRelation(Rtmp,s.n_inp(),s.n_out()), 1, Relation::Null())); - } - - for (DNF_Iterator c(R.query_DNF()); c; c++) { - Rtmp = Union(Identity(s.n_inp()), Relation(R, c.curr())); - tc = Composition(tc, Rtmp); - tc = Hull(tc, false, 1, Relation::Null()); - } - - tc = Restrict_Domain(tc,Domain(copy(s))); - tc.simplify(2,1); - tc = Restrict_Range(tc,Range(s)); - tc.simplify(2,1); - tc = Intersection(tc, Relation::Unknown(tc)); - - return tc; -} - - -/************************************** */ -/* Calculate R* on unbounded region */ -/* */ -/* Tomasz Klimek 05-06-2010 */ -/************************************** */ - -Relation ClosureOnUnboundedRegion(NOT_CONST Relation &r) { - - Relation s = consume_and_regurgitate(r); - Relation R = Relation::False(s.n_inp(), s.n_out()); - Relation tc = Identity(s.n_inp()); - Relation Rtmp,tcTmp; - - for (DNF_Iterator c(s.query_DNF()); c; c++) { - Rtmp = is_DForm_or_Uniform(Relation(s, c.curr())); - - if (!(Rtmp.is_null())) { - tcTmp = TransitiveClosure(Rtmp, 1, Relation::Null()); - - if (!(tcTmp.is_exact())){ - tcTmp = R = Relation::Null(); - /* fprintf(DebugFile,"\nTC is inexact!"); */ - return tcTmp; - } - } - else { - R = Relation::Null(); - /* fprintf(DebugFile,"\nR is not d-form relation!"); */ - return Relation::Null(); - } - - R = Union(R, tcTmp); - } - - for (DNF_Iterator c(R.query_DNF()); c; c++) { - Rtmp = Union(Identity(s.n_inp()), Relation(R, c.curr())); - tc = Composition(tc, Rtmp); - tc.simplify(2,1); - } - - tc = Difference(tc, Identity(s.n_inp())); - - return tc; - -} - - - - -/******************************* */ -/* Try to select sets of domain */ -/* and range */ -/* */ -/* Tomasz Klimek 05-06-2010 */ -/******************************* */ - -Relation SelectRegionForClosure(NOT_CONST Relation &r){ - - Relation s = consume_and_regurgitate(r); - Relation DR = Union(Domain(copy(s)),Range(copy(s))); - Relation region,tc,tcTmp; - - region = SimpleHull(copy(DR)); - region.simplify(2,1); - - tc = ClosureOnUnboundedRegion(copy(s)); - - if (tc.is_null()) { - return tc; - } - - tcTmp = Restrict_Domain(copy(tc),copy(region)); - tcTmp.simplify(2,1); - tcTmp = Restrict_Range(tcTmp,region); - tcTmp.simplify(2,1); - - if (checkExactness(copy(s), copy(tcTmp))) { - s = tc = Relation::Null(); - return tcTmp; - } - - tcTmp = Relation::Null(); - region = Hull(DR,false,1,Relation::Null()); - - tcTmp = Restrict_Domain(copy(tc),copy(region)); - tcTmp.simplify(2,1); - tcTmp = Restrict_Range(tcTmp,region); - tcTmp.simplify(2,1); - - if (checkExactness(copy(s), copy(tcTmp))) { - s = tc = Relation::Null(); - return tcTmp; - } - - tcTmp = Relation::Null(); - - tc = Restrict_Domain(tc,Domain(copy(s))); - tc.simplify(2,1); - tc = Restrict_Range(tc,Domain(copy(s))); - tc.simplify(2,1); - - if (checkExactness(copy(s), copy(tc))) { - s = Relation::Null(); - return tc; - } - - tc = Relation::Null(); - - return ApproxClosure(s); - -} - - - - -/************************************** */ -/* Calculate R* */ -/* */ -/* Tomasz Klimek 05-06-2010 */ -/************************************** */ - -Relation calculateTransitiveClosure(NOT_CONST Relation &r) { - - Relation s = consume_and_regurgitate(r); - Relation tc = Relation::False(s.n_inp(), s.n_out()); - long* relationsSet = NULL; - Relation commonRegion, regionTmp; - Relation inputRelations; - long i,j=-1; - long N,M; - Relation R; - - - commonRegion = SelectRegionForClosure(copy(s)); - - if (commonRegion.is_null()) { - return ApproxClosure(s); - } - - if (commonRegion.is_exact()) { - return commonRegion; - } - - commonRegion = Relation::Null(); - N = M = s.number_of_conjuncts(); - relationsSet = (long*)calloc(N,sizeof(long)); - - if (relationsSet == NULL) { - return Relation::False(s.n_inp(), s.n_out()); - } - - for (; N > 1;) { - for ( i=0; i<N; i++ ) { - if ( i < j ) { - continue; - } - else if ( j == -1 ) { - relationsSet[i] = 1; - } - else if ( i > j ) { - relationsSet[i] = relationsSet[i-1] + 1; - } - else if ( i == j ) { - relationsSet[i] += 1; - } - if ( relationsSet[i] <= M ) { - j = i; - } - else { - j = i - 1; - break; - } - } - - if ( j+1 == N) { - /* fprintf(DebugFile,"\n"); - for(i=0;i<N;i++){ - fprintf(DebugFile," %ld", relationsSet[i]); - } - fprintf(DebugFile,"\n"); */ - - commonRegion = getCommonRegion( copy(s), relationsSet, N); - commonRegion.simplify(2,1); - inputRelations = getRelationsSet( copy(s), relationsSet, N); - inputRelations.simplify(2,1); - - /* ******************* */ - /* Check on rectangle */ - /* ******************* */ - regionTmp = SimpleHull(copy(commonRegion)); - regionTmp.simplify(2,1); - R = relationsOnCommonRegion( copy(inputRelations), regionTmp); - R.simplify(2,1); - regionTmp = SelectRegionForClosure(R); - - if (regionTmp.is_exact()) { - /* fprintf(DebugFile,"\nDescribed on rectangle region\n"); */ - tc = Union( tc, regionTmp ); - } - else { - /* ******************* */ - /* Check on hull */ - /* ******************* */ - - R = Relation::Null(); - regionTmp = Relation::Null(); - regionTmp = Hull(copy(commonRegion),false,1,Relation::Null()); - regionTmp.simplify(2,1); - R = relationsOnCommonRegion( copy(inputRelations), regionTmp); - R.simplify(2,1); - regionTmp = SelectRegionForClosure(R); - - if (regionTmp.is_exact()) { - /* fprintf(DebugFile,"\nDescribed on Hull\n"); */ - tc = Union( tc, regionTmp); - } - else { - /* ********************************** */ - /* Check on sets of domain and range */ - /* ********************************** */ - - R = Relation::Null(); - regionTmp = Relation::Null(); - R = relationsOnCommonRegion( copy(inputRelations), copy(commonRegion) ); - R.simplify(2,1); - regionTmp = SelectRegionForClosure(R); - - if (regionTmp.is_exact()) { - /* fprintf(DebugFile,"\nDescribed on sets of doamin and range\n"); */ - tc = Union( tc, regionTmp ); - } - else { - commonRegion = Relation::Null(); - inputRelations = Relation::Null(); - regionTmp = Relation::Null(); - R = Relation::Null(); - - return ApproxClosure(s); - } - } - } - - commonRegion = Relation::Null(); - inputRelations = Relation::Null(); - - regionTmp = Relation::Null(); - R = Relation::Null(); - } - - if ( j == -1 ) N--; - - } - - R = Relation::Null(); - - for (DNF_Iterator c(s.query_DNF()); c; c++) { - if (!Must_Be_Subset(Relation(s, c.curr()), copy(tc))) { - /* fprintf(DebugFile,"\nIs not a subset\n"); */ - tc = Union( tc, SelectRegionForClosure(Relation(s, c.curr()))); - } - } - - if (!(tc.is_exact())){ - return ApproxClosure(s); - } - - tc = compose_N(tc); - - if (tc.is_null()) { - return ApproxClosure(s); - } - - return tc; - -} - - - - - -} // namespace |