term/Term.h
00001 /*
00002  * Term.h
00003  *
00004  *  Created on: Sep 1, 2008
00005  *      Author: tdillig
00006  */
00007 
00008 #ifndef TERM_H_
00009 #define TERM_H_
00010 
00011 #include <string>
00012 #include "VarMap.h"
00013 #include <iostream>
00014 #include <unordered_map>
00015 #include <unordered_set>
00016 #include "Leaf.h"
00017 #include "Term.h"
00018 #include "util.h"
00019 #include "term-shared.h"
00020 
00021 #include <boost/serialization/list.hpp>
00022 #include <boost/serialization/string.hpp>
00023 #include <boost/serialization/version.hpp>
00024 #include <boost/serialization/split_member.hpp>
00025 #include <boost/serialization/shared_ptr.hpp>
00026 #include <boost/serialization/base_object.hpp>
00027 #include <boost/serialization/export.hpp>
00028 #include <sstream>
00029 
00030 using namespace std;
00031 enum term_type{
00032         CONSTANT_TERM,
00033         VARIABLE_TERM,
00034         FUNCTION_TERM,
00035         ARITHMETIC_TERM
00036 };
00037 
00038 class Term;
00039 class Constraint;
00040 
00041 namespace std {
00042 
00043 template <>
00044 struct hash<Term*> {
00045         size_t operator() (const Term* const & x) const;
00046 };
00047 
00048 struct term_eq
00049 {
00050   bool operator()(const Term* l1, const Term* l2) const;
00051 };
00052 
00053 }
00054 using namespace __gnu_cxx;
00055 
00056 static set<Term*> delete_terms;
00057 
00058 enum term_attribute_type
00059 {
00060         TERM_ATTRIB_NO_ATTRIB,
00061         TERM_ATTRIB_GEQZ, // >=0
00062         TERM_ATTRIB_GTZ // >0
00063 };
00064 
00065 /*
00066  * Abstract class that represents constant, variable or
00067  * function terms. All terms must be shared through the
00068  * get_term(t) function in LeafMap.h
00069  */
00070 class Term {
00071         friend class boost::serialization::access;
00072         friend class CNode;
00073 protected:
00074 public:
00075         size_t hash_c;
00076         term_type type;
00077 
00078         /*
00079          * A restriction on the values a term can have.
00080          * For instance, for a term t associated with an unsigned program variable,
00081          * there would be t >= 0 attribute.
00082          */
00083         term_attribute_type attribute;
00084 
00085         /*
00086          * This is zero if this term is not extended by a subclass.
00087          */
00088         int specialization_type;
00089         static unordered_set<Term*, std::hash<Term*>, term_eq> terms;
00090 
00091 
00092         template<class Archive>
00093         void save(Archive & ar, const unsigned int version) const
00094         {
00095 
00096                 ar & type;
00097                 ar & specialization_type;
00098                 ar & attribute;
00099 
00100 
00101         }
00102         template<class Archive>
00103         void load(Archive & ar, const unsigned int version)
00104         {
00105                 ar & type;
00106                 ar & specialization_type;
00107                 ar & attribute;
00108                 hash_c = 0;
00109 
00110 
00111         }
00112         BOOST_SERIALIZATION_SPLIT_MEMBER()
00113 
00114 
00115 protected:
00116         inline Term()
00117         {
00118                 representative = NULL;
00119                 this->attribute = TERM_ATTRIB_NO_ATTRIB;
00120                 this->specialization_type = 0;
00121 
00122         }
00123 public:
00124         static Term* get_term(Term* t);
00125         static set<Term*> to_delete;
00126         static Term* get_term_nodelete(Term* t);
00127 
00128 
00129         static Term* uniquify_term(Term* t);
00130 
00131 protected:
00132         static void clear();
00133 public:
00134 
00135         static void delete_loaded_terms();
00136 
00137         virtual bool operator==(const Term& other) = 0;
00138         virtual string to_string()=0;
00139         inline term_type get_term_type()
00140         {
00141                 return type;
00142         }
00143         inline bool is_specialized()
00144         {
00145                 return this->specialization_type != 0;
00146         }
00147 
00148         inline int get_specialization()
00149         {
00150                 return specialization_type;
00151         }
00152         inline term_attribute_type get_attribute()
00153         {
00154                 return attribute;
00155         }
00156         inline string get_attribute_string()
00157         {
00158                 if(attribute == TERM_ATTRIB_NO_ATTRIB) return "";
00159                 else if(attribute == TERM_ATTRIB_GEQZ) return to_string() + ">= 0";
00160                 else if(attribute == TERM_ATTRIB_GTZ) return to_string() + "> 0";
00161                 else assert(false);
00162 
00163 
00164         }
00165 
00166         /*
00167          * Returns the attributes on this terms as well
00168          * as on any nested subterms.
00169          */
00170         void get_attributes(set<CNode*> & attributes);
00171 
00172         void set_attribute(term_attribute_type ta);
00173 
00174         virtual ~Term();
00175         inline size_t hash_code()
00176         {
00177                 return hash_c;
00178         }
00179         /*
00180          * Returns ids of all vars nested inside this term
00181          */
00182         void get_nested_vars(set<int>& vars);
00183         void get_nested_terms(set<Term*>& terms, bool include_function_subterms = true,
00184                         bool include_constants = true);
00185         virtual Term* substitute(map<Term*, Term*>& subs) = 0;
00186 
00187         Term* substitute(Term* (*sub_func)(Term* t));
00188 
00189         virtual Term* substitute(Term* (*sub_func)(Term* t, void* data), void* my_data);
00190 
00191         /*
00192          * Clears all the (nested) representative fields used for Fast Union Find.
00193          */
00194         void clear_representatives();
00195 
00196         /*
00197          * Returns any nested old_terms with new_term.
00198          */
00199         Term* replace_term(Term* old_term, Term* new_term);
00200 
00201         /*
00202          * Returns the set of variable names used in this term.
00203          */
00204         void get_vars(set<string>& vars);
00205         void get_vars(set<int>& vars);
00206         void get_vars(set<Term*>& vars);
00207 
00208         bool contains_term(Term* t);
00209         bool contains_term(set<Term*>& terms);
00210         bool contains_var(int var_id);
00211 
00212         void get_all_fun_ids(set<int> & ids);
00213 
00214         void get_all_arguments(int fun_id, int arg_num, set<Term*> & args);
00215         void get_all_first_arguments(set<int>& fn_ids, map<int, set<Term*> >&
00216                         fn_id_to_first_arg);
00217 
00218         Term* replace_argument(int fun_id, int arg_num, Term* replacement);
00219 
00220         Term* replace_first_argument(map<int, Term*>&  fun_id_to_replacements);
00221 
00222 
00223         /*
00224          * Does this term and the other term share any subterms?
00225          */
00226         bool shares_subterms(Term* other);
00227 
00228         /*
00229          * Does this term contains any nested variable terms?
00230          */
00231         bool contains_var();
00232 
00233         /*
00234          * Returns a term where all occurences of old_var_id are
00235          * replaced by new_var_id.
00236          */
00237         Term* rename_variable(int old_var_id, int new_var_id);
00238         Term* rename_variables(map<int, int>& replacements);
00239 
00240         /*
00241          * Flips the sign of this term -> x becomes -x etc.
00242          */
00243         Term* flip_sign();
00244 
00245         /*
00246          * Multiplies the term by the specified constant
00247          */
00248         Term* multiply(long int factor);
00249 
00250         Term* add(long int constant);
00251         Term* add(Term* t);
00252         Term* subtract(Term* t);
00253 
00254         Term* evalute_term(map<Term*, SatValue>& assignments);
00255 
00256         Term* multiply(Term* t);
00257 
00258 
00259 
00260 
00261 
00262 public:
00263         Term* representative;
00264 
00265 };
00266 
00267 
00268 
00269 #endif /* TERM_H_ */