ConstraintSolver.h
00001 /*
00002  * ConstraintSolver.h
00003  *
00004  *  Created on: Sep 16, 2008
00005  *      Author: tdillig
00006  */
00007 
00008 #ifndef CONSTRAINTSOLVER_H_
00009 #define CONSTRAINTSOLVER_H_
00010 
00011 
00012 #include "CNode.h"
00013 #include <map>
00014 #include <set>
00015 #include <vector>
00016 
00017 
00018 enum atom_op_type
00019 {
00020         ATOM_EQ,
00021         ATOM_NEQ,
00022         ATOM_LEQ,
00023         ATOM_LT,
00024         ATOM_GT,
00025         ATOM_GEQ,
00026         ATOM_MOD
00027 };
00028 
00029 using namespace std;
00030 
00031 typedef pair<CNode*, CNode*> constraint_type;
00032 typedef int c_id;
00033 
00034 class VariableTerm;
00035 
00036 
00037 using namespace __gnu_cxx;
00038 
00039 struct cnode_eq
00040 {
00041   bool operator()(const CNode *const l1, const CNode*const l2) const
00042   {
00043     return *(CNode*)l1==*(CNode*)l2;
00044   }
00045 };
00046 
00047 struct fun_bg
00048 {
00049         CNode* key;
00050         Term* quantified_var;
00051         CNode* nc_val;
00052         CNode* sc_val;
00053 };
00054 
00055 class AccessPath;
00056 class IndexVarManager;
00057 class Constraint;
00058 class FunctionTerm;
00059 
00060 
00061 class ConstraintSolver {
00062         friend class Constraint;
00063         friend class Term;
00064 private:
00065         map<c_id, constraint_type> constraints;
00066         map<constraint_type, c_id > reverse_constraints;
00067         int id_count;
00068 
00069 
00070         bool bg_false;
00071 
00072         /*
00073          * General background constraint, such as the constraint under which
00074          * this function continues executing or the constraint under which
00075          * loop terminates and so on.
00076          */
00077         CNode *general_background;
00078 
00079         /*
00080          * A mapping from literals L introduced as placeholders
00081          * for imprecise constraints to an (NC, SC) pair
00082          * such that L => NC and SC => L
00083          * L is either of the form d=c, d>=c, or d(i)=c,
00084          * and d(i)>c. If L constaints a function term d,
00085          * then the meaning of this background constraint
00086          * is really a universally quantified axiom, i.e.,
00087          * Ai. SC(i) => L(i) => NC(i).
00088          */
00089         map<CNode*, pair<CNode*, CNode*> > background;
00090 
00091         /*
00092          * A mapping from from function terms to their
00093          * universally quantified arguments.
00094          */
00095         map<int, Term*> fn_to_qvars;
00096         set<int> fn_ids;
00097 
00098 
00099         map<CNode*, CNode*> nc_reps;
00100         map<CNode*, CNode*> sc_reps;
00101 
00102         /*
00103          * The set of keys in the background_map
00104          */
00105         set<CNode*> bg_keys;
00106 
00107 
00108         vector<pair<int, string> > hardest;
00109 
00110         vector<pair<int, string> > hardest_eliminate_overapproximate;
00111 
00112         vector<pair<int, string> > hardest_eliminate_underapproximate;
00113 
00114         bool bg_enabled;
00115 
00116 
00117 
00118 
00119 public:
00120         ConstraintSolver();
00121         virtual ~ConstraintSolver();
00122         void clear();
00123         void clear_local_data();
00124         void clear_stats();
00125 
00126         int num_sat_queries;
00127         int num_bg_queries;
00128         int solve_time;
00129 
00130         int eq_time;
00131         int num_eqs;
00132 
00133         int bg_simp_time;
00134 
00135 
00136         int num_eliminate_over_queries;
00137         int num_eliminate_under_queries;
00138         int eliminate_over_time;
00139         int eliminate_under_time;
00140 
00141 
00142 
00143         string stats_to_string();
00144 
00145 
00146 private:
00147         c_id get_true_constraint();
00148         c_id get_false_constraint();
00149         c_id get_atom(Term* t1, Term* t2, atom_op_type op);
00150         c_id get_constraint_from_cnode(CNode* n);
00151         c_id get_constraint_from_string(string & s);
00152 
00153         c_id nc(c_id id);
00154         c_id sc(c_id id);
00155         CNode* get_nc(c_id& id);
00156         CNode* get_sc(c_id& id);
00157 
00158         bool is_sat(c_id & id);
00159         bool is_sat_discard(c_id & id);
00160 
00161         inline CNode* is_sat(CNode* node,
00162                         simplification_level level, bool use_nc,
00163                         void* assignments = NULL);
00164 
00165         inline CNode* is_sat(CNode* node, CNode* assumption,
00166                         simplification_level level, bool use_nc,
00167                         void* assignments = NULL);
00168 
00169         bool is_valid(c_id id);
00170         bool is_valid_discard(c_id id);
00171         inline CNode* is_valid(CNode* node, simplification_level level);
00172         bool implies(c_id c1, c_id c2);
00173 
00174         c_id and_constraint(c_id id1, c_id id2);
00175         c_id or_constraint(c_id id1, c_id id2);
00176         c_id not_constraint(c_id id);
00177         c_id make_ncsc(c_id nc, c_id sc);
00178 
00179         void clear_bg();
00180 
00181         string constraint_to_string(c_id id);
00182 
00183         /*
00184          * is nc1==nc2 && sc1 == sc2 ?
00185          */
00186         bool is_equal(c_id id1, c_id id2);
00187 
00188         /*
00189          * does c1=>c2 && c2 >= c1 ?
00190          */
00191         bool is_equivalent(c_id id1, c_id id2);
00192         bool is_precise(c_id id) const;
00193 
00194         bool implies(CNode* n1, CNode* n2);
00195 
00196         c_id get_id(constraint_type& c);
00197 
00198 
00199         void get_free_vars(c_id id, set<Term*>& vars);
00200 
00201         void get_terms(c_id id, set<Term*>& terms, bool include_nested_terms);
00202 
00203 
00204 
00205         /*
00206          * Functions for eliminating existentially quantified variables.
00207          */
00208         c_id eliminate_evar(c_id id, VariableTerm* var);
00209         c_id eliminate_evars(c_id id, set<VariableTerm*>& vars);
00210 
00211         /*
00212          * Functions for eliminating universally quantified variables.
00213          */
00214         c_id eliminate_uvar(c_id id, VariableTerm* var);
00215         c_id eliminate_uvars(c_id id, set<VariableTerm*>& vars);
00216 
00217         c_id divide(c_id id, long int c, Term* t);
00218 
00219 
00220         /*
00221          * Functions for eliminating free variables
00222          */
00223         c_id eliminate_free_var(c_id id, VariableTerm* var);
00224         c_id eliminate_free_vars(c_id id, set<VariableTerm*>& vars);
00225         CNode* eliminate_free_var_nc(CNode* nc, VariableTerm* v);
00226         CNode* eliminate_free_var_sc(CNode* sc, VariableTerm* v);
00227 
00228 
00229         bool get_assignment(c_id it, set<pair<string, string> > & assignments);
00230 
00231         bool get_assignment(c_id it, map<Term*, SatValue> & assignments);
00232 
00233 
00234         bool contains_inequality(c_id id);
00235 
00236 
00237 
00238 
00239         Term* find_equality(c_id id, Term* t);
00240 
00241         void find_equalities(c_id id, Term* t, set<Term*> & eqs);
00242 
00243         c_id replace_constraint(c_id old_id, c_id to_replace, c_id replacement);
00244 
00245 
00246         /*
00247          * Determines if t1 and t2 have a linear equality relation.
00248          */
00249         bool has_equality_relation(c_id id, Term* t1, Term* t2);
00250 
00251 
00252         void get_disjunctive_equalities(c_id id, Term* var,
00253                         map<Term*, Constraint> & equalities);
00254 
00255 
00256         c_id replace_term(c_id old_id, Term* to_replace, Term*
00257                         replacement);
00258         c_id replace_terms(c_id old_id, map<Term*, Term*>& replacements);
00259 
00260         c_id replace_terms(c_id old_id, Term* (*sub_func)(Term* t, void* data),
00261                         void* my_data)
00262         {
00263                 constraint_type ct = constraints[old_id];
00264                 CNode* nc= ct.first;
00265                 CNode* sc = ct.second;
00266                 CNode* new_nc = nc->substitute(sub_func, my_data);
00267                 if(nc == sc) {
00268                         if(nc == new_nc) return old_id;
00269                         constraint_type ct(new_nc, new_nc);
00270                         return get_id(ct);
00271                 }
00272 
00273                 CNode* new_sc = sc->substitute(sub_func, my_data);
00274                 ct = constraint_type(new_nc, new_sc);
00275                 return get_id(ct);
00276         }
00277 
00278         bool contains_term(c_id id, Term* t);
00279         bool contains_term(c_id id, set<Term*>& terms);
00280 
00281         c_id replace_constraints(c_id old_id, map<Constraint, Constraint>& replacements);
00282 
00283         //c_id increment_index(c_id old_id, AccessPath* base, AccessPath* delta);
00284 
00285 
00286 
00287         /*
00288          * key_id => value_id
00289          * Note that if key_id contains a function term f(i), then this is
00290          * a univerally quantified axiom of the form Ai. key(i) => value_id(i)
00291          * If a formula contains any instantiation of key(i), we need to
00292          * conjoin all relevant instantiations of value(i).
00293          */
00294         void add_axiom(c_id key_id, c_id value_id, bool check_function_term);
00295 
00296 
00297         void replace_term_in_axioms(Term* old_t, Term* new_t);
00298 
00299         /*
00300          * For any SAT query, the constraint identified
00301          * by id should be taken into account.
00302          */
00303         void set_background_knowledge(c_id id);
00304 
00305 
00306 
00307 
00308         CNode* eliminate_var(CNode* n, VariableTerm* var,
00309                         simplification_level level, bool over);
00310 
00311         CNode* eliminate_var(CNode* n, vector<VariableTerm*> & vars,
00312                         simplification_level level, bool over);
00313 
00314         void add_to_hardest(vector<pair<int, string> > & hardest, int time,
00315                         const string& cur);
00316 
00317         string get_hardest(vector<pair<int, string> > & hardest);
00318 
00319         c_id assume(c_id id, c_id other);
00320 
00321         string bg_to_string();
00322         c_id get_general_background();
00323 
00324         int nc_size(c_id id);
00325         int sc_size(c_id id);
00326 
00327         c_id propagate_background(c_id id);
00328 
00329         /*
00330          * If background is disabled, sat and validity queries do not
00331          * take background axioms into account.
00332          */
00333         void disable_background();
00334 
00335         int msa(set<VariableTerm*> & msa, c_id id, map<VariableTerm*, int>& costs);
00336         int msa(set<VariableTerm*> & msa, c_id id, set<c_id>& bg,
00337                         map<VariableTerm*, int>& costs);
00338 
00339         pair<CNode*, CNode*> get_cnodes(c_id id);
00340 
00341 private:
00342 
00343         bool is_mod_term(Term* t);
00344 
00345         // Valid mod term for us means its second operand is a constant
00346         bool is_valid_mod_term(Term* t);
00347 
00348         /*
00349          * If some  literal such as d=1 implies a formula containing
00350          * a key in the bg_keys set, then this function also adds
00351          * additional dependencies. For example, if d=1 -> d2=2 & flag and
00352          *  d2=2 -> x=5, then include_background_dependencies(d2=2 & flag)
00353          *  yields d2=2 & flag & d2=2->x=5.
00354          */
00355         CNode* include_background_dependencies(CNode* bg_value, bool use_nc = true);
00356 
00357         /*
00358          * Like the one above, but only returns the dependencies without
00359          * including the node.
00360          */
00361         CNode* get_background_dependencies(CNode* node, bool use_nc = true);
00362 
00363         void get_relevant_axioms(CNode* constraint, set<CNode*>& relevant_axioms);
00364 
00365         /*
00366          * Adds the axioms sc => key => nc to the background.
00367          */
00368         void add_background(CNode* key, CNode* nc, CNode* sc);
00369 
00370         /*
00371          * Updates the nc_reps and sc_reps maps which store
00372          * nc and sc without their dependencies expanded.
00373          */
00374         void add_to_rep_map(CNode* key, CNode* nc, CNode* sc);
00375 
00376         CNode* simplify(CNode* c);
00377 
00378         /*
00379          * Given a map from d(i) to its NC(i) or SC(i), returns (by reference)
00380          * another map that contains the relevant instantiations of this map
00381          * according to terms used in c.
00382          */
00383         void instantiate_axioms(CNode* c, map<CNode*, CNode*>& axioms,
00384                         map<CNode*, CNode*> & instantiated_axioms);
00385 
00386 
00387         c_id get_new_id(c_id old_id);
00388 
00389 
00390         void to_dnf(c_id c, set<c_id> & dnf);
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 };
00400 
00401 #endif /* CONSTRAINTSOLVER_H_ */