solver/BooleanAbstractor.h
00001 /*
00002  * BooleanAbstractor.h
00003  *
00004  *  Created on: Jul 25, 2009
00005  *      Author: tdillig
00006  */
00007 
00008 #ifndef BOOLEANABSTRACTOR_H_
00009 #define BOOLEANABSTRACTOR_H_
00010 
00011 #include <map>
00012 using namespace std;
00013 
00014 
00015 class CNode;
00016 class Leaf;
00017 class BooleanVar;
00018 
00019 
00020 #include "CNF.h"
00021 #include "SatSolver.h"
00022 #include "Term.h"
00023 
00024 
00025 /*
00026  * Constructs the boolean skeleton of the given SMT formula to be fed to
00027  * the SAT solver.
00028  */
00029 
00030 class BooleanAbstractor {
00031 
00032 private:
00033 
00034         CNode* original;
00035 
00036         enum edge_op
00037         {
00038                 EDGEOP_NOOP = 0,
00039                 EDGEOP_EQ = 1,
00040                 EDGEOP_NEQ = 2,
00041                 EDGEOP_LT = 4,
00042                 EDGEOP_LEQ = 8
00043         };
00044 
00045         struct edge;
00046         struct node;
00047 
00048         struct node
00049         {
00050                 Term* t;
00051                 set<edge*> outgoing_edges;
00052                 set<edge*> incoming_edges;
00053 
00054                 node(Term* t)
00055                 {
00056                         this->t = t;
00057                 }
00058 
00059                 string to_string()
00060                 {
00061                         return t->to_string();
00062                 }
00063         };
00064 
00065         struct edge
00066         {
00067                 node* source;
00068                 node* target;
00069                 edge_op op;
00070 
00071                 edge(node* source, node* target, edge_op op)
00072                 {
00073                         this->source = source;
00074                         this->target = target;
00075                         this->op = op;
00076                         source->outgoing_edges.insert(this);
00077                         target->incoming_edges.insert(this);
00078                 }
00079 
00080                 string to_string()
00081                 {
00082                         return source->t->to_string() + " -> " + target->t->to_string();
00083 
00084                 }
00085 
00086                 string to_string(edge_op op)
00087                 {
00088                         string op_string = "";
00089                         if(op == EDGEOP_LT) op_string = "<";
00090                         else if(op == EDGEOP_LEQ) op_string = "<=";
00091                         else if(op == EDGEOP_EQ) op_string = "=";
00092                         else op_string = "!=";
00093                         return source->t->to_string() + op_string + target->t->to_string();
00094 
00095                 }
00096 
00097                 ~edge()
00098                 {
00099                         source->outgoing_edges.erase(this);
00100                         target->incoming_edges.erase(this);
00101                 }
00102 
00103         };
00104 
00105         map<Term*, node*> term_to_node_map;
00106 
00107         /*
00108          * A node is a frontier node if either a) it has no outgoing edge
00109          * or b) it has no incoming edges or c)it has one incoming and one
00110          * outgoing edge from/to the same node.
00111          */
00112         set<node*> frontier_nodes;
00113 
00114         /*
00115          * A representation of simple equality and inequality (=, <, <=, !=)
00116          * relations between pairs of terms.
00117          */
00118         set<edge*> relation_graph;
00119 
00120         /*edge_op
00121          * We collect all used constants in order to add
00122          * disequality edges between them.
00123          */
00124         set<Term*> used_constants;
00125         map<pair<node*, node*>, edge*> edge_matrix;
00126 
00127         /*
00128          * The set of all literals used in the formula.
00129          */
00130         set<CNode*> literals;
00131 
00132         /*
00133          * The set of relevant implications we should add to the boolean abstraction.
00134          */
00135         set<CNode*> valid_implications;
00136 
00137         /*
00138          * All learned implications
00139          */
00140         CNode* learned;
00141 
00142 
00143         int max_implications;
00144 
00145 
00146 public:
00147         BooleanAbstractor(CNode* node);
00148         CNode* get_learned_implications();
00149         ~BooleanAbstractor();
00150 
00151 private:
00152         node* get_node_from_term(Term* t);
00153         void build_relation_graph();
00154         void add_edge(Term* source, Term* target, edge_op op,
00155                         bool add_used_constant = true);
00156         void add_edge(node* source, node* target, edge_op op,
00157                         set<edge*>* added_edges = NULL);
00158         string relation_graph_to_dotty();
00159 
00160         bool is_frontier_node(node* n);
00161         bool is_frontier_node(node* n, set<edge*> & processed_edges);
00162 
00163         void add_initial_frontier_nodes();
00164 
00165         /*
00166          * By basic implications, we mean implications of the form
00167          * a > b-> a>=b, a>b->a!=b etc. If L1 and L2 are literals present in
00168          * the original formula and there is an implication relation between
00169          * them, then we add this implication to the formula.
00170          */
00171         void add_basic_implications();
00172 
00173         /*
00174          * Adds constraints of the form
00175          * x=1 -> x!=2 & x<= 3 & x<4.... etc.
00176          * if these literals exist in the
00177          * formula.
00178          */
00179         void add_constant_relations();
00180 
00181         /*
00182          * Adds the implication prec -> concl if either the conclusion
00183          * or its negation is present in the set of literals present in the
00184          * original formula.
00185          */
00186         void add_implication(CNode* prec, CNode* concl);
00187 
00188 
00189 
00190         /*
00191          * Makes the relation graph chordal so the number of cycles we have
00192          * to consider is cubic rather than exponential in the number of nodes.
00193          */
00194         void make_chordal();
00195 
00196         /*
00197          * Adds an edge between the source of in and the target of out
00198          * and adds the new edge to the set of processed edges.
00199          */
00200         void wire_edge(edge* in, edge* out, set<edge*>& processed_edges);
00201 
00202         /*
00203          * Given the chordal relation graph, this function adds all
00204          * relevant implications.
00205          */
00206         void add_implications();
00207 
00208         /*
00209          * Is there any edge between n1 and n2, disregarding direction of the edges?
00210          */
00211         inline bool edge_between(node* n1, node* n2);
00212 
00213 
00214         /*
00215          * Given a op1 b and b op2 c, can we deduce a < c?
00216          */
00217         bool deduce_lt(edge_op op1, edge_op op2);
00218 
00219         /*
00220          * Given a op1 b and b op2 c, can we deduce a <= c?
00221          */
00222         bool deduce_leq(edge_op op1, edge_op op2);
00223 
00224         /*
00225          * Given a op1 b and b op2 c, can we deduce a = c?
00226          */
00227         bool deduce_eq(edge_op op1, edge_op op2);
00228 
00229         /*
00230          * Given op1 and op2, can we deduce the op called ded_op?
00231          * e.g. > and = can deduce > and >=.
00232          */
00233         bool deduce_op(edge_op op1, edge_op op2, edge_op ded_op);
00234 
00235         /*
00236          * Is the given deduction relevant?
00237          */
00238         bool is_relevant_deduction(node* source, node* target, edge_op op);
00239 
00240         /*
00241          * Adds the implication e1 & e2 -> deduction.
00242          */
00243         void add_implication(edge* e1, edge* e2, CNode* deduction, edge_op op);
00244 
00245         /*
00246          * Gives the literal representation of this edge.
00247          */
00248         CNode* edge_to_literal(edge* e, edge_op op);
00249 
00250 };
00251 
00252 #endif /* BOOLEANABSTRACTOR_H_ */