Merge quantifiers2-trunk:
authorFrançois Bobot <francois@bobot.eu>
Fri, 27 Jul 2012 13:36:32 +0000 (13:36 +0000)
committerFrançois Bobot <francois@bobot.eu>
Fri, 27 Jul 2012 13:36:32 +0000 (13:36 +0000)
   - new syntax for rewrite rules
   - better rewrite rules theory
   - remove the rewriting with rewrite rules during ppRewrite temporarily
   - theory can define their own candidate generator
   - define a general candidate generator (inefficient ask to every theory)
   - split inst_match between the pattern matching used for quantifiers (inst_match.*) and
     the one used for rewrite rules (rr_inst_match.*):
      - the pattern matching is less exhaustive for quantifiers,
      - the one for rewrite rules can use efficient-e-matching.

69 files changed:
src/context/cdo.h
src/context/cdqueue.h
src/expr/command.cpp
src/expr/command.h
src/expr/node.h
src/parser/smt2/Smt2.g
src/printer/smt2/smt2_printer.cpp
src/theory/Makefile.am
src/theory/arith/theory_arith_instantiator.cpp
src/theory/arrays/theory_arrays_instantiator.cpp
src/theory/arrays/theory_arrays_instantiator.h
src/theory/datatypes/Makefile.am
src/theory/datatypes/theory_datatypes.h
src/theory/datatypes/theory_datatypes_candidate_generator.h [new file with mode: 0644]
src/theory/datatypes/theory_datatypes_instantiator.cpp
src/theory/datatypes/theory_datatypes_instantiator.h
src/theory/inst_match.cpp
src/theory/inst_match.h
src/theory/instantiator_default.cpp
src/theory/quantifiers/instantiation_engine.cpp
src/theory/quantifiers/model_engine.cpp
src/theory/quantifiers/rep_set_iterator.cpp
src/theory/quantifiers/term_database.cpp
src/theory/quantifiers/term_database.h
src/theory/quantifiers/theory_quantifiers.h
src/theory/quantifiers_engine.cpp
src/theory/quantifiers_engine.h
src/theory/rewriterules/theory_rewriterules.cpp
src/theory/rewriterules/theory_rewriterules.h
src/theory/rewriterules/theory_rewriterules_params.h
src/theory/rewriterules/theory_rewriterules_rules.cpp
src/theory/rewriterules/theory_rewriterules_type_rules.h
src/theory/rr_inst_match.cpp [new file with mode: 0644]
src/theory/rr_inst_match.h [new file with mode: 0644]
src/theory/rr_inst_match_impl.h [new file with mode: 0644]
src/theory/rr_trigger.cpp [new file with mode: 0644]
src/theory/rr_trigger.h [new file with mode: 0644]
src/theory/theory.h
src/theory/theory_engine.h
src/theory/trigger.cpp
src/theory/trigger.h
src/theory/uf/equality_engine.cpp
src/theory/uf/equality_engine.h
src/theory/uf/inst_strategy.cpp
src/theory/uf/inst_strategy.h
src/theory/uf/theory_uf_candidate_generator.cpp
src/theory/uf/theory_uf_candidate_generator.h
src/theory/uf/theory_uf_instantiator.cpp
src/theory/uf/theory_uf_instantiator.h
src/util/options.cpp
src/util/options.h
test/regress/regress0/Makefile.am
test/regress/regress0/quantifiers/Makefile.am
test/regress/regress0/rewriterules/Makefile.am
test/regress/regress0/rewriterules/datatypes_clark.smt2
test/regress/regress0/rewriterules/datatypes_clark_quantification.smt2 [new file with mode: 0644]
test/regress/regress0/rewriterules/length_gen_010.smt2
test/regress/regress0/rewriterules/native_arrays.smt2 [new file with mode: 0644]
test/regress/regress0/rewriterules/native_datatypes.smt2 [new file with mode: 0644]
test/regress/regress0/rewriterules/native_datatypes2.smt2 [new file with mode: 0644]
test/regress/regress0/rewriterules/reachability_back_to_the_future.smt2 [new file with mode: 0644]
test/regress/regress0/rewriterules/reachability_back_to_the_future_extended.smt2 [new file with mode: 0644]
test/regress/regress0/rewriterules/reachability_bbttf_eT_arrays.smt2 [new file with mode: 0644]
test/regress/regress0/rewriterules/reachability_bttf_ext_Thomas.smt2 [new file with mode: 0644]
test/regress/regress0/rewriterules/relation.smt2 [new file with mode: 0644]
test/regress/regress0/rewriterules/set_A_new_fast_tableau-base.smt2
test/regress/regress0/rewriterules/set_A_new_fast_tableau-base_sat.smt2
test/regress/regress0/rewriterules/simulate_rewritting.smt2 [new file with mode: 0644]
test/regress/regress0/rewriterules/test_efficient_ematching.smt2 [new file with mode: 0644]

index 025e8e33717c696c3ebb22cd17ef09bd15b32036..1fc1eebe6fd7710c91b47913fbd6dd7141bfd797 100644 (file)
@@ -59,7 +59,7 @@ protected:
    * using the ContextMemoryManager.
    */
   virtual ContextObj* save(ContextMemoryManager* pCMM) {
-    Debug("context") << "save cdo " << this << " (value " << get() << ")";
+    Debug("context") << "save cdo " << this;
     ContextObj* p = new(pCMM) CDO<T>(*this);
     Debug("context") << " to " << p << std::endl;
     return p;
@@ -70,7 +70,7 @@ protected:
    * saved data back from the saved copy using operator= for T.
    */
   virtual void restore(ContextObj* pContextObj) {
-    //Debug("context") << "restore cdo " << this << " from " << get();
+    //Debug("context") << "restore cdo " << this;
     d_data = ((CDO<T>*) pContextObj)->d_data;
     //Debug("context") << " to " << get() << std::endl;
   }
index b43217cfe7ed03fc805869e6ca88732d2ffd32b1..abdcc04938520de6d2eba474608150bf01b72cf8 100644 (file)
@@ -63,7 +63,7 @@ protected:
    *  We assume that the base class do the job inside their copy constructor.
    */
   ContextObj* save(ContextMemoryManager* pCMM) {
-    ContextObj* data = new(pCMM) CDQueue<T>(*this);
+    ContextObj* data = new(pCMM) CDQueue<T, CleanUp, Allocator>(*this);
     // We save the d_size in d_lastsave and we should never destruct below this
     // indices before the corresponding restore.
     d_lastsave = ParentType::d_size;
@@ -83,7 +83,7 @@ protected:
    * the list pointer and the allocated size are not changed.
    */
   void restore(ContextObj* data) {
-    CDQueue<T>* qdata = static_cast<CDQueue<T>*>(data);
+    CDQueue<T, CleanUp, Allocator>* qdata = static_cast<CDQueue<T, CleanUp, Allocator>*>(data);
     d_iter = qdata->d_iter;
     d_lastsave = qdata->d_lastsave;
     ParentType::restore(data);
index f4b40cbb3dbcf5e2594d64868bb0af746d315c17..12830a618f3ec724966db3615cfb96d0cfd2c7c0 100644 (file)
@@ -1137,6 +1137,219 @@ Command* DatatypeDeclarationCommand::clone() const {
   return new DatatypeDeclarationCommand(d_datatypes);
 }
 
+/* class RewriteRuleCommand */
+
+RewriteRuleCommand::RewriteRuleCommand(const VExpr & vars,
+                                       const std::vector< Expr> & guards,
+                                       const Expr & head, const Expr & body,
+                                       Triggers triggers) throw() :
+  d_vars(vars), d_guards(guards), d_head(head), d_body(body), d_triggers(triggers) {
+}
+
+RewriteRuleCommand::RewriteRuleCommand(const VExpr & vars,
+                                       const Expr & head, const Expr & body) throw() :
+  d_vars(vars), d_head(head), d_body(body) {
+}
+
+const RewriteRuleCommand::VExpr & RewriteRuleCommand::getVars() const throw(){
+  return d_vars;
+};
+const RewriteRuleCommand::VExpr & RewriteRuleCommand::getGuards() const throw(){
+  return d_guards;
+};
+const Expr & RewriteRuleCommand::getHead() const throw(){
+  return d_head;
+};
+const Expr & RewriteRuleCommand::getBody() const throw(){
+  return d_body;
+};
+const RewriteRuleCommand::Triggers & RewriteRuleCommand::getTriggers() const throw(){
+  return d_triggers;
+};
+
+
+void RewriteRuleCommand::invoke(SmtEngine* smtEngine) throw() {
+  try {
+    ExprManager* em = smtEngine->getExprManager();
+    /** build vars list */
+    Expr vars = em->mkExpr(kind::BOUND_VAR_LIST, d_vars);
+    /** build guards list */
+    Expr guards;
+    if(d_guards.size() == 0) guards = em->mkConst<bool>(true);
+    else if(d_guards.size() == 1) guards = d_guards[0];
+    else guards = em->mkExpr(kind::AND,d_guards);
+    /** build expression */
+    Expr expr;
+    if( d_triggers.empty() ){
+      expr = em->mkExpr(kind::RR_REWRITE,vars,guards,d_head,d_body);
+    } else {
+      /** build triggers list */
+      std::vector<Expr> vtriggers;
+      vtriggers.reserve(d_triggers.size());
+      for(Triggers::const_iterator i = d_triggers.begin(),
+            end = d_triggers.end(); i != end; ++i){
+        vtriggers.push_back(em->mkExpr(kind::INST_PATTERN,*i));
+      }
+      Expr triggers = em->mkExpr(kind::INST_PATTERN_LIST,vtriggers);
+      expr = em->mkExpr(kind::RR_REWRITE,vars,guards,d_head,d_body,triggers);
+    }
+    smtEngine->assertFormula(expr);
+    d_commandStatus = CommandSuccess::instance();
+  } catch(exception& e) {
+    d_commandStatus = new CommandFailure(e.what());
+  }
+}
+
+Command* RewriteRuleCommand::exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap) {
+  /** Convert variables */
+  VExpr vars; vars.reserve(d_vars.size());
+  for(VExpr::iterator i = d_vars.begin(), end = d_vars.end();
+      i == end; ++i){
+    vars.push_back(i->exportTo(exprManager, variableMap));
+  };
+  /** Convert guards */
+  VExpr guards; guards.reserve(d_guards.size());
+  for(VExpr::iterator i = d_guards.begin(), end = d_guards.end();
+      i == end; ++i){
+    guards.push_back(i->exportTo(exprManager, variableMap));
+  };
+  /** Convert triggers */
+  Triggers triggers; triggers.resize(d_triggers.size());
+  for(size_t i = 0, end = d_triggers.size();
+      i < end; ++i){
+    triggers[i].reserve(d_triggers[i].size());
+    for(VExpr::iterator j = d_triggers[i].begin(), jend = d_triggers[i].end();
+        j == jend; ++i){
+      triggers[i].push_back(j->exportTo(exprManager, variableMap));
+    };
+  };
+  /** Convert head and body */
+  Expr head = d_head.exportTo(exprManager, variableMap);
+  Expr body = d_body.exportTo(exprManager, variableMap);
+  /** Create the converted rules */
+  return new RewriteRuleCommand(vars,guards,head,body,triggers);
+}
+
+Command* RewriteRuleCommand::clone() const {
+  return new RewriteRuleCommand(d_vars,d_guards,d_head,d_body,d_triggers);
+}
+
+/* class PropagateRuleCommand */
+
+PropagateRuleCommand::PropagateRuleCommand(const VExpr & vars,
+                                           const VExpr & guards,
+                                           const VExpr & heads,
+                                           const Expr & body,
+                                           const Triggers triggers,
+                                           bool deduction
+                                           ) throw() :
+  d_vars(vars), d_guards(guards), d_heads(heads), d_body(body), d_triggers(triggers), d_deduction(deduction) {
+}
+
+PropagateRuleCommand::PropagateRuleCommand(const VExpr & vars,
+                                           const VExpr & heads,
+                                           const Expr & body,
+                                           bool deduction
+                                           ) throw() :
+  d_vars(vars), d_heads(heads), d_body(body), d_deduction(deduction) {
+}
+
+const PropagateRuleCommand::VExpr & PropagateRuleCommand::getVars() const throw(){
+  return d_vars;
+};
+const PropagateRuleCommand::VExpr & PropagateRuleCommand::getGuards() const throw(){
+  return d_guards;
+};
+const PropagateRuleCommand::VExpr & PropagateRuleCommand::getHeads() const throw(){
+  return d_heads;
+};
+const Expr & PropagateRuleCommand::getBody() const throw(){
+  return d_body;
+};
+const PropagateRuleCommand::Triggers & PropagateRuleCommand::getTriggers() const throw(){
+  return d_triggers;
+};
+bool PropagateRuleCommand::isDeduction() const throw(){
+  return d_deduction;
+};
+
+
+void PropagateRuleCommand::invoke(SmtEngine* smtEngine) throw() {
+  try {
+    ExprManager* em = smtEngine->getExprManager();
+    /** build vars list */
+    Expr vars = em->mkExpr(kind::BOUND_VAR_LIST, d_vars);
+    /** build guards list */
+    Expr guards;
+    if(d_guards.size() == 0) guards = em->mkConst<bool>(true);
+    else if(d_guards.size() == 1) guards = d_guards[0];
+    else guards = em->mkExpr(kind::AND,d_guards);
+    /** build heads list */
+    Expr heads;
+    if(d_heads.size() == 1) heads = d_heads[0];
+    else heads = em->mkExpr(kind::AND,d_heads);
+    /** build expression */
+    Expr expr;
+    if( d_triggers.empty() ){
+      expr = em->mkExpr(kind::RR_REWRITE,vars,guards,heads,d_body);
+    } else {
+      /** build triggers list */
+      std::vector<Expr> vtriggers;
+      vtriggers.reserve(d_triggers.size());
+      for(Triggers::const_iterator i = d_triggers.begin(),
+            end = d_triggers.end(); i != end; ++i){
+        vtriggers.push_back(em->mkExpr(kind::INST_PATTERN,*i));
+      }
+      Expr triggers = em->mkExpr(kind::INST_PATTERN_LIST,vtriggers);
+      expr = em->mkExpr(kind::RR_REWRITE,vars,guards,heads,d_body,triggers);
+    }
+    smtEngine->assertFormula(expr);
+    d_commandStatus = CommandSuccess::instance();
+  } catch(exception& e) {
+    d_commandStatus = new CommandFailure(e.what());
+  }
+}
+
+Command* PropagateRuleCommand::exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap) {
+  /** Convert variables */
+  VExpr vars; vars.reserve(d_vars.size());
+  for(VExpr::iterator i = d_vars.begin(), end = d_vars.end();
+      i == end; ++i){
+    vars.push_back(i->exportTo(exprManager, variableMap));
+  };
+  /** Convert guards */
+  VExpr guards; guards.reserve(d_guards.size());
+  for(VExpr::iterator i = d_guards.begin(), end = d_guards.end();
+      i == end; ++i){
+    guards.push_back(i->exportTo(exprManager, variableMap));
+  };
+  /** Convert heads */
+  VExpr heads; heads.reserve(d_heads.size());
+  for(VExpr::iterator i = d_heads.begin(), end = d_heads.end();
+      i == end; ++i){
+    heads.push_back(i->exportTo(exprManager, variableMap));
+  };
+  /** Convert triggers */
+  Triggers triggers; triggers.resize(d_triggers.size());
+  for(size_t i = 0, end = d_triggers.size();
+      i < end; ++i){
+    triggers[i].reserve(d_triggers[i].size());
+    for(VExpr::iterator j = d_triggers[i].begin(), jend = d_triggers[i].end();
+        j == jend; ++i){
+      triggers[i].push_back(j->exportTo(exprManager, variableMap));
+    };
+  };
+  /** Convert head and body */
+  Expr body = d_body.exportTo(exprManager, variableMap);
+  /** Create the converted rules */
+  return new PropagateRuleCommand(vars,guards,heads,body,triggers);
+}
+
+Command* PropagateRuleCommand::clone() const {
+  return new PropagateRuleCommand(d_vars,d_guards,d_heads,d_body,d_triggers);
+}
+
+
 /* output stream insertion operator for benchmark statuses */
 std::ostream& operator<<(std::ostream& out,
                          BenchmarkStatus status) throw() {
index 123fe01826fec66807b4de4c1bac3395a425dba1..9f1722f9f29c60022cb6509dc4492bba7dae043c 100644 (file)
@@ -599,6 +599,69 @@ public:
   Command* clone() const;
 };/* class DatatypeDeclarationCommand */
 
+class CVC4_PUBLIC RewriteRuleCommand : public Command {
+protected:
+  typedef std::vector< Expr > VExpr;
+  VExpr d_vars;
+  VExpr d_guards;
+  Expr d_head;
+  Expr d_body;
+  typedef std::vector< std::vector< Expr > > Triggers;
+  Triggers d_triggers;
+public:
+  RewriteRuleCommand(const VExpr & vars,
+                     const std::vector< Expr> & guards,
+                     const Expr & head, const Expr & body,
+                     Triggers d_triggers
+                     ) throw();
+  RewriteRuleCommand(const VExpr & vars,
+                     const Expr & head, const Expr & body) throw();
+  ~RewriteRuleCommand() throw() {}
+  const VExpr & getVars() const throw();
+  const VExpr & getGuards() const throw();
+  const Expr & getHead() const throw();
+  const Expr & getBody() const throw();
+  const Triggers & getTriggers() const throw();
+  void invoke(SmtEngine* smtEngine) throw();
+  Command* exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap);
+  Command* clone() const;
+};/* class RewriteRuleCommand */
+
+class CVC4_PUBLIC PropagateRuleCommand : public Command {
+protected:
+  typedef std::vector< Expr > VExpr;
+  VExpr d_vars;
+  VExpr d_guards;
+  VExpr d_heads;
+  Expr d_body;
+  typedef std::vector< std::vector< Expr > > Triggers;
+  Triggers d_triggers;
+  bool d_deduction;
+public:
+  PropagateRuleCommand(const VExpr & vars,
+                         const VExpr & guards,
+                         const VExpr & heads,
+                         const Expr & body,
+                         Triggers d_triggers,
+                         /* true if we want a deduction rule */
+                         bool d_deduction = false
+                         ) throw();
+  PropagateRuleCommand(const VExpr & vars,
+                       const VExpr & heads, const Expr & body,
+                       bool d_deduction = false) throw();
+  ~PropagateRuleCommand() throw() {}
+  const VExpr & getVars() const throw();
+  const VExpr & getGuards() const throw();
+  const VExpr & getHeads() const throw();
+  const Expr & getBody() const throw();
+  const Triggers & getTriggers() const throw();
+  bool isDeduction() const throw();
+  void invoke(SmtEngine* smtEngine) throw();
+  Command* exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap);
+  Command* clone() const;
+};/* class PropagateRuleCommand */
+
+
 class CVC4_PUBLIC QuitCommand : public Command {
 public:
   QuitCommand() throw();
index 0b150d25dbe2a68487693de6535e1ec9a961d166..b0fda33543d613df40c8a250589f73a33a8ca8f7 100644 (file)
@@ -892,6 +892,25 @@ inline std::ostream& operator<<(std::ostream& out, TNode n) {
   return out;
 }
 
+/**
+ * Serializes a vector of node to the given stream.
+ *
+ * @param out the output stream to use
+ * @param ns the vector of nodes to output to the stream
+ * @return the stream
+ */
+template<bool ref_count>
+inline std::ostream& operator<<(std::ostream& out,
+                                const std::vector< NodeTemplate<ref_count> > & ns) {
+  for(typename std::vector< NodeTemplate<ref_count> >::const_iterator
+        i=ns.begin(), end=ns.end();
+      i != end; ++i){
+    out << *i;
+  }
+  return out;
+}
+
+
 }/* CVC4 namespace */
 
 #include <ext/hash_map>
index be5a797bf2da8782a55c91c540266486540efcbb..56fa93a94719a4a0bdc4e96f9e86be7ea907e85c 100644 (file)
@@ -398,6 +398,126 @@ extendedCommand[CVC4::Command*& cmd]
       }
     | { cmd = new EchoCommand(); }
     )
+  | rewriterulesCommand[cmd]
+  ;
+
+rewriterulesCommand[CVC4::Command*& cmd]
+@declarations {
+  std::vector<std::pair<std::string, Type> > sortedVarNames;
+  std::vector<Expr> args, guards, heads, triggers;
+  Expr head, body, expr, expr2, bvl;
+  Kind kind;
+}
+  : /* rewrite rules */
+    REWRITE_RULE_TOK
+    LPAREN_TOK sortedVarList[sortedVarNames] RPAREN_TOK
+    {
+      kind = CVC4::kind::RR_REWRITE;
+      PARSER_STATE->pushScope();
+      for(std::vector<std::pair<std::string, CVC4::Type> >::const_iterator i =
+            sortedVarNames.begin(), iend = sortedVarNames.end();
+          i != iend;
+          ++i) {
+        args.push_back(PARSER_STATE->mkVar((*i).first, (*i).second));
+      }
+      bvl = MK_EXPR(kind::BOUND_VAR_LIST, args);
+    }
+    LPAREN_TOK (termList[guards,expr])? RPAREN_TOK
+    term[head, expr2] term[body, expr2]
+    LPAREN_TOK ( pattern[expr] { triggers.push_back( expr ); } )* RPAREN_TOK
+    {
+      args.clear();
+      args.push_back(head);
+      args.push_back(body);
+      /* triggers */
+      if( !triggers.empty() ){
+        expr2 = MK_EXPR(kind::INST_PATTERN_LIST, triggers);
+        args.push_back(expr2);
+      };
+      expr = MK_EXPR(kind, args);
+      args.clear();
+      args.push_back(bvl);
+      /* guards */
+      switch( guards.size() ){
+      case 0:
+        args.push_back(MK_CONST(bool(true))); break;
+      case 1:
+        args.push_back(guards[0]); break;
+      default:
+        expr2 = MK_EXPR(kind::AND, guards);
+        args.push_back(expr2); break;
+      };
+      args.push_back(expr);
+      expr = MK_EXPR(CVC4::kind::REWRITE_RULE, args);
+      cmd = new AssertCommand(expr); }
+    /* propagation rule */
+  | rewritePropaKind[kind]
+    LPAREN_TOK sortedVarList[sortedVarNames] RPAREN_TOK
+    {
+      PARSER_STATE->pushScope();
+      for(std::vector<std::pair<std::string, CVC4::Type> >::const_iterator i =
+            sortedVarNames.begin(), iend = sortedVarNames.end();
+          i != iend;
+          ++i) {
+        args.push_back(PARSER_STATE->mkVar((*i).first, (*i).second));
+      }
+      bvl = MK_EXPR(kind::BOUND_VAR_LIST, args);
+    }
+    LPAREN_TOK (termList[guards,expr])? RPAREN_TOK
+    LPAREN_TOK (termList[heads,expr])? RPAREN_TOK
+    term[body, expr2]
+    LPAREN_TOK ( pattern[expr] { triggers.push_back( expr ); } )* RPAREN_TOK
+    {
+      args.clear();
+      /* heads */
+      switch( heads.size() ){
+      case 0:
+        args.push_back(MK_CONST(bool(true))); break;
+      case 1:
+        args.push_back(heads[0]); break;
+      default:
+        expr2 = MK_EXPR(kind::AND, heads);
+        args.push_back(expr2); break;
+      };
+      args.push_back(body);
+      /* triggers */
+      if( !triggers.empty() ){
+        expr2 = MK_EXPR(kind::INST_PATTERN_LIST, triggers);
+        args.push_back(expr2);
+      };
+      expr = MK_EXPR(kind, args);
+      args.clear();
+      args.push_back(bvl);
+      /* guards */
+      switch( guards.size() ){
+      case 0:
+        args.push_back(MK_CONST(bool(true))); break;
+      case 1:
+        args.push_back(guards[0]); break;
+      default:
+        expr2 = MK_EXPR(kind::AND, guards);
+        args.push_back(expr2); break;
+      };
+      args.push_back(expr);
+      expr = MK_EXPR(CVC4::kind::REWRITE_RULE, args);
+      cmd = new AssertCommand(expr); }
+  ;
+
+rewritePropaKind[CVC4::Kind& kind]
+  :
+  REDUCTION_RULE_TOK    { $kind = CVC4::kind::RR_REDUCTION; }
+  | PROPAGATION_RULE_TOK  { $kind = CVC4::kind::RR_DEDUCTION; }
+  ;
+
+pattern[CVC4::Expr& expr]
+@declarations {
+  std::vector<Expr> patexpr;
+}
+  : LPAREN_TOK termList[patexpr,expr] RPAREN_TOK
+    {
+      expr = MK_EXPR(kind::INST_PATTERN, patexpr);
+      //std::cout << "parsed pattern expr " << retExpr << std::endl;
+    }
   ;
 
 simpleSymbolicExpr[CVC4::SExpr& sexpr]
@@ -1076,6 +1196,9 @@ POP_TOK : 'pop';
 DECLARE_DATATYPES_TOK : 'declare-datatypes';
 GET_MODEL_TOK : 'get-model';
 ECHO_TOK : 'echo';
+REWRITE_RULE_TOK : 'assert-rewrite';
+REDUCTION_RULE_TOK : 'assert-reduction';
+PROPAGATION_RULE_TOK : 'assert-propagation';
 
 // attributes
 ATTRIBUTE_PATTERN_TOK : ':pattern';
index a3b22ac241a63d689f6a83172066763c631fca5e..892de551c51eb00cfa3bb4b6db043c2042c80920 100644 (file)
@@ -282,7 +282,7 @@ void Smt2Printer::toStream(std::ostream& out, TNode n,
   case kind::FORALL: out << "forall "; break;
   case kind::EXISTS: out << "exists "; break;
   case kind::BOUND_VAR_LIST:
-    out << '(';
+    // the left parenthesis is already printed (before the switch)
     for(TNode::iterator i = n.begin(),
           iend = n.end();
         i != iend; ) {
@@ -290,8 +290,10 @@ void Smt2Printer::toStream(std::ostream& out, TNode n,
       (*i).toStream(out, toDepth < 0 ? toDepth : toDepth - 1,
                     types, language::output::LANG_SMTLIB_V2);
       out << ' ';
-      (*i).getType().toStream(out, toDepth < 0 ? toDepth : toDepth - 1,
-                              false, language::output::LANG_SMTLIB_V2);
+      out << (*i).getType();
+      // The following code do stange things
+      // (*i).getType().toStream(out, toDepth < 0 ? toDepth : toDepth - 1,
+      //                         false, language::output::LANG_SMTLIB_V2);
       out << ')';
       if(++i != iend) {
         out << ' ';
index 1aae03aa50e3b9ba9abdd2427230e5832e4143af..2bd85f71201de2b5b51a14f3b3c68e4f842a8a34 100644 (file)
@@ -40,8 +40,12 @@ libtheory_la_SOURCES = \
        quantifiers_engine.cpp \
        instantiator_default.h \
        instantiator_default.cpp \
+       rr_inst_match.h \
+       rr_inst_match_impl.h \
+       rr_inst_match.cpp \
+       rr_trigger.h \
+       rr_trigger.cpp \
        inst_match.h \
-       inst_match_impl.h \
        inst_match.cpp \
        trigger.h \
        trigger.cpp \
index c4cb2f4935018ce011d30eac25d652e528ea9c49..ab3a1548efefd7b29d0b9bc6cbefd70430f5cbd2 100644 (file)
@@ -376,7 +376,7 @@ bool InstantiatorTheoryArith::doInstantiation2( Node f, Node term, ArithVar x, I
   }
   instVal = Rewriter::rewrite( instVal );
   //use as instantiation value for var
-  m.d_map[ var ] = instVal;
+  m.set(var, instVal);
   Debug("quant-arith") << "Add instantiation " << m << std::endl;
   return d_quantEngine->addInstantiation( f, m );
 }
index 2e446c57f81d1deb7a5114b437437f5e57f9b811..ca9001fe5e682a465f0ae693a062ed8c229c995c 100644 (file)
@@ -17,6 +17,7 @@
 #include "theory/theory_engine.h"
 #include "theory/arrays/theory_arrays_instantiator.h"
 #include "theory/arrays/theory_arrays.h"
+#include "theory/uf/theory_uf_candidate_generator.h"
 
 using namespace std;
 using namespace CVC4;
@@ -83,3 +84,16 @@ Node InstantiatorTheoryArrays::getRepresentative( Node a ){
   }
 }
 
+rrinst::CandidateGenerator* InstantiatorTheoryArrays::getRRCanGenClasses(){
+  arrays::TheoryArrays* ar = static_cast<arrays::TheoryArrays *>(getTheory());
+  eq::EqualityEngine* ee =
+    static_cast<eq::EqualityEngine*>(ar->getEqualityEngine());
+  return new eq::rrinst::CandidateGeneratorTheoryEeClasses(ee);
+}
+
+rrinst::CandidateGenerator* InstantiatorTheoryArrays::getRRCanGenClass(){
+  arrays::TheoryArrays* ar = static_cast<arrays::TheoryArrays *>(getTheory());
+  eq::EqualityEngine* ee =
+    static_cast<eq::EqualityEngine*>(ar->getEqualityEngine());
+  return new eq::rrinst::CandidateGeneratorTheoryEeClass(ee);
+}
index ade43fdb02bca0bb6108b923c3236ca9f0956511..f711229b29810b292a2fef7a164485fd73af51ff 100644 (file)
@@ -21,6 +21,7 @@
 #define __CVC4__INSTANTIATOR_THEORY_ARRAYS_H
 
 #include "theory/quantifiers_engine.h"
+#include "theory/uf/equality_engine.h"
 
 namespace CVC4 {
 namespace theory {
@@ -48,10 +49,13 @@ public:
   bool areEqual( Node a, Node b );
   bool areDisequal( Node a, Node b );
   Node getRepresentative( Node a );
+  /** general creators of candidate generators */
+  rrinst::CandidateGenerator* getRRCanGenClasses();
+  rrinst::CandidateGenerator* getRRCanGenClass();
 };/* class Instantiatior */
 
 }
 }
 }
 
-#endif
\ No newline at end of file
+#endif
index 14bbf64d4c821583c0a05bfe6798eea7fa630a52..f282ce74dd2a48ada683af4b32efd7ae4f2e0ebd 100644 (file)
@@ -16,6 +16,7 @@ libdatatypes_la_SOURCES = \
        explanation_manager.h \
        explanation_manager.cpp \
        theory_datatypes_instantiator.h \
-       theory_datatypes_instantiator.cpp
+       theory_datatypes_instantiator.cpp \
+       theory_datatypes_candidate_generator.h
 
 EXTRA_DIST = kinds
index 783c0ebc7efe67c0fcbd6605f9dfafae0da96a46..80c20a7d9466207d0ffa785efef48dacd61754dc 100644 (file)
@@ -38,9 +38,17 @@ namespace theory {
 namespace datatypes {
 
 class InstantiatorTheoryDatatypes;
+class EqualityQueryTheory;
+
+namespace rrinst{
+  class CandidateGeneratorTheoryClass;
+}
 
 class TheoryDatatypes : public Theory {
   friend class InstantiatorTheoryDatatypes;
+  friend class EqualityQueryTheory;
+  friend class rrinst::CandidateGeneratorTheoryClass;
+
 private:
   typedef context::CDChunkList<TNode> EqList;
   typedef context::CDHashMap<Node, EqList*, NodeHashFunction> EqLists;
diff --git a/src/theory/datatypes/theory_datatypes_candidate_generator.h b/src/theory/datatypes/theory_datatypes_candidate_generator.h
new file mode 100644 (file)
index 0000000..46c7ce7
--- /dev/null
@@ -0,0 +1,67 @@
+/*********************                                                        */
+/*! \file theory_uf_candidate generator.h
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Theory datatypes candidate generator
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY_DATATYPES_CANDIDATE_GENERATOR_H
+#define __CVC4__THEORY_DATATYPES_CANDIDATE_GENERATOR_H
+
+#include "theory/quantifiers_engine.h"
+#include "theory/datatypes/theory_datatypes.h"
+#include "theory/rr_inst_match.h"
+
+namespace CVC4 {
+namespace theory {
+namespace datatypes {
+
+namespace rrinst {
+typedef CVC4::theory::rrinst::CandidateGenerator CandidateGenerator;
+
+// Just iterate amoung the equivalence class of the given node
+// node::Null() *can't* be given to reset
+class CandidateGeneratorTheoryClass : public CandidateGenerator{
+private:
+  //instantiator pointer
+  TheoryDatatypes* d_th;
+  //the equality class iterator
+  TheoryDatatypes::EqListN::const_iterator d_eqc_i;
+  TheoryDatatypes::EqListN* d_eqc;
+public:
+  CandidateGeneratorTheoryClass( TheoryDatatypes* th): d_th( th ), d_eqc(NULL){}
+  ~CandidateGeneratorTheoryClass(){}
+  void resetInstantiationRound(){};
+  void reset( TNode n ){
+    TheoryDatatypes::EqListsN::const_iterator i = d_th->d_equivalence_class.find(n);
+    if(i == d_th->d_equivalence_class.end()){
+      d_eqc = NULL;
+    } else {
+      d_eqc = (*i).second;
+      d_eqc_i = d_eqc->begin();
+    }
+  }; //* the argument is not used
+  TNode getNextCandidate(){
+    if( d_eqc == NULL || d_eqc_i == d_eqc->end() ) return Node::null();
+    return *(d_eqc_i++);
+  };
+};
+
+
+}
+}
+}
+}
+
+#endif /* __CVC4__THEORY_DATATYPES_CANDIDATE_GENERATOR_H */
index 9495e4d48b0cec942a18785b1b2407c0361bbb38..57e9324dff9c1644b27a75f1423511bc9d4d8901 100644 (file)
@@ -15,6 +15,7 @@
  **/
 
 #include "theory/datatypes/theory_datatypes_instantiator.h"
+#include "theory/datatypes/theory_datatypes_candidate_generator.h"
 #include "theory/datatypes/theory_datatypes.h"
 #include "theory/theory_engine.h"
 #include "theory/quantifiers/term_database.h"
@@ -26,9 +27,9 @@ using namespace CVC4::context;
 using namespace CVC4::theory;
 using namespace CVC4::theory::datatypes;
 
-InstantiatorTheoryDatatypes::InstantiatorTheoryDatatypes(context::Context* c, QuantifiersEngine* ie, Theory* th) :
-Instantiator( c, ie, th ){
 
+InstantiatorTheoryDatatypes::InstantiatorTheoryDatatypes(context::Context* c, QuantifiersEngine* ie, TheoryDatatypes* th) :
+Instantiator( c, ie, th ){
 }
 
 void InstantiatorTheoryDatatypes::assertNode( Node assertion ){
@@ -60,7 +61,7 @@ int InstantiatorTheoryDatatypes::process( Node f, Theory::Effort effort, int e )
         if( i.getType().isDatatype() ){
           Node n = getValueFor( i );
           Debug("quant-datatypes-debug") << "Value for " << i << " is " << n << std::endl;
-          m.d_map[ i ] = n;
+          m.set(i,n);
         }
       }
       d_quantEngine->addInstantiation( f, m );
@@ -168,3 +169,8 @@ bool InstantiatorTheoryDatatypes::areDisequal( Node a, Node b ){
 Node InstantiatorTheoryDatatypes::getRepresentative( Node a ){
   return ((TheoryDatatypes*)d_th)->getRepresentative( a );
 }
+
+CVC4::theory::rrinst::CandidateGenerator* InstantiatorTheoryDatatypes::getRRCanGenClass(){
+  TheoryDatatypes* th = static_cast<TheoryDatatypes *>(getTheory());
+  return new datatypes::rrinst::CandidateGeneratorTheoryClass(th);
+}
index a080465af21483577c99b069c7d9dd9ac6f1b093..fd7190a220c7495500db0aaac472e76843fa8e6c 100644 (file)
@@ -28,10 +28,12 @@ namespace CVC4 {
 namespace theory {
 namespace datatypes {
 
+class TheoryDatatypes;
+
 class InstantiatorTheoryDatatypes : public Instantiator{
   friend class QuantifiersEngine;
 public:
-  InstantiatorTheoryDatatypes(context::Context* c, QuantifiersEngine* ie, Theory* th);
+  InstantiatorTheoryDatatypes(context::Context* c, QuantifiersEngine* ie, TheoryDatatypes* th);
   ~InstantiatorTheoryDatatypes() {}
 
   /** assertNode function, assertion is asserted to theory */
@@ -59,10 +61,13 @@ public:
   bool areEqual( Node a, Node b );
   bool areDisequal( Node a, Node b );
   Node getRepresentative( Node a );
+    /** general creators of candidate generators */
+  CVC4::theory::rrinst::CandidateGenerator* getRRCanGenClass();
 };/* class InstantiatiorTheoryDatatypes  */
 
+
 }
 }
 }
 
-#endif
\ No newline at end of file
+#endif
index abcf5aa7fa0f567a2da35b4b8ce461743420690c..4f1bfe67e8bebcd85ce257e7a32c3b0f5c3ddd9c 100644 (file)
@@ -30,6 +30,7 @@ using namespace CVC4;
 using namespace CVC4::kind;
 using namespace CVC4::context;
 using namespace CVC4::theory;
+using namespace CVC4::theory::inst;
 
 
 bool CandidateGenerator::isLegalCandidate( Node n ){
@@ -71,16 +72,24 @@ InstMatch::InstMatch( InstMatch* m ) {
   d_map = m->d_map;
 }
 
-bool InstMatch::setMatch( EqualityQuery* q, Node v, Node m ){
-  if( d_map.find( v )==d_map.end() ){
-    d_map[v] = m;
+bool InstMatch::setMatch( EqualityQuery* q, TNode v, TNode m, bool & set ){
+  std::map< Node, Node >::iterator vn = d_map.find( v );
+  if( vn==d_map.end() ){
+    set = true;
+    this->set(v,m);
     Debug("matching-debug") << "Add partial " << v << "->" << m << std::endl;
     return true;
   }else{
-    return q->areEqual( d_map[v], m );
+    set = false;
+    return q->areEqual( vn->second, m );
   }
 }
 
+bool InstMatch::setMatch( EqualityQuery* q, TNode v, TNode m ){
+  bool set;
+  return setMatch(q,v,m,set);
+}
+
 bool InstMatch::add( InstMatch& m ){
   for( std::map< Node, Node >::iterator it = m.d_map.begin(); it != m.d_map.end(); ++it ){
     if( d_map.find( it->first )==d_map.end() ){
@@ -174,7 +183,7 @@ void InstMatch::computeTermVec( const std::vector< Node >& vars, std::vector< No
 void InstMatchTrie::addInstMatch2( QuantifiersEngine* qe, Node f, InstMatch& m, int index, ImtIndexOrder* imtio ){
   if( long(index)<long(f[0].getNumChildren()) && ( !imtio || long(index)<long(imtio->d_order.size()) ) ){
     int i_index = imtio ? imtio->d_order[index] : index;
-    Node n = m.d_map[ qe->getTermDatabase()->getInstantiationConstant( f, i_index ) ];
+    Node n = m.get( qe->getTermDatabase()->getInstantiationConstant( f, i_index ) );
     d_data[n].addInstMatch2( qe, f, m, index+1, imtio );
   }
 }
@@ -185,7 +194,7 @@ bool InstMatchTrie::existsInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m
     return true;
   }else{
     int i_index = imtio ? imtio->d_order[index] : index;
-    Node n = m.d_map[ qe->getTermDatabase()->getInstantiationConstant( f, i_index ) ];
+    Node n = m.get( qe->getTermDatabase()->getInstantiationConstant( f, i_index ) );
     std::map< Node, InstMatchTrie >::iterator it = d_data.find( n );
     if( it!=d_data.end() ){
       if( it->second.existsInstMatch( qe, f, m, modEq, index+1, imtio ) ){
@@ -301,10 +310,10 @@ void InstMatchGenerator::initializePattern( Node pat, QuantifiersEngine* qe ){
     //we will be producing candidates via literal matching heuristics
     if( d_pattern.getKind()!=NOT ){
       //candidates will be all equalities
-      d_cg = new uf::CandidateGeneratorTheoryUfLitEq( ith, d_match_pattern );
+      d_cg = new uf::inst::CandidateGeneratorTheoryUfLitEq( ith, d_match_pattern );
     }else{
       //candidates will be all disequalities
-      d_cg = new uf::CandidateGeneratorTheoryUfLitDeq( ith, d_match_pattern );
+      d_cg = new uf::inst::CandidateGeneratorTheoryUfLitDeq( ith, d_match_pattern );
     }
   }else if( d_pattern.getKind()==EQUAL || d_pattern.getKind()==IFF || d_pattern.getKind()==NOT ){
     Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
@@ -313,20 +322,16 @@ void InstMatchGenerator::initializePattern( Node pat, QuantifiersEngine* qe ){
     }else{
       Assert( Trigger::isAtomicTrigger( d_match_pattern ) );
       //we are matching only in a particular equivalence class
-      d_cg = new uf::CandidateGeneratorTheoryUf( ith, d_match_pattern.getOperator() );
+      d_cg = new uf::inst::CandidateGeneratorTheoryUf( ith, d_match_pattern.getOperator() );
       //store the equivalence class that we will call d_cg->reset( ... ) on
       d_eq_class = d_pattern[1];
     }
   }else if( Trigger::isAtomicTrigger( d_match_pattern ) ){
-    if( d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ){
-      //we will manually add candidates to queue
-      d_cg = new CandidateGeneratorQueue;
-      //register this candidate generator
-      ith->registerCandidateGenerator( d_cg, d_match_pattern );
-    }else{
-      //we will be scanning lists trying to find d_match_pattern.getOperator()
-      d_cg = new uf::CandidateGeneratorTheoryUf( ith, d_match_pattern.getOperator() );
-    }
+    //if( d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ){
+      //Warning() << "Currently efficient e matching is not taken into account for quantifiers: " << d_pattern << std::endl;
+    //}
+    //we will be scanning lists trying to find d_match_pattern.getOperator()
+    d_cg = new uf::inst::CandidateGeneratorTheoryUf( ith, d_match_pattern.getOperator() );
   }else{
     d_cg = new CandidateGeneratorQueue;
     if( !Trigger::getPatternArithmetic( d_match_pattern.getAttribute(InstConstantAttribute()), d_match_pattern, d_arith_coeffs ) ){
@@ -347,7 +352,7 @@ void InstMatchGenerator::initializePattern( Node pat, QuantifiersEngine* qe ){
 /** get match (not modulo equality) */
 bool InstMatchGenerator::getMatch( Node t, InstMatch& m, QuantifiersEngine* qe ){
   Debug("matching") << "Matching " << t << " against pattern " << d_match_pattern << " ("
-                    << m.d_map.size() << ")" << ", " << d_children.size() << std::endl;
+                    << m.size() << ")" << ", " << d_children.size() << std::endl;
   Assert( !d_match_pattern.isNull() );
   if( qe->d_optMatchIgnoreModelBasis && t.getAttribute(ModelBasisAttribute()) ){
     return true;
@@ -373,9 +378,9 @@ bool InstMatchGenerator::getMatch( Node t, InstMatch& m, QuantifiersEngine* qe )
             //match is in conflict
             Debug("matching-debug") << "Match in conflict " << t[i] << " and "
                                     << d_match_pattern[i] << " because "
-                                    << partial[0].d_map[d_match_pattern[i]]
+                                    << partial[0].get(d_match_pattern[i])
                                     << std::endl;
-            Debug("matching-fail") << "Match fail: " << partial[0].d_map[d_match_pattern[i]] << " and " << t[i] << std::endl;
+            Debug("matching-fail") << "Match fail: " << partial[0].get(d_match_pattern[i]) << " and " << t[i] << std::endl;
             return false;
           }
         }
@@ -443,14 +448,14 @@ bool InstMatchGenerator::getMatchArithmetic( Node t, InstMatch& m, QuantifiersEn
     for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
       Debug("matching-arith") << it->first << " -> " << it->second << std::endl;
       if( !it->first.isNull() ){
-        if( m.d_map.find( it->first )==m.d_map.end() ){
+        if( m.find( it->first )==m.end() ){
           //see if we can choose this to set
           if( ic.isNull() && ( it->second.isNull() || !it->first.getType().isInteger() ) ){
             ic = it->first;
           }
         }else{
-          Debug("matching-arith") << "already set " << m.d_map[ it->first ] << std::endl;
-          Node tm = m.d_map[ it->first ];
+          Debug("matching-arith") << "already set " << m.get( it->first ) << std::endl;
+          Node tm = m.get( it->first );
           if( !it->second.isNull() ){
             tm = NodeManager::currentNM()->mkNode( MULT, it->second, tm );
           }
@@ -473,12 +478,12 @@ bool InstMatchGenerator::getMatchArithmetic( Node t, InstMatch& m, QuantifiersEn
         Node coeff = NodeManager::currentNM()->mkConst( Rational(1) / d_arith_coeffs[ ic ].getConst<Rational>() );
         tm = NodeManager::currentNM()->mkNode( MULT, coeff, tm );
       }
-      m.d_map[ ic ] = Rewriter::rewrite( tm );
+      m.set( ic, Rewriter::rewrite( tm ));
       //set the rest to zeros
       for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
         if( !it->first.isNull() ){
-          if( m.d_map.find( it->first )==m.d_map.end() ){
-            m.d_map[ it->first ] = NodeManager::currentNM()->mkConst( Rational(0) );
+          if( m.find( it->first )==m.end() ){
+            m.set( it->first, NodeManager::currentNM()->mkConst( Rational(0) ) );
           }
         }
       }
@@ -754,7 +759,7 @@ void InstMatchGeneratorMulti::processNewInstantiations( QuantifiersEngine* qe, I
   }else if( trieIndex<(int)d_children_trie[childIndex].getOrdering()->d_order.size() ){
     int curr_index = d_children_trie[childIndex].getOrdering()->d_order[trieIndex];
     Node curr_ic = qe->getTermDatabase()->getInstantiationConstant( d_f, curr_index );
-    if( m.d_map.find( curr_ic )==m.d_map.end() ){
+    if( m.find( curr_ic )==m.end() ){
       //if( d_var_to_node[ curr_index ].size()==1 ){    //FIXME
       //  //unique variable(s), defer calculation
       //  unique_var_tries.push_back( IndexedTrie( std::pair< int, int >( childIndex, trieIndex ), tr ) );
@@ -765,14 +770,14 @@ void InstMatchGeneratorMulti::processNewInstantiations( QuantifiersEngine* qe, I
         //shared and non-set variable, add to InstMatch
         for( std::map< Node, InstMatchTrie >::iterator it = tr->d_data.begin(); it != tr->d_data.end(); ++it ){
           InstMatch mn( &m );
-          mn.d_map[ curr_ic ] = it->first;
+          mn.set( curr_ic, it->first);
           processNewInstantiations( qe, mn, addedLemmas, &(it->second), unique_var_tries,
                                     trieIndex+1, childIndex, endChildIndex, modEq );
         }
       //}
     }else{
       //shared and set variable, try to merge
-      Node n = m.d_map[ curr_ic ];
+      Node n = m.get( curr_ic );
       std::map< Node, InstMatchTrie >::iterator it = tr->d_data.find( n );
       if( it!=tr->d_data.end() ){
         processNewInstantiations( qe, m, addedLemmas, &(it->second), unique_var_tries,
@@ -819,7 +824,7 @@ void InstMatchGeneratorMulti::processNewInstantiations2( QuantifiersEngine* qe,
       //unique non-set variable, add to InstMatch
       for( std::map< Node, InstMatchTrie >::iterator it = tr->d_data.begin(); it != tr->d_data.end(); ++it ){
         InstMatch mn( &m );
-        mn.d_map[ curr_ic ] = it->first;
+        mn.set( curr_ic, it->first);
         processNewInstantiations2( qe, mn, addedLemmas, unique_var_tries, uvtIndex, &(it->second), trieIndex+1 );
       }
     }else{
@@ -875,11 +880,11 @@ void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngin
       Node ic = d_match_pattern[argIndex];
       for( std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
         Node t = it->first;
-        if( m.d_map[ ic ].isNull() || m.d_map[ ic ]==t ){
-          Node prev = m.d_map[ ic ];
-          m.d_map[ ic ] = t;
+        if( m.get( ic ).isNull() || m.get( ic )==t ){
+          Node prev = m.get( ic );
+          m.set( ic, t);
           addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
-          m.d_map[ ic ] = prev;
+          m.set( ic, prev);
         }
       }
     }else{
@@ -897,7 +902,7 @@ int InstMatchGeneratorSimple::addTerm( Node f, Node t, QuantifiersEngine* qe ){
   InstMatch m;
   for( int i=0; i<(int)t.getNumChildren(); i++ ){
     if( d_match_pattern[i].getKind()==INST_CONSTANT ){
-      m.d_map[d_match_pattern[i]] = t[i];
+      m.set(d_match_pattern[i], t[i]);
     }else if( !qe->getEqualityQuery()->areEqual( d_match_pattern[i], t[i] ) ){
       return 0;
     }
index 7cc5b2249aabc297e47a6601b66f13f2a5b24b7e..31a59b2612580e419de52786d43a96b17d68b24c 100644 (file)
@@ -44,14 +44,40 @@ typedef expr::Attribute< NoMatchAttributeId,
                          true // context dependent
                        > NoMatchAttribute;
 
+// attribute for "contains instantiation constants from"
+struct InstConstantAttributeId {};
+typedef expr::Attribute<InstConstantAttributeId, Node> InstConstantAttribute;
+
+struct InstLevelAttributeId {};
+typedef expr::Attribute<InstLevelAttributeId, uint64_t> InstLevelAttribute;
+
+struct InstVarNumAttributeId {};
+typedef expr::Attribute<InstVarNumAttributeId, uint64_t> InstVarNumAttribute;
+
+// Attribute that tell if a node have been asserted in this branch
+struct AvailableInTermDbId {};
+/** use the special for boolean flag */
+typedef expr::Attribute<AvailableInTermDbId,
+                        bool,
+                        expr::attr::NullCleanupStrategy,
+                        true  // context dependent
+                        > AvailableInTermDb;
+
+
 class QuantifiersEngine;
+namespace quantifiers{
+  class TermArgTrie;
+}
 
-namespace uf {
+namespace uf{
   class InstantiatorTheoryUf;
   class TheoryUF;
 }/* CVC4::theory::uf namespace */
 
-class CandidateGenerator {
+namespace inst {
+
+class CandidateGenerator
+{
 public:
   CandidateGenerator(){}
   ~CandidateGenerator(){}
@@ -95,7 +121,7 @@ public:
 class EqualityQuery {
 public:
   EqualityQuery(){}
-  ~EqualityQuery(){}
+  virtual ~EqualityQuery(){};
   /** contains term */
   virtual bool hasTerm( Node a ) = 0;
   /** get the representative of the equivalence class of a */
@@ -113,12 +139,16 @@ public:
 
 /** basic class defining an instantiation */
 class InstMatch {
+  /* map from variable to ground terms */
+  std::map< Node, Node > d_map;
 public:
   InstMatch();
   InstMatch( InstMatch* m );
 
   /** set the match of v to m */
-  bool setMatch( EqualityQuery* q, Node v, Node m );
+  bool setMatch( EqualityQuery* q, TNode v, TNode m );
+  /* This version tell if the variable has been set */
+  bool setMatch( EqualityQuery* q, TNode v, TNode m, bool & set);
   /** fill all unfilled values with m */
   bool add( InstMatch& m );
   /** if compatible, fill all unfilled values with m and return true
@@ -140,10 +170,30 @@ public:
   void computeTermVec( const std::vector< Node >& vars, std::vector< Node >& match );
   /** clear */
   void clear(){ d_map.clear(); }
+  /** erase */
+  template<class Iterator>
+  void erase(Iterator begin, Iterator end){
+    for(Iterator i = begin; i != end; ++i){
+      d_map.erase(*i);
+    };
+  }
+  void erase(Node node){ d_map.erase(node); }
   /** is_empty */
   bool empty(){ return d_map.empty(); }
-  /* map from variable to ground terms */
-  std::map< Node, Node > d_map;
+  /** set */
+  void set(TNode var, TNode n){
+    //std::cout << "var.getType() " << var.getType() << "n.getType() " << n.getType() << std::endl ;
+    Assert( !var.isNull() );
+    Assert( n.isNull() ||// For a strange use in inst_match.cpp InstMatchGeneratorSimple::addInstantiations
+            var.getType() == n.getType() );
+    d_map[var] = n;
+  }
+  Node get(TNode var){ return d_map[var]; }
+  size_t size(){ return d_map.size(); }
+  /* iterator */
+  std::map< Node, Node >::iterator begin(){ return d_map.begin(); };
+  std::map< Node, Node >::iterator end(){ return d_map.end(); };
+  std::map< Node, Node >::iterator find(Node var){ return d_map.find(var); };
   /* Node used for matching the trigger only for mono-trigger (just for
      efficiency because I need only that) */
   Node d_matched;
@@ -207,67 +257,6 @@ public:
   }
 };/* class InstMatchTrieOrdered */
 
-template<bool modEq = false>
-class InstMatchTrie2 {
-private:
-
-  class Tree {
-  public:
-    typedef std::hash_map< Node, Tree *, NodeHashFunction > MLevel;
-    MLevel e;
-    const size_t level; //context level of creation
-    Tree() CVC4_UNDEFINED;
-    const Tree & operator =(const Tree & t) CVC4_UNDEFINED;
-    Tree(size_t l): level(l) {};
-    ~Tree(){
-      for(typename MLevel::iterator i = e.begin(); i!=e.end(); ++i)
-        delete(i->second);
-    };
-  };/* class InstMatchTrie2::Tree */
-
-
-  typedef std::pair<Tree *, TNode> Mod;
-
-  class CleanUp {
-  public:
-    inline void operator()(Mod * m){
-      typename Tree::MLevel::iterator i = m->first->e.find(m->second);
-      Assert (i != m->first->e.end()); //should not have been already removed
-      m->first->e.erase(i);
-    }
-  };/* class InstMatchTrie2::CleanUp */
-
-  EqualityQuery* d_eQ;
-  eq::EqualityEngine* d_eE;
-
-  /* before for the order of destruction */
-  Tree d_data;
-
-  context::Context* d_context;
-  context::CDList<Mod, CleanUp, std::allocator<Mod> > d_mods;
-
-  typedef std::map<Node, Node>::const_iterator mapIter;
-
-  /** add the substitution given by the iterator*/
-  void addSubTree( Tree* root, mapIter current, mapIter end, size_t currLevel);
-  /** test if it exists match, modulo uf-equations if modEq is true if
-   *  return false the deepest point of divergence is put in [e] and
-   *  [diverge].
-   */
-  bool existsInstMatch( Tree* root,
-                        mapIter & current, mapIter& end,
-                        Tree*& e, mapIter& diverge) const;
-
-public:
-  InstMatchTrie2(context::Context* c,  QuantifiersEngine* q);
-  InstMatchTrie2(const InstMatchTrie2&) CVC4_UNDEFINED;
-  const InstMatchTrie2& operator=(const InstMatchTrie2 & e) CVC4_UNDEFINED;
-  /** add match m in the trie,
-      modEq specify to take into account equalities,
-      return true if it was never seen */
-  bool addInstMatch( InstMatch& m);
-};/* class InstMatchTrie2 */
-
 /** base class for producing InstMatch objects */
 class IMGenerator {
 public:
@@ -405,10 +394,6 @@ public:
   int addTerm( Node f, Node t, QuantifiersEngine* qe );
 };/* class InstMatchGeneratorMulti */
 
-namespace quantifiers{
-  class TermArgTrie;
-}
-
 /** smart (single)-trigger implementation */
 class InstMatchGeneratorSimple : public IMGenerator {
 private:
@@ -438,6 +423,11 @@ public:
   int addTerm( Node f, Node t, QuantifiersEngine* qe );
 };/* class InstMatchGeneratorSimple */
 
+}/* CVC4::theory::inst namespace */
+
+typedef CVC4::theory::inst::InstMatch InstMatch;
+typedef CVC4::theory::inst::EqualityQuery EqualityQuery;
+
 }/* CVC4::theory namespace */
 }/* CVC4 namespace */
 
index a1766ce3c69fb2e31a98d14342873f5531624f41..cff16962aff5dfaf828ba688c51d9a30082125e3 100644 (file)
@@ -46,7 +46,7 @@ int InstantiatorDefault::process( Node f, Theory::Effort effort, int e ){
       if( d_quantEngine->getTheoryEngine()->theoryOf( i )==getTheory() ){    //if it belongs to this theory
         Node val = d_th->getValue( i );
         Debug("quant-default") << "Default Instantiate for " << d_th->getId() << ", setting " << i << " = " << val << std::endl;
-        m.d_map[ i ] = val;
+        m.set( i, val);
       }
     }
     d_quantEngine->addInstantiation( f, m );
index fae54c151109e1f05d5d658f6df544ffc3c16fe4..2b79cd8b9d50fc44cf6bfc0376eafdf4091c51bf 100644 (file)
@@ -104,7 +104,7 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
         int e_use = e;
         if( e_use>=0 ){
           //use each theory instantiator to instantiate f
-          for( int i=0; i<theory::THEORY_LAST; i++ ){
+          for( theory::TheoryId i=theory::THEORY_FIRST; i<theory::THEORY_LAST; ++i ){
             if( d_quantEngine->getInstantiator( i ) ){
               Debug("inst-engine-debug") << "Do " << d_quantEngine->getInstantiator( i )->identify() << " " << e_use << std::endl;
               int quantStatus = d_quantEngine->getInstantiator( i )->doInstantiation( f, effort, e_use );
@@ -126,7 +126,7 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
   //Notice() << "All instantiators finished, # added lemmas = " << (int)d_lemmas_waiting.size() << std::endl;
   if( !d_quantEngine->hasAddedLemma() ){
     Debug("inst-engine-stuck") << "No instantiations produced at this state: " << std::endl;
-    for( int i=0; i<theory::THEORY_LAST; i++ ){
+    for( theory::TheoryId i=theory::THEORY_FIRST; i<theory::THEORY_LAST; ++i ){
       if( d_quantEngine->getInstantiator( i ) ){
         d_quantEngine->getInstantiator( i )->debugPrint("inst-engine-stuck");
         Debug("inst-engine-stuck") << std::endl;
index ad259f8641f2cc95724818942e154071f491bf7d..663f270eb8ce0b438a62d425641c6298ed152455 100644 (file)
@@ -39,6 +39,7 @@ using namespace CVC4::kind;
 using namespace CVC4::context;
 using namespace CVC4::theory;
 using namespace CVC4::theory::quantifiers;
+using namespace CVC4::theory::inst;
 
 ModelEngineBuilder::ModelEngineBuilder( QuantifiersEngine* qe ) :
 TheoryEngineModelBuilder( qe->getTheoryEngine() ),
@@ -503,7 +504,7 @@ int ModelEngine::initializeQuantifier( Node f ){
       ics.push_back( ic );
       terms.push_back( t );
       //calculate the basis match for f
-      d_builder.d_quant_basis_match[f].d_map[ ic ] = t;
+      d_builder.d_quant_basis_match[f].set( ic, t);
     }
     ++(d_statistics.d_num_quants_init);
     //register model basis body
index 02041480f5ecba9d3deaf169e5d39f69afb2db50..a29f815dbf8d38531f855f3771d43f2359662277 100644 (file)
@@ -97,7 +97,7 @@ bool RepSetIterator::isFinished(){
 \r
 void RepSetIterator::getMatch( QuantifiersEngine* qe, InstMatch& m ){\r
   for( int i=0; i<(int)d_index.size(); i++ ){\r
-    m.d_map[ qe->getTermDatabase()->getInstantiationConstant( d_f, d_index_order[i] ) ] = getTerm( i );\r
+    m.set( qe->getTermDatabase()->getInstantiationConstant( d_f, d_index_order[i] ), getTerm( i ));\r
   }\r
 }\r
 \r
index 55ea693ef6a0a65049dee3e52d8cc53a7088863a..55715353dd3ab13ef51a4d371efe8c365290ff62 100644 (file)
-/*********************                                                        */\r
-/*! \file term_database.cpp\r
- ** \verbatim\r
- ** Original author: ajreynol\r
- ** Major contributors: none\r
- ** Minor contributors (to current version): none\r
- ** This file is part of the CVC4 prototype.\r
- ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)\r
- ** Courant Institute of Mathematical Sciences\r
- ** New York University\r
- ** See the file COPYING in the top-level source directory for licensing\r
- ** information.\endverbatim\r
- **\r
- ** \brief Implementation of term databse class\r
- **/\r
-\r
- #include "theory/quantifiers/term_database.h"\r
- #include "theory/quantifiers_engine.h"\r
- #include "theory/uf/theory_uf_instantiator.h"\r
- #include "theory/theory_engine.h"\r
- #include "theory/quantifiers/first_order_model.h"\r
-\r
-using namespace std;\r
-using namespace CVC4;\r
-using namespace CVC4::kind;\r
-using namespace CVC4::context;\r
-using namespace CVC4::theory;\r
-using namespace CVC4::theory::quantifiers;\r
-\r
- bool TermArgTrie::addTerm2( QuantifiersEngine* qe, Node n, int argIndex ){\r
-   if( argIndex<(int)n.getNumChildren() ){\r
-     Node r = qe->getEqualityQuery()->getRepresentative( n[ argIndex ] );\r
-     std::map< Node, TermArgTrie >::iterator it = d_data.find( r );\r
-     if( it==d_data.end() ){\r
-       d_data[r].addTerm2( qe, n, argIndex+1 );\r
-       return true;\r
-     }else{\r
-       return it->second.addTerm2( qe, n, argIndex+1 );\r
-     }\r
-   }else{\r
-     //store n in d_data (this should be interpretted as the "data" and not as a reference to a child)\r
-     d_data[n].d_data.clear();\r
-     return false;\r
-   }\r
- }\r
-\r
- void TermDb::addTerm( Node n, std::vector< Node >& added, bool withinQuant ){\r
-   //don't add terms in quantifier bodies\r
-   if( !withinQuant || Options::current()->registerQuantBodyTerms ){\r
-     if( d_processed.find( n )==d_processed.end() ){\r
-       d_processed[n] = true;\r
-       //if this is an atomic trigger, consider adding it\r
-       if( Trigger::isAtomicTrigger( n ) ){\r
-         if( !n.hasAttribute(InstConstantAttribute()) ){\r
-           Debug("term-db") << "register trigger term " << n << std::endl;\r
-           //Notice() << "register trigger term " << n << std::endl;\r
-           Node op = n.getOperator();\r
-           d_op_map[op].push_back( n );\r
-           d_type_map[ n.getType() ].push_back( n );\r
-           added.push_back( n );\r
-\r
-           uf::InstantiatorTheoryUf* d_ith = (uf::InstantiatorTheoryUf*)d_quantEngine->getInstantiator( THEORY_UF );\r
-           for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
-             addTerm( n[i], added, withinQuant );\r
-             if( Options::current()->efficientEMatching ){\r
-               if( d_parents[n[i]][op].empty() ){\r
-                 //must add parent to equivalence class info\r
-                 Node nir = d_ith->getRepresentative( n[i] );\r
-                 uf::EqClassInfo* eci_nir = d_ith->getEquivalenceClassInfo( nir );\r
-                 if( eci_nir ){\r
-                   eci_nir->d_pfuns[ op ] = true;\r
-                 }\r
-               }\r
-               //add to parent structure\r
-               if( std::find( d_parents[n[i]][op][i].begin(), d_parents[n[i]][op][i].end(), n )==d_parents[n[i]][op][i].end() ){\r
-                 d_parents[n[i]][op][i].push_back( n );\r
-               }\r
-             }\r
-           }\r
-           if( Options::current()->efficientEMatching ){\r
-             //new term, add n to candidate generators\r
-             for( int i=0; i<(int)d_ith->d_cand_gens[op].size(); i++ ){\r
-               d_ith->d_cand_gens[op][i]->addCandidate( n );\r
-             }\r
-           }\r
-           if( Options::current()->eagerInstQuant ){\r
-             if( !n.hasAttribute(InstLevelAttribute()) && n.getAttribute(InstLevelAttribute())==0 ){\r
-               int addedLemmas = 0;\r
-               for( int i=0; i<(int)d_ith->d_op_triggers[op].size(); i++ ){\r
-                 addedLemmas += d_ith->d_op_triggers[op][i]->addTerm( n );\r
-               }\r
-               //Message() << "Terms, added lemmas: " << addedLemmas << std::endl;\r
-               d_quantEngine->flushLemmas( &d_quantEngine->getTheoryEngine()->getTheory( THEORY_QUANTIFIERS )->getOutputChannel() );\r
-             }\r
-           }\r
-         }\r
-       }\r
-       for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
-         addTerm( n[i], added, withinQuant );\r
-       }\r
-     }\r
-   }\r
- }\r
-\r
- void TermDb::reset( Theory::Effort effort ){\r
-   int nonCongruentCount = 0;\r
-   int congruentCount = 0;\r
-   int alreadyCongruentCount = 0;\r
-   //rebuild d_func/pred_map_trie for each operation, this will calculate all congruent terms\r
-   for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){\r
-     if( !it->second.empty() ){\r
-       if( it->second[0].getType()==NodeManager::currentNM()->booleanType() ){\r
-         d_pred_map_trie[ 0 ][ it->first ].d_data.clear();\r
-         d_pred_map_trie[ 1 ][ it->first ].d_data.clear();\r
-       }else{\r
-         d_func_map_trie[ it->first ].d_data.clear();\r
-         for( int i=0; i<(int)it->second.size(); i++ ){\r
-           Node n = it->second[i];\r
-           if( !n.getAttribute(NoMatchAttribute()) ){\r
-             if( !d_func_map_trie[ it->first ].addTerm( d_quantEngine, n ) ){\r
-               NoMatchAttribute nma;\r
-               n.setAttribute(nma,true);\r
-               congruentCount++;\r
-             }else{\r
-               nonCongruentCount++;\r
-             }\r
-           }else{\r
-             congruentCount++;\r
-             alreadyCongruentCount++;\r
-           }\r
-         }\r
-       }\r
-     }\r
-   }\r
-   for( int i=0; i<2; i++ ){\r
-     Node n = NodeManager::currentNM()->mkConst( i==1 );\r
-     eq::EqClassIterator eqc( d_quantEngine->getEqualityQuery()->getRepresentative( n ),\r
-                               ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine() );\r
-     while( !eqc.isFinished() ){\r
-       Node en = (*eqc);\r
-       if( en.getKind()==APPLY_UF && !en.hasAttribute(InstConstantAttribute()) ){\r
-         if( !en.getAttribute(NoMatchAttribute()) ){\r
-           Node op = en.getOperator();\r
-           if( !d_pred_map_trie[i][op].addTerm( d_quantEngine, en ) ){\r
-             NoMatchAttribute nma;\r
-             en.setAttribute(nma,true);\r
-             congruentCount++;\r
-           }else{\r
-             nonCongruentCount++;\r
-           }\r
-         }else{\r
-           alreadyCongruentCount++;\r
-         }\r
-       }\r
-       ++eqc;\r
-     }\r
-   }\r
-   Debug("term-db-cong") << "TermDb: Reset" << std::endl;\r
-   Debug("term-db-cong") << "Congruent/Non-Congruent = ";\r
-   Debug("term-db-cong") << congruentCount << "(" << alreadyCongruentCount << ") / " << nonCongruentCount << std::endl;\r
-}\r
-\r
-void TermDb::registerModelBasis( Node n, Node gn ){\r
-  if( d_model_basis.find( n )==d_model_basis.end() ){\r
-    d_model_basis[n] = gn;\r
-    for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
-      registerModelBasis( n[i], gn[i] );\r
-    }\r
-  }\r
-}\r
-\r
-Node TermDb::getModelBasisTerm( TypeNode tn, int i ){\r
-  if( d_model_basis_term.find( tn )==d_model_basis_term.end() ){\r
-    std::stringstream ss;\r
-    ss << Expr::setlanguage(Options::current()->outputLanguage);\r
-    ss << "e_" << tn;\r
-    d_model_basis_term[tn] = NodeManager::currentNM()->mkVar( ss.str(), tn );\r
-    ModelBasisAttribute mba;\r
-    d_model_basis_term[tn].setAttribute(mba,true);\r
-  }\r
-  return d_model_basis_term[tn];\r
-}\r
-\r
-Node TermDb::getModelBasisOpTerm( Node op ){\r
-  if( d_model_basis_op_term.find( op )==d_model_basis_op_term.end() ){\r
-    TypeNode t = op.getType();\r
-    std::vector< Node > children;\r
-    children.push_back( op );\r
-    for( size_t i=0; i<t.getNumChildren()-1; i++ ){\r
-      children.push_back( getModelBasisTerm( t[i] ) );\r
-    }\r
-    d_model_basis_op_term[op] = NodeManager::currentNM()->mkNode( APPLY_UF, children );\r
-  }\r
-  return d_model_basis_op_term[op];\r
-}\r
-\r
-void TermDb::computeModelBasisArgAttribute( Node n ){\r
-  if( !n.hasAttribute(ModelBasisArgAttribute()) ){\r
-    uint64_t val = 0;\r
-    //determine if it has model basis attribute\r
-    for( int j=0; j<(int)n.getNumChildren(); j++ ){\r
-      if( n[j].getAttribute(ModelBasisAttribute()) ){\r
-        val = 1;\r
-        break;\r
-      }\r
-    }\r
-    ModelBasisArgAttribute mbaa;\r
-    n.setAttribute( mbaa, val );\r
-  }\r
-}\r
-\r
-void TermDb::makeInstantiationConstantsFor( Node f ){\r
-  if( d_inst_constants.find( f )==d_inst_constants.end() ){\r
-    Debug("quantifiers-engine") << "Instantiation constants for " << f << " : " << std::endl;\r
-    for( int i=0; i<(int)f[0].getNumChildren(); i++ ){\r
-      d_vars[f].push_back( f[0][i] );\r
-      //make instantiation constants\r
-      Node ic = NodeManager::currentNM()->mkInstConstant( f[0][i].getType() );\r
-      d_inst_constants_map[ic] = f;\r
-      d_inst_constants[ f ].push_back( ic );\r
-      Debug("quantifiers-engine") << "  " << ic << std::endl;\r
-      //set the var number attribute\r
-      InstVarNumAttribute ivna;\r
-      ic.setAttribute(ivna,i);\r
-    }\r
-  }\r
-}\r
-\r
-void TermDb::setInstantiationLevelAttr( Node n, uint64_t level ){\r
-  if( !n.hasAttribute(InstLevelAttribute()) ){\r
-    InstLevelAttribute ila;\r
-    n.setAttribute(ila,level);\r
-  }\r
-  for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
-    setInstantiationLevelAttr( n[i], level );\r
-  }\r
-}\r
-\r
-\r
-void TermDb::setInstantiationConstantAttr( Node n, Node f ){\r
-  if( !n.hasAttribute(InstConstantAttribute()) ){\r
-    bool setAttr = false;\r
-    if( n.getKind()==INST_CONSTANT ){\r
-      setAttr = true;\r
-    }else{\r
-      for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
-        setInstantiationConstantAttr( n[i], f );\r
-        if( n[i].hasAttribute(InstConstantAttribute()) ){\r
-          setAttr = true;\r
-        }\r
-      }\r
-    }\r
-    if( setAttr ){\r
-      InstConstantAttribute ica;\r
-      n.setAttribute(ica,f);\r
-      //also set the no-match attribute\r
-      NoMatchAttribute nma;\r
-      n.setAttribute(nma,true);\r
-    }\r
-  }\r
-}\r
-\r
-\r
-Node TermDb::getCounterexampleBody( Node f ){\r
-  std::map< Node, Node >::iterator it = d_counterexample_body.find( f );\r
-  if( it==d_counterexample_body.end() ){\r
-    makeInstantiationConstantsFor( f );\r
-    Node n = getSubstitutedNode( f[1], f );\r
-    d_counterexample_body[ f ] = n;\r
-    return n;\r
-  }else{\r
-    return it->second;\r
-  }\r
-}\r
-\r
-Node TermDb::getSkolemizedBody( Node f ){\r
-  Assert( f.getKind()==FORALL );\r
-  if( d_skolem_body.find( f )==d_skolem_body.end() ){\r
-    std::vector< Node > vars;\r
-    for( int i=0; i<(int)f[0].getNumChildren(); i++ ){\r
-      Node skv = NodeManager::currentNM()->mkSkolem( f[0][i].getType() );\r
-      d_skolem_constants[ f ].push_back( skv );\r
-      vars.push_back( f[0][i] );\r
-    }\r
-    d_skolem_body[ f ] = f[ 1 ].substitute( vars.begin(), vars.end(),\r
-                                            d_skolem_constants[ f ].begin(), d_skolem_constants[ f ].end() );\r
-    if( f.hasAttribute(InstLevelAttribute()) ){\r
-      setInstantiationLevelAttr( d_skolem_body[ f ], f.getAttribute(InstLevelAttribute()) );\r
-    }\r
-  }\r
-  return d_skolem_body[ f ];\r
-}\r
-\r
-\r
-Node TermDb::getSubstitutedNode( Node n, Node f ){\r
-  return convertNodeToPattern(n,f,d_vars[f],d_inst_constants[ f ]);\r
-}\r
-\r
-Node TermDb::convertNodeToPattern( Node n, Node f, const std::vector<Node> & vars,\r
-                                              const std::vector<Node> & inst_constants){\r
-  Node n2 = n.substitute( vars.begin(), vars.end(),\r
-                          inst_constants.begin(),\r
-                          inst_constants.end() );\r
-  setInstantiationConstantAttr( n2, f );\r
-  return n2;\r
-}\r
-\r
-Node TermDb::getFreeVariableForInstConstant( Node n ){\r
-  TypeNode tn = n.getType();\r
-  if( d_free_vars.find( tn )==d_free_vars.end() ){\r
-    //if integer or real, make zero\r
-    if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){\r
-      Rational z(0);\r
-      d_free_vars[tn] = NodeManager::currentNM()->mkConst( z );\r
-    }else{\r
-      if( d_type_map[ tn ].empty() ){\r
-        d_free_vars[tn] = NodeManager::currentNM()->mkVar( tn );\r
-      }else{\r
-        d_free_vars[tn] = d_type_map[ tn ][ 0 ];\r
-      }\r
-    }\r
-  }\r
-  return d_free_vars[tn];\r
-}
\ No newline at end of file
+/*********************                                                        */
+/*! \file term_database.cpp
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: none
+ ** Minor contributors (to current version): bobot
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Implementation of term databse class
+ **/
+
+ #include "theory/quantifiers/term_database.h"
+ #include "theory/quantifiers_engine.h"
+ #include "theory/uf/theory_uf_instantiator.h"
+ #include "theory/theory_engine.h"
+ #include "theory/quantifiers/first_order_model.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+
+using namespace CVC4::theory::inst;
+ bool TermArgTrie::addTerm2( QuantifiersEngine* qe, Node n, int argIndex ){
+   if( argIndex<(int)n.getNumChildren() ){
+     Node r = qe->getEqualityQuery()->getRepresentative( n[ argIndex ] );
+     std::map< Node, TermArgTrie >::iterator it = d_data.find( r );
+     if( it==d_data.end() ){
+       d_data[r].addTerm2( qe, n, argIndex+1 );
+       return true;
+     }else{
+       return it->second.addTerm2( qe, n, argIndex+1 );
+     }
+   }else{
+     //store n in d_data (this should be interpretted as the "data" and not as a reference to a child)
+     d_data[n].d_data.clear();
+     return false;
+   }
+ }
+
+void addTermEfficient( Node n, std::set< Node >& added){
+  static AvailableInTermDb aitdi;
+  if (Trigger::isAtomicTrigger( n ) && !n.getAttribute(aitdi)){
+    //Already processed but new in this branch
+    n.setAttribute(aitdi,true);
+    added.insert( n );
+    for( size_t i=0; i< n.getNumChildren(); i++ ){
+      addTermEfficient(n[i],added);
+    }
+  }
+
+}
+
+
+void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant ){
+   //don't add terms in quantifier bodies
+  if( withinQuant && !Options::current()->registerQuantBodyTerms ){
+    return;
+  }
+     if( d_processed.find( n )==d_processed.end() ){
+    ++(d_quantEngine->d_statistics.d_term_in_termdb);
+    d_processed.insert(n);
+    n.setAttribute(AvailableInTermDb(),true);
+       //if this is an atomic trigger, consider adding it
+    //Call the children?
+    if( Trigger::isAtomicTrigger( n ) || n.getKind() == kind::APPLY_CONSTRUCTOR ){
+         if( !n.hasAttribute(InstConstantAttribute()) ){
+           Debug("term-db") << "register trigger term " << n << std::endl;
+        //std::cout << "register trigger term " << n << std::endl;
+           Node op = n.getOperator();
+           d_op_map[op].push_back( n );
+           d_type_map[ n.getType() ].push_back( n );
+        added.insert( n );
+
+           uf::InstantiatorTheoryUf* d_ith = (uf::InstantiatorTheoryUf*)d_quantEngine->getInstantiator( THEORY_UF );
+           for( int i=0; i<(int)n.getNumChildren(); i++ ){
+             addTerm( n[i], added, withinQuant );
+             if( Options::current()->efficientEMatching ){
+               if( d_parents[n[i]][op].empty() ){
+                 //must add parent to equivalence class info
+                 Node nir = d_ith->getRepresentative( n[i] );
+                 uf::EqClassInfo* eci_nir = d_ith->getEquivalenceClassInfo( nir );
+                 if( eci_nir ){
+                   eci_nir->d_pfuns[ op ] = true;
+                 }
+               }
+               //add to parent structure
+               if( std::find( d_parents[n[i]][op][i].begin(), d_parents[n[i]][op][i].end(), n )==d_parents[n[i]][op][i].end() ){
+                 d_parents[n[i]][op][i].push_back( n );
+              Assert(!getParents(n[i],op,i).empty());
+             }
+           }
+           if( Options::current()->eagerInstQuant ){
+             if( !n.hasAttribute(InstLevelAttribute()) && n.getAttribute(InstLevelAttribute())==0 ){
+               int addedLemmas = 0;
+               for( int i=0; i<(int)d_ith->d_op_triggers[op].size(); i++ ){
+                 addedLemmas += d_ith->d_op_triggers[op][i]->addTerm( n );
+               }
+               //Message() << "Terms, added lemmas: " << addedLemmas << std::endl;
+               d_quantEngine->flushLemmas( &d_quantEngine->getTheoryEngine()->getTheory( THEORY_QUANTIFIERS )->getOutputChannel() );
+             }
+           }
+         }
+       }
+    }else{
+       for( int i=0; i<(int)n.getNumChildren(); i++ ){
+         addTerm( n[i], added, withinQuant );
+       }
+     }
+  }else{
+     if( Options::current()->efficientEMatching &&
+         !n.hasAttribute(InstConstantAttribute())){
+       //Efficient e-matching must be notified
+       //The term in triggers are not important here
+       Debug("term-db") << "New in this branch term " << n << std::endl;
+       addTermEfficient(n,added);
+   }
+ }
+};
+
+ void TermDb::reset( Theory::Effort effort ){
+   int nonCongruentCount = 0;
+   int congruentCount = 0;
+   int alreadyCongruentCount = 0;
+   //rebuild d_func/pred_map_trie for each operation, this will calculate all congruent terms
+   for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){
+     if( !it->second.empty() ){
+       if( it->second[0].getType()==NodeManager::currentNM()->booleanType() ){
+         d_pred_map_trie[ 0 ][ it->first ].d_data.clear();
+         d_pred_map_trie[ 1 ][ it->first ].d_data.clear();
+       }else{
+         d_func_map_trie[ it->first ].d_data.clear();
+         for( int i=0; i<(int)it->second.size(); i++ ){
+           Node n = it->second[i];
+           if( !n.getAttribute(NoMatchAttribute()) ){
+             if( !d_func_map_trie[ it->first ].addTerm( d_quantEngine, n ) ){
+               NoMatchAttribute nma;
+               n.setAttribute(nma,true);
+               congruentCount++;
+             }else{
+               nonCongruentCount++;
+             }
+           }else{
+             congruentCount++;
+             alreadyCongruentCount++;
+           }
+         }
+       }
+     }
+   }
+   for( int i=0; i<2; i++ ){
+     Node n = NodeManager::currentNM()->mkConst( i==1 );
+     eq::EqClassIterator eqc( d_quantEngine->getEqualityQuery()->getRepresentative( n ),
+                               ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine() );
+     while( !eqc.isFinished() ){
+       Node en = (*eqc);
+       if( en.getKind()==APPLY_UF && !en.hasAttribute(InstConstantAttribute()) ){
+         if( !en.getAttribute(NoMatchAttribute()) ){
+           Node op = en.getOperator();
+           if( !d_pred_map_trie[i][op].addTerm( d_quantEngine, en ) ){
+             NoMatchAttribute nma;
+             en.setAttribute(nma,true);
+             congruentCount++;
+           }else{
+             nonCongruentCount++;
+           }
+         }else{
+           alreadyCongruentCount++;
+         }
+       }
+       ++eqc;
+     }
+   }
+   Debug("term-db-cong") << "TermDb: Reset" << std::endl;
+   Debug("term-db-cong") << "Congruent/Non-Congruent = ";
+   Debug("term-db-cong") << congruentCount << "(" << alreadyCongruentCount << ") / " << nonCongruentCount << std::endl;
+}
+
+void TermDb::registerModelBasis( Node n, Node gn ){
+  if( d_model_basis.find( n )==d_model_basis.end() ){
+    d_model_basis[n] = gn;
+    for( int i=0; i<(int)n.getNumChildren(); i++ ){
+      registerModelBasis( n[i], gn[i] );
+    }
+  }
+}
+
+Node TermDb::getModelBasisTerm( TypeNode tn, int i ){
+  if( d_model_basis_term.find( tn )==d_model_basis_term.end() ){
+    std::stringstream ss;
+    ss << Expr::setlanguage(Options::current()->outputLanguage);
+    ss << "e_" << tn;
+    d_model_basis_term[tn] = NodeManager::currentNM()->mkVar( ss.str(), tn );
+    ModelBasisAttribute mba;
+    d_model_basis_term[tn].setAttribute(mba,true);
+  }
+  return d_model_basis_term[tn];
+}
+
+Node TermDb::getModelBasisOpTerm( Node op ){
+  if( d_model_basis_op_term.find( op )==d_model_basis_op_term.end() ){
+    TypeNode t = op.getType();
+    std::vector< Node > children;
+    children.push_back( op );
+    for( size_t i=0; i<t.getNumChildren()-1; i++ ){
+      children.push_back( getModelBasisTerm( t[i] ) );
+    }
+    d_model_basis_op_term[op] = NodeManager::currentNM()->mkNode( APPLY_UF, children );
+  }
+  return d_model_basis_op_term[op];
+}
+
+void TermDb::computeModelBasisArgAttribute( Node n ){
+  if( !n.hasAttribute(ModelBasisArgAttribute()) ){
+    uint64_t val = 0;
+    //determine if it has model basis attribute
+    for( int j=0; j<(int)n.getNumChildren(); j++ ){
+      if( n[j].getAttribute(ModelBasisAttribute()) ){
+        val = 1;
+        break;
+      }
+    }
+    ModelBasisArgAttribute mbaa;
+    n.setAttribute( mbaa, val );
+  }
+}
+
+void TermDb::makeInstantiationConstantsFor( Node f ){
+  if( d_inst_constants.find( f )==d_inst_constants.end() ){
+    Debug("quantifiers-engine") << "Instantiation constants for " << f << " : " << std::endl;
+    for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
+      d_vars[f].push_back( f[0][i] );
+      //make instantiation constants
+      Node ic = NodeManager::currentNM()->mkInstConstant( f[0][i].getType() );
+      d_inst_constants_map[ic] = f;
+      d_inst_constants[ f ].push_back( ic );
+      Debug("quantifiers-engine") << "  " << ic << std::endl;
+      //set the var number attribute
+      InstVarNumAttribute ivna;
+      ic.setAttribute(ivna,i);
+    }
+  }
+}
+
+void TermDb::setInstantiationLevelAttr( Node n, uint64_t level ){
+  if( !n.hasAttribute(InstLevelAttribute()) ){
+    InstLevelAttribute ila;
+    n.setAttribute(ila,level);
+  }
+  for( int i=0; i<(int)n.getNumChildren(); i++ ){
+    setInstantiationLevelAttr( n[i], level );
+  }
+}
+
+
+void TermDb::setInstantiationConstantAttr( Node n, Node f ){
+  if( !n.hasAttribute(InstConstantAttribute()) ){
+    bool setAttr = false;
+    if( n.getKind()==INST_CONSTANT ){
+      setAttr = true;
+    }else{
+      for( int i=0; i<(int)n.getNumChildren(); i++ ){
+        setInstantiationConstantAttr( n[i], f );
+        if( n[i].hasAttribute(InstConstantAttribute()) ){
+          setAttr = true;
+        }
+      }
+    }
+    if( setAttr ){
+      InstConstantAttribute ica;
+      n.setAttribute(ica,f);
+      //also set the no-match attribute
+      NoMatchAttribute nma;
+      n.setAttribute(nma,true);
+    }
+  }
+}
+
+
+Node TermDb::getCounterexampleBody( Node f ){
+  std::map< Node, Node >::iterator it = d_counterexample_body.find( f );
+  if( it==d_counterexample_body.end() ){
+    makeInstantiationConstantsFor( f );
+    Node n = getSubstitutedNode( f[1], f );
+    d_counterexample_body[ f ] = n;
+    return n;
+  }else{
+    return it->second;
+  }
+}
+
+Node TermDb::getSkolemizedBody( Node f ){
+  Assert( f.getKind()==FORALL );
+  if( d_skolem_body.find( f )==d_skolem_body.end() ){
+    std::vector< Node > vars;
+    for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
+      Node skv = NodeManager::currentNM()->mkSkolem( f[0][i].getType() );
+      d_skolem_constants[ f ].push_back( skv );
+      vars.push_back( f[0][i] );
+    }
+    d_skolem_body[ f ] = f[ 1 ].substitute( vars.begin(), vars.end(),
+                                            d_skolem_constants[ f ].begin(), d_skolem_constants[ f ].end() );
+    if( f.hasAttribute(InstLevelAttribute()) ){
+      setInstantiationLevelAttr( d_skolem_body[ f ], f.getAttribute(InstLevelAttribute()) );
+    }
+  }
+  return d_skolem_body[ f ];
+}
+
+
+Node TermDb::getSubstitutedNode( Node n, Node f ){
+  return convertNodeToPattern(n,f,d_vars[f],d_inst_constants[ f ]);
+}
+
+Node TermDb::convertNodeToPattern( Node n, Node f, const std::vector<Node> & vars,
+                                              const std::vector<Node> & inst_constants){
+  Node n2 = n.substitute( vars.begin(), vars.end(),
+                          inst_constants.begin(),
+                          inst_constants.end() );
+  setInstantiationConstantAttr( n2, f );
+  return n2;
+}
+
+Node TermDb::getFreeVariableForInstConstant( Node n ){
+  TypeNode tn = n.getType();
+  if( d_free_vars.find( tn )==d_free_vars.end() ){
+    //if integer or real, make zero
+    if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){
+      Rational z(0);
+      d_free_vars[tn] = NodeManager::currentNM()->mkConst( z );
+    }else{
+      if( d_type_map[ tn ].empty() ){
+        d_free_vars[tn] = NodeManager::currentNM()->mkVar( tn );
+      }else{
+        d_free_vars[tn] = d_type_map[ tn ][ 0 ];
+      }
+    }
+  }
+  return d_free_vars[tn];
+}
+
+const std::vector<Node> & TermDb::getParents(TNode n, TNode f, int arg){
+  std::hash_map< Node, std::hash_map< Node, std::hash_map< int, std::vector< Node > >,NodeHashFunction  >,NodeHashFunction  >::const_iterator
+    rn = d_parents.find( n );
+  if( rn !=d_parents.end() ){
+    std::hash_map< Node, std::hash_map< int, std::vector< Node > > , NodeHashFunction  > ::const_iterator
+      rf = rn->second.find(f);
+    if( rf != rn->second.end() ){
+      std::hash_map< int, std::vector< Node > > ::const_iterator
+        ra = rf->second.find(arg);
+      if( ra != rf->second.end() ){
+        return ra->second;
+      }
+    }
+  }
+  static std::vector<Node> empty;
+  return empty;
+}
index 5bf3d7900ef656d2efbee931fb13e4c96baa6835..5004a82dc1b668ca539cbae62e03cb8229c7f941 100644 (file)
@@ -48,7 +48,7 @@ private:
   /** calculated no match terms */\r
   bool d_matching_active;\r
   /** terms processed */\r
-  std::map< Node, bool > d_processed;\r
+  std::hash_set< Node, NodeHashFunction > d_processed;\r
 public:\r
   TermDb( QuantifiersEngine* qe ) : d_quantEngine( qe ), d_matching_active( true ){}\r
   ~TermDb(){}\r
@@ -61,7 +61,7 @@ public:
   /** map from type nodes to terms of that type */\r
   std::map< TypeNode, std::vector< Node > > d_type_map;\r
   /** add a term to the database */\r
-  void addTerm( Node n, std::vector< Node >& added, bool withinQuant = false );\r
+  void addTerm( Node n, std::set< Node >& added, bool withinQuant = false );\r
   /** reset (calculate which terms are active) */\r
   void reset( Theory::Effort effort );\r
   /** set active */\r
@@ -75,7 +75,9 @@ public:
         has operator "op", and n'["index"] = n.\r
       for example, d_parents[n][f][1] = { f( t1, n ), f( t2, n ), ... }\r
   */\r
-  std::map< Node, std::map< Node, std::map< int, std::vector< Node > > > > d_parents;\r
+  /* Todo replace int by size_t */\r
+  std::hash_map< Node, std::hash_map< Node, std::hash_map< int, std::vector< Node >  >, NodeHashFunction  > , NodeHashFunction > d_parents;\r
+  const std::vector<Node> & getParents(TNode n, TNode f, int arg);\r
 private:\r
   //map from types to model basis terms\r
   std::map< TypeNode, Node > d_model_basis_term;\r
index 517786400d89b8ed557275dc062378bf7bce6683..1e42abd22630515083fd620c2b42f422f306f021 100644 (file)
 #include <map>
 
 namespace CVC4 {
+class TheoryEngine;
+
 namespace theory {
 namespace quantifiers {
 
-class TheoryEngine;
 class ModelEngine;
 class InstantiationEngine;
 
index e4e3df9beb3abea2a8a73f6ac1881669a4aef90b..448224b81c02439b60f6d467f9eff321fb9641a9 100644 (file)
@@ -32,6 +32,7 @@ using namespace CVC4;
 using namespace CVC4::kind;
 using namespace CVC4::context;
 using namespace CVC4::theory;
+using namespace CVC4::theory::inst;
 
 //#define COMPUTE_RELEVANCE
 //#define REWRITE_ASSERTED_QUANTIFIERS
@@ -93,7 +94,11 @@ d_active( c ){
   d_optInstLimit = 0;
 }
 
-Instantiator* QuantifiersEngine::getInstantiator( int id ){
+QuantifiersEngine::~QuantifiersEngine(){
+  delete(d_term_db);
+}
+
+Instantiator* QuantifiersEngine::getInstantiator( theory::TheoryId id ){
   return d_te->getTheory( id )->getInstantiator();
 }
 
@@ -212,7 +217,7 @@ void QuantifiersEngine::registerQuantifier( Node f ){
 
 void QuantifiersEngine::registerPattern( std::vector<Node> & pattern) {
   for(std::vector<Node>::iterator p = pattern.begin(); p != pattern.end(); ++p){
-    std::vector< Node > added;
+    std::set< Node > added;
     getTermDatabase()->addTerm(*p,added);
   }
 }
@@ -236,7 +241,7 @@ void QuantifiersEngine::propagate( Theory::Effort level ){
 }
 
 void QuantifiersEngine::resetInstantiationRound( Theory::Effort level ){
-  for( int i=0; i<theory::THEORY_LAST; i++ ){
+  for( theory::TheoryId i=theory::THEORY_FIRST; i<theory::THEORY_LAST; ++i ){
     if( getInstantiator( i ) ){
       getInstantiator( i )->resetInstantiationRound( level );
     }
@@ -245,13 +250,19 @@ void QuantifiersEngine::resetInstantiationRound( Theory::Effort level ){
 }
 
 void QuantifiersEngine::addTermToDatabase( Node n, bool withinQuant ){
-  std::vector< Node > added;
-  getTermDatabase()->addTerm( n, added, withinQuant );
-#ifdef COMPUTE_RELEVANCE
-  for( int i=0; i<(int)added.size(); i++ ){
-    if( !withinQuant ){
-      setRelevance( added[i].getOperator(), 0 );
+    std::set< Node > added;
+    getTermDatabase()->addTerm( n, added, withinQuant );
+    if( Options::current()->efficientEMatching ){
+      uf::InstantiatorTheoryUf* d_ith = (uf::InstantiatorTheoryUf*)getInstantiator( THEORY_UF );
+      d_ith->newTerms(added);
     }
+#ifdef COMPUTE_RELEVANCE
+    //added contains also the Node that just have been asserted in this branch
+    for( std::set< Node >::iterator i=added.begin(), end=added.end();
+         i!=end; i++ ){
+      if( !withinQuant ){
+        setRelevance( i->getOperator(), 0 );
+      }
   }
 #endif
 
@@ -530,7 +541,15 @@ QuantifiersEngine::Statistics::Statistics():
   d_triggers("QuantifiersEngine::Triggers", 0),
   d_simple_triggers("QuantifiersEngine::Triggers_Simple", 0),
   d_multi_triggers("QuantifiersEngine::Triggers_Multi", 0),
-  d_multi_trigger_instantiations("QuantifiersEngine::Multi_Trigger_Instantiations", 0)
+  d_multi_trigger_instantiations("QuantifiersEngine::Multi_Trigger_Instantiations", 0),
+  d_term_in_termdb("QuantifiersEngine::Term_in_TermDb", 0),
+  d_num_mono_candidates("QuantifiersEngine::NumMonoCandidates", 0),
+  d_num_mono_candidates_new_term("QuantifiersEngine::NumMonoCandidatesNewTerm", 0),
+  d_num_multi_candidates("QuantifiersEngine::NumMultiCandidates", 0),
+  d_mono_candidates_cache_hit("QuantifiersEngine::MonoCandidatesCacheHit", 0),
+  d_mono_candidates_cache_miss("QuantifiersEngine::MonoCandidatesCacheMiss", 0),
+  d_multi_candidates_cache_hit("QuantifiersEngine::MultiCandidatesCacheHit", 0),
+  d_multi_candidates_cache_miss("QuantifiersEngine::MultiCandidatesCacheMiss", 0)
 {
   StatisticsRegistry::registerStat(&d_num_quant);
   StatisticsRegistry::registerStat(&d_instantiation_rounds);
@@ -548,6 +567,14 @@ QuantifiersEngine::Statistics::Statistics():
   StatisticsRegistry::registerStat(&d_simple_triggers);
   StatisticsRegistry::registerStat(&d_multi_triggers);
   StatisticsRegistry::registerStat(&d_multi_trigger_instantiations);
+  StatisticsRegistry::registerStat(&d_term_in_termdb);
+  StatisticsRegistry::registerStat(&d_num_mono_candidates);
+  StatisticsRegistry::registerStat(&d_num_mono_candidates_new_term);
+  StatisticsRegistry::registerStat(&d_num_multi_candidates);
+  StatisticsRegistry::registerStat(&d_mono_candidates_cache_hit);
+  StatisticsRegistry::registerStat(&d_mono_candidates_cache_miss);
+  StatisticsRegistry::registerStat(&d_multi_candidates_cache_hit);
+  StatisticsRegistry::registerStat(&d_multi_candidates_cache_miss);
 }
 
 QuantifiersEngine::Statistics::~Statistics(){
@@ -567,6 +594,14 @@ QuantifiersEngine::Statistics::~Statistics(){
   StatisticsRegistry::unregisterStat(&d_simple_triggers);
   StatisticsRegistry::unregisterStat(&d_multi_triggers);
   StatisticsRegistry::unregisterStat(&d_multi_trigger_instantiations);
+  StatisticsRegistry::unregisterStat(&d_term_in_termdb);
+  StatisticsRegistry::unregisterStat(&d_num_mono_candidates);
+  StatisticsRegistry::unregisterStat(&d_num_mono_candidates_new_term);
+  StatisticsRegistry::unregisterStat(&d_num_multi_candidates);
+  StatisticsRegistry::unregisterStat(&d_mono_candidates_cache_hit);
+  StatisticsRegistry::unregisterStat(&d_mono_candidates_cache_miss);
+  StatisticsRegistry::unregisterStat(&d_multi_candidates_cache_hit);
+  StatisticsRegistry::unregisterStat(&d_multi_candidates_cache_miss);
 }
 
 /** compute symbols */
@@ -608,7 +643,7 @@ bool EqualityQueryQuantifiersEngine::hasTerm( Node a ){
   if( ee->hasTerm( a ) ){
     return true;
   }
-  for( int i=0; i<theory::THEORY_LAST; i++ ){
+  for( theory::TheoryId i=theory::THEORY_FIRST; i<theory::THEORY_LAST; ++i ){
     if( d_qe->getInstantiator( i ) ){
       if( d_qe->getInstantiator( i )->hasTerm( a ) ){
         return true;
@@ -623,7 +658,7 @@ Node EqualityQueryQuantifiersEngine::getRepresentative( Node a ){
   if( ee->hasTerm( a ) ){
     return ee->getRepresentative( a );
   }
-  for( int i=0; i<theory::THEORY_LAST; i++ ){
+  for( theory::TheoryId i=theory::THEORY_FIRST; i<theory::THEORY_LAST; ++i ){
     if( d_qe->getInstantiator( i ) ){
       if( d_qe->getInstantiator( i )->hasTerm( a ) ){
         return d_qe->getInstantiator( i )->getRepresentative( a );
@@ -643,7 +678,7 @@ bool EqualityQueryQuantifiersEngine::areEqual( Node a, Node b ){
         return true;
       }
     }
-    for( int i=0; i<theory::THEORY_LAST; i++ ){
+    for( theory::TheoryId i=theory::THEORY_FIRST; i<theory::THEORY_LAST; ++i ){
       if( d_qe->getInstantiator( i ) ){
         if( d_qe->getInstantiator( i )->areEqual( a, b ) ){
           return true;
@@ -662,7 +697,7 @@ bool EqualityQueryQuantifiersEngine::areDisequal( Node a, Node b ){
       return true;
     }
   }
-  for( int i=0; i<theory::THEORY_LAST; i++ ){
+  for( theory::TheoryId i=theory::THEORY_FIRST; i<theory::THEORY_LAST; ++i ){
     if( d_qe->getInstantiator( i ) ){
       if( d_qe->getInstantiator( i )->areDisequal( a, b ) ){
         return true;
@@ -674,7 +709,7 @@ bool EqualityQueryQuantifiersEngine::areDisequal( Node a, Node b ){
 }
 
 Node EqualityQueryQuantifiersEngine::getInternalRepresentative( Node a ){
-  //for( int i=0; i<theory::THEORY_LAST; i++ ){
+  //for( theory::TheoryId i=theory::THEORY_FIRST; i<theory::THEORY_LAST; ++i ){
   //  if( d_qe->getInstantiator( i ) ){
   //    if( d_qe->getInstantiator( i )->hasTerm( a ) ){
   //      return d_qe->getInstantiator( i )->getInternalRepresentative( a );
@@ -684,3 +719,217 @@ Node EqualityQueryQuantifiersEngine::getInternalRepresentative( Node a ){
   //return a;
   return d_qe->getInstantiator( THEORY_UF )->getInternalRepresentative( a );
 }
+
+inst::EqualityQuery* QuantifiersEngine::getEqualityQuery(TypeNode t) {
+  /** Should use skeleton (in order to have the type and the kind
+      or any needed other information) instead of only the type */
+
+  // TheoryId id = Theory::theoryOf(t);
+  // inst::EqualityQuery* eq = d_eq_query_arr[id];
+  // if(eq == NULL) return d_eq_query_arr[theory::THEORY_UF];
+  // else return eq;
+
+  /** hack because the generic one is too slow */
+  // TheoryId id = Theory::theoryOf(t);
+  // if( true || id == theory::THEORY_UF){
+  //   uf::InstantiatorTheoryUf* ith = static_cast<uf::InstantiatorTheoryUf*>( getInstantiator( theory::THEORY_UF ));
+  //   return new uf::EqualityQueryInstantiatorTheoryUf(ith);
+  // }
+  // inst::EqualityQuery* eq = d_eq_query_arr[id];
+  // if(eq == NULL) return d_eq_query_arr[theory::THEORY_UF];
+  // else return eq;
+
+
+  //Currently we use the generic EqualityQuery
+  return getEqualityQuery();
+}
+
+
+// // Just iterate amoung the equivalence class of the given node
+// // node::Null() *can't* be given to reset
+// class CandidateGeneratorClassGeneric : public CandidateGenerator{
+// private:
+//   //instantiator pointer
+//   EqualityEngine* d_ee;
+//   //the equality class iterator
+//   eq::EqClassIterator d_eqc;
+//   /* For the case where the given term doesn't exists in uf */
+//   Node d_retNode;
+// public:
+//   CandidateGeneratorTheoryEeClass( EqualityEngine* ee): d_ee( ee ){}
+//   ~CandidateGeneratorTheoryEeClass(){}
+//   void resetInstantiationRound(){};
+//   void reset( TNode eqc ){
+//     Assert(!eqc.isNull());
+//     if( d_ee->hasTerm( eqc ) ){
+//       /* eqc is in uf  */
+//       eqc = d_ee->getRepresentative( eqc );
+//       d_eqc = eq::EqClassIterator( eqc, d_ee );
+//       d_retNode = Node::null();
+//     }else{
+//       /* If eqc if not a term known by uf, it is the only one in its
+//          equivalence class. So we will return only it */
+//       d_retNode = eqc;
+//       d_eqc = eq::EqClassIterator();
+//     }
+//   }; //* the argument is not used
+//   TNode getNextCandidate(){
+//     if(d_retNode.isNull()){
+//       if( !d_eqc.isFinished() ) return (*(d_eqc++));
+//       else return Node::null();
+//     }else{
+//       /* the case where eqc not in uf */
+//       Node ret = d_retNode;
+//       d_retNode = Node::null(); /* d_eqc.isFinished() must be true */
+//       return ret;
+//     }
+//   };
+// };
+
+
+class GenericCandidateGeneratorClasses: public rrinst::CandidateGenerator{
+
+  /** The candidate generators */
+  rrinst::CandidateGenerator* d_can_gen[theory::THEORY_LAST];
+  /** The current theory which candidategenerator is used */
+  TheoryId d_can_gen_id;
+
+public:
+  GenericCandidateGeneratorClasses(QuantifiersEngine * qe){
+    for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+      if(qe->getInstantiator(i) != NULL)
+        d_can_gen[i] = qe->getInstantiator(i)->getRRCanGenClasses();
+      else d_can_gen[i] = NULL;
+    };
+  }
+
+  ~GenericCandidateGeneratorClasses(){
+    for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+      delete(d_can_gen[i]);
+    };
+  }
+
+  void resetInstantiationRound(){
+    for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+      if(d_can_gen[i] != NULL) d_can_gen[i]->resetInstantiationRound();
+    };
+    d_can_gen_id=THEORY_FIRST;
+  }
+
+  void reset(TNode eqc){
+    Assert(eqc.isNull());
+    for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+      if(d_can_gen[i] != NULL) d_can_gen[i]->reset(eqc);
+    };
+    d_can_gen_id=THEORY_FIRST;
+    lookForNextTheory();
+  }
+
+  TNode getNextCandidate(){
+    Assert(THEORY_FIRST <= d_can_gen_id && d_can_gen_id <= THEORY_LAST);
+    /** No more */
+    if(d_can_gen_id == THEORY_LAST) return TNode::null();
+    /** Try with this theory */
+    TNode cand = d_can_gen[d_can_gen_id]->getNextCandidate();
+    if( !cand.isNull() ) return cand;
+    lookForNextTheory();
+    return getNextCandidate();
+  }
+
+  void lookForNextTheory(){
+    do{ /* look for the next available generator */
+      ++d_can_gen_id;
+    } while( d_can_gen_id < THEORY_LAST && d_can_gen[d_can_gen_id] == NULL);
+  }
+
+};
+
+class GenericCandidateGeneratorClass: public rrinst::CandidateGenerator{
+
+  /** The candidate generators */
+  rrinst::CandidateGenerator* d_can_gen[theory::THEORY_LAST];
+  /** The current theory which candidategenerator is used */
+  TheoryId d_can_gen_id;
+  /** current node to look for equivalence class */
+  Node d_node;
+  /** QuantifierEngine */
+  QuantifiersEngine* d_qe;
+
+public:
+  GenericCandidateGeneratorClass(QuantifiersEngine * qe): d_qe(qe) {
+    for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+      if(d_qe->getInstantiator(i) != NULL)
+        d_can_gen[i] = d_qe->getInstantiator(i)->getRRCanGenClass();
+      else d_can_gen[i] = NULL;
+    };
+  }
+
+  ~GenericCandidateGeneratorClass(){
+    for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+      delete(d_can_gen[i]);
+    };
+  }
+
+  void resetInstantiationRound(){
+    for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+      if(d_can_gen[i] != NULL) d_can_gen[i]->resetInstantiationRound();
+    };
+    d_can_gen_id=THEORY_FIRST;
+  }
+
+  void reset(TNode eqc){
+    for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+      if(d_can_gen[i] != NULL) d_can_gen[i]->reset(eqc);
+    };
+    d_can_gen_id=THEORY_FIRST;
+    d_node = eqc;
+    lookForNextTheory();
+  }
+
+  TNode getNextCandidate(){
+    Assert(THEORY_FIRST <= d_can_gen_id && d_can_gen_id <= THEORY_LAST);
+    /** No more */
+    if(d_can_gen_id == THEORY_LAST) return TNode::null();
+    /** Try with this theory */
+    TNode cand = d_can_gen[d_can_gen_id]->getNextCandidate();
+    if( !cand.isNull() ) return cand;
+    lookForNextTheory();
+    return getNextCandidate();
+  }
+
+  void lookForNextTheory(){
+    do{ /* look for the next available generator, where the element is */
+      ++d_can_gen_id;
+    } while(
+            d_can_gen_id < THEORY_LAST &&
+            (d_can_gen[d_can_gen_id] == NULL ||
+             !d_qe->getInstantiator( d_can_gen_id )->hasTerm( d_node ))
+            );
+  }
+
+};
+
+
+rrinst::CandidateGenerator* QuantifiersEngine::getRRCanGenClasses() {
+  return new GenericCandidateGeneratorClasses(this);
+}
+
+rrinst::CandidateGenerator* QuantifiersEngine::getRRCanGenClass() {
+  return new GenericCandidateGeneratorClass(this);
+}
+
+rrinst::CandidateGenerator* QuantifiersEngine::getRRCanGenClasses(TypeNode t) {
+  // TheoryId id = Theory::theoryOf(t);
+  // rrinst::CandidateGenerator* eq = getInstantiator(id)->getRRCanGenClasses();
+  // if(eq == NULL) return getInstantiator(id)->getRRCanGenClasses();
+  // else return eq;
+  return getRRCanGenClasses();
+}
+
+rrinst::CandidateGenerator* QuantifiersEngine::getRRCanGenClass(TypeNode t) {
+  // TheoryId id = Theory::theoryOf(t);
+  // rrinst::CandidateGenerator* eq = getInstantiator(id)->getRRCanGenClass();
+  // if(eq == NULL) return getInstantiator(id)->getRRCanGenClass();
+  // else return eq;
+  return getRRCanGenClass();
+}
index 5477214b05ef348b407e6ddb07db0c4540e91f83..157c0ac5398d20688cbb8ffcc5c4e9d242cf807c 100644 (file)
@@ -21,7 +21,8 @@
 
 #include "theory/theory.h"
 #include "util/hash.h"
-#include "theory/trigger.h"
+#include "theory/inst_match.h"
+#include "theory/rr_inst_match.h"
 
 #include "util/stats.h"
 
@@ -33,16 +34,6 @@ namespace CVC4 {
 
 class TheoryEngine;
 
-// attribute for "contains instantiation constants from"
-struct InstConstantAttributeId {};
-typedef expr::Attribute<InstConstantAttributeId, Node> InstConstantAttribute;
-
-struct InstLevelAttributeId {};
-typedef expr::Attribute<InstLevelAttributeId, uint64_t> InstLevelAttribute;
-
-struct InstVarNumAttributeId {};
-typedef expr::Attribute<InstVarNumAttributeId, uint64_t> InstVarNumAttribute;
-
 namespace theory {
 
 class QuantifiersEngine;
@@ -126,7 +117,7 @@ namespace quantifiers {
 class QuantifiersEngine {
   friend class quantifiers::InstantiationEngine;
   friend class quantifiers::ModelEngine;
-  friend class InstMatch;
+  friend class inst::InstMatch;
 private:
   typedef context::CDHashMap< Node, bool, NodeHashFunction > BoolMap;
   /** reference to theory engine object */
@@ -139,7 +130,7 @@ private:
   quantifiers::ModelEngine* d_model_engine;
   /** equality query class */
   EqualityQuery* d_eq_query;
-
+public:
   /** list of all quantifiers (pre-rewrite) */
   std::vector< Node > d_quants;
   /** list of all quantifiers (post-rewrite) */
@@ -153,7 +144,7 @@ private:
   /** has added lemma this round */
   bool d_hasAddedLemma;
   /** inst matches produced for each quantifier */
-  std::map< Node, InstMatchTrie > d_inst_match_trie;
+  std::map< Node, inst::InstMatchTrie > d_inst_match_trie;
   /** owner of quantifiers */
   std::map< Node, Theory* > d_owner;
   /** term database */
@@ -184,13 +175,24 @@ private:
 
 public:
   QuantifiersEngine(context::Context* c, TheoryEngine* te);
-  ~QuantifiersEngine(){}
+  ~QuantifiersEngine();
   /** get instantiator for id */
-  Instantiator* getInstantiator( int id );
+  Instantiator* getInstantiator( theory::TheoryId id );
   /** get theory engine */
   TheoryEngine* getTheoryEngine() { return d_te; }
-  /** get equality query object */
-  EqualityQuery* getEqualityQuery() { return d_eq_query; }
+  /** get equality query object for the given type. The default is the
+      generic one */
+  inst::EqualityQuery* getEqualityQuery(TypeNode t);
+  inst::EqualityQuery* getEqualityQuery() {
+    return d_eq_query;
+  }
+  /** get equality query object for the given type. The default is the
+      one of UF */
+  rrinst::CandidateGenerator* getRRCanGenClasses(TypeNode t);
+  rrinst::CandidateGenerator* getRRCanGenClass(TypeNode t);
+  /* generic candidate generator */
+  rrinst::CandidateGenerator* getRRCanGenClasses();
+  rrinst::CandidateGenerator* getRRCanGenClass();
   /** get instantiation engine */
   quantifiers::InstantiationEngine* getInstantiationEngine() { return d_inst_engine; }
   /** get model engine */
@@ -301,6 +303,14 @@ public:
     IntStat d_simple_triggers;
     IntStat d_multi_triggers;
     IntStat d_multi_trigger_instantiations;
+    IntStat d_term_in_termdb;
+    IntStat d_num_mono_candidates;
+    IntStat d_num_mono_candidates_new_term;
+    IntStat d_num_multi_candidates;
+    IntStat d_mono_candidates_cache_hit;
+    IntStat d_mono_candidates_cache_miss;
+    IntStat d_multi_candidates_cache_hit;
+    IntStat d_multi_candidates_cache_miss;
     Statistics();
     ~Statistics();
   };/* class QuantifiersEngine::Statistics */
index 265026b392d2e94483100f15ffed512addc4f24e..57bc6d9cffe51c69fac2c8ec867d98f1862801c7 100644 (file)
@@ -23,6 +23,8 @@
 
 #include "theory/rewriterules/theory_rewriterules_preprocess.h"
 #include "theory/rewriter.h"
+#include "util/options.h"
+
 
 using namespace std;
 using namespace CVC4;
@@ -30,6 +32,7 @@ using namespace CVC4::kind;
 using namespace CVC4::context;
 using namespace CVC4::theory;
 using namespace CVC4::theory::rewriterules;
+using namespace CVC4::theory::rrinst;
 
 
 namespace CVC4 {
@@ -69,14 +72,14 @@ size_t RuleInst::findGuard(TheoryRewriteRules & re, size_t start)const{
     Node g = substNode(re,rule->guards[start],cache);
     switch(re.addWatchIfDontKnow(g,this,start)){
     case ATRUE:
-      Debug("rewriterules") << g << "is true" << std::endl;
+      Debug("rewriterules::guards") << g << "is true" << std::endl;
       ++start;
       continue;
     case AFALSE:
-      Debug("rewriterules") << g << "is false" << std::endl;
+      Debug("rewriterules::guards") << g << "is false" << std::endl;
       return -1;
     case ADONTKNOW:
-      Debug("rewriterules") << g << "is unknown" << std::endl;
+      Debug("rewriterules::guards") << g << "is unknown" << std::endl;
       return start;
     }
   }
@@ -132,31 +135,31 @@ TheoryRewriteRules::TheoryRewriteRules(context::Context* c,
                                        QuantifiersEngine* qe) :
   Theory(THEORY_REWRITERULES, c, u, out, valuation, logicInfo, qe),
   d_rules(c), d_ruleinsts(c), d_guardeds(c), d_checkLevel(c,0),
-  d_explanations(c), d_ruleinsts_to_add()
+  d_explanations(c), d_ruleinsts_to_add(), d_ppAssert_on(false)
   {
   d_true = NodeManager::currentNM()->mkConst<bool>(true);
   d_false = NodeManager::currentNM()->mkConst<bool>(false);
-  Debug("rewriterules") << Node::setdepth(-1);
-  Debug("rewriterules-rewrite") << Node::setdepth(-1);
 }
 
 void TheoryRewriteRules::addMatchRuleTrigger(const RewriteRule * r,
                                              InstMatch & im,
                                              bool delay){
   ++r->nb_matched;
+  ++d_statistics.d_match_found;
   if(rewrite_instantiation) im.applyRewrite();
   if(representative_instantiation)
     im.makeRepresentative( getQuantifiersEngine() );
 
   if(!cache_match || !r->inCache(*this,im)){
     ++r->nb_applied;
+    ++d_statistics.d_cache_miss;
     std::vector<Node> subst;
     im.computeTermVec(getQuantifiersEngine(), r->inst_vars , subst);
     RuleInst * ri = new RuleInst(*this,r,subst,
                                  r->directrr ? im.d_matched : Node::null());
-    Debug("rewriterules") << "One matching found"
-                          << (delay? "(delayed)":"")
-                          << ":" << *ri << std::endl;
+    Debug("rewriterules::matching") << "One matching found"
+                                    << (delay? "(delayed)":"")
+                                    << ":" << *ri << std::endl;
     // Find the first non verified guard, don't save the rule if the
     // rule can already be fired In fact I save it otherwise strange
     // things append.
@@ -168,6 +171,8 @@ void TheoryRewriteRules::addMatchRuleTrigger(const RewriteRule * r,
         d_ruleinsts.push_back(ri);
       else delete(ri);
     };
+  }else{
+    ++d_statistics.d_cache_hit;
   };
 }
 
@@ -179,7 +184,11 @@ void TheoryRewriteRules::check(Effort level) {
   while(!done()) {
     // Get all the assertions
     // TODO: Test that it have already been ppAsserted
-    get();
+
+    //if we are here and ppAssert has not been done
+    // that means that ppAssert is off so we need to assert now
+    if(!d_ppAssert_on) addRewriteRule(get());
+    else get();
     // Assertion assertion = get();
     // TNode fact = assertion.assertion;
 
@@ -190,30 +199,30 @@ void TheoryRewriteRules::check(Effort level) {
 
     };
 
-  Debug("rewriterules") << "Check:" << d_checkLevel << (level==EFFORT_FULL? " EFFORT_FULL":"") << std::endl;
+  Debug("rewriterules::check") << "RewriteRules::Check start " << d_checkLevel << (level==EFFORT_FULL? " EFFORT_FULL":"") << std::endl;
 
   /** Test each rewrite rule */
   for(size_t rid = 0, end = d_rules.size(); rid < end; ++rid) {
     RewriteRule * r = d_rules[rid];
     if (level!=EFFORT_FULL && r->d_split) continue;
-    Debug("rewriterules") << "  rule: " << r << std::endl;
+    Debug("rewriterules::check") << "RewriteRules::Check  rule: " << *r << std::endl;
     Trigger & tr = r->trigger;
     //reset instantiation round for trigger (set up match production)
     tr.resetInstantiationRound();
-    //begin iterating from the first match produced by the trigger
-    tr.reset( Node::null() );
 
     /** Test the possible matching one by one */
-    InstMatch im;
-    while(tr.getNextMatch( im )){
+    while(tr.getNextMatch()){
+      InstMatch im = tr.getInstMatch();
       addMatchRuleTrigger(r, im, true);
-      im.clear();
     }
   }
 
   const bool do_notification = d_checkLevel == 0 || level==EFFORT_FULL;
   bool polldone = false;
 
+  if(level==EFFORT_FULL) ++d_statistics.d_full_check;
+  else ++d_statistics.d_check;
+
   GuardedMap::const_iterator p = d_guardeds.begin();
   do{
 
@@ -221,7 +230,7 @@ void TheoryRewriteRules::check(Effort level) {
     //dequeue instantiated rules
     for(; !d_ruleinsts_to_add.empty();){
       RuleInst * ri = d_ruleinsts_to_add.back(); d_ruleinsts_to_add.pop_back();
-      if(simulateRewritting && ri->alreadyRewritten(*this)) break;
+      if(simulateRewritting && ri->alreadyRewritten(*this)) continue;
       if(ri->findGuard(*this, 0) != ri->rule->guards.size())
         d_ruleinsts.push_back(ri);
       else delete(ri);
@@ -239,7 +248,7 @@ void TheoryRewriteRules::check(Effort level) {
       bool value;
       if(getValuation().hasSatValue(g,value)){
         if(value) polldone = true; //One guard is true so pass n check
-        Debug("rewriterules") << "Poll value:" << g
+        Debug("rewriterules::guards") << "Poll value:" << g
                              << " is " << (value ? "true" : "false") << std::endl;
         notification(g,value);
         //const Guarded & glast2 = (*l)[l->size()-1];
@@ -266,14 +275,14 @@ void TheoryRewriteRules::check(Effort level) {
       // If it has a value it should already has been notified
       bool value; value = value; // avoiding the warning in non debug mode
       Assert(!getValuation().hasSatValue(g,value));
-      Debug("rewriterules") << "Narrowing on:" << g << std::endl;
+      Debug("rewriterules::check") << "RewriteRules::Check Narrowing on:" << g << std::endl;
       /** Can split on already rewritten instrule... but... */
       getOutputChannel().split(g);
     }
   }
 
   Assert(d_ruleinsts_to_add.empty());
-  Debug("rewriterules") << "Check done:" << d_checkLevel << std::endl;
+  Debug("rewriterules::check") << "RewriteRules::Check done " << d_checkLevel << std::endl;
 
 };
 
@@ -283,7 +292,13 @@ Trigger TheoryRewriteRules::createTrigger( TNode n, std::vector<Node> & pattern
   //  Debug("rewriterules") << "createTrigger:";
   getQuantifiersEngine()->registerPattern(pattern);
   return *Trigger::mkTrigger(getQuantifiersEngine(),n,pattern,
-                             match_gen_kind, true);
+                             Options::current()->efficientEMatching?
+                             Trigger::MATCH_GEN_EFFICIENT_E_MATCH :
+                             Trigger::MATCH_GEN_DEFAULT,
+                             true,
+                             Trigger::TR_MAKE_NEW,
+                             false);
+  //                             Options::current()->smartMultiTriggers);
 };
 
 bool TheoryRewriteRules::notifyIfKnown(const GList * const ltested,
@@ -299,9 +314,9 @@ bool TheoryRewriteRules::notifyIfKnown(const GList * const ltested,
 
 void TheoryRewriteRules::notification(GList * const lpropa, bool b){
   if (b){
-    for(GList::const_iterator g = lpropa->begin();
-        g != lpropa->end(); ++g) {
-      (*g).nextGuard(*this);
+    for(size_t ig = 0;
+        ig != lpropa->size(); ++ig) {
+      (*lpropa)[ig].nextGuard(*this);
     };
     lpropa->push_back(Guarded(RULEINST_TRUE,0));
   }else{
@@ -315,16 +330,6 @@ void TheoryRewriteRules::notification(GList * const lpropa, bool b){
 
 Answer TheoryRewriteRules::addWatchIfDontKnow(Node g0, const RuleInst* ri,
                                               const size_t gid){
-  /** TODO: Should use the representative of g, but should I keep the
-      mapping for myself? */
-  //AJR: removed this code after talking with Francois
-  ///* If it false in one model (current valuation) it's false for all */
-  //if (useCurrentModel){
-  //  Node val = getValuation().getValue(g0);
-  //  Debug("rewriterules") << "getValue:" << g0 << " = "
-  //                        << val << " is " << (val == d_false) << std::endl;
-  //  if (val == d_false) return AFALSE;
-  //};
   /** Currently create a node with a literal */
   Node g = getValuation().ensureLiteral(g0);
   GuardedMap::iterator l_i = d_guardeds.find(g);
@@ -384,68 +389,119 @@ void TheoryRewriteRules::notifyEq(TNode lhs, TNode rhs) {
 };
 
 
+Node TheoryRewriteRules::normalizeConjunction(NodeBuilder<> & conjunction){
+  Assert(conjunction.getKind() == kind::AND);
+  switch(conjunction.getNumChildren()){
+  case 0:
+    return d_true;
+  case 1:
+    return conjunction[0];
+  default:
+    return conjunction;
+  }
+
+}
+
+void explainInstantiation(const RuleInst *inst, TNode substHead, NodeBuilder<> & conjunction ){
+  TypeNode booleanType = NodeManager::currentNM()->booleanType();
+  // if the rule is directly applied by the rewriter,
+  // we should take care to use the representative that can't be directly rewritable:
+  // If "car(a)" is somewhere and we know that "a = cons(x,l)" we shouldn't
+  // add the constraint car(cons(x,l) = x because it is rewritten to x = x.
+  // But we should say cons(a) = x
+  Assert(!inst->d_matched.isNull());
+  Assert( inst->d_matched.getKind() == kind::APPLY_UF);
+  Assert( substHead.getKind() == kind::APPLY_UF );
+  Assert( inst->d_matched.getOperator() == substHead.getOperator() );
+  Assert(conjunction.getKind() == kind::AND);
+  // replace the left hand side by the term really matched
+  NodeBuilder<2> nb;
+  for(size_t i = 0,
+        iend = inst->d_matched.getNumChildren(); i < iend; ++i){
+    nb.clear( inst->d_matched[i].getType(false) == booleanType ?
+              kind::IFF : kind::EQUAL );
+    nb << inst->d_matched[i] << substHead[i];
+    conjunction << static_cast<Node>(nb);
+  }
+}
+
+Node skolemizeBody( Node f ){
+  /*TODO skolemize the subformula of s with constant or skolemize
+    directly in the body of the rewrite rule with an uninterpreted
+    function.
+   */
+  if ( f.getKind()!=EXISTS ) return f;
+  std::vector< Node > vars;
+  std::vector< Node > csts;
+  for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
+    csts.push_back( NodeManager::currentNM()->mkSkolem( f[0][i].getType()) );
+    vars.push_back( f[0][i] );
+  }
+  return f[ 1 ].substitute( vars.begin(), vars.end(),
+                            csts.begin(), csts.end() );
+}
+
+
 void TheoryRewriteRules::propagateRule(const RuleInst * inst, TCache cache){
   //   Debug("rewriterules") << "A rewrite rules is verified. Add lemma:";
-  Debug("rewriterules") << "propagateRule" << *inst << std::endl;
+  Debug("rewriterules::propagate") << "propagateRule" << *inst << std::endl;
   const RewriteRule * rule = inst->rule;
   ++rule->nb_applied;
   // Can be more something else than an equality in fact (eg. propagation rule)
-  Node equality = inst->substNode(*this,rule->body,cache);
+  Node equality = skolemizeBody(inst->substNode(*this,rule->body,cache));
   if(propagate_as_lemma){
     Node lemma = equality;
-    if(rule->guards.size() > 0){
-      // TODO: problem with reduction rule => instead of <=>
-      lemma = substGuards(inst, cache).impNode(equality);
-    };
     if(rule->directrr){
-      TypeNode booleanType = NodeManager::currentNM()->booleanType();
-      // if the rule is directly applied by the rewriter,
-      // we should take care to use the representative that can't be directly rewritable:
-      // If "car(a)" is somewhere and we know that "a = cons(x,l)" we shouldn't
-      // add the constraint car(cons(x,l) = x because it is rewritten to x = x.
-      // But we should say cons(a) = x
-      Assert(lemma.getKind() == kind::EQUAL ||
-             lemma.getKind() == kind::IMPLIES);
-      Assert(!inst->d_matched.isNull());
-      Assert( inst->d_matched.getOperator() == lemma[0].getOperator() );
-      // replace the left hand side by the term really matched
+      NodeBuilder<> conjunction(kind::AND);
+      explainInstantiation(inst,
+                           rule->guards.size() > 0?
+                           inst->substNode(*this,rule->guards[0],cache) : equality[0],
+                           conjunction);
       Debug("rewriterules-directrr") << "lemma:" << lemma << " :: " << inst->d_matched;
-      Node hyp;
-      NodeBuilder<2> nb;
-      if(inst->d_matched.getNumChildren() == 1){
-        nb.clear( inst->d_matched[0].getType(false) == booleanType ?
-                  kind::IFF : kind::EQUAL );
-        nb << inst->d_matched[0] << lemma[0][0];
-        hyp = nb;
-      }else{
-        NodeBuilder<> andb(kind::AND);
-        for(size_t i = 0,
-              iend = inst->d_matched.getNumChildren(); i < iend; ++i){
-          nb.clear( inst->d_matched[i].getType(false) == booleanType ?
-                    kind::IFF : kind::EQUAL );
-          nb << inst->d_matched[i] << lemma[0][i];
-          andb << static_cast<Node>(nb);
-        }
-        hyp = andb;
-      };
-      nb.clear(lemma.getKind());
-      nb << inst->d_matched << lemma[1];
-      lemma = hyp.impNode(static_cast<Node>(nb));
+      //rewrite rule
+      TypeNode booleanType = NodeManager::currentNM()->booleanType();
+      if(equality[1].getType(false) == booleanType)
+        equality = inst->d_matched.iffNode(equality[1]);
+      else equality = inst->d_matched.eqNode(equality[1]);
+      lemma = normalizeConjunction(conjunction).impNode(equality);
       Debug("rewriterules-directrr") << " -> " << lemma << std::endl;
-    };
-    // Debug("rewriterules") << "lemma:" << lemma << std::endl;
+    }
+    else if(rule->guards.size() > 0){
+      // We can use implication for reduction rules since the head is known
+      // to be true
+      NodeBuilder<> conjunction(kind::AND);
+      substGuards(inst,cache,conjunction);
+      lemma = normalizeConjunction(conjunction).impNode(equality);
+    }
+    Debug("rewriterules::propagate") << "propagated " << lemma << std::endl;
     getOutputChannel().lemma(lemma);
   }else{
-    Assert(!direct_rewrite);
-    Node lemma_lit = getValuation().ensureLiteral(equality);
+    Node lemma_lit = equality;
+    if(rule->directrr && rule->guards.size() == 0)
+      lemma_lit = inst->d_matched.eqNode(equality[1]); // rewrite rules
+    lemma_lit = getValuation().ensureLiteral(lemma_lit);
     ExplanationMap::const_iterator p = d_explanations.find(lemma_lit);
     if(p!=d_explanations.end()) return; //Already propagated
     bool value;
     if(getValuation().hasSatValue(lemma_lit,value)){
       /* Already assigned */
       if (!value){
-        Node conflict = substGuards(inst,cache,lemma_lit);
-        getOutputChannel().conflict(conflict);
+        NodeBuilder<> conflict(kind::AND);
+
+        if(rule->directrr){
+          explainInstantiation(inst,
+                               rule->guards.size() > 0?
+                               inst->substNode(*this,rule->guards[0],cache) : equality[0],
+                               conflict);
+          if(rule->guards.size() > 0){
+            //reduction rule
+            Assert(rule->guards.size() == 1);
+            conflict << inst->d_matched; //this one will be two times
+          }
+        }
+        substGuards(inst,cache,conflict);
+        conflict << lemma_lit;
+        getOutputChannel().conflict(normalizeConjunction(conflict));
       };
     }else{
       getOutputChannel().propagate(lemma_lit);
@@ -456,57 +512,79 @@ void TheoryRewriteRules::propagateRule(const RuleInst * inst, TCache cache){
   if(simulateRewritting){
     static NoMatchAttribute rewrittenNodeAttribute;
     // Tag the rewritted terms
-    for(std::vector<Node>::iterator i = rule->to_remove.begin();
-        i == rule->to_remove.end(); ++i){
-      (*i).setAttribute(rewrittenNodeAttribute,true);
+    // for(std::vector<Node>::iterator i = rule->to_remove.begin();
+    //     i == rule->to_remove.end(); ++i){
+    //   (*i).setAttribute(rewrittenNodeAttribute,true);
+    // };
+    for(size_t i = 0; i < rule->to_remove.size(); ++i){
+      Node rewritten = inst->substNode(*this,rule->to_remove[i],cache);
+      Debug("rewriterules::simulateRewriting") << "tag " << rewritten << " as rewritten" << std::endl;
+      rewritten.setAttribute(rewrittenNodeAttribute,true);
     };
+
   };
 
-  //Verify that this instantiation can't immediately fire another rule
-  for(RewriteRule::BodyMatch::const_iterator p = rule->body_match.begin();
-      p != rule->body_match.end(); ++p){
-    RewriteRule * r = (*p).second;
-    // Debug("rewriterules") << "  rule: " << r << std::endl;
-    // Use trigger2 since we can be in check
-    Trigger & tr = r->trigger_for_body_match;
-    InstMatch im;
-    TNode m = inst->substNode(*this,(*p).first, cache);
-    tr.getMatch(m,im);
-    if(!im.empty()){
-      im.d_matched = m;
-      addMatchRuleTrigger(r, im);
+  if ( compute_opt && !rule->body_match.empty() ){
+
+    uf::TheoryUF* uf = static_cast<uf::TheoryUF *>(getQuantifiersEngine()->getTheoryEngine()->getTheory( theory::THEORY_UF ));
+    eq::EqualityEngine* ee =
+      static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
+
+    //Verify that this instantiation can't immediately fire another rule
+    for(RewriteRule::BodyMatch::const_iterator p = rule->body_match.begin();
+        p != rule->body_match.end(); ++p){
+      RewriteRule * r = (*p).second;
+      // Use trigger2 since we can be in check
+      ApplyMatcher * tr = r->trigger_for_body_match;
+      Assert(tr != NULL);
+      tr->resetInstantiationRound(getQuantifiersEngine());
+      InstMatch im;
+      TNode m = inst->substNode(*this,(*p).first, cache);
+      Assert( m.getKind() == kind::APPLY_UF );
+      ee->addTerm(m);
+      if( tr->reset(m,im,getQuantifiersEngine()) ){
+        im.d_matched = m;
+        Debug("rewriterules::matching") << "SimulatedRewrite: " << std::endl;
+        addMatchRuleTrigger(r, im);
+      }
     }
+
   }
 };
 
-
-Node TheoryRewriteRules::substGuards(const RuleInst *inst,
+void TheoryRewriteRules::substGuards(const RuleInst *inst,
                                      TCache cache,
-                                     /* Already substituted */
-                                     Node last){
+                                     NodeBuilder<> & conjunction){
   const RewriteRule * r = inst->rule;
-  /** No guards */
-  const size_t size = r->guards.size();
-  if(size == 0) return (last.isNull()?d_true:last);
-  /** One guard */
-  if(size == 1 && last.isNull()) return inst->substNode(*this,r->guards[0],cache);
   /** Guards */ /* TODO remove the duplicate with a set like in uf? */
-  NodeBuilder<> conjunction(kind::AND);
   for(std::vector<Node>::const_iterator p = r->guards.begin();
       p != r->guards.end(); ++p) {
     Assert(!p->isNull());
     conjunction << inst->substNode(*this,*p,cache);
   };
-  if (!last.isNull()) conjunction << last;
-  return conjunction;
 }
 
 Node TheoryRewriteRules::explain(TNode n){
   ExplanationMap::const_iterator p = d_explanations.find(n);
   Assert(p!=d_explanations.end(),"I forget the explanation...");
-  RuleInst i = (*p).second;
-  //Notice() << n << "<-" << *(i.rule) << std::endl;
-  return substGuards(&i, TCache ());
+  RuleInst inst = (*p).second;
+  const RewriteRule * rule = inst.rule;
+  TCache cache;
+  NodeBuilder<> explanation(kind::AND);
+  if(rule->directrr){
+    explainInstantiation(&inst,
+                         rule->guards.size() > 0?
+                         inst.substNode(*this,rule->guards[0],cache):
+                         inst.substNode(*this,rule->body[0]  ,cache),
+                         explanation);
+    if(rule->guards.size() > 0){
+      //reduction rule
+      Assert(rule->guards.size() == 1);
+      explanation << inst.d_matched; //this one will be two times
+    }
+  };
+  substGuards(&inst, cache ,explanation);
+  return normalizeConjunction(explanation);
 }
 
 void TheoryRewriteRules::collectModelInfo( TheoryModel* m ){
@@ -515,9 +593,39 @@ void TheoryRewriteRules::collectModelInfo( TheoryModel* m ){
 
 Theory::PPAssertStatus TheoryRewriteRules::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
   addRewriteRule(in);
+  d_ppAssert_on = true;
   return PP_ASSERT_STATUS_UNSOLVED;
 }
 
+TheoryRewriteRules::Statistics::Statistics():
+  d_num_rewriterules("TheoryRewriteRules::Num_RewriteRules", 0),
+  d_check("TheoryRewriteRules::Check", 0),
+  d_full_check("TheoryRewriteRules::FullCheck", 0),
+  d_poll("TheoryRewriteRules::Poll", 0),
+  d_match_found("TheoryRewriteRules::MatchFound", 0),
+  d_cache_hit("TheoryRewriteRules::CacheHit", 0),
+  d_cache_miss("TheoryRewriteRules::CacheMiss", 0)
+{
+  StatisticsRegistry::registerStat(&d_num_rewriterules);
+  StatisticsRegistry::registerStat(&d_check);
+  StatisticsRegistry::registerStat(&d_full_check);
+  StatisticsRegistry::registerStat(&d_poll);
+  StatisticsRegistry::registerStat(&d_match_found);
+  StatisticsRegistry::registerStat(&d_cache_hit);
+  StatisticsRegistry::registerStat(&d_cache_miss);
+}
+
+TheoryRewriteRules::Statistics::~Statistics(){
+  StatisticsRegistry::unregisterStat(&d_num_rewriterules);
+  StatisticsRegistry::unregisterStat(&d_check);
+  StatisticsRegistry::unregisterStat(&d_full_check);
+  StatisticsRegistry::unregisterStat(&d_poll);
+  StatisticsRegistry::unregisterStat(&d_match_found);
+  StatisticsRegistry::unregisterStat(&d_cache_hit);
+  StatisticsRegistry::unregisterStat(&d_cache_miss);
+}
+
+
 }/* CVC4::theory::rewriterules namespace */
 }/* CVC4::theory namespace */
 }/* CVC4 namespace */
index d1c3eecf3258c9b21bfb088e4063cee1a09705cf..fcbdfe8b9f8e7c745fad0fdcece5cc85bec23f02 100644 (file)
@@ -27,7 +27,9 @@
 #include "theory/theory_engine.h"
 #include "theory/quantifiers_engine.h"
 #include "context/context_mm.h"
-#include "theory/inst_match_impl.h"
+#include "theory/rr_inst_match_impl.h"
+#include "theory/rr_trigger.h"
+#include "theory/rr_inst_match.h"
 #include "util/stats.h"
 #include "theory/rewriterules/theory_rewriterules_preprocess.h"
 #include "theory/model.h"
@@ -35,6 +37,8 @@
 namespace CVC4 {
 namespace theory {
 namespace rewriterules {
+using namespace CVC4::theory::rrinst;
+typedef CVC4::theory::rrinst::Trigger Trigger;
 
 typedef std::hash_map<TNode, TNode, TNodeHashFunction> TCache;
 
@@ -45,6 +49,7 @@ typedef std::hash_map<TNode, TNode, TNodeHashFunction> TCache;
   class RewriteRule{
   public:
     // constant
+    const size_t id; //for debugging
     const bool d_split;
     mutable Trigger trigger;
     std::vector<Node> guards;
@@ -58,7 +63,7 @@ typedef std::hash_map<TNode, TNode, TNodeHashFunction> TCache;
        rule) */
     typedef context::CDList< std::pair<TNode,RewriteRule* > > BodyMatch;
     mutable BodyMatch body_match;
-    mutable Trigger trigger_for_body_match; // used because we can be matching
+    mutable ApplyMatcher * trigger_for_body_match; // used because we can be matching
                                     // trigger when we need new match.
                                     // So currently we use another
                                     // trigger for that.
@@ -70,7 +75,7 @@ typedef std::hash_map<TNode, TNode, TNodeHashFunction> TCache;
     const bool directrr;
 
     RewriteRule(TheoryRewriteRules & re,
-                Trigger & tr, Trigger & tr2,
+                Trigger & tr, ApplyMatcher * tr2,
                 std::vector<Node> & g, Node b, TNode nt,
                 std::vector<Node> & fv,std::vector<Node> & iv,
                 std::vector<Node> & to_r, bool drr);
@@ -183,6 +188,7 @@ private:
       inside check */
   typedef std::vector< RuleInst* > QRuleInsts;
   QRuleInsts d_ruleinsts_to_add;
+  bool d_ppAssert_on; //Indicate if a ppAssert have been done
 
  public:
   /** true and false for predicate */
@@ -240,15 +246,17 @@ private:
      already true */
   bool notifyIfKnown(const GList * const ltested, GList * const lpropa);
 
-  Node substGuards(const RuleInst * inst,
+  void substGuards(const RuleInst * inst,
                    TCache cache,
-                   Node last = Node::null());
+                   NodeBuilder<> & conjunction);
 
   void addRewriteRule(const Node r);
   void computeMatchBody ( const RewriteRule * r, size_t start = 0);
   void addMatchRuleTrigger(const RewriteRule* r,
                            InstMatch & im, bool delay = true);
 
+  Node normalizeConjunction(NodeBuilder<> & conjunction);
+
   /* rewrite pattern */
   typedef std::hash_map< Node, rewriter::RRPpRewrite*, NodeHashFunction > RegisterRRPpRewrite;
   RegisterRRPpRewrite d_registeredRRPpRewrite;
@@ -257,6 +265,21 @@ private:
                          rewriter::Subst & pvars,
                          rewriter::Subst & vars);
 
+    /** statistics class */
+  class Statistics {
+  public:
+    IntStat d_num_rewriterules;
+    IntStat d_check;
+    IntStat d_full_check;
+    IntStat d_poll;
+    IntStat d_match_found;
+    IntStat d_cache_hit;
+    IntStat d_cache_miss;
+    Statistics();
+    ~Statistics();
+  };
+  Statistics d_statistics;
+
 };/* class TheoryRewriteRules */
 
 }/* CVC4::theory::rewriterules namespace */
index 9ab2ae3e79bac7d499bc17d7603c0aeb85bad637..de51215d11dcce02a513fa361cc3143ce7dd0c18 100644 (file)
@@ -17,7 +17,6 @@
  ** \todo document this file
  **/
 
-
 #ifndef __CVC4__THEORY__REWRITERULES__THEORY_REWRITERULES_PARAMS_H
 #define __CVC4__THEORY__REWRITERULES__THEORY_REWRITERULES_PARAMS_H
 
@@ -58,7 +57,7 @@ static const bool representative_instantiation = false;
 
    Allow to break loop with other theories.
  */
-static const size_t checkSlowdown = 10;
+static const size_t checkSlowdown = 0;
 
 /**
    Use the current model to eliminate guard before asking for notification
@@ -68,14 +67,7 @@ static const bool useCurrentModel = false;
 /**
    Simulate rewriting by tagging rewritten terms.
  */
-static const bool simulateRewritting = false;
-
-/**
-   Choose the kind of matching to use:
-   - InstMatchGenerator::MATCH_GEN_DEFAULT 0
-   - InstMatchGenerator::MATCH_GEN_EFFICIENT_E_MATCH 1
-*/
-static const int match_gen_kind = 0;
+static const bool simulateRewritting = true;
 
 /**
    Do narrowing at full effort
@@ -85,7 +77,7 @@ static const bool narrowing_full_effort = false;
 /**
    Direct rewrite: Add rewrite rules directly in the rewriter.
  */
-static const bool direct_rewrite = true;
+static const bool direct_rewrite = false;
 
 }/* CVC4::theory::rewriterules namespace */
 }/* CVC4::theory namespace */
index c3116aba08afd7816b84b28f62e48b40123098da..1ad8fdaa7def4ea7b9882cf0cad8e10dbe34920c 100644 (file)
@@ -21,6 +21,7 @@
 #include "theory/rewriterules/theory_rewriterules_params.h"
 #include "theory/rewriterules/theory_rewriterules_preprocess.h"
 #include "theory/rewriterules/theory_rewriterules.h"
+#include "util/options.h"
 
 #include "theory/quantifiers/term_database.h"
 
@@ -30,12 +31,46 @@ using namespace CVC4::kind;
 using namespace CVC4::context;
 using namespace CVC4::theory;
 using namespace CVC4::theory::rewriterules;
+using namespace CVC4::theory::rrinst;
 
 
 namespace CVC4 {
 namespace theory {
 namespace rewriterules {
 
+// TODO replace by a real dictionnary
+// We should create a real substitution? slower more precise
+// We don't do that often
+bool nonunifiable( TNode t0, TNode pattern, const std::vector<Node> & vars){
+  typedef std::vector<std::pair<TNode,TNode> > tstack;
+  tstack stack(1,std::make_pair(t0,pattern)); // t * pat
+
+  while(!stack.empty()){
+    const std::pair<TNode,TNode> p = stack.back(); stack.pop_back();
+    const TNode & t = p.first;
+    const TNode & pat = p.second;
+
+    // t or pat is a variable currently we consider that can match anything
+    if( find(vars.begin(),vars.end(),t) != vars.end() ) continue;
+    if( pat.getKind() == INST_CONSTANT ) continue;
+
+    // t and pat are nonunifiable
+    if( !Trigger::isAtomicTrigger( t ) || !Trigger::isAtomicTrigger( pat ) ) {
+      if(t == pat) continue;
+      else return true;
+    };
+    if( t.getOperator() != pat.getOperator() ) return true;
+
+    //put the children on the stack
+    for( size_t i=0; i < pat.getNumChildren(); i++ ){
+      stack.push_back(std::make_pair(t[i],pat[i]));
+    };
+  }
+  // The heuristic can't find non-unifiability
+  return false;
+}
+
+
 void TheoryRewriteRules::computeMatchBody ( const RewriteRule * rule,
                                             size_t start){
   std::vector<TNode> stack(1,rule->new_terms);
@@ -50,9 +85,9 @@ void TheoryRewriteRules::computeMatchBody ( const RewriteRule * rule,
     if( t.getKind() == APPLY_UF ){
       for(size_t rid = start, end = d_rules.size(); rid < end; ++rid) {
         RewriteRule * r = d_rules[rid];
-        if(r->d_split) continue;
-        Trigger & tr = const_cast<Trigger &> (r->trigger_for_body_match);
-        if(!tr.nonunifiable(t, rule->free_vars)){
+        if(r->d_split || r->trigger_for_body_match == NULL) continue;
+        //the split rules are not computed and the one with multi-pattern
+        if( !nonunifiable(t, r->trigger_for_body_match->d_pattern, rule->free_vars)){
           rule->body_match.push_back(std::make_pair(t,r));
         }
       }
@@ -74,7 +109,10 @@ inline void addPattern(TheoryRewriteRules & re,
                        TNode r){
   if (tri.getKind() == kind::NOT && tri[0].getKind() == kind::APPLY_UF)
     tri = tri[0];
-  pattern.push_back(re.getQuantifiersEngine()->getTermDatabase()->
+  pattern.push_back(
+                    Options::current()->rewriteRulesAsAxioms?
+                    static_cast<Node>(tri):
+                    re.getQuantifiersEngine()->getTermDatabase()->
                     convertNodeToPattern(tri,r,vars,inst_constants));
 }
 
@@ -106,6 +144,7 @@ bool checkPatternVars(const std::vector<Node> & pattern,
 void TheoryRewriteRules::addRewriteRule(const Node r)
 {
   Assert(r.getKind() == kind::REWRITE_RULE);
+  Kind rrkind = r[2].getKind();
   /*   Replace variables by Inst_* variable and tag the terms that
        contain them */
   std::vector<Node> vars;
@@ -125,16 +164,20 @@ void TheoryRewriteRules::addRewriteRule(const Node r)
                                    when fired */
   /* shortcut */
   TNode head = r[2][0];
-  switch(r[2].getKind()){
+  TypeNode booleanType = NodeManager::currentNM()->booleanType();
+  switch(rrkind){
   case kind::RR_REWRITE:
     /* Equality */
     to_remove.push_back(head);
     addPattern(*this,head,pattern,vars,inst_constants,r);
-    body = head.eqNode(body);
+    if(head.getType(false) == booleanType) body = head.iffNode(body);
+    else body = head.eqNode(body);
     break;
   case kind::RR_REDUCTION:
     /** Add head to remove */
-    to_remove.push_back(head);
+      for(Node::iterator i = head.begin(); i != head.end(); ++i) {
+        to_remove.push_back(*i);
+      };
   case kind::RR_DEDUCTION:
     /** Add head to guards and pattern */
     switch(head.getKind()){
@@ -171,32 +214,65 @@ void TheoryRewriteRules::addRewriteRule(const Node r)
   };
   /* Add the other triggers */
   if( r[2].getNumChildren() >= 3 )
-    for(Node::iterator i = r[2][2].begin(); i != r[2][2].end(); ++i) {
+    for(Node::iterator i = r[2][2][0].begin(); i != r[2][2][0].end(); ++i) {
       // todo test during typing that its a good term (no not, atom, or term...)
-      addPattern(*this,(*i)[0],pattern,vars,inst_constants,r);
+      addPattern(*this,*i,pattern,vars,inst_constants,r);
     };
   // Assert(pattern.size() == 1, "currently only single pattern are supported");
+
+
+
+
+  //If we convert to usual axioms
+  if(Options::current()->rewriteRulesAsAxioms){
+    NodeBuilder<> forallB(kind::FORALL);
+    forallB << r[0];
+    NodeBuilder<> guardsB(kind::AND);
+    guardsB.append(guards);
+    forallB << normalizeConjunction(guardsB).impNode(body);
+    NodeBuilder<> patternB(kind::INST_PATTERN);
+    patternB.append(pattern);
+    NodeBuilder<> patternListB(kind::INST_PATTERN_LIST);
+    patternListB << static_cast<Node>(patternB);
+    forallB << static_cast<Node>(patternListB);
+    getOutputChannel().lemma((Node) forallB);
+    return;
+  }
+
+  //turn all to propagate
+  // if(true){
+  //   NodeBuilder<> guardsB(kind::AND);
+  //   guardsB.append(guards);
+  //   body = normalizeConjunction(guardsB).impNode(body);
+  //   guards.clear();
+  //   rrkind = kind::RR_DEDUCTION;
+  // }
+
+
   //Every variable must be seen in the pattern
   if (!checkPatternVars(pattern,inst_constants)){
-    Warning() << "The rule" << r <<
+    Warning() << Node::setdepth(-1) << "The rule" << r <<
       " has been removed since it doesn't contain every variables."
               << std::endl;
     return;
   }
 
+
   //Add to direct rewrite rule
   bool directrr = false;
   if(direct_rewrite &&
-     ((guards.size() == 0 && r[2].getKind() == kind::RR_REWRITE) ||
-      (guards.size() == 1 && r[2].getKind() == kind::RR_REDUCTION))
+     guards.size() == 0 && rrkind == kind::RR_REWRITE
      && pattern.size() == 1){
     directrr = addRewritePattern(pattern[0],new_terms, inst_constants, vars);
   }
 
+
   // final construction
   Trigger trigger = createTrigger(r,pattern);
-  Trigger trigger2 = createTrigger(r,pattern); //Hack
-  RewriteRule * rr = new RewriteRule(*this, trigger, trigger2,
+  ApplyMatcher * applymatcher =
+    pattern.size() == 1 && pattern[0].getKind() == kind::APPLY_UF?
+    new ApplyMatcher(pattern[0],getQuantifiersEngine()) : NULL;
+  RewriteRule * rr = new RewriteRule(*this, trigger, applymatcher,
                                      guards, body, new_terms,
                                      vars, inst_constants, to_remove,
                                      directrr);
@@ -209,7 +285,7 @@ void TheoryRewriteRules::addRewriteRule(const Node r)
       computeMatchBody(d_rules[rid],
                        d_rules.size() - 1);
 
-  Debug("rewriterules") << "created rewriterule"<< (rr->d_split?"(split)":"") << ":(" << d_rules.size() - 1 << ")"
+  Debug("rewriterules::new") << "created rewriterule"<< (rr->d_split?"(split)":"") << ":(" << d_rules.size() - 1 << ")"
                         << *rr << std::endl;
 
 }
@@ -227,7 +303,7 @@ bool willDecide(TNode node, bool positive = true){
   case XOR:
     return true;
   case IMPLIES:
-    return false;
+    return true;
   case ITE:
     return true;
   case NOT:
@@ -237,45 +313,50 @@ bool willDecide(TNode node, bool positive = true){
   }
 }
 
-
+static size_t id_next = 0;
 RewriteRule::RewriteRule(TheoryRewriteRules & re,
-                         Trigger & tr, Trigger & tr2,
+                         Trigger & tr, ApplyMatcher * applymatcher,
                          std::vector<Node> & g, Node b, TNode nt,
                          std::vector<Node> & fv,std::vector<Node> & iv,
                          std::vector<Node> & to_r, bool drr) :
-  d_split(willDecide(b)),
+  id(++id_next), d_split(willDecide(b)),
   trigger(tr), body(b), new_terms(nt), free_vars(), inst_vars(),
-  body_match(re.getSatContext()),trigger_for_body_match(tr2),
+  body_match(re.getSatContext()),trigger_for_body_match(applymatcher),
   d_cache(re.getSatContext(),re.getQuantifiersEngine()), directrr(drr){
   free_vars.swap(fv); inst_vars.swap(iv); guards.swap(g); to_remove.swap(to_r);
 };
 
 
 bool RewriteRule::inCache(TheoryRewriteRules & re, InstMatch & im)const{
-  return !d_cache.addInstMatch(im);
+  bool res = !d_cache.addInstMatch(im);
+  Debug("rewriterules::matching") << "rewriterules::cache " << im
+                                  << (res ? " HIT" : " MISS") << std::endl;
+  return res;
 };
 
 /** A rewrite rule */
 void RewriteRule::toStream(std::ostream& out) const{
+  out << "[" << id << "] ";
   for(std::vector<Node>::const_iterator
         iter = guards.begin(); iter != guards.end(); ++iter){
     out << *iter;
   };
   out << "=>" << body << std::endl;
-  out << "[";
+  out << "{";
   for(BodyMatch::const_iterator
         iter = body_match.begin(); iter != body_match.end(); ++iter){
-    out << (*iter).first << "(" << (*iter).second << ")" << ",";
+    out << (*iter).first << "[" << (*iter).second->id << "]" << ",";
   };
-  out << "]" << (directrr?"*":"") << std::endl;
+  out << "}" << (directrr?"*":"") << std::endl;
 }
 
 RewriteRule::~RewriteRule(){
-  Debug("rewriterule-stats") << *this
+  Debug("rewriterule::stats") << *this
                              << "  (" << nb_matched
                              << ","   << nb_applied
                              << ","   << nb_propagated
                              << ")" << std::endl;
+  delete(trigger_for_body_match);
 }
 
 bool TheoryRewriteRules::addRewritePattern(TNode pattern, TNode body,
index 8bc4522a14d52f39fa37e327a4a383d3681b6e0c..605324b201271a4a001e1103c510917a9d649128 100644 (file)
@@ -45,16 +45,16 @@ public:
     Assert(n.getKind() == kind::REWRITE_RULE && n.getNumChildren()==3 );
     if( check ){
       if( n[ 0 ].getType(check)!=nodeManager->boundVarListType() ){
-        throw TypeCheckingExceptionPrivate(n,
+        throw TypeCheckingExceptionPrivate(n[0],
                      "first argument of rewrite rule is not bound var list");
       }
       if( n[ 1 ].getType(check)!=nodeManager->booleanType() ){
-        throw TypeCheckingExceptionPrivate(n,
+        throw TypeCheckingExceptionPrivate(n[1],
                      "guard of rewrite rule is not an actual guard");
       }
       if( n[2].getType(check) !=
           TypeNode(nodeManager->mkTypeConst<TypeConstant>(RRHB_TYPE))){
-        throw TypeCheckingExceptionPrivate(n,
+        throw TypeCheckingExceptionPrivate(n[2],
                      "not a correct rewrite rule");
       }
     }
diff --git a/src/theory/rr_inst_match.cpp b/src/theory/rr_inst_match.cpp
new file mode 100644 (file)
index 0000000..3ba0c8d
--- /dev/null
@@ -0,0 +1,1447 @@
+/*********************                                                        */
+/*! \file inst_match.cpp
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Implementation of inst match class
+ **/
+
+#include "theory/inst_match.h"
+#include "theory/rr_inst_match.h"
+#include "theory/rr_trigger.h"
+#include "theory/rr_inst_match_impl.h"
+#include "theory/theory_engine.h"
+#include "theory/quantifiers_engine.h"
+#include "theory/uf/theory_uf_instantiator.h"
+#include "theory/uf/theory_uf_candidate_generator.h"
+#include "theory/datatypes/theory_datatypes_candidate_generator.h"
+#include "theory/uf/equality_engine.h"
+#include "theory/arrays/theory_arrays.h"
+
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::rrinst;
+using namespace CVC4::theory::uf::rrinst;
+using namespace CVC4::theory::eq::rrinst;
+
+namespace CVC4{
+namespace theory{
+namespace rrinst{
+
+typedef CVC4::theory::inst::InstMatch InstMatch;
+typedef CVC4::theory::inst::CandidateGeneratorQueue CandidateGeneratorQueue;
+
+template<bool modEq>
+class InstMatchTrie2Pairs
+{
+  typename std::vector< std::vector < typename InstMatchTrie2Gen<modEq>::Tree > > d_data;
+  InstMatchTrie2Gen<modEq> d_backtrack;
+public:
+  InstMatchTrie2Pairs(context::Context* c,  QuantifiersEngine* q, size_t n):
+  d_backtrack(c,q) {
+    // resize to a triangle
+    //
+    // |     *
+    // |   * *
+    // | * * *
+    // | -----> i
+    d_data.resize(n);
+    for(size_t i=0; i < n; ++i){
+      d_data[i].resize(i+1,typename InstMatchTrie2Gen<modEq>::Tree(0));
+    }
+  };
+  InstMatchTrie2Pairs(const InstMatchTrie2Pairs &) CVC4_UNDEFINED;
+  const InstMatchTrie2Pairs & operator =(const InstMatchTrie2Pairs & e) CVC4_UNDEFINED;
+  /** add match m in the trie,
+      return true if it was never seen */
+  inline bool addInstMatch( size_t i, size_t j, InstMatch& m){
+    size_t k = std::min(i,j);
+    size_t l = std::max(i,j);
+    return d_backtrack.addInstMatch(m,&(d_data[l][k]));
+  };
+  inline bool addInstMatch( size_t i, InstMatch& m){
+    return d_backtrack.addInstMatch(m,&(d_data[i][i]));
+  };
+
+};
+
+
+// Currently the implementation doesn't take into account that
+// variable should have the same value given.
+// TODO use the d_children way perhaps
+// TODO replace by a real dictionnary
+// We should create a real substitution? slower more precise
+// We don't do that often
+bool nonunifiable( TNode t0, TNode pat, const std::vector<Node> & vars){
+  if(pat.isNull()) return true;
+
+  typedef std::vector<std::pair<TNode,TNode> > tstack;
+  tstack stack(1,std::make_pair(t0,pat)); // t * pat
+
+  while(!stack.empty()){
+    const std::pair<TNode,TNode> p = stack.back(); stack.pop_back();
+    const TNode & t = p.first;
+    const TNode & pat = p.second;
+
+    // t or pat is a variable currently we consider that can match anything
+    if( find(vars.begin(),vars.end(),t) != vars.end() ) continue;
+    if( pat.getKind() == INST_CONSTANT ) continue;
+
+    // t and pat are nonunifiable
+    if( !Trigger::isAtomicTrigger( t ) || !Trigger::isAtomicTrigger( pat ) ) {
+      if(t == pat) continue;
+      else return true;
+    };
+    if( t.getOperator() != pat.getOperator() ) return true;
+
+    //put the children on the stack
+    for( size_t i=0; i < pat.getNumChildren(); i++ ){
+      stack.push_back(std::make_pair(t[i],pat[i]));
+    };
+  }
+  // The heuristic can't find non-unifiability
+  return false;
+};
+
+/** New things */
+class DumbMatcher: public Matcher{
+  void resetInstantiationRound( QuantifiersEngine* qe ){};
+  bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe ){
+    return false;
+  }
+  bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+    return false;
+  }
+};
+
+class DumbPatMatcher: public PatMatcher{
+  void resetInstantiationRound( QuantifiersEngine* qe ){};
+  bool reset( InstMatch& m, QuantifiersEngine* qe ){
+    return false;
+  }
+  bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+    return false;
+  }
+};
+
+
+/* The order of the matching is:
+   reset arg1, nextMatch arg1, reset arg2, nextMatch arg2, ... */
+ApplyMatcher::ApplyMatcher( Node pat, QuantifiersEngine* qe): d_pattern(pat){
+  //  Assert( pat.hasAttribute(InstConstantAttribute()) );
+
+  //set-up d_variables, d_constants, d_childrens
+  for( size_t i=0; i< d_pattern.getNumChildren(); ++i ){
+    EqualityQuery* q = qe->getEqualityQuery(d_pattern[i].getType());
+    Assert( q != NULL );
+    if( d_pattern[i].hasAttribute(InstConstantAttribute()) ){
+      if( d_pattern[i].getKind()==INST_CONSTANT ){
+        //It's a variable
+        d_variables.push_back(make_triple((TNode)d_pattern[i],i,q));
+      }else{
+        //It's neither a constant argument neither a variable
+        //we create the matcher for the subpattern
+        d_childrens.push_back(make_triple(mkMatcher((TNode)d_pattern[i], qe),i,q));
+      };
+    }else{
+      // It's a constant
+      d_constants.push_back(make_triple((TNode)d_pattern[i],i,q));
+    }
+  }
+}
+
+void ApplyMatcher::resetInstantiationRound( QuantifiersEngine* qe ){
+  for( size_t i=0; i< d_childrens.size(); i++ ){
+    d_childrens[i].first->resetInstantiationRound( qe );
+  }
+}
+
+bool ApplyMatcher::reset(TNode t, InstMatch & m, QuantifiersEngine* qe){
+  Debug("matching") << "Matching " << t << " against pattern " << d_pattern << " ("
+                    << m.size() << ")"  << std::endl;
+
+  //if t is null
+  Assert( !t.isNull() );
+  Assert( !t.hasAttribute(InstConstantAttribute()) );
+  Assert( t.getKind()==d_pattern.getKind() );
+  Assert( (t.getKind()!=APPLY_UF && t.getKind()!=APPLY_CONSTRUCTOR)
+          || t.getOperator()==d_pattern.getOperator() );
+
+  typedef std::vector< triple<TNode,size_t,EqualityQuery*> >::iterator iterator;
+  for(iterator i = d_constants.begin(), end = d_constants.end();
+      i != end; ++i){
+    if( !i->third->areEqual( i->first, t[i->second] ) ){
+      Debug("matching-fail") << "Match fail arg: " << i->first << " and " << t[i->second] << std::endl;
+      //setMatchFail( qe, d_pattern[i], t[i] );
+      //ground arguments are not equal
+      return false;
+    }
+  }
+
+  d_binded.clear();
+  bool set;
+  for(iterator i = d_variables.begin(), end = d_variables.end();
+      i != end; ++i){
+    if( !m.setMatch( i->third, i->first, t[i->second], set) ){
+      //match is in conflict
+      Debug("matching-debug") << "Match in conflict " << t[i->second] << " and "
+                              << i->first << " because "
+                              << m.get(i->first)
+                              << std::endl;
+      Debug("matching-fail") << "Match fail: " << m.get(i->first) << " and " << t[i->second] << std::endl;
+      //setMatchFail( qe, partial[0].d_map[d_pattern[i]], t[i] );
+      m.erase(d_binded.begin(), d_binded.end());
+      return false;
+    }else{
+      if(set){ //The variable has just been set
+        d_binded.push_back(i->first);
+      }
+    }
+  }
+
+  //now, fit children into match
+  //we will be requesting candidates for matching terms for each child
+  d_reps.clear();
+  for( size_t i=0; i< d_childrens.size(); i++ ){
+    Debug("matching-debug") << "Take the representative of " << t[ d_childrens[i].second ] << std::endl;
+    Assert( d_childrens[i].third->hasTerm(t[ d_childrens[i].second ]) );
+    Node rep = d_childrens[i].third->getRepresentative( t[ d_childrens[i].second ] );
+    d_reps.push_back( rep );
+  }
+
+  if(d_childrens.size() == 0) return true;
+  else return getNextMatch(m, qe, true);
+}
+
+bool ApplyMatcher::getNextMatch(InstMatch& m, QuantifiersEngine* qe, bool reset){
+  Assert(d_childrens.size() > 0);
+  const size_t max = d_childrens.size() - 1;
+  size_t index = reset ? 0 : max;
+  Assert(d_childrens.size() == d_reps.size());
+  while(true){
+    if(reset ?
+       d_childrens[index].first->reset( d_reps[index], m, qe ) :
+       d_childrens[index].first->getNextMatch( m, qe )){
+      if(index==max) return true;
+      ++index;
+      reset=true;
+    }else{
+      if(index==0){
+        m.erase(d_binded.begin(), d_binded.end());
+        return false;
+      }
+      --index;
+      reset=false;
+    };
+  }
+}
+
+bool ApplyMatcher::getNextMatch(InstMatch& m, QuantifiersEngine* qe){
+  if(d_childrens.size() == 0){
+    m.erase(d_binded.begin(), d_binded.end());
+    return false;
+  } else return getNextMatch(m, qe, false);
+}
+
+/** Proxy that call the sub-matcher on the result return by the given candidate generator */
+template <class CG, class M>
+class CandidateGeneratorMatcher: public Matcher{
+  /** candidate generator */
+  CG d_cg;
+  /** the sub-matcher */
+  M d_m;
+public:
+  CandidateGeneratorMatcher(CG cg, M m): d_cg(cg), d_m(m)
+  {/* last is Null */};
+  void resetInstantiationRound( QuantifiersEngine* qe ){
+    d_cg.resetInstantiationRound();
+    d_m.resetInstantiationRound(qe);
+  };
+  bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe ){
+    d_cg.reset(n);
+    return findMatch(m,qe);
+  }
+  bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+    // The sub-matcher has another match
+    return d_m.getNextMatch(m, qe) || findMatch(m,qe);
+  }
+private:
+  bool findMatch( InstMatch& m, QuantifiersEngine* qe ){
+    // Otherwise try to find a new candidate that has at least one match
+    while(true){
+      TNode n = d_cg.getNextCandidate();//kept somewhere Term-db
+      Debug("matching") << "GenCand " << n << " (" << this << ")" << std::endl;
+      if(n.isNull()) return false;
+      if(d_m.reset(n,m,qe)) return true;
+    };
+  }
+};
+
+/** Proxy that call the sub-matcher on the result return by the given candidate generator */
+template<class M>
+class PatOfMatcher: public PatMatcher{
+  M d_m;
+public:
+  inline PatOfMatcher(M m): d_m(m){}
+  void resetInstantiationRound(QuantifiersEngine* qe){
+    d_m.resetInstantiationRound(qe);
+  }
+  bool reset(InstMatch& m, QuantifiersEngine* qe){
+    return d_m.reset(Node::null(),m,qe);
+  };
+  bool getNextMatch(InstMatch& m, QuantifiersEngine* qe){
+    return d_m.getNextMatch(m,qe);
+  };
+};
+
+class ArithMatcher: public Matcher{
+private:
+  /** for arithmetic matching */
+  std::map< Node, Node > d_arith_coeffs;
+  /** get the match against ground term or formula t.
+      d_match_mattern and t should have the same shape.
+      only valid for use where !d_match_pattern.isNull().
+  */
+  /** the variable that are set by this matcher */
+  std::vector< TNode > d_binded; /* TNode because the variables are already in d_arith_coeffs */
+  Node d_pattern; //for debugging
+public:
+  ArithMatcher(Node pat, QuantifiersEngine* qe);
+  void resetInstantiationRound( QuantifiersEngine* qe ){};
+  bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe );
+  bool getNextMatch( InstMatch& m, QuantifiersEngine* qe );
+};
+
+/** Match just a variable */
+class VarMatcher: public Matcher{
+  Node d_var;
+  bool d_binded; /* True if the reset bind the variable to some value */
+  EqualityQuery* d_q;
+public:
+  VarMatcher(Node var, QuantifiersEngine* qe): d_var(var), d_binded(false){
+    d_q = qe->getEqualityQuery(var.getType());
+  }
+  void resetInstantiationRound( QuantifiersEngine* qe ){};
+  bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe ){
+    if(!m.setMatch( d_q, d_var, n, d_binded )){
+      //match is in conflict
+      Debug("matching-fail") << "Match fail: " << m.get(d_var)
+                             << " and " << n << std::endl;
+      return false;
+    } else return true;
+  };
+  bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+    //match is in conflict
+    if (d_binded) m.erase(d_var);
+    return false;
+  }
+};
+
+template <class M, class Test >
+class TestMatcher: public Matcher{
+  M d_m;
+  Test d_test;
+public:
+  inline TestMatcher(M m, Test test): d_m(m), d_test(test){}
+  inline void resetInstantiationRound(QuantifiersEngine* qe){
+    d_m.resetInstantiationRound(qe);
+  }
+  inline bool reset(TNode n, InstMatch& m, QuantifiersEngine* qe){
+    return d_test(n) && d_m.reset(n, m, qe);
+  }
+  inline bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+    return d_m.getNextMatch(m, qe);
+  }
+};
+
+class LegalOpTest/*: public unary_function<TNode,bool>*/ {
+  Node d_op;
+public:
+  inline LegalOpTest(Node op): d_op(op){}
+  inline bool operator() (TNode n) {
+    return
+      CandidateGenerator::isLegalCandidate(n) &&
+      // ( // n.getKind()==SELECT || n.getKind()==STORE ||
+      //  n.getKind()==APPLY_UF || n.getKind()==APPLY_CONSTRUCTOR) &&
+      n.hasOperator() &&
+      n.getOperator()==d_op;
+  };
+};
+
+class LegalKindTest/* : public unary_function<TNode,bool>*/ {
+  Kind d_kind;
+public:
+  inline LegalKindTest(Kind kind): d_kind(kind){}
+  inline bool operator() (TNode n) {
+    return
+      CandidateGenerator::isLegalCandidate(n) &&
+      n.getKind()==d_kind;
+  };
+};
+
+class LegalTypeTest/* : public unary_function<TNode,bool>*/ {
+  TypeNode d_type;
+public:
+  inline LegalTypeTest(TypeNode type): d_type(type){}
+  inline bool operator() (TNode n) {
+    return
+      CandidateGenerator::isLegalCandidate(n) &&
+      n.getType()==d_type;
+  };
+};
+
+class LegalTest/* : public unary_function<TNode,bool>*/ {
+public:
+  inline bool operator() (TNode n) {
+    return CandidateGenerator::isLegalCandidate(n);
+  };
+};
+
+size_t numFreeVar(TNode t){
+  size_t n = 0;
+  for( size_t i=0, size =t.getNumChildren(); i < size; ++i ){
+    if( t[i].hasAttribute(InstConstantAttribute()) ){
+      if( t[i].getKind()==INST_CONSTANT ){
+        //variable
+        ++n;
+      }else{
+        //neither variable nor constant
+        n += numFreeVar(t[i]);
+      }
+    }
+  }
+  return n;
+}
+
+class OpMatcher: public Matcher{
+  /* The matcher */
+  typedef ApplyMatcher AuxMatcher3;
+  typedef TestMatcher< AuxMatcher3, LegalOpTest > AuxMatcher2;
+  typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClass, AuxMatcher2> AuxMatcher1;
+  AuxMatcher1 d_cgm;
+  static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
+    Assert( pat.getKind() == kind::APPLY_UF );
+    /** In reverse order of matcher sequence */
+    AuxMatcher3 am3(pat,qe);
+    /** Keep only the one that have the good operator */
+    AuxMatcher2 am2(am3,LegalOpTest(pat.getOperator()));
+    /** Iter on the equivalence class of the given term */
+    uf::TheoryUF* uf = static_cast<uf::TheoryUF *>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF ));
+    eq::EqualityEngine* ee =
+      static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
+    CandidateGeneratorTheoryEeClass cdtUfEq(ee);
+    /* Create a matcher from the candidate generator */
+    AuxMatcher1 am1(cdtUfEq,am2);
+    return am1;
+  }
+  size_t d_num_var;
+  Node d_pat;
+public:
+  OpMatcher( Node pat, QuantifiersEngine* qe ):
+    d_cgm(createCgm(pat, qe)),d_num_var(numFreeVar(pat)),
+    d_pat(pat) {}
+
+  void resetInstantiationRound( QuantifiersEngine* qe ){
+    d_cgm.resetInstantiationRound(qe);
+  };
+  bool reset( TNode t, InstMatch& m, QuantifiersEngine* qe ){
+    // size_t m_size = m.d_map.size();
+    // if(m_size == d_num_var){
+    //   uf::EqualityEngine<uf::TheoryUF::NotifyClass>* ee = (static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF )))->getEqualityEngine();
+    //   std::cout << "!";
+    //   return ee->areEqual(m.subst(d_pat),t);
+    // }else{
+    // std::cout << m.d_map.size() << std::endl;
+    return d_cgm.reset(t, m, qe);
+    // }
+  }
+  bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+    return d_cgm.getNextMatch(m, qe);
+  }
+};
+
+class DatatypesMatcher: public Matcher{
+  /* The matcher */
+  typedef ApplyMatcher AuxMatcher3;
+  typedef TestMatcher< AuxMatcher3, LegalOpTest > AuxMatcher2;
+  typedef CandidateGeneratorMatcher< datatypes::rrinst::CandidateGeneratorTheoryClass, AuxMatcher2> AuxMatcher1;
+  AuxMatcher1 d_cgm;
+  static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
+    Assert( pat.getKind() == kind::APPLY_CONSTRUCTOR,
+            "For datatypes only constructor are accepted in pattern" );
+    /** In reverse order of matcher sequence */
+    AuxMatcher3 am3(pat,qe);
+    /** Keep only the one that have the good operator */
+    AuxMatcher2 am2(am3,LegalOpTest(pat.getOperator()));
+    /** Iter on the equivalence class of the given term */
+    datatypes::TheoryDatatypes* dt = static_cast<datatypes::TheoryDatatypes *>(qe->getTheoryEngine()->getTheory( theory::THEORY_DATATYPES ));
+    datatypes::rrinst::CandidateGeneratorTheoryClass cdtDtEq(dt);
+    /* Create a matcher from the candidate generator */
+    AuxMatcher1 am1(cdtDtEq,am2);
+    return am1;
+  }
+  Node d_pat;
+public:
+  DatatypesMatcher( Node pat, QuantifiersEngine* qe ):
+    d_cgm(createCgm(pat, qe)),
+    d_pat(pat) {}
+
+  void resetInstantiationRound( QuantifiersEngine* qe ){
+    d_cgm.resetInstantiationRound(qe);
+  };
+  bool reset( TNode t, InstMatch& m, QuantifiersEngine* qe ){
+    Debug("matching") << "datatypes: " << t << " matches " << d_pat << std::endl;
+    return d_cgm.reset(t, m, qe);
+  }
+  bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+    return d_cgm.getNextMatch(m, qe);
+  }
+};
+
+class ArrayMatcher: public Matcher{
+  /* The matcher */
+  typedef ApplyMatcher AuxMatcher3;
+  typedef TestMatcher< AuxMatcher3, LegalKindTest > AuxMatcher2;
+  typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClass, AuxMatcher2> AuxMatcher1;
+  AuxMatcher1 d_cgm;
+  static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
+    Assert( pat.getKind() == kind::SELECT || pat.getKind() == kind::STORE );
+    /** In reverse order of matcher sequence */
+    AuxMatcher3 am3(pat,qe);
+    /** Keep only the one that have the good operator */
+    AuxMatcher2 am2(am3, LegalKindTest(pat.getKind()));
+    /** Iter on the equivalence class of the given term */
+    arrays::TheoryArrays* ar = static_cast<arrays::TheoryArrays *>(qe->getTheoryEngine()->getTheory( theory::THEORY_ARRAY ));
+    eq::EqualityEngine* ee =
+      static_cast<eq::EqualityEngine*>(ar->getEqualityEngine());
+    CandidateGeneratorTheoryEeClass cdtUfEq(ee);
+    /* Create a matcher from the candidate generator */
+    AuxMatcher1 am1(cdtUfEq,am2);
+    return am1;
+  }
+  size_t d_num_var;
+  Node d_pat;
+public:
+  ArrayMatcher( Node pat, QuantifiersEngine* qe ):
+    d_cgm(createCgm(pat, qe)),d_num_var(numFreeVar(pat)),
+    d_pat(pat) {}
+
+  void resetInstantiationRound( QuantifiersEngine* qe ){
+    d_cgm.resetInstantiationRound(qe);
+  };
+  bool reset( TNode t, InstMatch& m, QuantifiersEngine* qe ){
+    // size_t m_size = m.d_map.size();
+    // if(m_size == d_num_var){
+    //   uf::EqualityEngine<uf::TheoryUF::NotifyClass>* ee = (static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF )))->getEqualityEngine();
+    //   std::cout << "!";
+    //   return ee->areEqual(m.subst(d_pat),t);
+    // }else{
+    // std::cout << m.d_map.size() << std::endl;
+    return d_cgm.reset(t, m, qe);
+    // }
+  }
+  bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+    return d_cgm.getNextMatch(m, qe);
+  }
+};
+
+class AllOpMatcher: public PatMatcher{
+  /* The matcher */
+  typedef ApplyMatcher AuxMatcher3;
+  typedef TestMatcher< AuxMatcher3, LegalTest > AuxMatcher2;
+  typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryUfOp, AuxMatcher2> AuxMatcher1;
+  AuxMatcher1 d_cgm;
+  static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
+    Assert( pat.hasOperator() );
+    /** In reverse order of matcher sequence */
+    AuxMatcher3 am3(pat,qe);
+    /** Keep only the one that have the good operator */
+    AuxMatcher2 am2(am3,LegalTest());
+    /** Iter on the equivalence class of the given term */
+    TermDb* tdb = qe->getTermDatabase();
+    CandidateGeneratorTheoryUfOp cdtUfEq(pat.getOperator(),tdb);
+    /* Create a matcher from the candidate generator */
+    AuxMatcher1 am1(cdtUfEq,am2);
+    return am1;
+  }
+  size_t d_num_var;
+  Node d_pat;
+public:
+  AllOpMatcher( TNode pat, QuantifiersEngine* qe ):
+    d_cgm(createCgm(pat, qe)), d_num_var(numFreeVar(pat)),
+    d_pat(pat) {}
+
+  void resetInstantiationRound( QuantifiersEngine* qe ){
+    d_cgm.resetInstantiationRound(qe);
+  };
+  bool reset( InstMatch& m, QuantifiersEngine* qe ){
+    //    std::cout << m.d_map.size() << "/" << d_num_var << std::endl;
+    return d_cgm.reset(Node::null(), m, qe);
+  }
+  bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+    return d_cgm.getNextMatch(m, qe);
+  }
+};
+
+template <bool classes> /** true classes | false class */
+class GenericCandidateGeneratorClasses: public CandidateGenerator{
+private:
+  CandidateGenerator* d_cg;
+  QuantifiersEngine* d_qe;
+
+public:
+  void mkCandidateGenerator(){
+    if(classes)
+      d_cg = d_qe->getRRCanGenClasses();
+    else
+     d_cg = d_qe->getRRCanGenClass();
+  }
+
+  GenericCandidateGeneratorClasses(QuantifiersEngine* qe):
+    d_qe(qe) {
+    mkCandidateGenerator();
+  }
+  ~GenericCandidateGeneratorClasses(){
+    delete(d_cg);
+  }
+  const GenericCandidateGeneratorClasses & operator =(const GenericCandidateGeneratorClasses & m){
+    mkCandidateGenerator();
+    return m;
+  };
+  GenericCandidateGeneratorClasses(const GenericCandidateGeneratorClasses & m):
+  d_qe(m.d_qe){
+    mkCandidateGenerator();
+  }
+  void resetInstantiationRound(){
+    d_cg->resetInstantiationRound();
+  };
+  void reset( TNode eqc ){
+    Assert( !classes || eqc.isNull() );
+    d_cg->reset(eqc);
+  }; //* the argument is not used
+  TNode getNextCandidate(){
+    return d_cg->getNextCandidate();
+  };
+}; /* MetaCandidateGeneratorClasses */
+
+
+class GenericMatcher: public Matcher{
+  /* The matcher */
+  typedef ApplyMatcher AuxMatcher3;
+  typedef TestMatcher< AuxMatcher3, LegalOpTest > AuxMatcher2;
+  typedef CandidateGeneratorMatcher< GenericCandidateGeneratorClasses<false>, AuxMatcher2> AuxMatcher1;
+  AuxMatcher1 d_cgm;
+  static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
+    /** In reverse order of matcher sequence */
+    AuxMatcher3 am3(pat,qe);
+    /** Keep only the one that have the good operator */
+    AuxMatcher2 am2(am3,LegalOpTest(pat.getOperator()));
+    /** Iter on the equivalence class of the given term */
+    GenericCandidateGeneratorClasses<false> cdtG(qe);
+    /* Create a matcher from the candidate generator */
+    AuxMatcher1 am1(cdtG,am2);
+    return am1;
+  }
+  Node d_pat;
+public:
+  GenericMatcher( Node pat, QuantifiersEngine* qe ):
+    d_cgm(createCgm(pat, qe)),
+    d_pat(pat) {}
+
+  void resetInstantiationRound( QuantifiersEngine* qe ){
+    d_cgm.resetInstantiationRound(qe);
+  };
+  bool reset( TNode t, InstMatch& m, QuantifiersEngine* qe ){
+    return d_cgm.reset(t, m, qe);
+  }
+  bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+    return d_cgm.getNextMatch(m, qe);
+  }
+};
+
+
+class GenericPatMatcher: public PatMatcher{
+  /* The matcher */
+  typedef ApplyMatcher AuxMatcher3;
+  typedef TestMatcher< AuxMatcher3, LegalOpTest > AuxMatcher2;
+  typedef CandidateGeneratorMatcher< GenericCandidateGeneratorClasses<true>, AuxMatcher2> AuxMatcher1;
+  AuxMatcher1 d_cgm;
+  static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
+    /** In reverse order of matcher sequence */
+    AuxMatcher3 am3(pat,qe);
+    /** Keep only the one that have the good operator */
+    AuxMatcher2 am2(am3,LegalOpTest(pat.getOperator()));
+    /** Iter on the equivalence class of the given term */
+    GenericCandidateGeneratorClasses<true> cdtG(qe);
+    /* Create a matcher from the candidate generator */
+    AuxMatcher1 am1(cdtG,am2);
+    return am1;
+  }
+  Node d_pat;
+public:
+  GenericPatMatcher( Node pat, QuantifiersEngine* qe ):
+    d_cgm(createCgm(pat, qe)),
+    d_pat(pat) {}
+
+  void resetInstantiationRound( QuantifiersEngine* qe ){
+    d_cgm.resetInstantiationRound(qe);
+  };
+  bool reset( InstMatch& m, QuantifiersEngine* qe ){
+    return d_cgm.reset(Node::null(), m, qe);
+  }
+  bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+    return d_cgm.getNextMatch(m, qe);
+  }
+};
+
+class MetaCandidateGeneratorClasses: public CandidateGenerator{
+private:
+  CandidateGenerator* d_cg;
+  TypeNode d_ty;
+  TheoryEngine* d_te;
+
+public:
+  CandidateGenerator* mkCandidateGenerator(TypeNode ty, TheoryEngine* te){
+    Debug("inst-match-gen") << "MetaCandidateGenerator for type: " << ty
+                            << " Theory : " << Theory::theoryOf(ty) << std::endl;
+    if( Theory::theoryOf(ty) == theory::THEORY_DATATYPES ){
+      // datatypes::TheoryDatatypes* dt = static_cast<datatypes::TheoryDatatypes *>(te->getTheory( theory::THEORY_DATATYPES ));
+      // return new datatypes::rrinst::CandidateGeneratorTheoryClasses(dt);
+      Unimplemented("MetaCandidateGeneratorClasses for THEORY_DATATYPES");
+    }else if ( Theory::theoryOf(ty) == theory::THEORY_ARRAY ){
+      arrays::TheoryArrays* ar = static_cast<arrays::TheoryArrays *>(te->getTheory( theory::THEORY_ARRAY ));
+      eq::EqualityEngine* ee =
+        static_cast<eq::EqualityEngine*>(ar->getEqualityEngine());
+      return new CandidateGeneratorTheoryEeClasses(ee);
+    } else {
+      uf::TheoryUF* uf = static_cast<uf::TheoryUF*>(te->getTheory( theory::THEORY_UF ));
+      eq::EqualityEngine* ee =
+        static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
+      return new CandidateGeneratorTheoryEeClasses(ee);
+    }
+  }
+  MetaCandidateGeneratorClasses(TypeNode ty, TheoryEngine* te):
+    d_ty(ty), d_te(te) {
+    d_cg = mkCandidateGenerator(ty,te);
+  }
+  ~MetaCandidateGeneratorClasses(){
+    delete(d_cg);
+  }
+  const MetaCandidateGeneratorClasses & operator =(const MetaCandidateGeneratorClasses & m){
+    d_cg = mkCandidateGenerator(m.d_ty, m.d_te);
+    return m;
+  };
+  MetaCandidateGeneratorClasses(const MetaCandidateGeneratorClasses & m):
+  d_ty(m.d_ty), d_te(m.d_te){
+    d_cg = mkCandidateGenerator(m.d_ty, m.d_te);
+  }
+  void resetInstantiationRound(){
+    d_cg->resetInstantiationRound();
+  };
+  void reset( TNode eqc ){
+    d_cg->reset(eqc);
+  }; //* the argument is not used
+  TNode getNextCandidate(){
+    return d_cg->getNextCandidate();
+  };
+}; /* MetaCandidateGeneratorClasses */
+
+/** Match just a variable */
+class AllVarMatcher: public PatMatcher{
+private:
+  /* generator */
+  typedef VarMatcher AuxMatcher3;
+  typedef TestMatcher< AuxMatcher3, LegalTypeTest > AuxMatcher2;
+  typedef CandidateGeneratorMatcher< MetaCandidateGeneratorClasses, AuxMatcher2 > AuxMatcher1;
+  AuxMatcher1 d_cgm;
+  static inline AuxMatcher1 createCgm(TNode pat, QuantifiersEngine* qe){
+    Assert( pat.getKind()==INST_CONSTANT );
+    TypeNode ty = pat.getType();
+    Debug("inst-match-gen") << "create AllVarMatcher for type: " << ty << std::endl;
+    /** In reverse order of matcher sequence */
+    /** Distribute it to all the pattern */
+    AuxMatcher3 am3(pat,qe);
+    /** Keep only the one that have the good type */
+    AuxMatcher2 am2(am3,LegalTypeTest(ty));
+    /** Generate one term by eq classes */
+    MetaCandidateGeneratorClasses mcdt(ty,qe->getTheoryEngine());
+    /* Create a matcher from the candidate generator */
+    AuxMatcher1 am1(mcdt,am2);
+    return am1;
+  }
+public:
+  AllVarMatcher( TNode pat, QuantifiersEngine* qe ):
+    d_cgm(createCgm(pat, qe)){}
+
+  void resetInstantiationRound( QuantifiersEngine* qe ){
+    d_cgm.resetInstantiationRound(qe);
+  };
+  bool reset( InstMatch& m, QuantifiersEngine* qe ){
+    return d_cgm.reset(Node::null(), m, qe); //cdtUfEq doesn't use it's argument for reset
+  }
+  bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+    return d_cgm.getNextMatch(m, qe);
+  }
+};
+
+/** Match all the pattern with the same term */
+class SplitMatcher: public Matcher{
+private:
+  const size_t size;
+  ApplyMatcher d_m; /** Use ApplyMatcher by creating a fake application */
+public:
+  SplitMatcher(std::vector< Node > pats, QuantifiersEngine* qe):
+    size(pats.size()),
+    d_m(NodeManager::currentNM()->mkNode(kind::INST_PATTERN,pats), qe) {}
+  void resetInstantiationRound( QuantifiersEngine* qe ){
+    d_m.resetInstantiationRound(qe);
+  };
+  bool reset( TNode ex, InstMatch& m, QuantifiersEngine* qe ){
+    NodeBuilder<> n(kind::INST_PATTERN);
+    for(size_t i = 0; i < size; ++i) n << ex;
+    Node nn = n;
+    return d_m.reset(nn,m,qe);
+  };
+  bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+    return getNextMatch(m, qe);
+  }
+};
+
+
+/** Match uf term in a fixed equivalence class */
+class UfCstEqMatcher: public PatMatcher{
+private:
+  /* equivalence class to match */
+  Node d_cst;
+  /* generator */
+  OpMatcher d_cgm;
+public:
+  UfCstEqMatcher( Node pat, Node cst, QuantifiersEngine* qe ):
+    d_cst(cst),
+    d_cgm(OpMatcher(pat,qe)) {};
+  void resetInstantiationRound( QuantifiersEngine* qe ){
+    d_cgm.resetInstantiationRound(qe);
+  };
+  bool reset( InstMatch& m, QuantifiersEngine* qe ){
+    return d_cgm.reset(d_cst, m, qe);
+  }
+  bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+    return d_cgm.getNextMatch(m, qe);
+  }
+};
+
+/** Match equalities */
+class UfEqMatcher: public PatMatcher{
+private:
+  /* generator */
+  typedef SplitMatcher AuxMatcher3;
+  typedef TestMatcher< AuxMatcher3, LegalTypeTest > AuxMatcher2;
+  typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClasses, AuxMatcher2 > AuxMatcher1;
+  AuxMatcher1 d_cgm;
+  static inline AuxMatcher1 createCgm(std::vector<Node> & pat, QuantifiersEngine* qe){
+    Assert( pat.size() > 0);
+    TypeNode ty = pat[0].getType();
+    for(size_t i = 1; i < pat.size(); ++i){
+      Assert(pat[i].getType() == ty);
+    }
+    /** In reverse order of matcher sequence */
+    /** Distribute it to all the pattern */
+    AuxMatcher3 am3(pat,qe);
+    /** Keep only the one that have the good type */
+    AuxMatcher2 am2(am3,LegalTypeTest(ty));
+    /** Generate one term by eq classes */
+    uf::TheoryUF* uf = static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF ));
+    eq::EqualityEngine* ee =
+      static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
+    CandidateGeneratorTheoryEeClasses cdtUfEq(ee);
+    /* Create a matcher from the candidate generator */
+    AuxMatcher1 am1(cdtUfEq,am2);
+    return am1;
+  }
+public:
+  UfEqMatcher( std::vector<Node> & pat, QuantifiersEngine* qe ):
+    d_cgm(createCgm(pat, qe)){}
+
+  void resetInstantiationRound( QuantifiersEngine* qe ){
+    d_cgm.resetInstantiationRound(qe);
+  };
+  bool reset( InstMatch& m, QuantifiersEngine* qe ){
+    return d_cgm.reset(Node::null(), m, qe); //cdtUfEq doesn't use it's argument for reset
+  }
+  bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+    return d_cgm.getNextMatch(m, qe);
+  }
+};
+
+
+/** Match dis-equalities */
+class UfDeqMatcher: public PatMatcher{
+private:
+  /* generator */
+  typedef ApplyMatcher AuxMatcher3;
+
+  class EqTest/* : public unary_function<Node,bool>*/ {
+    TypeNode d_type;
+  public:
+    inline EqTest(TypeNode type): d_type(type){};
+    inline bool operator() (Node n) {
+      return
+        CandidateGenerator::isLegalCandidate(n) &&
+        n.getKind() == kind::EQUAL &&
+        n[0].getType()==d_type;
+    };
+  };
+  typedef TestMatcher< AuxMatcher3, EqTest > AuxMatcher2;
+  typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClass, AuxMatcher2 > AuxMatcher1;
+  AuxMatcher1 d_cgm;
+  Node false_term;
+  static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
+    Assert( pat.getKind() == kind::NOT);
+    TNode eq = pat[0];
+    Assert( eq.getKind() == kind::EQUAL);
+    TypeNode ty = eq[0].getType();
+    /** In reverse order of matcher sequence */
+    /** Distribute it to all the pattern */
+    AuxMatcher3 am3(eq,qe);
+    /** Keep only the one that have the good type */
+    AuxMatcher2 am2(am3,EqTest(ty));
+    /** Will generate all the terms of the eq class of false */
+    uf::TheoryUF* uf = static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF ));
+    eq::EqualityEngine* ee =
+      static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
+    CandidateGeneratorTheoryEeClass cdtUfEq(ee);
+    /* Create a matcher from the candidate generator */
+    AuxMatcher1 am1(cdtUfEq,am2);
+    return am1;
+  }
+public:
+  UfDeqMatcher( Node pat, QuantifiersEngine* qe ):
+    d_cgm(createCgm(pat, qe)),
+    false_term((static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF )))->getEqualityEngine()->
+                getRepresentative(NodeManager::currentNM()->mkConst<bool>(false) )){};
+  void resetInstantiationRound( QuantifiersEngine* qe ){
+    d_cgm.resetInstantiationRound(qe);
+  };
+  bool reset( InstMatch& m, QuantifiersEngine* qe ){
+    return d_cgm.reset(false_term, m, qe);
+  }
+  bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+    return d_cgm.getNextMatch(m, qe);
+  }
+};
+
+Matcher* mkMatcher( Node pat, QuantifiersEngine* qe ){
+  Debug("inst-match-gen") << "mkMatcher: Pattern term is " << pat << std::endl;
+
+  // if( pat.getKind() == kind::APPLY_UF){
+  //   return new OpMatcher(pat, qe);
+  // } else if( pat.getKind() == kind::APPLY_CONSTRUCTOR ){
+  //   return new DatatypesMatcher(pat, qe);
+  // } else if( pat.getKind() == kind::SELECT || pat.getKind() == kind::STORE ){
+  //   return new ArrayMatcher(pat, qe);
+  if( pat.getKind() == kind::APPLY_UF ||
+      pat.getKind() == kind::APPLY_CONSTRUCTOR ||
+      pat.getKind() == kind::SELECT || pat.getKind() == kind::STORE ){
+    return new GenericMatcher(pat, qe);
+  } else { /* Arithmetic? */
+    /** TODO: something simpler to see if the pattern is a good
+        arithmetic pattern */
+    std::map< Node, Node > d_arith_coeffs;
+    if( !Trigger::getPatternArithmetic( pat.getAttribute(InstConstantAttribute()), pat, d_arith_coeffs ) ){
+      std::cout << "(?) Unknown matching pattern is " << pat << std::endl;
+      Unimplemented("pattern not implemented");
+      return new DumbMatcher();
+    }else{
+      Debug("matching-arith") << "Generated arithmetic pattern for " << pat << ": " << std::endl;
+      for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+        Debug("matching-arith") << "   " << it->first << " -> " << it->second << std::endl;
+      }
+      ArithMatcher am3 (pat, qe);
+      TestMatcher<ArithMatcher, LegalTypeTest>
+        am2(am3,LegalTypeTest(pat.getType()));
+      /* generator */
+      uf::TheoryUF* uf = static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF ));
+      eq::EqualityEngine* ee =
+        static_cast<eq::EqualityEngine*> (uf->getEqualityEngine());
+      CandidateGeneratorTheoryEeClass cdtUfEq(ee);
+      return new CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClass,
+        TestMatcher<ArithMatcher, LegalTypeTest> > (cdtUfEq,am2);
+    }
+  }
+};
+
+PatMatcher* mkPattern( Node pat, QuantifiersEngine* qe ){
+  Debug("inst-match-gen") << "Pattern term is " << pat << std::endl;
+  Assert( pat.hasAttribute(InstConstantAttribute()) );
+
+  if( pat.getKind()==kind::NOT && pat[0].getKind() == kind::EQUAL){
+    /* Difference */
+    return new UfDeqMatcher(pat, qe);
+  } else if (pat.getKind() == kind::EQUAL){
+    if( !pat[0].hasAttribute(InstConstantAttribute() )){
+        Assert(pat[1].hasAttribute(InstConstantAttribute()));
+        return new UfCstEqMatcher(pat[1], pat[0], qe);
+    }else if( !pat[1].hasAttribute(InstConstantAttribute() )){
+      Assert(pat[0].hasAttribute(InstConstantAttribute()));
+      return new UfCstEqMatcher(pat[0], pat[1], qe);
+    }else{
+      std::vector< Node > pats(pat.begin(),pat.end());
+      return new UfEqMatcher(pats,qe);
+    }
+  } else if( Trigger::isAtomicTrigger( pat ) ){
+    return new AllOpMatcher(pat, qe);
+    // return new GenericPatMatcher(pat, qe);
+  } else if( pat.getKind()==INST_CONSTANT ){
+    // just a variable
+    return new AllVarMatcher(pat, qe);
+  } else { /* Arithmetic? */
+    /** TODO: something simpler to see if the pattern is a good
+        arithmetic pattern */
+    std::map< Node, Node > d_arith_coeffs;
+    if( !Trigger::getPatternArithmetic( pat.getAttribute(InstConstantAttribute()), pat, d_arith_coeffs ) ){
+      Debug("inst-match-gen") << "(?) Unknown matching pattern is " << pat << std::endl;
+      std::cout << "(?) Unknown matching pattern is " << pat << std::endl;
+      return new DumbPatMatcher();
+    }else{
+      Debug("matching-arith") << "Generated arithmetic pattern for " << pat << ": " << std::endl;
+      for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+        Debug("matching-arith") << "   " << it->first << " -> " << it->second << std::endl;
+      }
+      ArithMatcher am3 (pat, qe);
+      TestMatcher<ArithMatcher, LegalTest>
+        am2(am3,LegalTest());
+      /* generator */
+      TermDb* tdb = qe->getTermDatabase();
+      CandidateGeneratorTheoryUfType cdtUfEq(pat.getType(),tdb);
+      typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryUfType,
+                                          TestMatcher<ArithMatcher, LegalTest> > AuxMatcher1;
+      return new PatOfMatcher<AuxMatcher1>(AuxMatcher1(cdtUfEq,am2));
+    }
+  }
+};
+
+ArithMatcher::ArithMatcher(Node pat, QuantifiersEngine* qe): d_pattern(pat){
+
+  if(Trigger::getPatternArithmetic(pat.getAttribute(InstConstantAttribute()), pat, d_arith_coeffs ) )
+    {
+    Debug("inst-match-gen") << "(?) Unknown matching pattern is " << d_pattern << std::endl;
+    Assert(false);
+  }else{
+    Debug("matching-arith") << "Generated arithmetic pattern for " << d_pattern << ": " << std::endl;
+    for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+      Debug("matching-arith") << "   " << it->first << " -> " << it->second << std::endl;
+    }
+  }
+
+};
+
+bool ArithMatcher::reset( TNode t, InstMatch& m, QuantifiersEngine* qe ){
+  Debug("matching-arith") << "Matching " << t << " " << d_pattern << std::endl;
+  d_binded.clear();
+  if( !d_arith_coeffs.empty() ){
+    NodeBuilder<> tb(kind::PLUS);
+    Node ic = Node::null();
+    for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+      Debug("matching-arith") << it->first << " -> " << it->second << std::endl;
+      if( !it->first.isNull() ){
+        if( m.find( it->first )==m.end() ){
+          //see if we can choose this to set
+          if( ic.isNull() && ( it->second.isNull() || !it->first.getType().isInteger() ) ){
+            ic = it->first;
+          }
+        }else{
+          Debug("matching-arith") << "already set " << m.get( it->first ) << std::endl;
+          Node tm = m.get( it->first );
+          if( !it->second.isNull() ){
+            tm = NodeManager::currentNM()->mkNode( MULT, it->second, tm );
+          }
+          tb << tm;
+        }
+      }else{
+        tb << it->second;
+      }
+    }
+    if( !ic.isNull() ){
+      Node tm;
+      if( tb.getNumChildren()==0 ){
+        tm = t;
+      }else{
+        tm = tb.getNumChildren()==1 ? tb.getChild( 0 ) : tb;
+        tm = NodeManager::currentNM()->mkNode( MINUS, t, tm );
+      }
+      if( !d_arith_coeffs[ ic ].isNull() ){
+        Assert( !ic.getType().isInteger() );
+        Node coeff = NodeManager::currentNM()->mkConst( Rational(1) / d_arith_coeffs[ ic ].getConst<Rational>() );
+        tm = NodeManager::currentNM()->mkNode( MULT, coeff, tm );
+      }
+      m.set( ic, Rewriter::rewrite( tm ));
+      d_binded.push_back(ic);
+      //set the rest to zeros
+      for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+        if( !it->first.isNull() ){
+          if( m.find( it->first )==m.end() ){
+            m.set( it->first, NodeManager::currentNM()->mkConst( Rational(0) ));
+            d_binded.push_back(ic);
+          }
+        }
+      }
+      Debug("matching-arith") << "Setting " << ic << " to " << tm << std::endl;
+      return true;
+    }else{
+      m.erase(d_binded.begin(), d_binded.end());
+      return false;
+    }
+  }else{
+    m.erase(d_binded.begin(), d_binded.end());
+    return false;
+  }
+};
+
+bool ArithMatcher::getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+  m.erase(d_binded.begin(), d_binded.end());
+  return false;
+};
+
+
+class MultiPatsMatcher: public PatsMatcher{
+private:
+  bool d_reset_done;
+  std::vector< PatMatcher* > d_patterns;
+  InstMatch d_im;
+  bool reset( QuantifiersEngine* qe ){
+    d_im.clear();
+    d_reset_done = true;
+
+    return getNextMatch(qe,true);
+  };
+
+  bool getNextMatch(QuantifiersEngine* qe, bool reset){
+    const size_t max = d_patterns.size() - 1;
+    size_t index = reset ? 0 : max;
+    while(true){
+      Debug("matching") << "MultiPatsMatcher::index " << index << "/"
+                        << max << (reset ? " reset_phase" : "") << std::endl;
+      if(reset ?
+         d_patterns[index]->reset( d_im, qe ) :
+         d_patterns[index]->getNextMatch( d_im, qe )){
+        if(index==max) return true;
+        ++index;
+        reset=true;
+      }else{
+        if(index==0) return false;
+        --index;
+        reset=false;
+      };
+    }
+  }
+
+public:
+  MultiPatsMatcher(std::vector< Node > & pats, QuantifiersEngine* qe):
+    d_reset_done(false){
+    Assert(pats.size() > 0);
+    for( size_t i=0; i< pats.size(); i++ ){
+      d_patterns.push_back(mkPattern(pats[i],qe));
+    };
+  };
+  void resetInstantiationRound( QuantifiersEngine* qe ){
+    for( size_t i=0; i< d_patterns.size(); i++ ){
+      d_patterns[i]->resetInstantiationRound( qe );
+    };
+    d_reset_done = false;
+    d_im.clear();
+  };
+  bool getNextMatch( QuantifiersEngine* qe ){
+    Assert(d_patterns.size()>0);
+    if(d_reset_done) return getNextMatch(qe,false);
+    else return reset(qe);
+  }
+  const InstMatch& getInstMatch(){return d_im;};
+
+  int addInstantiations( InstMatch& baseMatch, Node quant, QuantifiersEngine* qe);
+};
+
+enum EffiStep{
+  ES_STOP,
+  ES_GET_MONO_CANDIDATE,
+  ES_GET_MULTI_CANDIDATE,
+  ES_RESET1,
+  ES_RESET2,
+  ES_NEXT1,
+  ES_NEXT2,
+  ES_RESET_OTHER,
+  ES_NEXT_OTHER,
+};
+static inline std::ostream& operator<<(std::ostream& out, const EffiStep& step) {
+  switch(step){
+  case ES_STOP: out << "STOP"; break;
+  case ES_GET_MONO_CANDIDATE: out << "GET_MONO_CANDIDATE"; break;
+  case ES_GET_MULTI_CANDIDATE: out << "GET_MULTI_CANDIDATE"; break;
+  case ES_RESET1: out << "RESET1"; break;
+  case ES_RESET2: out << "RESET2"; break;
+  case ES_NEXT1: out << "NEXT1"; break;
+  case ES_NEXT2: out << "NEXT2"; break;
+  case ES_RESET_OTHER: out << "RESET_OTHER"; break;
+  case ES_NEXT_OTHER: out << "NEXT_OTHER"; break;
+  }
+  return out;
+}
+
+
+int MultiPatsMatcher::addInstantiations( InstMatch& baseMatch, Node quant, QuantifiersEngine* qe){
+  //now, try to add instantiation for each match produced
+  int addedLemmas = 0;
+  resetInstantiationRound( qe );
+  d_im.add( baseMatch );
+  while( getNextMatch( qe ) ){
+    InstMatch im_copy = getInstMatch();
+    //m.makeInternal( d_quantEngine->getEqualityQuery() );
+    if( qe->addInstantiation( quant, im_copy ) ){
+      addedLemmas++;
+    }
+  }
+  //return number of lemmas added
+  return addedLemmas;
+}
+
+PatsMatcher* mkPatterns( std::vector< Node > pat, QuantifiersEngine* qe ){
+  return new MultiPatsMatcher( pat, qe);
+}
+
+class MultiEfficientPatsMatcher: public PatsMatcher{
+private:
+  bool d_phase_mono;
+  bool d_phase_new_term;
+  std::vector< PatMatcher* > d_patterns;
+  std::vector< Matcher* > d_direct_patterns;
+  InstMatch d_im;
+  uf::EfficientHandler d_eh;
+  uf::EfficientHandler::MultiCandidate d_mc;
+  InstMatchTrie2Pairs<true> d_cache;
+  std::vector<Node> d_pats;
+  // bool indexDone( size_t i){
+  //   return i == d_c.first.second ||
+  //     ( i == d_c.second.second && d_c.second.first.empty());
+  // }
+
+
+
+  static const EffiStep ES_START = ES_GET_MONO_CANDIDATE;
+  EffiStep d_step;
+
+  //return true if it becomes bigger than d_patterns.size() - 1
+  bool incrIndex(size_t & index){
+    if(index == d_patterns.size() - 1) return true;
+    ++index;
+    if(index == d_mc.first.second
+       || (!d_phase_mono && index == d_mc.second.second))
+      return incrIndex(index);
+    else return false;
+  }
+
+  //return true if it becomes smaller than 0
+  bool decrIndex(size_t & index){
+    if(index == 0) return true;
+    --index;
+    if(index == d_mc.first.second
+       || (!d_phase_mono && index == d_mc.second.second))
+      return decrIndex(index);
+    else return false;
+  }
+
+  bool resetOther( QuantifiersEngine* qe ){
+    return getNextMatchOther(qe,true);
+  };
+
+
+  bool getNextMatchOther(QuantifiersEngine* qe, bool reset){
+    size_t index = reset ? 0 : d_patterns.size();
+    if(!reset && decrIndex(index)) return false;
+    if( reset &&
+        (index == d_mc.first.second
+         || (!d_phase_mono && index == d_mc.second.second))
+        && incrIndex(index)) return true;
+    while(true){
+      Debug("matching") << "MultiEfficientPatsMatcher::index " << index << "/"
+                        << d_patterns.size() - 1 << std::endl;
+      if(reset ?
+         d_patterns[index]->reset( d_im, qe ) :
+         d_patterns[index]->getNextMatch( d_im, qe )){
+        if(incrIndex(index)) return true;
+        reset=true;
+      }else{
+        if(decrIndex(index)) return false;
+        reset=false;
+      };
+    }
+  }
+
+  inline EffiStep TestMonoCache(QuantifiersEngine* qe){
+    if( //!d_phase_new_term ||
+       d_pats.size() == 1) return ES_RESET_OTHER;
+    if(d_cache.addInstMatch(d_mc.first.second,d_im)){
+      Debug("inst-match::cache") << "Cache miss" << d_im << std::endl;
+      ++qe->d_statistics.d_mono_candidates_cache_miss;
+      return ES_RESET_OTHER;
+    } else {
+      Debug("inst-match::cache") << "Cache hit" << d_im << std::endl;
+      ++qe->d_statistics.d_mono_candidates_cache_hit;
+      return ES_NEXT1;
+    }
+    // ++qe->d_statistics.d_mono_candidates_cache_miss;
+    // return ES_RESET_OTHER;
+  }
+
+  inline EffiStep TestMultiCache(QuantifiersEngine* qe){
+    if(d_cache.addInstMatch(d_mc.first.second,d_mc.second.second,d_im)){
+      ++qe->d_statistics.d_multi_candidates_cache_miss;
+      return ES_RESET_OTHER;
+    } else {
+      ++qe->d_statistics.d_multi_candidates_cache_hit;
+      return ES_NEXT2;
+    }
+  }
+
+
+public:
+
+  bool getNextMatch( QuantifiersEngine* qe ){
+    Assert( d_step == ES_START || d_step == ES_NEXT_OTHER || d_step == ES_STOP );
+    while(true){
+      Debug("matching") << "d_step=" << d_step << " "
+                        << "d_im=" << d_im << std::endl;
+      switch(d_step){
+      case ES_GET_MONO_CANDIDATE:
+        Assert(d_im.empty());
+        if(d_phase_new_term ? d_eh.getNextMonoCandidate(d_mc.first) : d_eh.getNextMonoCandidateNewTerm(d_mc.first)){
+          if(d_phase_new_term) ++qe->d_statistics.d_num_mono_candidates_new_term;
+          else ++qe->d_statistics.d_num_mono_candidates;
+          d_phase_mono = true;
+          d_step = ES_RESET1;
+        } else if (!d_phase_new_term){
+          d_phase_new_term = true;
+          d_step = ES_GET_MONO_CANDIDATE;
+        } else {
+          d_phase_new_term = false;
+          d_step = ES_GET_MULTI_CANDIDATE;
+        }
+        break;
+      case ES_GET_MULTI_CANDIDATE:
+        Assert(d_im.empty());
+        if(d_eh.getNextMultiCandidate(d_mc)){
+          ++qe->d_statistics.d_num_multi_candidates;
+          d_phase_mono = false;
+          d_step = ES_RESET1;
+        } else d_step = ES_STOP;
+        break;
+      case ES_RESET1:
+        if(d_direct_patterns[d_mc.first.second]->reset(d_mc.first.first,d_im,qe))
+          d_step = d_phase_mono ? TestMonoCache(qe) : ES_RESET2;
+        else d_step = d_phase_mono ? ES_GET_MONO_CANDIDATE : ES_GET_MULTI_CANDIDATE;
+        break;
+      case ES_RESET2:
+        Assert(!d_phase_mono);
+        if(d_direct_patterns[d_mc.second.second]->reset(d_mc.second.first,d_im,qe))
+          d_step = TestMultiCache(qe);
+        else d_step = ES_NEXT1;
+        break;
+      case ES_NEXT1:
+        if(d_direct_patterns[d_mc.first.second]->getNextMatch(d_im,qe))
+          d_step = d_phase_mono ? TestMonoCache(qe) : ES_RESET2;
+        else d_step = d_phase_mono ? ES_GET_MONO_CANDIDATE : ES_GET_MULTI_CANDIDATE;
+        break;
+      case ES_NEXT2:
+        if(d_direct_patterns[d_mc.second.second]->getNextMatch(d_im,qe))
+          d_step = TestMultiCache(qe);
+        else d_step = ES_NEXT1;
+        break;
+      case ES_RESET_OTHER:
+        if(resetOther(qe)){
+          d_step = ES_NEXT_OTHER;
+          return true;
+        } else d_step = d_phase_mono ? ES_NEXT1 : ES_NEXT2;
+        break;
+      case ES_NEXT_OTHER:
+        {
+          if(!getNextMatchOther(qe,false)){
+            d_step = d_phase_mono ? ES_NEXT1 : ES_NEXT2;
+          }else{
+            d_step = ES_NEXT_OTHER;
+            return true;
+          }
+        }
+        break;
+      case ES_STOP:
+        Assert(d_im.empty());
+        return false;
+      }
+    }
+  }
+
+  MultiEfficientPatsMatcher(std::vector< Node > & pats, QuantifiersEngine* qe):
+    d_eh(qe->getTheoryEngine()->getSatContext()),
+    d_cache(qe->getTheoryEngine()->getSatContext(),qe,pats.size()),
+    d_pats(pats), d_step(ES_START) {
+    Assert(pats.size() > 0);
+    for( size_t i=0; i< pats.size(); i++ ){
+      d_patterns.push_back(mkPattern(pats[i],qe));
+      if(pats[i].getKind()==kind::INST_CONSTANT){
+        d_direct_patterns.push_back(new VarMatcher(pats[i],qe));
+      } else if( pats[i].getKind() == kind::NOT && pats[i][0].getKind() == kind::EQUAL){
+        d_direct_patterns.push_back(new ApplyMatcher(pats[i][0],qe));
+      } else {
+        d_direct_patterns.push_back(new ApplyMatcher(pats[i],qe));
+      }
+    };
+    Theory* th_uf = qe->getTheoryEngine()->getTheory( theory::THEORY_UF );
+    uf::InstantiatorTheoryUf* ith = (uf::InstantiatorTheoryUf*)th_uf->getInstantiator();
+    ith->registerEfficientHandler(d_eh, pats);
+  };
+  void resetInstantiationRound( QuantifiersEngine* qe ){
+    Assert(d_step == ES_START || d_step == ES_STOP);
+    for( size_t i=0; i< d_patterns.size(); i++ ){
+      d_patterns[i]->resetInstantiationRound( qe );
+      d_direct_patterns[i]->resetInstantiationRound( qe );
+    };
+    d_step = ES_START;
+    d_phase_new_term = false;
+    Assert(d_im.empty());
+  };
+
+  const InstMatch& getInstMatch(){return d_im;};
+
+  int addInstantiations( InstMatch& baseMatch, Node quant, QuantifiersEngine* qe);
+};
+
+int MultiEfficientPatsMatcher::addInstantiations( InstMatch& baseMatch, Node quant, QuantifiersEngine* qe){
+  //now, try to add instantiation for each match produced
+  int addedLemmas = 0;
+  Assert(baseMatch.empty());
+  resetInstantiationRound( qe );
+  while( getNextMatch( qe ) ){
+    InstMatch im_copy = getInstMatch();
+    //m.makeInternal( d_quantEngine->getEqualityQuery() );
+    if( qe->addInstantiation( quant, im_copy ) ){
+      addedLemmas++;
+    }
+  }
+  //return number of lemmas added
+  return addedLemmas;
+};
+
+PatsMatcher* mkPatternsEfficient( std::vector< Node > pat, QuantifiersEngine* qe ){
+  return new MultiEfficientPatsMatcher( pat, qe);
+}
+
+} /* CVC4::theory::rrinst */
+} /* CVC4::theory */
+} /* CVC4 */
diff --git a/src/theory/rr_inst_match.h b/src/theory/rr_inst_match.h
new file mode 100644 (file)
index 0000000..d89b221
--- /dev/null
@@ -0,0 +1,263 @@
+/*********************                                                        */
+/*! \file inst_match.h
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief inst match class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__RR_INST_MATCH_H
+#define __CVC4__RR_INST_MATCH_H
+
+#include "theory/theory.h"
+#include "util/hash.h"
+#include "util/ntuple.h"
+
+#include <ext/hash_set>
+#include <iostream>
+#include <map>
+
+#include "theory/uf/equality_engine.h"
+#include "theory/uf/theory_uf.h"
+#include "context/cdlist.h"
+
+#include "theory/inst_match.h"
+#include "expr/node_manager.h"
+#include "expr/node_builder.h"
+
+//#define USE_EFFICIENT_E_MATCHING
+
+namespace CVC4 {
+namespace theory {
+
+namespace rrinst{
+
+class CandidateGenerator
+{
+public:
+  CandidateGenerator(){}
+  virtual ~CandidateGenerator(){};
+
+  /** Get candidates functions.  These set up a context to get all match candidates.
+      cg->reset( eqc );
+      do{
+        Node cand = cg->getNextCandidate();
+        //.......
+      }while( !cand.isNull() );
+      
+      eqc is the equivalence class you are searching in
+  */
+  virtual void reset( TNode eqc ) = 0;
+  virtual TNode getNextCandidate() = 0;
+  /** call this at the beginning of each instantiation round */
+  virtual void resetInstantiationRound() = 0;
+public:
+  /** legal candidate */
+  static inline bool isLegalCandidate( TNode n ){
+    return !n.getAttribute(NoMatchAttribute()) &&
+      ( !Options::current()->cbqi || !n.hasAttribute(InstConstantAttribute())) &&
+      ( !Options::current()->efficientEMatching || n.hasAttribute(AvailableInTermDb()) );
+}
+
+};
+
+
+inline std::ostream& operator<<(std::ostream& out, const InstMatch& m) {
+  m.toStream(out);
+  return out;
+}
+
+template<bool modEq = false> class InstMatchTrie2;
+template<bool modEq = false> class InstMatchTrie2Pairs;
+
+template<bool modEq = false>
+class InstMatchTrie2Gen
+{
+  friend class InstMatchTrie2<modEq>;
+  friend class InstMatchTrie2Pairs<modEq>;
+
+private:
+
+  class Tree {
+  public:
+    typedef std::hash_map< Node, Tree *, NodeHashFunction > MLevel;
+    MLevel e;
+    const size_t level; //context level of creation
+    Tree() CVC4_UNDEFINED;
+    const Tree & operator =(const Tree & t){
+      Assert(t.e.empty()); Assert(e.empty());
+      Assert(t.level == level);
+      return t;
+    }
+    Tree(size_t l): level(l) {};
+    ~Tree(){
+      for(typename MLevel::iterator i = e.begin(); i!=e.end(); ++i)
+        delete(i->second);
+    };
+  };
+
+
+  typedef std::pair<Tree *, TNode> Mod;
+
+  class CleanUp{
+  public:
+    inline void operator()(Mod * m){
+      typename Tree::MLevel::iterator i = m->first->e.find(m->second);
+      Assert (i != m->first->e.end()); //should not have been already removed
+      m->first->e.erase(i);
+    };
+  };
+
+  EqualityQuery* d_eQ;
+  CandidateGenerator * d_cG;
+
+  context::Context* d_context;
+  context::CDList<Mod, CleanUp, std::allocator<Mod> > d_mods;
+
+
+  typedef std::map<Node, Node>::const_iterator mapIter;
+
+  /** add the substitution given by the iterator*/
+  void addSubTree( Tree * root, mapIter current, mapIter end, size_t currLevel);
+  /** test if it exists match, modulo uf-equations if modEq is true if
+   *  return false the deepest point of divergence is put in [e] and
+   *  [diverge].
+   */
+  bool existsInstMatch( Tree * root,
+                        mapIter & current, mapIter & end,
+                        Tree * & e, mapIter & diverge) const;
+
+  /** add match m in the trie root
+      return true if it was never seen */
+  bool addInstMatch( InstMatch& m, Tree * root);
+
+public:
+  InstMatchTrie2Gen(context::Context* c,  QuantifiersEngine* q);
+  InstMatchTrie2Gen(const InstMatchTrie2Gen &) CVC4_UNDEFINED;
+  const InstMatchTrie2Gen & operator =(const InstMatchTrie2Gen & e) CVC4_UNDEFINED;
+};
+
+template<bool modEq>
+class InstMatchTrie2
+{
+  typename InstMatchTrie2Gen<modEq>::Tree d_data;
+  InstMatchTrie2Gen<modEq> d_backtrack;
+public:
+  InstMatchTrie2(context::Context* c,  QuantifiersEngine* q): d_data(0),
+                                                              d_backtrack(c,q) {};
+  InstMatchTrie2(const InstMatchTrie2 &) CVC4_UNDEFINED;
+  const InstMatchTrie2 & operator =(const InstMatchTrie2 & e) CVC4_UNDEFINED;
+  /** add match m in the trie,
+      return true if it was never seen */
+  inline bool addInstMatch( InstMatch& m){
+    return d_backtrack.addInstMatch(m,&d_data);
+  };
+
+};/* class InstMatchTrie2 */
+
+class Matcher
+{
+public:
+  /** reset instantiation round (call this whenever equivalence classes have changed) */
+  virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
+  /** reset the term to match, return false if there is no such term */
+  virtual bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe ) = 0;
+  /** get the next match. If it return false once you shouldn't call
+      getNextMatch again before doing a reset */
+  virtual bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) = 0;
+  /** If reset, or getNextMatch return false they remove from the
+      InstMatch the binding that they have previously created */
+
+  /** virtual Matcher in order to have definned behavior */
+  virtual ~Matcher(){};
+};
+
+
+class ApplyMatcher: public Matcher{
+private:
+  /** What to check first: constant and variable */
+  std::vector< triple< TNode,size_t,EqualityQuery* > > d_constants;
+  std::vector< triple< TNode,size_t,EqualityQuery* > > d_variables;
+  /** children generators, only the sub-pattern which are
+      neither a variable neither a constant appears */
+  std::vector< triple< Matcher*, size_t, EqualityQuery* > > d_childrens;
+  /** the variable that have been set by this matcher (during its own reset) */
+  std::vector< TNode > d_binded; /* TNode because the variable are already in d_pattern */
+  /** the representant of the argument of the term given by the last reset */
+  std::vector< Node > d_reps;
+public:
+  /** The pattern we are producing matches for */
+  Node d_pattern;
+public:
+  /** constructors */
+  ApplyMatcher( Node pat, QuantifiersEngine* qe);
+  /** destructor */
+  ~ApplyMatcher(){/*TODO delete dandling pointers? */}
+  /** reset instantiation round (call this whenever equivalence classes have changed) */
+  void resetInstantiationRound( QuantifiersEngine* qe );
+  /** reset the term to match */
+  bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe );
+  /** get the next match. */
+  bool getNextMatch(InstMatch& m, QuantifiersEngine* qe);
+private:
+  bool getNextMatch(InstMatch& m, QuantifiersEngine* qe, bool reset);
+};
+
+
+/* Match literal so you don't choose the equivalence class( */
+class PatMatcher
+{
+public:
+  /** reset instantiation round (call this whenever equivalence classes have changed) */
+  virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
+  /** reset the matcher, return false if there is no such term */
+  virtual bool reset( InstMatch& m, QuantifiersEngine* qe ) = 0;
+  /** get the next match. If it return false once you shouldn't call
+      getNextMatch again before doing a reset */
+  virtual bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) = 0;
+  /** If reset, or getNextMatch return false they remove from the
+      InstMatch the binding that they have previously created */
+};
+
+Matcher* mkMatcher( Node pat, QuantifiersEngine* qe );
+PatMatcher* mkPattern( Node pat, QuantifiersEngine* qe );
+
+/* Match literal so you don't choose the equivalence class( */
+class PatsMatcher
+{
+public:
+  /** reset instantiation round (call this whenever equivalence classes have changed) */
+  virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
+  /** reset the matcher, return false if there is no such term */
+  virtual bool getNextMatch( QuantifiersEngine* qe ) = 0;
+  virtual const InstMatch& getInstMatch() = 0;
+  /** Add directly the instantiation to quantifiers engine */
+  virtual int addInstantiations( InstMatch& baseMatch, Node quant, QuantifiersEngine* qe) = 0;
+};
+
+PatsMatcher* mkPatterns( std::vector< Node > pat, QuantifiersEngine* qe );
+PatsMatcher* mkPatternsEfficient( std::vector< Node > pat, QuantifiersEngine* qe );
+
+/** return true if whatever Node is subsituted for the variables the
+    given Node can't match the pattern */
+bool nonunifiable( TNode t, TNode pat, const std::vector<Node> & vars);
+
+class InstMatchGenerator;
+
+}/* CVC4::theory rrinst */
+
+}/* CVC4::theory namespace */
+
+}/* CVC4 namespace */
+
+#endif /* __CVC4__RR_INST_MATCH_H */
diff --git a/src/theory/rr_inst_match_impl.h b/src/theory/rr_inst_match_impl.h
new file mode 100644 (file)
index 0000000..04a15d4
--- /dev/null
@@ -0,0 +1,128 @@
+/*********************                                                        */
+/*! \file inst_match_impl.h
+ ** \verbatim
+ ** Original author: bobot
+ ** Major contributors: none
+ ** Minor contributors (to current version): taking, mdeters
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2012  The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief inst match class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__RR_INST_MATCH_IMPL_H
+#define __CVC4__RR_INST_MATCH_IMPL_H
+
+#include "theory/rr_inst_match.h"
+#include "theory/theory_engine.h"
+#include "theory/quantifiers_engine.h"
+#include "theory/uf/theory_uf_candidate_generator.h"
+#include "theory/uf/equality_engine.h"
+
+namespace CVC4 {
+namespace theory {
+namespace rrinst {
+
+template<bool modEq>
+InstMatchTrie2Gen<modEq>::InstMatchTrie2Gen(context::Context* c,  QuantifiersEngine* qe):
+  d_context(c), d_mods(c) {
+  d_eQ = qe->getEqualityQuery();
+  d_cG = qe->getRRCanGenClass();
+};
+
+/** add match m for quantifier f starting at index, take into account equalities q, return true if successful */
+template<bool modEq>
+void InstMatchTrie2Gen<modEq>::addSubTree( Tree * root, mapIter current, mapIter end, size_t currLevel ) {
+  if( current == end ) return;
+
+  Assert(root->e.find(current->second) == root->e.end());
+  Tree * root2 = new Tree(currLevel);
+  root->e.insert(std::make_pair(current->second, root2));
+  addSubTree(root2, ++current, end, currLevel );
+}
+
+/** exists match */
+template<bool modEq>
+bool InstMatchTrie2Gen<modEq>::existsInstMatch(InstMatchTrie2Gen<modEq>::Tree * root,
+                                            mapIter & current, mapIter & end,
+                                            Tree * & e, mapIter & diverge) const{
+  if( current == end ) {
+    Debug("Trie2") << "Trie2 Bottom " << std::endl;
+    --current;
+    return true;
+  }; //Already their
+
+  if (current->first > diverge->first){
+    // this point is the deepest point currently seen map are ordered
+    e = root;
+    diverge = current;
+  };
+
+  TNode n = current->second;
+  typename InstMatchTrie2Gen<modEq>::Tree::MLevel::iterator it =
+    root->e.find( n );
+  if( it!=root->e.end() &&
+      existsInstMatch( (*it).second, ++current, end, e, diverge) ){
+    Debug("Trie2") << "Trie2 Directly here " << n << std::endl;
+    --current;
+    return true;
+  }
+  Assert( it==root->e.end() || e != root );
+
+  // Even if n is in the trie others of the equivalence class
+  // can also be in it since the equality can have appeared
+  // after they have been added
+  if( modEq && d_eQ->hasTerm( n ) ){
+    //check modulo equality if any other instantiation match exists
+    d_cG->reset( d_eQ->getRepresentative( n ) );
+    for(TNode en = d_cG->getNextCandidate() ; !en.isNull() ;
+        en = d_cG->getNextCandidate() ){
+      if( en == n ) continue; // already tested
+      typename InstMatchTrie2Gen<modEq>::Tree::MLevel::iterator itc =
+        root->e.find( en );
+      if( itc!=root->e.end() &&
+          existsInstMatch( (*itc).second, ++current, end, e, diverge) ){
+        Debug("Trie2") << "Trie2 Indirectly here by equality " << n << " = " << en << std::endl;
+        --current;
+        return true;
+      }
+      Assert( itc==root->e.end() || e != root );
+    }
+  }
+  --current;
+  return false;
+}
+
+template<bool modEq>
+bool InstMatchTrie2Gen<modEq>::
+addInstMatch( InstMatch& m, InstMatchTrie2Gen<modEq>::Tree* e ) {
+  d_cG->resetInstantiationRound();
+ mapIter begin = m.begin();
+ mapIter end = m.end();
+ mapIter diverge = begin;
+ if( !existsInstMatch(e, begin, end, e, diverge ) ){
+   Assert(!diverge->second.isNull());
+   size_t currLevel = d_context->getLevel();
+   addSubTree( e, diverge, end, currLevel );
+   if(e->level != currLevel)
+     //If same level that e, will be removed at the same time than e
+     d_mods.push_back(std::make_pair(e,diverge->second));
+   return true;
+ }else{
+   return false;
+ }
+}
+
+}/* CVC4::theory::rrinst namespace */
+
+}/* CVC4::theory namespace */
+
+}/* CVC4 namespace */
+
+#endif /*  __CVC4__RR_INST_MATCH_IMPL_H */
diff --git a/src/theory/rr_trigger.cpp b/src/theory/rr_trigger.cpp
new file mode 100644 (file)
index 0000000..579608b
--- /dev/null
@@ -0,0 +1,523 @@
+/*********************                                                        */
+/*! \file trigger.cpp
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Implementation of trigger class
+ **/
+
+#include "theory/rr_trigger.h"
+#include "theory/theory_engine.h"
+#include "theory/quantifiers_engine.h"
+#include "theory/uf/theory_uf_instantiator.h"
+#include "theory/uf/theory_uf_candidate_generator.h"
+#include "theory/uf/equality_engine.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::rrinst;
+
+//#define NESTED_PATTERN_SELECTION
+
+Trigger* Trigger::TrTrie::getTrigger2( std::vector< Node >& nodes ){
+  if( nodes.empty() ){
+    return d_tr;
+  }else{
+    Node n = nodes.back();
+    nodes.pop_back();
+    if( d_children.find( n )!=d_children.end() ){
+      return d_children[n]->getTrigger2( nodes );
+    }else{
+      return NULL;
+    }
+  }
+}
+void Trigger::TrTrie::addTrigger2( std::vector< Node >& nodes, Trigger* t ){
+  if( nodes.empty() ){
+    d_tr = t;
+  }else{
+    Node n = nodes.back();
+    nodes.pop_back();
+    if( d_children.find( n )==d_children.end() ){
+      d_children[n] = new TrTrie;
+    }
+    d_children[n]->addTrigger2( nodes, t );
+  }
+}
+
+/** trigger static members */
+std::map< Node, std::vector< Node > > Trigger::d_var_contains;
+int Trigger::trCount = 0;
+Trigger::TrTrie Trigger::d_tr_trie;
+
+/** trigger class constructor */
+Trigger::Trigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool smartTriggers ) :
+d_quantEngine( qe ), d_f( f ){
+  trCount++;
+  d_nodes.insert( d_nodes.begin(), nodes.begin(), nodes.end() );
+  Debug("trigger") << "Trigger for " << f << ": " << d_nodes << std::endl;
+  if(matchOption == MATCH_GEN_DEFAULT) d_mg = mkPatterns( d_nodes, qe );
+  else d_mg = mkPatternsEfficient( d_nodes, qe );
+  if( d_nodes.size()==1 ){
+    if( isSimpleTrigger( d_nodes[0] ) ){
+      ++(qe->d_statistics.d_triggers);
+    }else{
+      ++(qe->d_statistics.d_simple_triggers);
+    }
+  }else{\r
+    Debug("multi-trigger") << "Multi-trigger " << (*this) << std::endl;
+    //std::cout << "Multi-trigger for " << f << " : " << std::endl;
+    //std::cout << "   " << (*this) << std::endl;
+    ++(qe->d_statistics.d_multi_triggers);
+  }
+}\r
+void Trigger::computeVarContains( Node n ) {\r
+  if( d_var_contains.find( n )==d_var_contains.end() ){\r
+    d_var_contains[n].clear();\r
+    computeVarContains2( n, n );\r
+  }\r
+}\r
+\r
+void Trigger::computeVarContains2( Node n, Node parent ){\r
+  if( n.getKind()==INST_CONSTANT ){\r
+    if( std::find( d_var_contains[parent].begin(), d_var_contains[parent].end(), n )==d_var_contains[parent].end() ){\r
+      d_var_contains[parent].push_back( n );\r
+    }\r
+  }else{\r
+    for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+      computeVarContains2( n[i], parent );\r
+    }\r
+  }\r
+}
+\r
+void Trigger::resetInstantiationRound(){\r
+  d_mg->resetInstantiationRound( d_quantEngine );\r
+}\r
+\r
+
+bool Trigger::getNextMatch(){\r
+  bool retVal = d_mg->getNextMatch( d_quantEngine );\r
+  //m.makeInternal( d_quantEngine->getEqualityQuery() );\r
+  return retVal;\r
+}\r
+
+// bool Trigger::getMatch( Node t, InstMatch& m ){
+//   //FIXME: this assumes d_mg is an inst match generator
+//   return ((InstMatchGenerator*)d_mg)->getMatch( t, m, d_quantEngine );
+// }
+\r
+
+int Trigger::addInstantiations( InstMatch& baseMatch ){\r
+  int addedLemmas = d_mg->addInstantiations( baseMatch,
+                                             d_nodes[0].getAttribute(InstConstantAttribute()),
+                                             d_quantEngine);\r
+  if( addedLemmas>0 ){\r
+    Debug("inst-trigger") << "Added " << addedLemmas << " lemmas, trigger was ";
+    for( int i=0; i<(int)d_nodes.size(); i++ ){
+      Debug("inst-trigger") << d_nodes[i] << " ";
+    }
+    Debug("inst-trigger") << std::endl;\r
+  }\r
+  return addedLemmas;\r
+}\r
+\r
+Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool keepAll, int trOption,\r
+                             bool smartTriggers ){\r
+  std::vector< Node > trNodes;\r
+  if( !keepAll ){\r
+    //only take nodes that contribute variables to the trigger when added\r
+    std::vector< Node > temp;\r
+    temp.insert( temp.begin(), nodes.begin(), nodes.end() );\r
+    std::map< Node, bool > vars;\r
+    std::map< Node, std::vector< Node > > patterns;\r
+    for( int i=0; i<(int)temp.size(); i++ ){\r
+      bool foundVar = false;\r
+      computeVarContains( temp[i] );\r
+      for( int j=0; j<(int)d_var_contains[ temp[i] ].size(); j++ ){\r
+        Node v = d_var_contains[ temp[i] ][j];\r
+        if( v.getAttribute(InstConstantAttribute())==f ){\r
+          if( vars.find( v )==vars.end() ){\r
+            vars[ v ] = true;\r
+            foundVar = true;\r
+          }\r
+        }\r
+      }\r
+      if( foundVar ){\r
+        trNodes.push_back( temp[i] );\r
+        for( int j=0; j<(int)d_var_contains[ temp[i] ].size(); j++ ){\r
+          Node v = d_var_contains[ temp[i] ][j];\r
+          patterns[ v ].push_back( temp[i] );\r
+        }\r
+      }\r
+    }\r
+    //now, minimalize the trigger\r
+    for( int i=0; i<(int)trNodes.size(); i++ ){\r
+      bool keepPattern = false;\r
+      Node n = trNodes[i];\r
+      for( int j=0; j<(int)d_var_contains[ n ].size(); j++ ){\r
+        Node v = d_var_contains[ n ][j];\r
+        if( patterns[v].size()==1 ){\r
+          keepPattern = true;\r
+          break;\r
+        }\r
+      }\r
+      if( !keepPattern ){\r
+        //remove from pattern vector\r
+        for( int j=0; j<(int)d_var_contains[ n ].size(); j++ ){\r
+          Node v = d_var_contains[ n ][j];\r
+          for( int k=0; k<(int)patterns[v].size(); k++ ){\r
+            if( patterns[v][k]==n ){\r
+              patterns[v].erase( patterns[v].begin() + k, patterns[v].begin() + k + 1 );\r
+              break;\r
+            }\r
+          }\r
+        }\r
+        //remove from trigger nodes\r
+        trNodes.erase( trNodes.begin() + i, trNodes.begin() + i + 1 );\r
+        i--;\r
+      }\r
+    }\r
+  }else{\r
+    trNodes.insert( trNodes.begin(), nodes.begin(), nodes.end() );\r
+  }\r
+\r
+  //check for duplicate?\r
+  if( trOption==TR_MAKE_NEW ){\r
+    //static int trNew = 0;\r
+    //static int trOld = 0;\r
+    //Trigger* t = d_tr_trie.getTrigger( trNodes );\r
+    //if( t ){\r
+    //  trOld++;\r
+    //}else{\r
+    //  trNew++;\r
+    //}\r
+    //if( (trNew+trOld)%100==0 ){\r
+    //  std::cout << "Trigger new old = " << trNew << " " << trOld << std::endl;\r
+    //}\r
+  }else{\r
+    Trigger* t = d_tr_trie.getTrigger( trNodes );\r
+    if( t ){\r
+      if( trOption==TR_GET_OLD ){\r
+        //just return old trigger\r
+        return t;\r
+      }else{\r
+        return NULL;\r
+      }\r
+    }\r
+  }\r
+  Trigger* t = new Trigger( qe, f, trNodes, matchOption, smartTriggers );\r
+  d_tr_trie.addTrigger( trNodes, t );\r
+  return t;\r
+}\r
+Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, Node n, int matchOption, bool keepAll, int trOption, bool smartTriggers ){\r
+  std::vector< Node > nodes;\r
+  nodes.push_back( n );\r
+  return mkTrigger( qe, f, nodes, matchOption, keepAll, trOption, smartTriggers );\r
+}\r
+
+bool Trigger::isUsableTrigger( std::vector< Node >& nodes, Node f ){
+  for( int i=0; i<(int)nodes.size(); i++ ){
+    if( !isUsableTrigger( nodes[i], f ) ){
+      return false;
+    }
+  }
+  return true;
+}\r
+\r
+bool Trigger::isUsable( Node n, Node f ){\r
+  if( n.getAttribute(InstConstantAttribute())==f ){\r
+    if( !isAtomicTrigger( n ) && n.getKind()!=INST_CONSTANT ){\r
+      std::map< Node, Node > coeffs;\r
+      return getPatternArithmetic( f, n, coeffs );\r
+    }else{\r
+      for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+        if( !isUsable( n[i], f ) ){\r
+          return false;\r
+        }\r
+      }\r
+      return true;\r
+    }\r
+  }else{\r
+    return true;\r
+  }\r
+}\r
+
+bool Trigger::isSimpleTrigger( Node n ){
+  if( isAtomicTrigger( n ) ){
+    for( int i=0; i<(int)n.getNumChildren(); i++ ){
+      if( n[i].getKind()!=INST_CONSTANT && n[i].hasAttribute(InstConstantAttribute()) ){
+        return false;
+      }
+    }
+    return true;
+  }else{
+    return false;
+  }
+}
+
+/** filter all nodes that have instances */
+void Trigger::filterInstances( std::vector< Node >& nodes ){
+  std::vector< bool > active;
+  active.resize( nodes.size(), true );
+  for( int i=0; i<(int)nodes.size(); i++ ){
+    for( int j=i+1; j<(int)nodes.size(); j++ ){
+      if( active[i] && active[j] ){
+        int result = isInstanceOf( nodes[i], nodes[j] );
+        if( result==1 ){
+          active[j] = false;
+        }else if( result==-1 ){
+          active[i] = false;
+        }
+      }
+    }
+  }
+  std::vector< Node > temp;
+  for( int i=0; i<(int)nodes.size(); i++ ){
+    if( active[i] ){
+      temp.push_back( nodes[i] );
+    }
+  }
+  nodes.clear();
+  nodes.insert( nodes.begin(), temp.begin(), temp.end() );
+}
+
+
+bool Trigger::collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt ){\r
+  if( patMap.find( n )==patMap.end() ){\r
+    patMap[ n ] = false;\r
+    if( tstrt==TS_MIN_TRIGGER ){\r
+      if( n.getKind()==FORALL ){\r
+#ifdef NESTED_PATTERN_SELECTION\r
+        //return collectPatTerms2( qe, f, qe->getOrCreateCounterexampleBody( n ), patMap, tstrt );\r
+        return collectPatTerms2( qe, f, qe->getBoundBody( n ), patMap, tstrt );\r
+#else\r
+        return false;\r
+#endif\r
+      }else{\r
+        bool retVal = false;\r
+        for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+          if( collectPatTerms2( qe, f, n[i], patMap, tstrt ) ){\r
+            retVal = true;\r
+          }\r
+        }\r
+        if( retVal ){\r
+          return true;\r
+        }else if( isUsableTrigger( n, f ) ){\r
+          patMap[ n ] = true;\r
+          return true;\r
+        }else{\r
+          return false;\r
+        }\r
+      }\r
+    }else{\r
+      bool retVal = false;\r
+      if( isUsableTrigger( n, f ) ){\r
+        patMap[ n ] = true;\r
+        if( tstrt==TS_MAX_TRIGGER ){\r
+          return true;\r
+        }else{\r
+          retVal = true;\r
+        }\r
+      }\r
+      if( n.getKind()==FORALL ){\r
+#ifdef NESTED_PATTERN_SELECTION\r
+        //if( collectPatTerms2( qe, f, qe->getOrCreateCounterexampleBody( n ), patMap, tstrt ) ){\r
+        //  retVal = true;\r
+        //}\r
+        if( collectPatTerms2( qe, f, qe->getBoundBody( n ), patMap, tstrt ) ){\r
+          retVal = true;\r
+        }\r
+#endif\r
+      }else{\r
+        for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+          if( collectPatTerms2( qe, f, n[i], patMap, tstrt ) ){\r
+            retVal = true;\r
+          }\r
+        }\r
+      }\r
+      return retVal;\r
+    }\r
+  }else{\r
+    return patMap[ n ];\r
+  }\r
+}
+
+void Trigger::collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, bool filterInst ){\r
+  std::map< Node, bool > patMap;
+  if( filterInst ){
+    //immediately do not consider any term t for which another term is an instance of t
+    std::vector< Node > patTerms2;
+    collectPatTerms( qe, f, n, patTerms2, TS_ALL, false );
+    std::vector< Node > temp;
+    temp.insert( temp.begin(), patTerms2.begin(), patTerms2.end() );
+    filterInstances( temp );
+    if( temp.size()!=patTerms2.size() ){
+      Debug("trigger-filter-instance") << "Filtered an instance: " << std::endl;
+      Debug("trigger-filter-instance") << "Old: ";
+      for( int i=0; i<(int)patTerms2.size(); i++ ){
+        Debug("trigger-filter-instance") << patTerms2[i] << " ";
+      }
+      Debug("trigger-filter-instance") << std::endl << "New: ";
+      for( int i=0; i<(int)temp.size(); i++ ){
+        Debug("trigger-filter-instance") << temp[i] << " ";
+      }
+      Debug("trigger-filter-instance") << std::endl;
+    }
+    if( tstrt==TS_ALL ){
+      patTerms.insert( patTerms.begin(), temp.begin(), temp.end() );
+      return;
+    }else{
+      //do not consider terms that have instances
+      for( int i=0; i<(int)patTerms2.size(); i++ ){
+        if( std::find( temp.begin(), temp.end(), patTerms2[i] )==temp.end() ){
+          patMap[ patTerms2[i] ] = false;
+        }
+      }
+    }
+  }
+  collectPatTerms2( qe, f, n, patMap, tstrt );
+  for( std::map< Node, bool >::iterator it = patMap.begin(); it != patMap.end(); ++it ){\r
+    if( it->second ){\r
+      patTerms.push_back( it->first );\r
+    }\r
+  }
+}
+
+/** is n1 an instance of n2 or vice versa? */
+int Trigger::isInstanceOf( Node n1, Node n2 ){
+  if( n1==n2 ){
+    return 1;
+  }else if( n1.getKind()==n2.getKind() ){
+    if( n1.getKind()==APPLY_UF ){
+      if( n1.getOperator()==n2.getOperator() ){
+        int result = 0;
+        for( int i=0; i<(int)n1.getNumChildren(); i++ ){
+          if( n1[i]!=n2[i] ){
+            int cResult = isInstanceOf( n1[i], n2[i] );
+            if( cResult==0 ){
+              return 0;
+            }else if( cResult!=result ){
+              if( result!=0 ){
+                return 0;
+              }else{
+                result = cResult;
+              }
+            }
+          }
+        }
+        return result;
+      }
+    }
+    return 0;
+  }else if( n2.getKind()==INST_CONSTANT ){
+    computeVarContains( n1 );
+    //if( std::find( d_var_contains[ n1 ].begin(), d_var_contains[ n1 ].end(), n2 )!=d_var_contains[ n1 ].end() ){
+    //  return 1;
+    //}
+    if( d_var_contains[ n1 ].size()==1 && d_var_contains[ n1 ][ 0 ]==n2 ){
+      return 1;
+    }
+  }else if( n1.getKind()==INST_CONSTANT ){
+    computeVarContains( n2 );
+    //if( std::find( d_var_contains[ n2 ].begin(), d_var_contains[ n2 ].end(), n1 )!=d_var_contains[ n2 ].end() ){
+    //  return -1;
+    //}
+    if( d_var_contains[ n2 ].size()==1 && d_var_contains[ n2 ][ 0 ]==n1 ){
+      return 1;
+    }
+  }
+  return 0;
+}
+
+bool Trigger::isVariableSubsume( Node n1, Node n2 ){
+  if( n1==n2 ){
+    return true;
+  }else{
+    //std::cout << "is variable subsume ? " << n1 << " " << n2 << std::endl;
+    computeVarContains( n1 );
+    computeVarContains( n2 );
+    for( int i=0; i<(int)d_var_contains[n2].size(); i++ ){
+      if( std::find( d_var_contains[n1].begin(), d_var_contains[n1].end(), d_var_contains[n2][i] )==d_var_contains[n1].end() ){
+        //std::cout << "no" << std::endl;
+        return false;
+      }
+    }
+    //std::cout << "yes" << std::endl;
+    return true;
+  }
+}
+
+void Trigger::getVarContains( Node f, std::vector< Node >& pats, std::map< Node, std::vector< Node > >& varContains ){
+  for( int i=0; i<(int)pats.size(); i++ ){
+    computeVarContains( pats[i] );
+    varContains[ pats[i] ].clear();
+    for( int j=0; j<(int)d_var_contains[pats[i]].size(); j++ ){
+      if( d_var_contains[pats[i]][j].getAttribute(InstConstantAttribute())==f ){
+        varContains[ pats[i] ].push_back( d_var_contains[pats[i]][j] );
+      }
+    }
+  }
+}
+\r
+void Trigger::getVarContainsNode( Node f, Node n, std::vector< Node >& varContains ){\r
+  computeVarContains( n );\r
+  for( int j=0; j<(int)d_var_contains[n].size(); j++ ){\r
+    if( d_var_contains[n][j].getAttribute(InstConstantAttribute())==f ){\r
+      varContains.push_back( d_var_contains[n][j] );\r
+    }\r
+  }\r
+}\r
+
+bool Trigger::getPatternArithmetic( Node f, Node n, std::map< Node, Node >& coeffs ){
+  if( n.getKind()==PLUS ){
+    Assert( coeffs.empty() );
+    NodeBuilder<> t(kind::PLUS);
+    for( int i=0; i<(int)n.getNumChildren(); i++ ){
+      if( n[i].hasAttribute(InstConstantAttribute()) ){
+        if( n[i].getKind()==INST_CONSTANT ){
+          if( n[i].getAttribute(InstConstantAttribute())==f ){
+            coeffs[ n[i] ] = Node::null();
+          }else{
+            coeffs.clear();
+            return false;
+          }
+        }else if( !getPatternArithmetic( f, n[i], coeffs ) ){
+          coeffs.clear();
+          return false;
+        }
+      }else{
+        t << n[i];
+      }
+    }
+    if( t.getNumChildren()==0 ){
+      coeffs[ Node::null() ] = NodeManager::currentNM()->mkConst( Rational(0) );
+    }else if( t.getNumChildren()==1 ){
+      coeffs[ Node::null() ]  = t.getChild( 0 );
+    }else{
+      coeffs[ Node::null() ]  = t;
+    }
+    return true;
+  }else if( n.getKind()==MULT ){
+    if( n[0].getKind()==INST_CONSTANT && n[0].getAttribute(InstConstantAttribute())==f ){
+      Assert( !n[1].hasAttribute(InstConstantAttribute()) );
+      coeffs[ n[0] ] = n[1];
+      return true;
+    }else if( n[1].getKind()==INST_CONSTANT && n[1].getAttribute(InstConstantAttribute())==f ){
+      Assert( !n[0].hasAttribute(InstConstantAttribute()) );
+      coeffs[ n[1] ] = n[0];
+      return true;
+    }
+  }
+  return false;
+}
diff --git a/src/theory/rr_trigger.h b/src/theory/rr_trigger.h
new file mode 100644 (file)
index 0000000..7ea4ee1
--- /dev/null
@@ -0,0 +1,176 @@
+/*********************                                                        */
+/*! \file trigger.h
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief trigger class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__RR_TRIGGER_H
+#define __CVC4__RR_TRIGGER_H
+
+#include "theory/rr_inst_match.h"
+
+namespace CVC4 {
+namespace theory {
+namespace rrinst {
+
+//a collect of nodes representing a trigger
+class Trigger {
+public:
+  static int trCount;
+private:
+  /** computation of variable contains */
+  static std::map< Node, std::vector< Node > > d_var_contains;
+  static void computeVarContains( Node n );
+  static void computeVarContains2( Node n, Node parent );
+private:
+  /** the quantifiers engine */
+  QuantifiersEngine* d_quantEngine;
+  /** the quantifier this trigger is for */
+  Node d_f;
+  /** match generators */
+  PatsMatcher * d_mg;
+private:
+  /** a trie of triggers */
+  class TrTrie
+  {
+  private:
+    Trigger* getTrigger2( std::vector< Node >& nodes );
+    void addTrigger2( std::vector< Node >& nodes, Trigger* t );
+  public:
+    TrTrie() : d_tr( NULL ){}
+    Trigger* d_tr;
+    std::map< Node, TrTrie* > d_children;
+    Trigger* getTrigger( std::vector< Node >& nodes ){
+      std::vector< Node > temp;
+      temp.insert( temp.begin(), nodes.begin(), nodes.end() );
+      std::sort( temp.begin(), temp.end() );
+      return getTrigger2( temp );
+    }
+    void addTrigger( std::vector< Node >& nodes, Trigger* t ){
+      std::vector< Node > temp;
+      temp.insert( temp.begin(), nodes.begin(), nodes.end() );
+      std::sort( temp.begin(), temp.end() );
+      return addTrigger2( temp, t );
+    }
+  };
+  /** all triggers will be stored in this trie */
+  static TrTrie d_tr_trie;
+private:
+  /** trigger constructor */
+  Trigger( QuantifiersEngine* ie, Node f, std::vector< Node >& nodes, int matchOption = 0, bool smartTriggers = false );
+public:
+  ~Trigger(){}
+public:
+  std::vector< Node > d_nodes;
+public:
+  void debugPrint( const char* c );
+  PatsMatcher* getGenerator() { return d_mg; }
+public:
+  /** reset instantiation round (call this whenever equivalence classes have changed) */
+  void resetInstantiationRound();
+  /** get next match.  must call reset( eqc ) once before this function. */
+  bool getNextMatch();
+  const InstMatch & getInstMatch(){return d_mg->getInstMatch();};
+  /** return whether this is a multi-trigger */
+  bool isMultiTrigger() { return d_nodes.size()>1; }
+public:
+  /** add all available instantiations exhaustively, in any equivalence class
+      if limitInst>0, limitInst is the max # of instantiations to try */
+  int addInstantiations( InstMatch& baseMatch);
+  /** mkTrigger method
+     ie     : quantifier engine;
+     f      : forall something ....
+     nodes  : (multi-)trigger
+     matchOption : which policy to use for creating matches (one of InstMatchGenerator::MATCH_GEN_* )
+     keepAll: don't remove unneeded patterns;
+     trOption : policy for dealing with triggers that already existed (see below)
+  */
+  enum {
+    //options for producing matches
+    MATCH_GEN_DEFAULT = 0,
+    MATCH_GEN_EFFICIENT_E_MATCH,   //generate matches via Efficient E
+  };
+  enum{
+    TR_MAKE_NEW,    //make new trigger even if it already may exist
+    TR_GET_OLD,     //return a previous trigger if it had already been created
+    TR_RETURN_NULL  //return null if a duplicate is found
+  };
+  static Trigger* mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes,
+                             int matchOption = 0, bool keepAll = true, int trOption = TR_MAKE_NEW,
+                             bool smartTriggers = false );
+  static Trigger* mkTrigger( QuantifiersEngine* qe, Node f, Node n,
+                             int matchOption = 0, bool keepAll = true, int trOption = TR_MAKE_NEW,
+                             bool smartTriggers = false );
+private:
+  /** is subterm of trigger usable */
+  static bool isUsable( Node n, Node f );
+  /** collect all APPLY_UF pattern terms for f in n */
+  static bool collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt );
+public:
+  //different strategies for choosing trigger terms
+  enum {
+    TS_MAX_TRIGGER = 0,
+    TS_MIN_TRIGGER,
+    TS_ALL,
+  };
+  static void collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, bool filterInst = false );
+public:
+  /** is usable trigger */
+  static inline bool isUsableTrigger( TNode n, TNode f ){
+    //return n.getAttribute(InstConstantAttribute())==f && n.getKind()==APPLY_UF;
+    return n.getAttribute(InstConstantAttribute())==f && isAtomicTrigger( n ) && isUsable( n, f );
+  }
+  static inline bool isAtomicTrigger( TNode n ){
+    return
+      n.getKind()==kind::APPLY_UF ||
+      n.getKind()==kind::SELECT ||
+      n.getKind()==kind::STORE;
+  }
+  static bool isUsableTrigger( std::vector< Node >& nodes, Node f );
+  static bool isSimpleTrigger( Node n );
+  /** filter all nodes that have instances */
+  static void filterInstances( std::vector< Node >& nodes );
+  /** -1: n1 is an instance of n2, 1: n1 is an instance of n2 */
+  static int isInstanceOf( Node n1, Node n2 );
+  /** variables subsume, return true if n1 contains all free variables in n2 */
+  static bool isVariableSubsume( Node n1, Node n2 );
+  /** get var contains */
+  static void getVarContains( Node f, std::vector< Node >& pats, std::map< Node, std::vector< Node > >& varContains );
+  static void getVarContainsNode( Node f, Node n, std::vector< Node >& varContains );
+  /** get pattern arithmetic */
+  static bool getPatternArithmetic( Node f, Node n, std::map< Node, Node >& coeffs );
+
+  inline void toStream(std::ostream& out) const {
+    out << "TRIGGER( ";
+    for( int i=0; i<(int)d_nodes.size(); i++ ){
+      if( i>0 ){ out << ", "; }
+      out << d_nodes[i];
+    }
+    out << " )";
+  }
+};
+
+inline std::ostream& operator<<(std::ostream& out, const Trigger & tr) {
+  tr.toStream(out);
+  return out;
+}
+
+}/* CVC4::theory::rrinst namespace */
+
+}/* CVC4::theory namespace */
+
+}/* CVC4 namespace */
+
+#endif /* __CVC4__RR_TRIGGER_H */
index 7d003bf25bf3790c419596693b04f515d95e756b..0cf7a87743d2d3c5201bbff6e956b303fb300f1a 100644 (file)
@@ -52,6 +52,10 @@ class InstStrategy;
 class QuantifiersEngine;
 class TheoryModel;
 
+namespace rrinst{
+class CandidateGenerator;
+}
+
 /**
  * Information about an assertion for the theories.
  */
@@ -834,6 +838,12 @@ public:
   virtual bool areDisequal( Node a, Node b ) { return false; }
   virtual Node getRepresentative( Node a ) { return a; }
   virtual Node getInternalRepresentative( Node a ) { return getRepresentative( a ); }
+public:
+  /** A Creator of CandidateGenerator for classes (one element in each
+      equivalence class) and class (every element of one equivalence
+      class) */
+  virtual rrinst::CandidateGenerator* getRRCanGenClasses(){ return NULL; };
+  virtual rrinst::CandidateGenerator* getRRCanGenClass(){ return NULL; };
 };/* class Instantiator */
 
 inline Assertion Theory::get() {
index f55c7c258e1f921e33e7415cdc58f907334553f3..449f4adc35c950468633b4a8eaba9098f04ff1d7 100644 (file)
@@ -449,6 +449,13 @@ public:
     return d_context;
   }
 
+  /**
+   * Get a pointer to the underlying user context.
+   */
+  inline context::Context* getUserContext() const {
+    return d_userContext;
+  }
+
   /**
    * Get a pointer to the underlying quantifiers engine.
    */
@@ -677,8 +684,8 @@ public:
   }
 
   /** Get the theory for id */
-  theory::Theory* getTheory(int id) {
-    return d_theoryTable[id];
+  theory::Theory* getTheory(theory::TheoryId theoryId) {
+    return d_theoryTable[theoryId];
   }
 
   /**
index 55ca07d77773f2c884feaa00e77e438db47dc484..14ba88ba180310d7a63daa160b3ae36bbb8b885a 100644 (file)
@@ -26,6 +26,7 @@ using namespace CVC4;
 using namespace CVC4::kind;
 using namespace CVC4::context;
 using namespace CVC4::theory;
+using namespace CVC4::theory::inst;
 
 //#define NESTED_PATTERN_SELECTION
 
index 476ef392e3ef9d76627905917235dedf334a80c6..84bc7ac2ea396ec03af93f0c88a2b084207cac47 100644 (file)
@@ -23,6 +23,7 @@
 
 namespace CVC4 {
 namespace theory {
+namespace inst {
 
 //a collect of nodes representing a trigger
 class Trigger {
@@ -163,6 +164,8 @@ inline std::ostream& operator<<(std::ostream& out, const Trigger & tr) {
   return out;
 }
 
+}/* CVC4::theory::inst namespace */
+
 }/* CVC4::theory namespace */
 
 }/* CVC4 namespace */
index fe75b5f59f4c97e25ab44171debcfd0c40b68436..9376c858d0edaccca8e1339531f88d8fd294fb40 100644 (file)
@@ -65,6 +65,10 @@ void EqualityEngine::init() {
   d_triggerDatabaseAllocatedSize = 100000;
   d_triggerDatabase = (char*) malloc(d_triggerDatabaseAllocatedSize);
 
+  //We can't notify during the initialization because it notifies
+  // QuantifiersEngine.AddTermToDatabase that try to access to the uf
+  // instantiator that currently doesn't exist.
+  ScopedBool sb(d_performNotify, false);
   addTerm(d_true);
   addTerm(d_false);
 
index 9228e29d46f5e12f2fed0c49fa7e3aca83292576..0b461131e3f8fc6ade768f0a04ddf1529f91a6df 100644 (file)
@@ -794,7 +794,7 @@ class EqClassesIterator {
 
 public:
 
-  EqClassesIterator() { }
+  EqClassesIterator(): d_ee(NULL), d_it(0){ }
   EqClassesIterator(eq::EqualityEngine* ee) : d_ee(ee) {
     d_it = 0;
     if ( d_it < d_ee->d_nodesCount &&
@@ -840,7 +840,7 @@ class EqClassIterator {
 
 public:
 
-  EqClassIterator() { }
+  EqClassIterator(): d_ee(NULL){ }
   EqClassIterator(Node eqc, eq::EqualityEngine* ee) : d_ee(ee) {
     Assert( d_ee->getRepresentative(eqc) == eqc );
     d_rep = eqc;
index 669df055a2c9978857e12c4479cfcf8abe6db094..5696251ed593ed8fd94150c8db54b646202b88f1 100644 (file)
@@ -28,6 +28,7 @@ using namespace CVC4::kind;
 using namespace CVC4::context;
 using namespace CVC4::theory;
 using namespace CVC4::theory::uf;
+using namespace CVC4::theory::inst;
 
 #define USE_SINGLE_TRIGGER_BEFORE_MULTI_TRIGGER
 //#define MULTI_TRIGGER_FULL_EFFORT_HALF
@@ -83,7 +84,7 @@ void InstStrategyCheckCESolved::calcSolved( Node f ){
     Node i = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );
     Node rep = d_th->getInternalRepresentative( i );
     if( !rep.hasAttribute(InstConstantAttribute()) ){
-      d_th->d_baseMatch[f].d_map[ i ] = rep;
+      d_th->d_baseMatch[f].set(i,rep);
     }else{
       d_solved[ f ] = false;
     }
index 09b8087f26d4d96a07c897b0f3c3e64b9d8aecf6..a0091c4b477a2d556716dffcb48670c23d8d90b5 100644 (file)
@@ -20,6 +20,7 @@
 #define __CVC4__INST_STRATEGY_H
 
 #include "theory/quantifiers_engine.h"
+#include "theory/trigger.h"
 
 #include "context/context.h"
 #include "context/context_mm.h"
@@ -59,7 +60,7 @@ private:
   /** InstantiatorTheoryUf class */
   InstantiatorTheoryUf* d_th;
   /** explicitly provided patterns */
-  std::map< Node, std::vector< Trigger* > > d_user_gen;
+  std::map< Node, std::vector< inst::Trigger* > > d_user_gen;
   /** counter for quantifiers */
   std::map< Node, int > d_counter;
   /** process functions */
@@ -75,7 +76,7 @@ public:
   /** get num patterns */
   int getNumUserGenerators( Node f ) { return (int)d_user_gen[f].size(); }
   /** get user pattern */
-  Trigger* getUserGenerator( Node f, int i ) { return d_user_gen[f][ i ]; }
+  inst::Trigger* getUserGenerator( Node f, int i ) { return d_user_gen[f][ i ]; }
   /** identify */
   std::string identify() const { return std::string("UserPatterns"); }
 };/* class InstStrategyUserPatterns */
@@ -99,7 +100,7 @@ private:
   /** generate additional triggers */
   bool d_generate_additional;
   /** triggers for each quantifier */
-  std::map< Node, std::map< Trigger*, bool > > d_auto_gen_trigger;
+  std::map< Node, std::map< inst::Trigger*, bool > > d_auto_gen_trigger;
   std::map< Node, int > d_counter;
   /** single, multi triggers for each quantifier */
   std::map< Node, std::vector< Node > > d_patTerms[2];
@@ -120,7 +121,7 @@ public:
   ~InstStrategyAutoGenTriggers(){}
 public:
   /** get auto-generated trigger */
-  Trigger* getAutoGenTrigger( Node f );
+  inst::Trigger* getAutoGenTrigger( Node f );
   /** identify */
   std::string identify() const { return std::string("AutoGenTriggers"); }
   /** set regenerate frequency, if fr<0, turn off regenerate */
index 5342188f79ad89cb883bc68040569e356353a327..80151d1e185f733d4852b3b7b3a18f8b31c5fe3b 100644 (file)
@@ -26,6 +26,11 @@ using namespace CVC4::context;
 using namespace CVC4::theory;
 using namespace CVC4::theory::uf;
 
+namespace CVC4{
+namespace theory{
+namespace uf{
+namespace inst{
+
 CandidateGeneratorTheoryUf::CandidateGeneratorTheoryUf( InstantiatorTheoryUf* ith, Node op ) :
   d_op( op ), d_ith( ith ), d_term_iter( -2 ){
   Assert( !d_op.isNull() );
@@ -45,6 +50,7 @@ void CandidateGeneratorTheoryUf::reset( Node eqc ){
       d_retNode = Node::null();
     }else{
       d_retNode = eqc;
+
     }
     d_term_iter = -1;
   }
@@ -169,3 +175,8 @@ Node CandidateGeneratorTheoryUfLitDeq::getNextCandidate(){
   }
   return Node::null();
 }
+
+}
+}
+}
+}
index 668d619db34877b11f1fa6f1c7f7baada67cedbc..a06f04f990b52f32f858e5871fb0ade6c9c0eba9 100644 (file)
 #define __CVC4__THEORY_UF_CANDIDATE_GENERATOR_H
 
 #include "theory/quantifiers_engine.h"
+#include "theory/quantifiers/term_database.h"
 #include "theory/uf/theory_uf_instantiator.h"
+#include "theory/rr_inst_match.h"
+
+using namespace CVC4::theory::quantifiers;
 
 namespace CVC4 {
 namespace theory {
+namespace eq {
+
+namespace rrinst{
+typedef CVC4::theory::rrinst::CandidateGenerator CandidateGenerator;
+
+//New CandidateGenerator. They have a simpler semantic than the old one
+
+// Just iterate amoung the equivalence classes
+// node::Null() must be given to reset
+class CandidateGeneratorTheoryEeClasses : public CandidateGenerator{
+private:
+  //the equality classes iterator
+  eq::EqClassesIterator d_eq;
+  //equalityengine pointer
+  EqualityEngine* d_ee;
+public:
+  CandidateGeneratorTheoryEeClasses( EqualityEngine * ee): d_ee( ee ){}
+  ~CandidateGeneratorTheoryEeClasses(){}
+  void resetInstantiationRound(){};
+  void reset( TNode eqc ){
+    Assert(eqc.isNull());
+    d_eq = eq::EqClassesIterator( d_ee );
+  }; //* the argument is not used
+  TNode getNextCandidate(){
+    if( !d_eq.isFinished() ) return (*(d_eq++));
+    else return Node::null();
+  };
+};
+
+// Just iterate amoung the equivalence class of the given node
+// node::Null() *can't* be given to reset
+class CandidateGeneratorTheoryEeClass : public CandidateGenerator{
+private:
+  //instantiator pointer
+  EqualityEngine* d_ee;
+  //the equality class iterator
+  eq::EqClassIterator d_eqc;
+  /* For the case where the given term doesn't exists in uf */
+  Node d_retNode;
+public:
+  CandidateGeneratorTheoryEeClass( EqualityEngine* ee): d_ee( ee ){}
+  ~CandidateGeneratorTheoryEeClass(){}
+  void resetInstantiationRound(){};
+  void reset( TNode eqc ){
+    Assert(!eqc.isNull());
+    if( d_ee->hasTerm( eqc ) ){
+      /* eqc is in uf  */
+      eqc = d_ee->getRepresentative( eqc );
+      d_eqc = eq::EqClassIterator( eqc, d_ee );
+      d_retNode = Node::null();
+    }else{
+      /* If eqc if not a term known by uf, it is the only one in its
+         equivalence class. So we will return only it */
+      d_retNode = eqc;
+      d_eqc = eq::EqClassIterator();
+    }
+  }; //* the argument is not used
+  TNode getNextCandidate(){
+    if(d_retNode.isNull()){
+      if( !d_eqc.isFinished() ) return (*(d_eqc++));
+      else return Node::null();
+    }else{
+      /* the case where eqc not in uf */
+      Node ret = d_retNode;
+      d_retNode = Node::null(); /* d_eqc.isFinished() must be true */
+      return ret;
+    }
+  };
+};
+
+
+} /* namespace rrinst */
+} /* namespace eq */
+
 namespace uf {
+namespace rrinst {
+
+typedef CVC4::theory::rrinst::CandidateGenerator CandidateGenerator;
+
+class CandidateGeneratorTheoryUfOp : public CandidateGenerator{
+private:
+  Node d_op;
+  //instantiator pointer
+  TermDb* d_tdb;
+  // Since new term can appears we restrict ourself to the one that
+  // exists at resetInstantiationRound
+  size_t d_term_iter_limit;
+  size_t d_term_iter;
+public:
+  CandidateGeneratorTheoryUfOp(Node op, TermDb* tdb): d_op(op), d_tdb( tdb ){}
+  ~CandidateGeneratorTheoryUfOp(){}
+  void resetInstantiationRound(){
+    d_term_iter_limit = d_tdb->d_op_map[d_op].size();
+  };
+  void reset( TNode eqc ){
+    Assert(eqc.isNull());
+    d_term_iter = 0;
+  }; //* the argument is not used
+  TNode getNextCandidate(){
+    if( d_term_iter<d_term_iter_limit ){
+      TNode n = d_tdb->d_op_map[d_op][d_term_iter];
+      ++d_term_iter;
+      return n;
+    } else return Node::null();
+  };
+};
+
+class CandidateGeneratorTheoryUfType : public CandidateGenerator{
+private:
+  TypeNode d_type;
+  //instantiator pointer
+  TermDb* d_tdb;
+  // Since new term can appears we restrict ourself to the one that
+  // exists at resetInstantiationRound
+  size_t d_term_iter_limit;
+  size_t d_term_iter;
+public:
+  CandidateGeneratorTheoryUfType(TypeNode type, TermDb* tdb): d_type(type), d_tdb( tdb ){}
+  ~CandidateGeneratorTheoryUfType(){}
+  void resetInstantiationRound(){
+    d_term_iter_limit = d_tdb->d_type_map[d_type].size();
+  };
+  void reset( TNode eqc ){
+    Assert(eqc.isNull());
+    d_term_iter = 0;
+  }; //* the argument is not used
+  TNode getNextCandidate(){
+    if( d_term_iter<d_term_iter_limit ){
+      TNode n = d_tdb->d_type_map[d_type][d_term_iter];
+      ++d_term_iter;
+      return n;
+    } else return Node::null();
+  };
+};
+
+} /* namespace rrinst */
+
+namespace inst{
+typedef CVC4::theory::inst::CandidateGenerator CandidateGenerator;
+
+//Old CandidateGenerator
 
 class CandidateGeneratorTheoryUfDisequal;
 
@@ -108,7 +252,8 @@ public:
 };
 
 
-}
+}/* CVC4::theory::uf::inst namespace */
+}/* CVC4::theory::uf namespace */
 }/* CVC4::theory namespace */
 }/* CVC4 namespace */
 
index e3999c163d74fc6b7e7dde04e59d1358ba46add3..257bed0a27d5737383bdb9ba12d01db9c745d9b3 100644 (file)
@@ -17,6 +17,7 @@
 #include "theory/uf/theory_uf_instantiator.h"
 #include "theory/theory_engine.h"
 #include "theory/uf/theory_uf.h"
+#include "theory/uf/theory_uf_candidate_generator.h"
 #include "theory/uf/equality_engine.h"
 #include "theory/quantifiers/term_database.h"
 
@@ -26,6 +27,15 @@ using namespace CVC4::kind;
 using namespace CVC4::context;
 using namespace CVC4::theory;
 using namespace CVC4::theory::uf;
+using namespace CVC4::theory::inst;
+
+namespace CVC4 {
+namespace theory {
+namespace uf {
+
+inline std::ostream& operator<<(std::ostream& out, const InstantiatorTheoryUf::Ips& ips) {
+  return out;
+};
 
 EqClassInfo::EqClassInfo( context::Context* c ) : d_funs( c ), d_pfuns( c ), d_disequal( c ){
 
@@ -33,13 +43,15 @@ EqClassInfo::EqClassInfo( context::Context* c ) : d_funs( c ), d_pfuns( c ), d_d
 
 //set member
 void EqClassInfo::setMember( Node n, quantifiers::TermDb* db ){
-  if( n.getKind()==APPLY_UF ){
-    d_funs[n.getOperator()] = true;
+  if( n.hasOperator() ){
+    d_funs.insertAtContextLevelZero(n.getOperator(),true);
   }
   //add parent functions
-  for( std::map< Node, std::map< int, std::vector< Node > > >::iterator it = db->d_parents[n].begin();
+  for( std::hash_map< Node, std::hash_map< int, std::vector< Node >  >, NodeHashFunction >::iterator it = db->d_parents[n].begin();
     it != db->d_parents[n].end(); ++it ){
-    d_pfuns[ it->first ] = true;
+    //TODO Is it true to do it at level 0? That depend when SetMember is called
+    // At worst it is a good overapproximation
+    d_pfuns.insertAtContextLevelZero( it->first, true);
   }
 }
 
@@ -62,6 +74,20 @@ void EqClassInfo::merge( EqClassInfo* eci ){
   }
 }
 
+inline void outputEqClassInfo( const char* c, const EqClassInfo* eci){
+  Debug(c) << " funs:";
+  for( EqClassInfo::BoolMap::iterator it = eci->d_funs.begin(); it != eci->d_funs.end(); it++ ) {
+    Debug(c) << (*it).first << ",";
+  }
+  Debug(c) << std::endl << "pfuns:";
+  for( EqClassInfo::BoolMap::iterator it = eci->d_pfuns.begin(); it != eci->d_pfuns.end(); it++ ) {
+    Debug(c) << (*it).first << ",";
+  }
+  Debug(c) << std::endl;
+}
+
+
+
 InstantiatorTheoryUf::InstantiatorTheoryUf(context::Context* c, CVC4::theory::QuantifiersEngine* qe, Theory* th) :
 Instantiator( c, qe, th )
 {
@@ -221,21 +247,92 @@ void InstantiatorTheoryUf::newEqClass( TNode n ){
   d_quantEngine->addTermToDatabase( n );
 }
 
+void InstantiatorTheoryUf::newTerms(SetNode& s){
+  static NoMatchAttribute rewrittenNodeAttribute;
+  /* op -> nodes (if the set is empty, the op is not interesting) */
+  std::hash_map< TNode, SetNode, TNodeHashFunction > h;
+  /* types -> nodes (if the set is empty, the type is not interesting) */
+  std::hash_map< TypeNode, SetNode, TypeNodeHashFunction > tyh;
+  for(SetNode::iterator i=s.begin(), end=s.end(); i != end; ++i){
+    if (i->getAttribute(rewrittenNodeAttribute)) continue; /* skip it */
+    if( !d_cand_gens.empty() ){
+      // op
+      TNode op = i->getOperator();
+      std::hash_map< TNode, SetNode, TNodeHashFunction >::iterator
+        is = h.find(op);
+      if(is == h.end()){
+        std::pair<std::hash_map< TNode, SetNode, TNodeHashFunction >::iterator,bool>
+          p = h.insert(make_pair(op,SetNode()));
+        is = p.first;
+        if(d_cand_gens.find(op) != d_cand_gens.end()){
+          is->second.insert(*i);
+        } /* else we have inserted an empty set */
+      }else if(!is->second.empty()){
+        is->second.insert(*i);
+      }
+    }
+    if( !d_cand_gen_types.empty() ){
+      //type
+      TypeNode ty = i->getType();
+      std::hash_map< TypeNode, SetNode, TypeNodeHashFunction >::iterator
+        is = tyh.find(ty);
+      if(is == tyh.end()){
+        std::pair<std::hash_map< TypeNode, SetNode, TypeNodeHashFunction >::iterator,bool>
+          p = tyh.insert(make_pair(ty,SetNode()));
+        is = p.first;
+        if(d_cand_gen_types.find(ty) != d_cand_gen_types.end()){
+          is->second.insert(*i);
+        } /* else we have inserted an empty set */
+      }else if(!is->second.empty()){
+        is->second.insert(*i);
+      }
+    }
+  }
+  //op
+  for(std::hash_map< TNode, SetNode, TNodeHashFunction >::iterator i=h.begin(), end=h.end();
+      i != end; ++i){
+    //new term, add n to candidate generators
+    if(i->second.empty()) continue;
+    std::map< Node, NodeNewTermDispatcher >::iterator
+      inpc = d_cand_gens.find(i->first);
+    //we know that this op exists
+    Assert(inpc != d_cand_gens.end());
+    inpc->second.send(i->second);
+  }
+  //type
+  for(std::hash_map< TypeNode, SetNode, TypeNodeHashFunction >::iterator i=tyh.begin(), end=tyh.end();
+      i != end; ++i){
+    //new term, add n to candidate generators
+    if(i->second.empty()) continue;
+    std::map< TypeNode, NodeNewTermDispatcher >::iterator
+      inpc = d_cand_gen_types.find(i->first);
+    //we know that this op exists
+    Assert(inpc != d_cand_gen_types.end());
+    inpc->second.send(i->second);
+  }
+
+}
+
+
 /** merge */
 void InstantiatorTheoryUf::merge( TNode a, TNode b ){
   if( Options::current()->efficientEMatching ){
+    //merge eqc_ops of b into a
+    EqClassInfo* eci_a = getOrCreateEquivalenceClassInfo( a );
+    EqClassInfo* eci_b = getOrCreateEquivalenceClassInfo( b );
+
     if( a.getKind()!=IFF && a.getKind()!=EQUAL && b.getKind()!=IFF && b.getKind()!=EQUAL ){
       Debug("efficient-e-match") << "Merging " << a << " with " << b << std::endl;
 
       //determine new candidates for instantiation
-      computeCandidatesPcPairs( a, b );
-      computeCandidatesPcPairs( b, a );
-      computeCandidatesPpPairs( a, b );
-      computeCandidatesPpPairs( b, a );
+      computeCandidatesPcPairs( a, eci_a, b, eci_b );
+      computeCandidatesPcPairs( b, eci_b, a, eci_a );
+      computeCandidatesPpPairs( a, eci_a, b, eci_b );
+      computeCandidatesPpPairs( b, eci_b, a, eci_a );
     }
-    //merge eqc_ops of b into a
-    EqClassInfo* eci_a = getOrCreateEquivalenceClassInfo( a );
-    EqClassInfo* eci_b = getOrCreateEquivalenceClassInfo( b );
+    computeCandidatesConstants( a, eci_a, b, eci_b);
+    computeCandidatesConstants( b, eci_b, a, eci_a);
+
     eci_a->merge( eci_b );
   }
 }
@@ -258,97 +355,99 @@ EqClassInfo* InstantiatorTheoryUf::getOrCreateEquivalenceClassInfo( Node n ){
   return d_eqc_ops[n];
 }
 
-void InstantiatorTheoryUf::computeCandidatesPcPairs( Node a, Node b ){
+void InstantiatorTheoryUf::computeCandidatesPcPairs( Node a, EqClassInfo* eci_a, Node b, EqClassInfo* eci_b ){
   Debug("efficient-e-match") << "Compute candidates for pc pairs..." << std::endl;
   Debug("efficient-e-match") << "  Eq class = [";
   outputEqClass( "efficient-e-match", a);
   Debug("efficient-e-match") << "]" << std::endl;
-  EqClassInfo* eci_a = getOrCreateEquivalenceClassInfo( a );
-  EqClassInfo* eci_b = getOrCreateEquivalenceClassInfo( a );
+  outputEqClassInfo("efficient-e-match",eci_a);
   for( BoolMap::iterator it = eci_a->d_funs.begin(); it != eci_a->d_funs.end(); it++ ) {
     //the child function:  a member of eq_class( a ) has top symbol g, in other words g is in funs( a )
     Node g = (*it).first;
     Debug("efficient-e-match") << "  Checking application " << g << std::endl;
     //look at all parent/child pairs
-    for( std::map< Node, std::map< Node, std::vector< InvertedPathString > > >::iterator itf = d_pc_pairs[g].begin();
+    for( std::map< Node, std::vector< std::pair< NodePcDispatcher*, Ips > > >::iterator itf = d_pc_pairs[g].begin();
          itf != d_pc_pairs[g].end(); ++itf ){
       //f/g is a parent/child pair
       Node f = itf->first;
-      if( eci_b->hasParent( f ) || true ){
+      if( eci_b->hasParent( f ) ){
         //DO_THIS: determine if f in pfuns( b ), only do the follow if so
         Debug("efficient-e-match") << "    Checking parent application " << f << std::endl;
         //scan through the list of inverted path strings/candidate generators
-        for( std::map< Node, std::vector< InvertedPathString > >::iterator cit = itf->second.begin();
-            cit != itf->second.end(); ++cit ){
-          Node pat = cit->first;
-          Debug("efficient-e-match") << "      Checking pattern " << pat << std::endl;
-          for( int c=0; c<(int)cit->second.size(); c++ ){
-            Debug("efficient-e-match") << "        Check inverted path string for pattern ";
-            outputInvertedPathString( "efficient-e-match", cit->second[c] );
-            Debug("efficient-e-match") << std::endl;
-
-            //collect all new relevant terms
-            std::vector< Node > terms;
-            terms.push_back( b );
-            collectTermsIps( cit->second[c], terms );
-            if( !terms.empty() ){
-              Debug("efficient-e-match") << "        -> Added terms (" << (int)terms.size() << "): ";
-              //add them as candidates to the candidate generator
-              for( int t=0; t<(int)terms.size(); t++ ){
-                Debug("efficient-e-match") << terms[t] << " ";
-                //Notice() << "Add candidate (PC) " << terms[t] << std::endl;
-                for( int cg=0; cg<(int)d_pat_cand_gens[pat].size(); cg++ ){
-                  d_pat_cand_gens[pat][cg]->addCandidate( terms[t] );
-                }
-              }
-              Debug("efficient-e-match") << std::endl;
-            }
+        for( std::vector< std::pair< NodePcDispatcher*, Ips > >::iterator cit = itf->second.begin();
+             cit != itf->second.end(); ++cit ){
+#ifdef CVC4_DEBUG
+          Debug("efficient-e-match") << "      Checking pattern " << cit->first->pat << std::endl;
+#endif
+          Debug("efficient-e-match") << "          Check inverted path string for pattern ";
+          outputIps( "efficient-e-match", cit->second );
+          Debug("efficient-e-match") << std::endl;
+
+          //collect all new relevant terms
+          SetNode terms;
+          terms.insert( b );
+          collectTermsIps( cit->second, terms );
+          if( terms.empty() ) continue;
+          Debug("efficient-e-match") << "        -> Added terms (" << terms.size() << "): ";
+          for( SetNode::const_iterator t=terms.begin(), end=terms.end();
+               t!=end; ++t ){
+            Debug("efficient-e-match") << (*t) << " ";
           }
+          Debug("efficient-e-match") << std::endl;
+          //add them as candidates to the candidate generator
+          cit->first->send(terms);
         }
       }
     }
   }
 }
 
-void InstantiatorTheoryUf::computeCandidatesPpPairs( Node a, Node b ){
+void InstantiatorTheoryUf::computeCandidatesPpPairs( Node a, EqClassInfo* eci_a, Node b, EqClassInfo* eci_b ){
   Debug("efficient-e-match") << "Compute candidates for pp pairs..." << std::endl;
-  EqClassInfo* eci_a = getOrCreateEquivalenceClassInfo( a );
-  EqClassInfo* eci_b = getOrCreateEquivalenceClassInfo( a );
-  for( std::map< Node, std::map< Node, std::map< Node, std::vector< IpsPair > > > >::iterator it = d_pp_pairs.begin();
+  for( std::map< Node, std::map< Node, std::vector< triple< NodePpDispatcher*, Ips, Ips > > > >::iterator it = d_pp_pairs.begin();
        it != d_pp_pairs.end(); ++it ){
     Node f = it->first;
     if( eci_a->hasParent( f ) ){
       Debug("efficient-e-match") << "  Checking parent application " << f << std::endl;
-      for( std::map< Node, std::map< Node, std::vector< IpsPair > > >::iterator it2 = it->second.begin();
+      for( std::map< Node, std::vector< triple<NodePpDispatcher*, Ips, Ips> > >::iterator it2 = it->second.begin();
            it2 != it->second.end(); ++it2 ){
         Node g = it2->first;
         if( eci_b->hasParent( g ) ){
           Debug("efficient-e-match") << "    Checking parent application " << g << std::endl;
           //if f in pfuns( a ) and g is in pfuns( b ), only do the follow if so
-          for( std::map< Node, std::vector< IpsPair > >::iterator cit = it2->second.begin();
+          for( std::vector< triple<NodePpDispatcher*, Ips, Ips> > ::iterator cit = it2->second.begin();
                cit != it2->second.end(); ++cit ){
-            Node pat = cit->first;
-            for( int c=0; c<(int)cit->second.size(); c++ ){
-              std::vector< Node > a_terms;
-              a_terms.push_back( a );
-              if( !a_terms.empty() ){
-                collectTermsIps( cit->second[c].first, a_terms );
-                std::vector< Node > b_terms;
-                b_terms.push_back( b );
-                collectTermsIps( cit->second[c].first, b_terms );
-                //take intersection
-                for( int t=0; t<(int)a_terms.size(); t++ ){
-                  if( std::find( b_terms.begin(), b_terms.end(), a_terms[t] )!=b_terms.end() ){
-                                //Notice() << "Add candidate (PP) " << a_terms[t] << std::endl;
-                    Debug("efficient-e-match") << "      -> Add term " << a_terms[t] << std::endl;
-                    //add to all candidate generators having this term
-                    for( int cg=0; cg<(int)d_pat_cand_gens[pat].size(); cg++ ){
-                      d_pat_cand_gens[pat][cg]->addCandidate( a_terms[t] );
-                    }
-                  }
-                }
-              }
+#ifdef CVC4_DEBUG
+            Debug("efficient-e-match") << "    Checking pattern " << cit->first->pat1 << " and " << cit->first->pat2 << std::endl;
+#endif
+            Debug("efficient-e-match") << "          Check inverted path string ";
+            outputIps( "efficient-e-match", cit->second );
+            SetNode a_terms;
+            a_terms.insert( a );
+            collectTermsIps( cit->second, a_terms );
+            if( a_terms.empty() ) continue;
+            Debug("efficient-e-match") << "          And check inverted path string ";
+            outputIps( "efficient-e-match", cit->third );
+            SetNode b_terms;
+            b_terms.insert( b );
+            collectTermsIps( cit->third, b_terms );
+            if( b_terms.empty() ) continue;
+            //Start debug
+            Debug("efficient-e-match") << "        -> Possibly Added termsA (" << a_terms.size() << "): ";
+            for( SetNode::const_iterator t=a_terms.begin(), end=a_terms.end();
+                 t!=end; ++t ){
+              Debug("efficient-e-match") << (*t) << " ";
+            }
+            Debug("efficient-e-match") << std::endl;
+            Debug("efficient-e-match") << "        -> Possibly Added termsB (" << b_terms.size() << "): ";
+            for( SetNode::const_iterator t=b_terms.begin(), end=b_terms.end();
+                 t!=end; ++t ){
+              Debug("efficient-e-match") << (*t) << " ";
             }
+            Debug("efficient-e-match") << std::endl;
+            //End debug
+
+            cit->first->send(a_terms,b_terms);
           }
         }
       }
@@ -356,39 +455,87 @@ void InstantiatorTheoryUf::computeCandidatesPpPairs( Node a, Node b ){
   }
 }
 
-void InstantiatorTheoryUf::collectTermsIps( InvertedPathString& ips, std::vector< Node >& terms, int index ){
-  if( index<(int)ips.size() && !terms.empty() ){
+
+void InstantiatorTheoryUf::computeCandidatesConstants( Node a, EqClassInfo* eci_a, Node b, EqClassInfo* eci_b ){
+  Debug("efficient-e-match") << "Compute candidates constants for cc pairs..." << std::endl;
+  Debug("efficient-e-match") << "  Eq class = [";
+  outputEqClass( "efficient-e-match", a);
+  Debug("efficient-e-match") << "]" << std::endl;
+  outputEqClassInfo("efficient-e-match",eci_a);
+  for( std::map< Node, std::map< Node, NodePcDispatcher* > >::iterator
+         it = d_cc_pairs.begin(), end = d_cc_pairs.end();
+       it != end; ++it ) {
+    Debug("efficient-e-match") << "  Checking application " << it->first << std::endl;
+    if( !eci_b->hasFunction(it->first) ) continue;
+    for( std::map< Node, NodePcDispatcher* >::iterator
+           itc = it->second.begin(), end = it->second.end();
+       itc != end; ++itc ) {
+      //The constant
+      Debug("efficient-e-match") << "    Checking constant " << a << std::endl;
+      if(getRepresentative(itc->first) != a) continue;
+      SetNode s;
+      eq::EqClassIterator eqc_iter( b, &((TheoryUF*)d_th)->d_equalityEngine );
+      while( !eqc_iter.isFinished() ){
+        Debug("efficient-e-match-debug") << "> look at " << (*eqc_iter)
+                                         << std::endl;
+        if( (*eqc_iter).hasOperator() && (*eqc_iter).getOperator() == it->first ) s.insert(*eqc_iter);
+        eqc_iter++;
+      }
+
+      if( s.empty() ) continue;
+      Debug("efficient-e-match") << "        -> Added terms (" << s.size() << "): ";
+      for( SetNode::const_iterator t=s.begin(), end=s.end();
+           t!=end; ++t ){
+        Debug("efficient-e-match") << (*t) << " ";
+      }
+      Debug("efficient-e-match") << std::endl;
+      itc->second->send(s);
+    }
+  }
+}
+
+void InstantiatorTheoryUf::collectTermsIps( Ips& ips, SetNode & terms ){
+  Assert( ips.size() > 0);
+  return collectTermsIps( ips, terms,  ips.size() - 1);
+}
+
+void InstantiatorTheoryUf::collectTermsIps( Ips& ips, SetNode& terms, int index ){
+  if( !terms.empty() ){
     Debug("efficient-e-match-debug") << "> Process " << index << std::endl;
     Node f = ips[index].first;
     int arg = ips[index].second;
 
     //for each term in terms, determine if any term (modulo equality) has parent "f" from position "arg"
-    bool addRep = ( index!=(int)ips.size()-1 );
-    std::vector< Node > newTerms;
-    for( int t=0; t<(int)terms.size(); t++ ){
-      collectParentsTermsIps( terms[t], f, arg, newTerms, addRep );
+    bool addRep = ( index!=0 ); // We want to keep the top symbol for the last
+    SetNode newTerms;
+    for( SetNode::const_iterator t=terms.begin(), end=terms.end();
+         t!=end; ++t ){
+      collectParentsTermsIps( *t, f, arg, newTerms, addRep );
     }
-    terms.clear();
-    terms.insert( terms.begin(), newTerms.begin(), newTerms.end() );
+    terms.swap(newTerms);
 
     Debug("efficient-e-match-debug") << "> Terms are now: ";
-    for( int t=0; t<(int)terms.size(); t++ ){
-      Debug("efficient-e-match-debug") << terms[t] << " ";
+    for( SetNode::const_iterator t=terms.begin(), end=terms.end();
+         t!=end; ++t ){
+      Debug("efficient-e-match-debug") << *t << " ";
     }
     Debug("efficient-e-match-debug") << std::endl;
 
-    collectTermsIps( ips, terms, index+1 );
+    if(index!=0) collectTermsIps( ips, terms, index-1 );
   }
 }
 
-bool InstantiatorTheoryUf::collectParentsTermsIps( Node n, Node f, int arg, std::vector< Node >& terms, bool addRep, bool modEq ){
+bool InstantiatorTheoryUf::collectParentsTermsIps( Node n, Node f, int arg, SetNode & terms, bool addRep, bool modEq ){ //modEq default true
   bool addedTerm = false;
-  if( ((TheoryUF*)d_th)->d_equalityEngine.hasTerm( n ) && modEq ){
+  
+  if( modEq && ((TheoryUF*)d_th)->d_equalityEngine.hasTerm( n )){
     Assert( getRepresentative( n )==n );
     //collect modulo equality
     //DO_THIS: this should (if necessary) compute a current set of (f, arg) parents for n and cache it
-    eq::EqClassIterator eqc_iter( getRepresentative( n ), &((TheoryUF*)d_th)->d_equalityEngine );
+    eq::EqClassIterator eqc_iter( n, &((TheoryUF*)d_th)->d_equalityEngine );
     while( !eqc_iter.isFinished() ){
+      Debug("efficient-e-match-debug") << "> look at " << (*eqc_iter)
+                                       << std::endl;
       if( collectParentsTermsIps( (*eqc_iter), f, arg, terms, addRep, false ) ){
         //if only one argument, we know we can stop (since all others added will be congruent)
         if( f.getType().getNumChildren()==2 ){
@@ -401,90 +548,263 @@ bool InstantiatorTheoryUf::collectParentsTermsIps( Node n, Node f, int arg, std:
   }else{
     quantifiers::TermDb* db = d_quantEngine->getTermDatabase();
     //see if parent f exists from argument arg
-    if( db->d_parents.find( n )!=db->d_parents.end() ){
-      if( db->d_parents[n].find( f )!=db->d_parents[n].end() ){
-        if( db->d_parents[n][f].find( arg )!=db->d_parents[n][f].end() ){
-          for( int i=0; i<(int)db->d_parents[n][f][arg].size(); i++ ){
-            Node t = db->d_parents[n][f][arg][i];
-            if( addRep ){
-              t = getRepresentative( t );
-            }
-            if( std::find( terms.begin(), terms.end(), t )==terms.end() ){
-              terms.push_back( t );
-            }
-            addedTerm = true;
-          }
-        }
-      }
+    const std::vector<Node> & parents = db->getParents(n,f,arg);
+    for( size_t i=0; i<parents.size(); ++i ){
+      TNode t = parents[i];
+      if(!CandidateGenerator::isLegalCandidate(t)) continue;
+      if( addRep ) t = getRepresentative( t );
+      terms.insert(t);
+      addedTerm = true;
     }
   }
   return addedTerm;
 }
 
-void InstantiatorTheoryUf::registerPatternElementPairs2( Node opat, Node pat, InvertedPathString& ips,
-                                                       std::map< Node, std::vector< std::pair< Node, InvertedPathString > > >& ips_map  ){
-  Assert( pat.getKind()==APPLY_UF );
+void InstantiatorTheoryUf::registerPatternElementPairs2( Node pat, Ips& ips, PpIpsMap & pp_ips_map, NodePcDispatcher* npc ){
+  Assert( pat.hasOperator() );
   //add information for possible pp-pair
+  ips.push_back( std::pair< Node, int >( pat.getOperator(), 0 ) ); //0 is just a dumb value
+
   for( int i=0; i<(int)pat.getNumChildren(); i++ ){
     if( pat[i].getKind()==INST_CONSTANT ){
-      ips_map[ pat[i] ].push_back( std::pair< Node, InvertedPathString >( pat.getOperator(), InvertedPathString( ips ) ) );
+      ips.back().second = i;
+      pp_ips_map[ pat[i] ].push_back( make_pair( pat.getOperator(), Ips( ips ) ) );
     }
   }
-  ips.push_back( std::pair< Node, int >( pat.getOperator(), 0 ) );
+
   for( int i=0; i<(int)pat.getNumChildren(); i++ ){
     if( pat[i].getKind()==APPLY_UF ){
       ips.back().second = i;
-      registerPatternElementPairs2( opat, pat[i], ips, ips_map );
+      registerPatternElementPairs2( pat[i], ips, pp_ips_map, npc );
       Debug("pattern-element-opt") << "Found pc-pair ( " << pat.getOperator() << ", " << pat[i].getOperator() << " )" << std::endl;
       Debug("pattern-element-opt") << "   Path = ";
-      outputInvertedPathString( "pattern-element-opt", ips );
+      outputIps( "pattern-element-opt", ips );
       Debug("pattern-element-opt") << std::endl;
       //pat.getOperator() and pat[i].getOperator() are a pc-pair
-      d_pc_pairs[ pat[i].getOperator() ][ pat.getOperator() ][opat].push_back( InvertedPathString( ips ) );
+      d_pc_pairs[ pat[i].getOperator() ][ pat.getOperator() ]
+        .push_back( make_pair(npc,Ips(ips)) );
     }
   }
   ips.pop_back();
 }
 
-void InstantiatorTheoryUf::registerPatternElementPairs( Node pat ){
-  InvertedPathString ips;
-  std::map< Node, std::vector< std::pair< Node, InvertedPathString > > > ips_map;
-  registerPatternElementPairs2( pat, pat, ips, ips_map );
-  for( std::map< Node, std::vector< std::pair< Node, InvertedPathString > > >::iterator it = ips_map.begin(); it != ips_map.end(); ++it ){
-    for( int j=0; j<(int)it->second.size(); j++ ){
-      for( int k=j+1; k<(int)it->second.size(); k++ ){
+void InstantiatorTheoryUf::registerPatternElementPairs( Node pat, PpIpsMap & pp_ips_map,
+                                                        NodePcDispatcher* npc,
+                                                        NodePpDispatcher* npp){
+  Ips ips;
+  registerPatternElementPairs2( pat, ips, pp_ips_map, npc );
+  for( PpIpsMap::iterator it = pp_ips_map.begin(); it != pp_ips_map.end(); ++it ){
+    // for each variable construct all the pp-pair
+    for( size_t j=0; j<it->second.size(); j++ ){
+      for( size_t k=j+1; k<it->second.size(); k++ ){
         //found a pp-pair
         Debug("pattern-element-opt") << "Found pp-pair ( " << it->second[j].first << ", " << it->second[k].first << " )" << std::endl;
         Debug("pattern-element-opt") << "   Paths = ";
-        outputInvertedPathString( "pattern-element-opt", it->second[j].second );
+        outputIps( "pattern-element-opt", it->second[j].second );
         Debug("pattern-element-opt") << " and ";
-        outputInvertedPathString( "pattern-element-opt", it->second[k].second );
+        outputIps( "pattern-element-opt", it->second[k].second );
         Debug("pattern-element-opt") << std::endl;
-        d_pp_pairs[ it->second[j].first ][ it->second[k].first ][pat].push_back( IpsPair( it->second[j].second, it->second[k].second ) );
+        d_pp_pairs[ it->second[j].first ][ it->second[k].first ]
+          .push_back( make_triple( npp, it->second[j].second, it->second[k].second ));
       }
     }
   }
+};
+
+void findPpSite(Node pat, InstantiatorTheoryUf::Ips& ips, InstantiatorTheoryUf::PpIpsMap & pp_ips_map){
+  Assert( pat.getKind()==APPLY_UF );
+  //add information for possible pp-pair
+
+  ips.push_back( make_pair( pat.getOperator(), 0) );
+  for( size_t i=0; i<pat.getNumChildren(); i++ ){
+    if( pat[i].getKind()==INST_CONSTANT ){
+      ips.back().second = i;
+      pp_ips_map[ pat[i] ].push_back( make_pair( pat.getOperator(), InstantiatorTheoryUf::Ips( ips ) ) );
+    }
+  }
+
+  for( size_t i=0; i<pat.getNumChildren(); i++ ){
+    if( pat[i].getKind()==APPLY_UF ){
+      ips.back().second = i;
+      findPpSite( pat[i], ips, pp_ips_map );
+    }
+  }
+  ips.pop_back();
 }
 
-void InstantiatorTheoryUf::registerCandidateGenerator( CandidateGenerator* cg, Node pat ){
-  Debug("efficient-e-match") << "Register candidate generator..." << pat << std::endl;
-  if( d_pat_cand_gens.find( pat )==d_pat_cand_gens.end() ){
-    registerPatternElementPairs( pat );
+void InstantiatorTheoryUf::combineMultiPpIpsMap(PpIpsMap & pp_ips_map, MultiPpIpsMap & multi_pp_ips_map,
+                                                EfficientHandler& eh, size_t index2,const std::vector<Node> & pats){
+  hash_map<size_t,NodePpDispatcher*> npps;
+  for( PpIpsMap::iterator it = pp_ips_map.begin(); it != pp_ips_map.end(); ++it ){
+    MultiPpIpsMap::iterator mit = multi_pp_ips_map.find(it->first);
+    if(mit == multi_pp_ips_map.end()) continue;
+    // for each variable construct all the pp-pair
+    // j the last pattern treated
+    for( std::vector< std::pair< Node, Ips > >::iterator j=it->second.begin(), jend = it->second.end() ;
+         j != jend; ++j){
+      // k one of the previous one
+      for( std::vector< triple< size_t, Node, Ips > >::iterator k=mit->second.begin(), kend = mit->second.end() ;
+           k != kend; ++k){
+        //found a pp-pair
+        Debug("pattern-element-opt") << "Found multi-pp-pair ( " << j->first
+                                     << ", " << k->second << " in "<< k->first
+                                     << " )" << std::endl;
+        Debug("pattern-element-opt") << "   Paths = ";
+        outputIps( "pattern-element-opt", j->second );
+        Debug("pattern-element-opt") << " and ";
+        outputIps( "pattern-element-opt", k->third );
+        Debug("pattern-element-opt") << std::endl;
+        NodePpDispatcher* dispatcher;
+        hash_map<size_t,NodePpDispatcher*>::iterator inpp = npps.find(k->first);
+        if( inpp != npps.end() ) dispatcher = inpp->second;
+        else{
+          dispatcher = new NodePpDispatcher();
+#ifdef CVC4_DEBUG
+          dispatcher->pat1 = pats[index2];
+          dispatcher->pat2 = pats[k->first];
+#endif
+          dispatcher->addPpDispatcher(&eh,index2,k->first);
+        };
+        d_pp_pairs[ j->first ][ k->second ].push_back( make_triple( dispatcher, j->second, k->third ));
+      }
+    }
   }
-  d_pat_cand_gens[pat].push_back( cg );
 
-  //take all terms from the uf term db and add to candidate generator
-  Node op = pat.getOperator();
-  quantifiers::TermDb* db = d_quantEngine->getTermDatabase();
-  for( int i=0; i<(int)db->d_op_map[op].size(); i++ ){
-    cg->addCandidate( db->d_op_map[op][i] );
+  /** Put pp_ips_map to multi_pp_ips_map */
+  for( PpIpsMap::iterator it = pp_ips_map.begin(); it != pp_ips_map.end(); ++it ){
+    for( std::vector< std::pair< Node, Ips > >::iterator j=it->second.begin(), jend = it->second.end() ;
+         j != jend; ++j){
+      multi_pp_ips_map[it->first].push_back(make_triple(index2, j->first, j->second));
+    }
+  }
+
+}
+
+
+void InstantiatorTheoryUf::registerEfficientHandler( EfficientHandler& handler,
+                                                     const std::vector< Node > & pats ){
+  Assert(pats.size() > 0);
+
+  MultiPpIpsMap multi_pp_ips_map;
+  PpIpsMap pp_ips_map;
+  //In a multi-pattern Pattern that is only a variable are specials,
+  //if the variable appears in another pattern, it can be discarded.
+  //Otherwise new term of this term can be candidate. So we stock them
+  //here before adding them.
+  std::vector< size_t > patVars;
+
+  Debug("pattern-element-opt") << "Register patterns" << pats << std::endl;
+  for(size_t i = 0; i < pats.size(); ++i){
+    if( pats[i].getKind() == kind::INST_CONSTANT){
+      patVars.push_back(i);
+      continue;
+    }
+    //to complete
+    if( pats[i].getKind() == kind::NOT && pats[i][0].getKind() == kind::EQUAL){
+      Node cst = NodeManager::currentNM()->mkConst<bool>(false);
+      TNode op = pats[i][0].getOperator();
+      if(d_cc_pairs[op][cst] == NULL){
+        d_cc_pairs[op][cst] = new NodePcDispatcher();
+      }
+      d_cc_pairs[op][cst]->addPcDispatcher(&handler,i);
+      continue;
+    }
+    //end to complete
+    Debug("pattern-element-opt") << " Register candidate generator..." << pats[i] << std::endl;
+    /* Has the pattern already been seen */
+    if( d_pat_cand_gens.find( pats[i] )==d_pat_cand_gens.end() ){
+      NodePcDispatcher* npc = new NodePcDispatcher();
+      NodePpDispatcher* npp = new NodePpDispatcher();
+#ifdef CVC4_DEBUG
+      npc->pat = pats[i];
+      npp->pat1 = pats[i];
+      npp->pat2 = pats[i];
+#endif
+      d_pat_cand_gens[pats[i]] = make_pair(npc,npp);
+      registerPatternElementPairs( pats[i], pp_ips_map, npc, npp );
+    }else{
+      Ips ips;
+      findPpSite(pats[i],ips,pp_ips_map);
+    }
+    //Has the top operator already been seen */
+    TNode op = pats[i].getOperator();
+    d_pat_cand_gens[pats[i]].first->addPcDispatcher(&handler,i);
+    d_pat_cand_gens[pats[i]].second->addPpDispatcher(&handler,i,i);
+    d_cand_gens[op].addNewTermDispatcher(&handler,i);
+    
+    combineMultiPpIpsMap(pp_ips_map,multi_pp_ips_map,handler,i,pats);
+
+    pp_ips_map.clear();
+  }
+
+  for(size_t i = 0; i < patVars.size(); ++i){
+    TNode var = pats[patVars[i]];
+    Assert( var.getKind() == kind::INST_CONSTANT );
+    if( multi_pp_ips_map.find(var) != multi_pp_ips_map.end() ){
+      //The variable appear in another pattern, skip it
+      continue;
+    };
+    d_cand_gen_types[var.getType()].addNewTermDispatcher(&handler,patVars[i]);
   }
-  d_cand_gens[op].push_back( cg );
 
+  //take all terms from the uf term db and add to candidate generator
+  if( pats[0].getKind() == kind::INST_CONSTANT ){
+    TypeNode ty = pats[0].getType();
+    rrinst::CandidateGenerator* cg = d_quantEngine->getRRCanGenClasses(ty);
+    cg->reset(Node::null());
+    TNode c;
+    SetNode ele;
+    while( !(c = cg->getNextCandidate()).isNull() ){
+      if( c.getType() == ty ) ele.insert(c);
+    }
+    if( !ele.empty() ){
+      // for(std::vector<Node>::iterator i = db->d_op_map[op].begin(), end = db->d_op_map[op].end(); i != end; ++i){
+      //   if(CandidateGenerator::isLegalCandidate(*i)) ele.insert(*i);
+      // }
+      if(Debug.isOn("efficient-e-match-stats")){
+        Debug("efficient-e-match-stats") << "pattern " << pats << " initialized with " << ele.size() << " terms"<< std::endl;
+      }
+      handler.addMonoCandidate(ele, 0);
+    }
+
+  } else if( pats[0].getKind() == kind::NOT && pats[0][0].getKind() == kind::EQUAL){
+    Node cst = NodeManager::currentNM()->mkConst<bool>(false);
+    TNode op = pats[0][0].getOperator();
+    cst = getRepresentative(cst);
+    SetNode ele;
+    eq::EqClassIterator eqc_iter( cst, &((TheoryUF*)d_th)->d_equalityEngine );
+    while( !eqc_iter.isFinished() ){
+      Debug("efficient-e-match-debug") << "> look at " << (*eqc_iter)
+                                       << std::endl;
+      if( (*eqc_iter).hasOperator() && (*eqc_iter).getOperator() == op ) ele.insert(*eqc_iter);
+      eqc_iter++;
+    }
+    if( !ele.empty() ){
+      if(Debug.isOn("efficient-e-match-stats")){
+        Debug("efficient-e-match-stats") << "pattern " << pats << " initialized with " << ele.size() << " terms"<< std::endl;
+      }
+      handler.addMonoCandidate(ele, 0);
+    }
+
+  } else {
+    Node op = pats[0].getOperator();
+    TermDb* db = d_quantEngine->getTermDatabase();
+    if(db->d_op_map[op].begin() != db->d_op_map[op].end()){
+      SetNode ele;
+      // for(std::vector<Node>::iterator i = db->d_op_map[op].begin(), end = db->d_op_map[op].end(); i != end; ++i){
+      //   if(CandidateGenerator::isLegalCandidate(*i)) ele.insert(*i);
+      // }
+      ele.insert(db->d_op_map[op].begin(), db->d_op_map[op].end());
+      if(Debug.isOn("efficient-e-match-stats")){
+        Debug("efficient-e-match-stats") << "pattern " << pats << " initialized with " << ele.size() << " terms"<< std::endl;
+      }
+      handler.addMonoCandidate(ele, 0);
+    }
+  }
   Debug("efficient-e-match") << "Done." << std::endl;
 }
 
-void InstantiatorTheoryUf::registerTrigger( Trigger* tr, Node op ){
+void InstantiatorTheoryUf::registerTrigger( theory::inst::Trigger* tr, Node op ){
   if( std::find( d_op_triggers[op].begin(), d_op_triggers[op].end(), tr )==d_op_triggers[op].end() ){
     d_op_triggers[op].push_back( tr );
   }
@@ -506,9 +826,28 @@ void InstantiatorTheoryUf::outputEqClass( const char* c, Node n ){
   }
 }
 
-void InstantiatorTheoryUf::outputInvertedPathString( const char* c, InvertedPathString& ips ){
+void InstantiatorTheoryUf::outputIps( const char* c, Ips& ips ){
   for( int i=0; i<(int)ips.size(); i++ ){
     if( i>0 ){ Debug( c ) << "."; }
     Debug( c ) << ips[i].first << "." << ips[i].second;
   }
 }
+
+rrinst::CandidateGenerator* InstantiatorTheoryUf::getRRCanGenClasses(){
+  uf::TheoryUF* uf = static_cast<uf::TheoryUF*>(getTheory());
+  eq::EqualityEngine* ee =
+    static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
+  return new eq::rrinst::CandidateGeneratorTheoryEeClasses(ee);
+}
+
+rrinst::CandidateGenerator* InstantiatorTheoryUf::getRRCanGenClass(){
+  uf::TheoryUF* uf = static_cast<uf::TheoryUF*>(getTheory());
+  eq::EqualityEngine* ee =
+    static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
+  return new eq::rrinst::CandidateGeneratorTheoryEeClass(ee);
+}
+
+
+} /* namespace uf */
+} /* namespace theory */
+} /* namespace cvc4 */
index 4ddc01986b9f66997d30da8510826a4662a07727..3a2a5cc0ed0e399e8269bb4b5a0159e3afe524c2 100644 (file)
@@ -27,6 +27,9 @@
 
 #include "util/stats.h"
 #include "theory/uf/theory_uf.h"
+#include "theory/trigger.h"
+#include "util/ntuple.h"
+#include "context/cdqueue.h"
 
 namespace CVC4 {
 namespace theory {
@@ -38,6 +41,300 @@ namespace quantifiers{
 namespace uf {
 
 class InstantiatorTheoryUf;
+class HandlerPcDispatcher;
+class HandlerPpDispatcher;
+
+typedef std::set<Node> SetNode;
+
+template<class T>
+class CleanUpPointer{
+public:
+  inline void operator()(T** e){
+    delete(*e);
+  };
+};
+
+class EfficientHandler{
+public:
+  typedef std::pair< Node, size_t > MonoCandidate;
+  typedef std::pair< MonoCandidate, MonoCandidate > MultiCandidate;
+  typedef std::pair< SetNode, size_t > MonoCandidates;
+  typedef std::pair< MonoCandidates, MonoCandidates > MultiCandidates;
+private:
+  /* Queue of candidates */
+  typedef context::CDQueue< MonoCandidates *, CleanUpPointer<MonoCandidates> > MonoCandidatesQueue;
+  typedef context::CDQueue< MultiCandidates *, CleanUpPointer<MultiCandidates> > MultiCandidatesQueue;
+  MonoCandidatesQueue d_monoCandidates;
+  typedef uf::SetNode::iterator SetNodeIter;
+  context::CDO<SetNodeIter> d_si;
+  context::CDO<bool> d_mono_not_first;
+
+  MonoCandidatesQueue d_monoCandidatesNewTerm;
+  context::CDO<SetNodeIter> d_si_new_term;
+  context::CDO<bool> d_mono_not_first_new_term;
+
+
+  MultiCandidatesQueue d_multiCandidates;
+  context::CDO<SetNodeIter> d_si1;
+  context::CDO<SetNodeIter> d_si2;
+  context::CDO<bool> d_multi_not_first;
+
+
+  friend class InstantiatorTheoryUf;
+  friend class HandlerPcDispatcher;
+  friend class HandlerPpDispatcher;
+  friend class HandlerNewTermDispatcher;
+protected:
+  void addMonoCandidate(SetNode & s, size_t index){
+    Assert(!s.empty());
+    d_monoCandidates.push(new MonoCandidates(s,index));
+  }
+  void addMonoCandidateNewTerm(SetNode & s, size_t index){
+    Assert(!s.empty());
+    d_monoCandidatesNewTerm.push(new MonoCandidates(s,index));
+  }
+  void addMultiCandidate(SetNode & s1, size_t index1, SetNode & s2, size_t index2){
+    Assert(!s1.empty() && !s2.empty());
+    d_multiCandidates.push(new MultiCandidates(MonoCandidates(s1,index1),
+                                               MonoCandidates(s2,index2)));
+  }
+public:
+  EfficientHandler(context::Context * c):
+    //false for d_mono_not_first beacause its the default constructor
+    d_monoCandidates(c), d_si(c), d_mono_not_first(c,false),
+    d_monoCandidatesNewTerm(c), d_si_new_term(c),
+    d_mono_not_first_new_term(c,false),
+    d_multiCandidates(c) , d_si1(c), d_si2(c), d_multi_not_first(c,false) {};
+
+  bool getNextMonoCandidate(MonoCandidate & candidate){
+    if(d_monoCandidates.empty()) return false;
+    const MonoCandidates * front = d_monoCandidates.front();
+    SetNodeIter si_tmp;
+    if(!d_mono_not_first){
+      Assert(front->first.begin() != front->first.end());
+      d_mono_not_first = true;
+      si_tmp=front->first.begin();
+    }else{
+      si_tmp = d_si;
+      ++si_tmp;
+    };
+    if(si_tmp != front->first.end()){
+      candidate.first = (*si_tmp);
+      candidate.second = front->second;
+      d_si = si_tmp;
+      Debug("efficienthandler") << "Mono produces " << candidate.first << " for " << candidate.second << std::endl;
+      return true;
+    };
+    d_monoCandidates.pop();
+    d_mono_not_first = false;
+    return getNextMonoCandidate(candidate);
+  };
+
+  bool getNextMonoCandidateNewTerm(MonoCandidate & candidate){
+    if(d_monoCandidatesNewTerm.empty()) return false;
+    const MonoCandidates * front = d_monoCandidatesNewTerm.front();
+    SetNodeIter si_tmp;
+    if(!d_mono_not_first_new_term){
+      Assert(front->first.begin() != front->first.end());
+      d_mono_not_first_new_term = true;
+      si_tmp=front->first.begin();
+    }else{
+      si_tmp = d_si_new_term;
+      ++si_tmp;
+    };
+    if(si_tmp != front->first.end()){
+      candidate.first = (*si_tmp);
+      candidate.second = front->second;
+      d_si_new_term = si_tmp;
+      Debug("efficienthandler") << "Mono produces " << candidate.first << " for " << candidate.second << std::endl;
+      return true;
+    };
+    d_monoCandidatesNewTerm.pop();
+    d_mono_not_first_new_term = false;
+    return getNextMonoCandidateNewTerm(candidate);
+  };
+
+  bool getNextMultiCandidate(MultiCandidate & candidate){
+    if(d_multiCandidates.empty()) return false;
+    const MultiCandidates* front = d_multiCandidates.front();
+    SetNodeIter si1_tmp;
+    SetNodeIter si2_tmp;
+    if(!d_multi_not_first){
+      Assert(front->first.first.begin() != front->first.first.end());
+      Assert(front->second.first.begin() != front->second.first.end());
+      si1_tmp = front->first.first.begin();
+      si2_tmp = front->second.first.begin();
+    }else{
+      si1_tmp = d_si1;
+      si2_tmp = d_si2;
+      ++si2_tmp;
+    };
+    if(si2_tmp != front->second.first.end()){
+      candidate.first.first = *si1_tmp;
+      candidate.first.second = front->first.second;
+      candidate.second.first = *si2_tmp;
+      candidate.second.second = front->second.second;
+      if(!d_multi_not_first){d_si1 = si1_tmp; d_multi_not_first = true; };
+      d_si2 = si2_tmp;
+      Debug("efficienthandler") << "Multi1 produces "
+                                << candidate.first.first << " for "
+                                << candidate.first.second << " and "
+                                << candidate.second.first << " for "
+                                << candidate.second.second << " and "
+                                << std::endl;
+      return true;
+    }; // end of the second set
+    si2_tmp = front->second.first.begin();
+    ++si1_tmp;
+    if(si1_tmp != front->first.first.end()){
+      candidate.first.first = *si1_tmp;
+      candidate.first.second = front->first.second;
+      candidate.second.first = *si2_tmp;
+      candidate.second.second = front->second.second;
+      d_si1 = si1_tmp;
+      d_si2 = si2_tmp;
+      Debug("efficienthandler") << "Multi2 produces "
+                                << candidate.first.first << " for "
+                                << candidate.first.second << " and "
+                                << candidate.second.first << " for "
+                                << candidate.second.second << " and "
+                                << std::endl;
+      return true;
+    }; // end of the first set
+    d_multiCandidates.pop();
+    d_multi_not_first = false;
+    return getNextMultiCandidate(candidate);
+  }
+};
+
+class PcDispatcher{
+public:
+  virtual ~PcDispatcher(){};
+  /* Send the node to the dispatcher */
+  virtual void send(SetNode & s) = 0;
+};
+
+
+class HandlerPcDispatcher: public PcDispatcher{
+  EfficientHandler* d_handler;
+  size_t d_index;
+public:
+  HandlerPcDispatcher(EfficientHandler* handler, size_t index):
+    d_handler(handler), d_index(index) {};
+  void send(SetNode & s){
+    d_handler->addMonoCandidate(s,d_index);
+  }
+};
+
+
+/** All the dispatcher that correspond to this node */
+class NodePcDispatcher: public PcDispatcher{
+#ifdef CVC4_DEBUG
+public:
+  Node pat;
+#endif/* CVC4_DEBUG*/
+private:
+  std::vector<HandlerPcDispatcher> d_dis;
+public:
+  void send(SetNode & s){
+    Assert(!s.empty());
+    for(std::vector<HandlerPcDispatcher>::iterator i = d_dis.begin(), end = d_dis.end();
+        i != end; ++i){
+      (*i).send(s);
+    }
+  }
+  void addPcDispatcher(EfficientHandler* handler, size_t index){
+    d_dis.push_back(HandlerPcDispatcher(handler,index));
+  }
+};
+
+
+class HandlerNewTermDispatcher: public PcDispatcher{
+  EfficientHandler* d_handler;
+  size_t d_index;
+public:
+  HandlerNewTermDispatcher(EfficientHandler* handler, size_t index):
+    d_handler(handler), d_index(index) {};
+  void send(SetNode & s){
+    d_handler->addMonoCandidateNewTerm(s,d_index);
+  }
+};
+
+/** All the dispatcher that correspond to this node */
+class NodeNewTermDispatcher: public PcDispatcher{
+#ifdef CVC4_DEBUG
+public:
+  Node pat;
+#endif/* CVC4_DEBUG*/
+private:
+  std::vector<HandlerNewTermDispatcher> d_dis;
+public:
+  void send(SetNode & s){
+    Assert(!s.empty());
+    for(std::vector<HandlerNewTermDispatcher>::iterator i = d_dis.begin(), end = d_dis.end();
+        i != end; ++i){
+      (*i).send(s);
+    }
+  }
+  void addNewTermDispatcher(EfficientHandler* handler, size_t index){
+    d_dis.push_back(HandlerNewTermDispatcher(handler,index));
+  }
+};
+
+class PpDispatcher{
+public:
+  virtual ~PpDispatcher(){};
+  /* Send the node to the dispatcher */
+  virtual void send(SetNode & s1, SetNode & s2, SetNode & sinter) = 0;
+};
+
+
+class HandlerPpDispatcher: public PpDispatcher{
+  EfficientHandler* d_handler;
+  size_t d_index1;
+  size_t d_index2;
+public:
+  HandlerPpDispatcher(EfficientHandler* handler, size_t index1, size_t index2):
+    d_handler(handler), d_index1(index1), d_index2(index2) {};
+  void send(SetNode & s1, SetNode & s2, SetNode & sinter){
+    if(d_index1 == d_index2){
+      if(!sinter.empty())
+        d_handler->addMonoCandidate(sinter,d_index1);
+    }else{
+      d_handler->addMultiCandidate(s1,d_index1,s2,d_index2);
+    }
+  }
+};
+
+
+/** All the dispatcher that correspond to this node */
+class NodePpDispatcher: public PpDispatcher{
+#ifdef CVC4_DEBUG
+public:
+  Node pat1;
+  Node pat2;
+#endif/* CVC4_DEBUG */
+private:
+  std::vector<HandlerPpDispatcher> d_dis;
+  void send(SetNode & s1, SetNode & s2, SetNode & inter){
+    for(std::vector<HandlerPpDispatcher>::iterator i = d_dis.begin(), end = d_dis.end();
+        i != end; ++i){
+      (*i).send(s1,s2,inter);
+    }
+  }
+public:
+  void send(SetNode & s1, SetNode & s2){
+    // can be done in HandlerPpDispatcher lazily
+    Assert(!s1.empty() && !s2.empty());
+    SetNode inter;
+    std::set_intersection( s1.begin(), s1.end(), s2.begin(), s2.end(),
+                           std::inserter( inter, inter.begin() ) );
+    send(s1,s2,inter);
+  }
+  void addPpDispatcher(EfficientHandler* handler, size_t index1, size_t index2){
+    d_dis.push_back(HandlerPpDispatcher(handler,index1,index2));
+  }
+};
 
 //equivalence class info
 class EqClassInfo
@@ -68,7 +365,7 @@ public:
 };
 
 class InstantiatorTheoryUf : public Instantiator{
-  friend class ::CVC4::theory::InstMatchGenerator;
+  friend class ::CVC4::theory::inst::InstMatchGenerator;
   friend class ::CVC4::theory::quantifiers::TermDb;
 protected:
   typedef context::CDHashMap<Node, bool, NodeHashFunction> BoolMap;
@@ -82,7 +379,14 @@ protected:
   InstStrategyUserPatterns* d_isup;
 public:
   InstantiatorTheoryUf(context::Context* c, CVC4::theory::QuantifiersEngine* qe, Theory* th);
-  ~InstantiatorTheoryUf() {}
+  ~InstantiatorTheoryUf() {
+    for(std::map< Node, std::pair<NodePcDispatcher*, NodePpDispatcher*> >::iterator
+          i = d_pat_cand_gens.begin(), end = d_pat_cand_gens.end();
+        i != end; i++){
+      delete(i->second.first);
+      delete(i->second.second);
+    }
+  }
   /** assertNode method */
   void assertNode( Node assertion );
   /** Pre-register a term.  Done one time for a Node, ever. */
@@ -127,6 +431,9 @@ public:
   bool areDisequal( Node a, Node b );
   Node getRepresentative( Node a );
   Node getInternalRepresentative( Node a );
+  /** general creators of candidate generators */
+  rrinst::CandidateGenerator* getRRCanGenClasses();
+  rrinst::CandidateGenerator* getRRCanGenClass();
   /** new node */
   void newEqClass( TNode n );
   /** merge */
@@ -136,47 +443,66 @@ public:
   /** get equivalence class info */
   EqClassInfo* getEquivalenceClassInfo( Node n );
   EqClassInfo* getOrCreateEquivalenceClassInfo( Node n );
+  typedef std::vector< std::pair< Node, int > > Ips;
+  typedef std::map< Node, std::vector< std::pair< Node, Ips > > > PpIpsMap;
+  typedef std::map< Node, std::vector< triple< size_t, Node, Ips > > > MultiPpIpsMap;
+
 private:
-  typedef std::vector< std::pair< Node, int > > InvertedPathString;
-  typedef std::pair< InvertedPathString, InvertedPathString > IpsPair;
   /** Parent/Child Pairs (for efficient E-matching)
       So, for example, if we have the pattern f( g( x ) ), then d_pc_pairs[g][f][f( g( x ) )] = { f.0 }.
   */
-  std::map< Node, std::map< Node, std::map< Node, std::vector< InvertedPathString > > > > d_pc_pairs;
+  std::map< Node, std::map< Node, std::vector< std::pair< NodePcDispatcher*, Ips > > > > d_pc_pairs;
   /** Parent/Parent Pairs (for efficient E-matching) */
-  std::map< Node, std::map< Node, std::map< Node, std::vector< IpsPair > > > > d_pp_pairs;
+  std::map< Node, std::map< Node, std::vector< triple< NodePpDispatcher*, Ips, Ips > > > > d_pp_pairs;
+  /** Constants/Child Pairs
+      So, for example, if we have the pattern f( x ) = c, then d_pc_pairs[f][c] = ..., pcdispatcher, ...
+  */
+  //TODO constant in pattern can use the same thing just add an Ips
+  std::map< Node, std::map< Node, NodePcDispatcher* > > d_cc_pairs;
   /** list of all candidate generators for each operator */
-  std::map< Node, std::vector< CandidateGenerator* > > d_cand_gens;
+  std::map< Node, NodeNewTermDispatcher > d_cand_gens;
+  /** list of all candidate generators for each type */
+  std::map< TypeNode, NodeNewTermDispatcher > d_cand_gen_types;
   /** map from patterns to candidate generators */
-  std::map< Node, std::vector< CandidateGenerator* > > d_pat_cand_gens;
+  std::map< Node, std::pair<NodePcDispatcher*, NodePpDispatcher*> > d_pat_cand_gens;
   /** helper functions */
-  void registerPatternElementPairs2( Node opat, Node pat, InvertedPathString& ips,
-                                     std::map< Node, std::vector< std::pair< Node, InvertedPathString > > >& ips_map );
-  void registerPatternElementPairs( Node pat );
+  void registerPatternElementPairs2( Node pat, Ips& ips,
+                                     PpIpsMap & pp_ips_map, NodePcDispatcher* npc);
+  void registerPatternElementPairs( Node pat, PpIpsMap & pp_ips_map,
+                                    NodePcDispatcher* npc, NodePpDispatcher* npp);
+  /** find the pp-pair between pattern inside multi-pattern*/
+  void combineMultiPpIpsMap(PpIpsMap & pp_ips_map, MultiPpIpsMap & multi_pp_ips_map,
+                            EfficientHandler& eh, size_t index2,
+                            const std::vector<Node> & pats); //pats for debug
   /** compute candidates for pc pairs */
-  void computeCandidatesPcPairs( Node a, Node b );
+  void computeCandidatesPcPairs( Node a, EqClassInfo*, Node b, EqClassInfo* );
   /** compute candidates for pp pairs */
-  void computeCandidatesPpPairs( Node a, Node b );
+  void computeCandidatesPpPairs( Node a, EqClassInfo*, Node b, EqClassInfo* );
+  /** compute candidates for cc pairs */
+  void computeCandidatesConstants( Node a, EqClassInfo*, Node b, EqClassInfo* );
   /** collect terms based on inverted path string */
-  void collectTermsIps( InvertedPathString& ips, std::vector< Node >& terms, int index = 0 );
-  bool collectParentsTermsIps( Node n, Node f, int arg, std::vector< Node >& terms, bool addRep, bool modEq = true );
+  void collectTermsIps( Ips& ips, SetNode& terms, int index);
+  bool collectParentsTermsIps( Node n, Node f, int arg, SetNode& terms, bool addRep, bool modEq = true );
 public:
+  void collectTermsIps( Ips& ips, SetNode& terms);
   /** Register candidate generator cg for pattern pat. (for use with efficient e-matching)
       This request will ensure that calls will be made to cg->addCandidate( n ) for all
       ground terms n that are relevant for matching with pat.
   */
-  void registerCandidateGenerator( CandidateGenerator* cg, Node pat );
 private:
   /** triggers */
-  std::map< Node, std::vector< Trigger* > > d_op_triggers;
+  std::map< Node, std::vector< inst::Trigger* > > d_op_triggers;
 public:
   /** register trigger (for eager quantifier instantiation) */
-  void registerTrigger( Trigger* tr, Node op );
+  void registerTrigger( inst::Trigger* tr, Node op );
+  void registerEfficientHandler( EfficientHandler& eh, const std::vector<Node> & pat );
+public:
+  void newTerms(SetNode& s);
 public:
   /** output eq class */
   void outputEqClass( const char* c, Node n );
   /** output inverted path string */
-  void outputInvertedPathString( const char* c, InvertedPathString& ips );
+  void outputIps( const char* c, Ips& ips );
 };/* class InstantiatorTheoryUf */
 
 /** equality query object using instantiator theory uf */
index e9efab5dd88cb03b8d3793bc10745fc9d2279648..c2b632b32f98c389fec5df088c1bea551a4e227d 100644 (file)
@@ -161,6 +161,7 @@ Options::Options() :
   literalMatchMode(LITERAL_MATCH_NONE),
   cbqi(false),
   cbqiSetByUser(false),
+  rewriteRulesAsAxioms(false),
   userPatternsQuant(true),
   flipDecision(false),
   printInstEngine(false),
@@ -294,12 +295,14 @@ Additional CVC4 options:\n\
    --register-quant-body-terms  consider ground terms within bodies of quantified formulas for matching\n\
    --inst-when=MODE       when to apply instantiation\n\
    --eager-inst-quant     apply quantifier instantiation eagerly\n\
-   --efficient-e-matching use efficient E-matching\n\
    --literal-matching=MODE  choose literal matching mode\n\
    --enable-cbqi          turns on counterexample-based quantifier instantiation [off by default]\n\
    --disable-cbqi         turns off counterexample-based quantifier instantiation\n\
    --ignore-user-patterns ignore user-provided patterns for quantifier instantiation\n\
    --enable-flip-decision turns on flip decision heuristic\n\
+ REWRITERULES:\n\
+   --efficient-e-matching use efficient E-matching (only for rewrite rules)\n\
+   --rewrite-rules-as-axioms convert rewrite rules into usual axioms (for debugging only)\n\
  FINITE_MODEL_FINDING:\n\
    --finite-model-find      use finite model finding heuristic for quantifier instantiation\n\
    --disable-uf-ss-regions  disable region-based method for discovering cliques and splits in uf strong solver\n\
@@ -642,6 +645,7 @@ enum OptionValue {
   DISABLE_CBQI,
   IGNORE_USER_PATTERNS,
   ENABLE_FLIP_DECISION,
+  REWRITE_RULES_AS_AXIOMS,
   PRINT_MODEL_ENGINE,
   PRINT_INST_ENGINE,
   PARALLEL_THREADS,
@@ -779,6 +783,7 @@ static struct option cmdlineOptions[] = {
   { "disable-cbqi", no_argument, NULL, DISABLE_CBQI },
   { "ignore-user-patterns", no_argument, NULL, IGNORE_USER_PATTERNS },
   { "enable-flip-decision", no_argument, NULL, ENABLE_FLIP_DECISION },
+  { "rewrite-rules-as-axioms", no_argument, NULL, REWRITE_RULES_AS_AXIOMS },
   { "print-m-e", no_argument, NULL, PRINT_MODEL_ENGINE },
   { "print-i-e", no_argument, NULL, PRINT_INST_ENGINE },
   { "threads", required_argument, NULL, PARALLEL_THREADS },
@@ -1379,6 +1384,9 @@ throw(OptionException) {
     case ENABLE_FLIP_DECISION:
       flipDecision = true;
       break;
+    case REWRITE_RULES_AS_AXIOMS:
+      rewriteRulesAsAxioms = true;
+      break;
     case PRINT_MODEL_ENGINE:
       printModelEngine = true;
       break;
index d89265b55d405ce234977e94b00b166aab6c6417..17d393e885516f2ab5bf5fe81f79619f7e07cbe3 100644 (file)
@@ -484,6 +484,11 @@ struct CVC4_PUBLIC Options {
   bool cbqiSetByUser;
 
   /**
+   * Whether to convert rewrite rules to usual axioms (for debugging only)
+   */
+  bool rewriteRulesAsAxioms;
+
+  /** 
    * Whether to use user patterns for pattern-based instantiation
    */
   bool userPatternsQuant;
index 58788c194b72cf7235e614eeb343df9c5d90b188..c11d1672977652e3ab0941173ea1bb9494e77ae1 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = . arith precedence uf uflra uflia bv arrays aufbv auflia datatypes quantifiers lemmas push-pop preprocess unconstrained decision
+SUBDIRS = . arith precedence uf uflra uflia bv arrays aufbv auflia datatypes quantifiers rewriterules lemmas push-pop preprocess unconstrained decision
 DIST_SUBDIRS = . arith precedence uf uflra uflia bv arrays aufbv auflia datatypes quantifiers rewriterules lemmas push-pop preprocess unconstrained decision
 
 BINARY = cvc4
index 97675b1118f3de7c0a59d61cfee24d1371f4193b..38cc59125e13d15a1e494cc69b805ea14d9db842 100644 (file)
@@ -50,8 +50,6 @@ TESTS =       \
 #              javafe.ast.StmtVec.009.smt2 \
 #              javafe.ast.WhileStmt.447.smt2 \
 #              javafe.tc.CheckCompilationUnit.001.smt2 \
-#              AdditiveMethods_AdditiveMethods..ctor.smt2 \
-#              AdditiveMethods_OwnedResults.Mz.smt2 \
 #              javafe.tc.FlowInsensitiveChecks.682.smt2 \
 #
 
index 94b558675987823287e4bdae83e0521175847b1b..c0a3fb9341b6b4a217d9d44f390245042789d92c 100644 (file)
@@ -1,4 +1,8 @@
 BINARY = cvc4
+
+CVC4_REGRESSION_ARGS ?= --efficient-e-matching
+export CVC4_REGRESSION_ARGS
+
 if PROOF_REGRESSIONS
 TESTS_ENVIRONMENT = LFSC="$(LFSC) $(LFSCARGS)" @srcdir@/../../run_regression $(RUN_REGRESSION_ARGS) --proof @top_builddir@/src/main/$(BINARY)
 else
@@ -13,7 +17,8 @@ MAKEFLAGS = -k
 TESTS =        \
        length_trick.smt2 length_trick2.smt2 length_gen_020.smt2 \
        datatypes.smt2 datatypes_sat.smt2 set_A_new_fast_tableau-base.smt2 \
-       set_A_new_fast_tableau-base_sat.smt2
+       set_A_new_fast_tableau-base_sat.smt2 relation.smt2 simulate_rewritting.smt2 \
+       reachability_back_to_the_future.smt2 native_arrays.smt2 reachability_bbttf_eT_arrays.smt2
 
 EXTRA_DIST = $(TESTS)
 
index eacb5ff6a08c932db9cc54e199b8ed19990cf883..f1e61a90193ab2f98272c5422f554aa9b12bee9a 100644 (file)
@@ -1,4 +1,4 @@
-(set-logic LRA)
+(set-logic AUFLIRA)
 
 ;; DATATYPE
 ;;   nat = succ(pred : nat) | zero,
 ;; injective
 
 (declare-fun inj1 (nat) nat)
-(assert (forall ((?x1 nat))
-                (! (! (=> true (=> true (= (inj1 (succ ?x1)) ?x1))) :pattern ((succ ?x1)) ) :rewrite-rule) ))
-
+(assert-propagation((?x1 nat))
+                 () () (= (inj1 (succ ?x1)) ?x1) (((succ ?x1))) )
 
 ;;;;;;;;;;;;;;;;;;;;
 ;; projection
 
 (declare-fun pred (nat) nat)
-(assert (forall ((?x1 nat))
-                (! (= (pred (succ ?x1)) ?x1) :rewrite-rule) ))
+(assert-rewrite ((?x1 nat)) () (pred (succ ?x1)) ?x1 () )
 
 (assert (= (pred zero) zero))
 
 ;; test
 (declare-fun is_succ (nat) Bool)
 (assert (= (is_succ zero) false))
-(assert (forall ((?x1 nat))
-                (! (! (=> true (=> true (= (is_succ (succ ?x1)) true))) :pattern ((succ ?x1)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 nat)) () () (= (is_succ (succ ?x1)) true) (((succ ?x1))) )
 
-(assert (forall ((?x1 nat))
-                (! (! (=> true (=> (is_succ ?x1) (= ?x1 (succ (pred ?x1))))) :pattern ((pred ?x1)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 nat)) () ((is_succ ?x1)) (= ?x1 (succ (pred ?x1))) (((pred ?x1))))
 
 (declare-fun is_zero (nat) Bool)
 (assert (= (is_zero zero) true))
-(assert (forall ((?x1 nat))
-                (! (=> true (=> (is_zero ?x1) (= ?x1 zero))) :rewrite-rule) ))
+(assert-propagation ((?x1 nat)) () ((is_zero ?x1)) (= ?x1 zero) ())
 
 ;;; directrr
-(assert (forall ((?x1 nat))
-                (! (= (is_succ (succ ?x1)) true) :rewrite-rule)))
-(assert (forall ((?x1 nat))
-                (! (= (is_zero (succ ?x1)) false) :rewrite-rule)))
+(assert-rewrite ((?x1 nat)) () (is_succ (succ ?x1)) true () )
+(assert-rewrite ((?x1 nat)) () (is_zero (succ ?x1)) false () )
 
 
 ;;;;;;;;;;;;;;;;;;;;
 ;; distinct
-(assert (forall ((?x1 nat))
-                (! (=> (is_zero ?x1) (not (is_succ ?x1)) ) :rewrite-rule) ))
-(assert (forall ((?x1 nat))
-                (! (=> (is_succ ?x1) (not (is_zero ?x1)) ) :rewrite-rule) ))
-(assert (forall ((?x1 nat))
-                (! (=> (not (is_zero ?x1)) (is_succ ?x1) ) :rewrite-rule) ))
-(assert (forall ((?x1 nat))
-                (! (=> (not (is_succ ?x1)) (is_zero ?x1) ) :rewrite-rule) ))
+(assert-propagation ((?x1 nat)) () ((is_zero ?x1)) (not (is_succ ?x1)) () )
+(assert-propagation ((?x1 nat)) () ((is_succ ?x1)) (not (is_zero ?x1)) () )
+(assert-propagation ((?x1 nat)) () ((not (is_zero ?x1))) (is_succ ?x1) () )
+(assert-propagation ((?x1 nat)) () ((not (is_succ ?x1))) (is_zero ?x1) () )
 
 ;;;;;;;;;;;;;;;;;;;
 ;; case-split
-(assert (forall ((?x1 nat))
-                (! (! (=> true (or (is_zero ?x1) (is_succ ?x1))) :pattern ((pred ?x1)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 nat)) () () (or (is_zero ?x1) (is_succ ?x1)) (((pred ?x1))) )
 
 ;;;;;;;;;;;;;;;;;;;
 ;; non-cyclic
 (declare-fun size_nat (nat) Real)
-(assert (forall ((?x1 nat))
-                (! (! (=> true (> (size_nat (succ ?x1)) (size_nat ?x1))) :pattern ((succ ?x1)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 nat)) () () (> (size_nat (succ ?x1)) (size_nat ?x1)) (((succ ?x1))) )
 
 
 
 ;; injective
 
 (declare-fun inj2 (list) tree)
-(assert (forall ((?x1 tree) (?x2 list))
-                (! (! (=> true (=> true (= (inj2 (cons ?x1 ?x2)) ?x1))) :pattern ((cons ?x1 ?x2)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 tree) (?x2 list)) () () (= (inj2 (cons ?x1 ?x2)) ?x1) (((cons ?x1 ?x2))) )
 
 (declare-fun inj3 (list) list)
-(assert (forall ((?x1 tree) (?x2 list))
-                (! (! (=> true (=> true (= (inj3 (cons ?x1 ?x2)) ?x2))) :pattern ((cons ?x1 ?x2)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 tree) (?x2 list)) () () (= (inj3 (cons ?x1 ?x2)) ?x2) (((cons ?x1 ?x2))) )
 
 
 ;;;;;;;;;;;;;;;;;;;;
 ;; projection
 
 (declare-fun car (list) tree)
-(assert (forall ((?x1 tree) (?x2 list))
-                (! (= (car (cons ?x1 ?x2)) ?x1) :rewrite-rule) ))
+(assert-rewrite ((?x1 tree) (?x2 list)) () (car (cons ?x1 ?x2)) ?x1 ())
 
 (assert (= (car null) (node null)))
 
 (declare-fun cdr (list) list)
-(assert (forall ((?x1 tree) (?x2 list))
-                (! (= (cdr (cons ?x1 ?x2)) ?x2) :rewrite-rule) ))
+(assert-rewrite ((?x1 tree) (?x2 list)) () (cdr (cons ?x1 ?x2)) ?x2 ())
 
 (assert (= (cdr null) null))
 
 ;; test
 (declare-fun is_cons (list) Bool)
 (assert (= (is_cons null) false))
-(assert (forall ((?x1 tree) (?x2 list))
-                (! (! (=> true (=> true (= (is_cons (cons ?x1 ?x2)) true))) :pattern ((cons ?x1 ?x2)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 tree) (?x2 list)) () () (= (is_cons (cons ?x1 ?x2)) true) (((cons ?x1 ?x2))) )
 
-(assert (forall ((?x1 list))
-                (! (! (=> true (=> (is_cons ?x1) (= ?x1 (cons (car ?x1) (cdr ?x1))))) :pattern ((car ?x1)) ) :rewrite-rule) ))
-(assert (forall ((?x1 list))
-                (! (! (=> true (=> (is_cons ?x1) (= ?x1 (cons (car ?x1) (cdr ?x1))))) :pattern ((cdr ?x1)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 list)) () ((is_cons ?x1)) (= ?x1 (cons (car ?x1) (cdr ?x1))) (((car ?x1))) )
+(assert-propagation ((?x1 list)) () ((is_cons ?x1)) (= ?x1 (cons (car ?x1) (cdr ?x1))) (((cdr ?x1))) )
 
 (declare-fun is_null (list) Bool)
 (assert (= (is_null null) true))
 
-(assert (forall ((?x1 list))
-                (! (! (=> true (=> (is_null ?x1) (= (car ?x1) (node null)))) :pattern ((car ?x1)) ) :rewrite-rule) ))
-(assert (forall ((?x1 list))
-                (! (! (=> true (=> (is_null ?x1) (= (cdr ?x1) null))) :pattern ((cdr ?x1)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 list)) () ((is_null ?x1)) (= (car ?x1) (node null)) (((car ?x1))) )
+(assert-propagation ((?x1 list)) () ((is_null ?x1)) (= (cdr ?x1) null) (((cdr ?x1))) )
 
-(assert (forall ((?x1 list))
-                (! (=> true (=> (is_null ?x1) (= ?x1 null))) :rewrite-rule) ))
+(assert-propagation ((?x1 list)) () ((is_null ?x1)) (= ?x1 null) ())
 
 ;;; directrr
-(assert (forall ((?x1 tree) (?x2 list))
-                (! (= (is_cons (cons ?x1 ?x2)) true) :rewrite-rule) ))
-(assert (forall ((?x1 tree) (?x2 list))
-                (! (= (is_null (cons ?x1 ?x2)) false) :rewrite-rule) ))
+(assert-rewrite ((?x1 tree) (?x2 list)) () (is_cons (cons ?x1 ?x2)) true ())
+(assert-rewrite ((?x1 tree) (?x2 list)) () (is_null (cons ?x1 ?x2)) false ())
 
 
 
 ;;;;;;;;;;;;;;;;;;;;
 ;; distinct
-(assert (forall ((?x1 list))
-                (! (=> (is_null ?x1) (not (is_cons ?x1)) ) :rewrite-rule) ))
-(assert (forall ((?x1 list))
-                (! (=> (is_cons ?x1) (not (is_null ?x1)) ) :rewrite-rule) ))
-(assert (forall ((?x1 list))
-                (! (=> (not (is_null ?x1)) (is_cons ?x1) ) :rewrite-rule) ))
-(assert (forall ((?x1 list))
-                (! (=> (not (is_cons ?x1)) (is_null ?x1) ) :rewrite-rule) ))
+(assert-propagation ((?x1 list)) () ((is_null ?x1)) (not (is_cons ?x1)) () )
+(assert-propagation ((?x1 list)) () ((is_cons ?x1)) (not (is_null ?x1)) () )
+(assert-propagation ((?x1 list)) () ((not (is_null ?x1))) (is_cons ?x1) () )
+(assert-propagation ((?x1 list)) () ((not (is_cons ?x1))) (is_null ?x1) () )
 
 ;;;;;;;;;;;;;;;;;;;
 ;; case-split
-(assert (forall ((?x1 list))
-            (! (! (=> true (or (is_null ?x1) (is_cons ?x1))) :pattern ((car ?x1)) ) :rewrite-rule) ))
-(assert (forall ((?x1 list))
-            (! (! (=> true (or (is_null ?x1) (is_cons ?x1))) :pattern ((cdr ?x1)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 list)) () () (or (is_null ?x1) (is_cons ?x1)) (((car ?x1))) )
+(assert-propagation ((?x1 list)) () () (or (is_null ?x1) (is_cons ?x1)) (((cdr ?x1))) )
 
 ;;;;;;;;;;;;;;;
 ;; tree
 ;; injective
 
 (declare-fun inj4 (tree) list)
-(assert (forall ((?x1 list))
-                (! (! (=> true (=> true (= (inj4 (node ?x1)) ?x1))) :pattern ((node ?x1)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 list)) () () (= (inj4 (node ?x1)) ?x1) (((node ?x1))) )
 
 (declare-fun inj5 (tree) nat)
-(assert (forall ((?x1 nat))
-                (! (! (=> true (=> true (= (inj5 (leaf ?x1)) ?x1))) :pattern ((leaf ?x1)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 nat)) () () (= (inj5 (leaf ?x1)) ?x1) (((leaf ?x1))) )
 
 
 ;;;;;;;;;;;;;;;;;;;;
 ;; projection
 
 (declare-fun children (tree) list)
-(assert (forall ((?x1 list))
-                (! (= (children (node ?x1)) ?x1) :rewrite-rule) ))
-(assert (forall ((?x1 nat))
-                (! (= (children (leaf ?x1)) null) :rewrite-rule) ))
-
+(assert-rewrite ((?x1 list)) () (children (node ?x1)) ?x1 () )
+(assert-rewrite ((?x1 nat)) () (children (leaf ?x1)) null () )
 
 (declare-fun data (tree) nat)
-(assert (forall ((?x1 nat))
-                (! (= (data (leaf ?x1)) ?x1) :rewrite-rule) ))
-(assert (forall ((?x1 list))
-                (! (= (data (node ?x1)) zero) :rewrite-rule) ))
+(assert-rewrite ((?x1 nat)) () (data (leaf ?x1)) ?x1 () )
+(assert-rewrite ((?x1 list)) () (data (node ?x1)) zero () )
 
 ;;;;;;;;;;;;;;;;;;;
 ;; test
 (declare-fun is_node (tree) Bool)
-(assert (forall ((?x1 list))
-                (! (! (=> true (=> true (= (is_node (node ?x1)) true))) :pattern ((node ?x1)) ) :rewrite-rule) ))
-
-(assert (forall ((?x1 tree))
-                (! (! (=> true (=> (is_node ?x1) (= ?x1 (node (children ?x1))))) :pattern ((children ?x1)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 list)) () () (= (is_node (node ?x1)) true) (((node ?x1))) )
 
-(assert (forall ((?x1 tree))
-                (! (! (=> true (=> (is_node ?x1) (= (data ?x1) zero))) :pattern ((data ?x1)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 tree)) () ((is_node ?x1)) (= ?x1 (node (children ?x1))) (((children ?x1))) )
+(assert-propagation ((?x1 tree)) () ((is_node ?x1)) (= (data ?x1) zero) (((data ?x1))) )
 
 
 (declare-fun is_leaf (tree) Bool)
-(assert (forall ((?x1 nat))
-                (! (! (=> true (=> true (= (is_leaf (leaf ?x1)) true))) :pattern ((leaf ?x1)) ) :rewrite-rule) ))
-
-(assert (forall ((?x1 tree))
-                (! (! (=> true (=> (is_leaf ?x1) (= ?x1 (leaf (data ?x1))))) :pattern ((data ?x1)) ) :rewrite-rule) ))
-(assert (forall ((?x1 tree))
-                (! (! (=> true (=> (is_leaf ?x1) (= (children ?x1) null))) :pattern ((children ?x1)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 nat)) () () (= (is_leaf (leaf ?x1)) true) (((leaf ?x1))) )
+(assert-propagation ((?x1 tree)) () ((is_leaf ?x1)) (= ?x1 (leaf (data ?x1))) (((data ?x1))) )
+(assert-propagation ((?x1 tree)) () ((is_leaf ?x1)) (= (children ?x1) null) (((children ?x1))) )
 
 ;;; directrr
-(assert (forall ((?x1 list))
-                (! (= (is_node (node ?x1)) true) :rewrite-rule) ))
-(assert (forall ((?x1 list))
-                (! (= (is_leaf (node ?x1)) false) :rewrite-rule) ))
-(assert (forall ((?x1 nat))
-                (! (= (is_leaf (leaf ?x1)) true) :rewrite-rule) ))
-(assert (forall ((?x1 nat))
-                (! (= (is_node (leaf ?x1)) false) :rewrite-rule) ))
+(assert-rewrite ((?x1 list)) () (is_node (node ?x1)) true () )
+(assert-rewrite ((?x1 list)) () (is_leaf (node ?x1)) false () )
+(assert-rewrite ((?x1 nat)) () (is_leaf (leaf ?x1)) true () )
+(assert-rewrite ((?x1 nat)) () (is_node (leaf ?x1)) false () )
 
 
 ;;;;;;;;;;;;;;;;;;;;
 ;; distinct
-(assert (forall ((?x1 tree))
-                (! (=> (is_node ?x1) (not (is_leaf ?x1)) ) :rewrite-rule) ))
-(assert (forall ((?x1 tree))
-                (! (=> (is_leaf ?x1) (not (is_node ?x1)) ) :rewrite-rule) ))
-(assert (forall ((?x1 tree))
-                (! (=> (not (is_node ?x1)) (is_leaf ?x1) ) :rewrite-rule) ))
-(assert (forall ((?x1 tree))
-                (! (=> (not (is_leaf ?x1)) (is_node ?x1) ) :rewrite-rule) ))
+(assert-propagation ((?x1 tree)) () ((is_node ?x1)) (not (is_leaf ?x1)) () )
+(assert-propagation ((?x1 tree)) () ((is_leaf ?x1)) (not (is_node ?x1)) () )
+(assert-propagation ((?x1 tree)) () ((not (is_node ?x1))) (is_leaf ?x1) () )
+(assert-propagation ((?x1 tree)) () ((not (is_leaf ?x1))) (is_node ?x1) () )
 
 ;;;;;;;;;;;;;;;;;;;
 ;; case-split
-(assert (forall ((?x1 tree))
-                (! (! (=> true (or (is_node ?x1) (is_leaf ?x1))) :pattern ((children ?x1)) ) :rewrite-rule) ))
-
-(assert (forall ((?x1 tree))
-                (! (! (=> true (or (is_node ?x1) (is_leaf ?x1))) :pattern ((data ?x1)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 tree)) () () (or (is_node ?x1) (is_leaf ?x1)) (((children ?x1))) )
+(assert-propagation ((?x1 tree)) () () (or (is_node ?x1) (is_leaf ?x1)) (((data ?x1))) )
 
 
 ;;;;;;;;;;;;;;;;;;
 ;; non-cyclic
 (declare-fun size_list (list) Real)
 (declare-fun size_tree (tree) Real)
-(assert (forall ((?x1 tree) (?x2 list))
-                (! (! (=> true (and (> (size_list (cons ?x1 ?x2)) (size_tree ?x1)) (> (size_list (cons ?x1 ?x2)) (size_list ?x2)))) :pattern ((cons ?x1 ?x2)) ) :rewrite-rule) ))
-(assert (forall ((?x1 list))
-                (! (! (=> true (> (size_tree (node ?x1)) (size_list ?x1))) :pattern ((node ?x1)) ) :rewrite-rule) ))
-(assert (forall ((?x1 nat))
-                (! (! (=> true (> (size_tree (leaf ?x1)) (size_nat ?x1))) :pattern ((leaf ?x1)) ) :rewrite-rule) ))
+(assert-propagation ((?x1 tree) (?x2 list)) () () (and (> (size_list (cons ?x1 ?x2)) (size_tree ?x1)) (> (size_list (cons ?x1 ?x2)) (size_list ?x2))) (((cons ?x1 ?x2))) )
+(assert-propagation ((?x1 list)) () () (> (size_tree (node ?x1)) (size_list ?x1)) (((node ?x1))) )
+(assert-propagation ((?x1 nat)) () () (> (size_tree (leaf ?x1)) (size_nat ?x1)) (((leaf ?x1))) )
diff --git a/test/regress/regress0/rewriterules/datatypes_clark_quantification.smt2 b/test/regress/regress0/rewriterules/datatypes_clark_quantification.smt2
new file mode 100644 (file)
index 0000000..6e22816
--- /dev/null
@@ -0,0 +1,264 @@
+(set-logic AUFLIRA)
+
+;; DATATYPE
+;;   nat = succ(pred : nat) | zero,
+;;   list = cons(car : tree, cdr : list) | null,
+;;   tree = node(children : list) | leaf(data : nat)
+;; END;
+
+;;;;;;;;;;;
+;; nat   ;;
+;;;;;;;;;;;
+(declare-sort nat 0)
+(declare-fun zero () nat)
+(declare-fun succ (nat) nat)
+
+;;;;;;;;;;;;;;;;
+;; injective
+
+(declare-fun inj1 (nat) nat)
+(assert (forall ((?x1 nat))
+                (! (= (inj1 (succ ?x1)) ?x1) :pattern ((succ ?x1)) ) ))
+
+
+;;;;;;;;;;;;;;;;;;;;
+;; projection
+
+(declare-fun pred (nat) nat)
+(assert (forall ((?x1 nat))
+                (! (= (pred (succ ?x1)) ?x1) :pattern ((pred (succ ?x1))) ) ))
+
+(assert (= (pred zero) zero))
+
+;;;;;;;;;;;;;;;;;;;
+;; test
+(declare-fun is_succ (nat) Bool)
+(assert (= (is_succ zero) false))
+(assert (forall ((?x1 nat))
+                (! (= (is_succ (succ ?x1)) true) :pattern ((succ ?x1)) ) ))
+
+(assert (forall ((?x1 nat))
+                (! (=> (is_succ ?x1) (= ?x1 (succ (pred ?x1)))) :pattern ((is_succ ?x1) (pred ?x1)) ) ))
+
+(declare-fun is_zero (nat) Bool)
+(assert (= (is_zero zero) true))
+(assert (forall ((?x1 nat))
+                (! (=> (is_zero ?x1) (= ?x1 zero)) :pattern ((is_zero ?x1)) ) ))
+
+;;; directrr
+(assert (forall ((?x1 nat))
+                (! (= (is_succ (succ ?x1)) true) :pattern ((is_succ (succ ?x1))) ) ))
+(assert (forall ((?x1 nat))
+                (! (= (is_zero (succ ?x1)) false) :pattern ((is_zero (succ ?x1))) )))
+
+
+;;;;;;;;;;;;;;;;;;;;
+;; distinct
+(assert (forall ((?x1 nat))
+                (! (=> (is_zero ?x1) (not (is_succ ?x1)) ) :pattern ((is_zero ?x1)) ) ))
+(assert (forall ((?x1 nat))
+                (! (=> (is_succ ?x1) (not (is_zero ?x1)) ) :pattern ((is_succ ?x1)) ) ))
+(assert (forall ((?x1 nat))
+                (! (=> (not (is_zero ?x1)) (is_succ ?x1) ) :pattern ((is_zero ?x1)) ) ))
+(assert (forall ((?x1 nat))
+                (! (=> (not (is_succ ?x1)) (is_zero ?x1) ) :pattern ((is_succ ?x1)) ) ))
+
+;;;;;;;;;;;;;;;;;;;
+;; case-split
+(assert (forall ((?x1 nat))
+                (! (or (is_zero ?x1) (is_succ ?x1)) :pattern ((pred ?x1)) ) ))
+
+;;;;;;;;;;;;;;;;;;;
+;; non-cyclic
+(declare-fun size_nat (nat) Real)
+(assert (forall ((?x1 nat))
+                (! (> (size_nat (succ ?x1)) (size_nat ?x1)) :pattern ((succ ?x1)) ) ))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;
+;; list and tree
+
+(declare-sort list 0)
+(declare-sort tree 0)
+
+;;;;;;;;;;;
+;; list  ;;
+;;;;;;;;;;;
+
+(declare-fun null () list)
+(declare-fun cons (tree list) list)
+
+(declare-fun node (list) tree)
+(declare-fun leaf (nat) tree)
+
+;;;;;;;;;;;;;;;;
+;; injective
+
+(declare-fun inj2 (list) tree)
+(assert (forall ((?x1 tree) (?x2 list))
+                (! (= (inj2 (cons ?x1 ?x2)) ?x1) :pattern ((cons ?x1 ?x2)) ) ))
+
+(declare-fun inj3 (list) list)
+(assert (forall ((?x1 tree) (?x2 list))
+                (! (= (inj3 (cons ?x1 ?x2)) ?x2) :pattern ((cons ?x1 ?x2)) ) ))
+
+
+;;;;;;;;;;;;;;;;;;;;
+;; projection
+
+(declare-fun car (list) tree)
+(assert (forall ((?x1 tree) (?x2 list))
+                (! (= (car (cons ?x1 ?x2)) ?x1) :pattern ((car (cons ?x1 ?x2))) ) ))
+
+(assert (= (car null) (node null)))
+
+(declare-fun cdr (list) list)
+(assert (forall ((?x1 tree) (?x2 list))
+                (! (= (cdr (cons ?x1 ?x2)) ?x2) :pattern ((cdr (cons ?x1 ?x2))) ) ))
+
+(assert (= (cdr null) null))
+
+;;;;;;;;;;;;;;;;;;;
+;; test
+(declare-fun is_cons (list) Bool)
+(assert (= (is_cons null) false))
+(assert (forall ((?x1 tree) (?x2 list))
+                (! (= (is_cons (cons ?x1 ?x2)) true) :pattern ((cons ?x1 ?x2)) ) ))
+
+(assert (forall ((?x1 list))
+                (! (=> (is_cons ?x1) (= ?x1 (cons (car ?x1) (cdr ?x1)))) :pattern ((is_cons ?x1)(car ?x1)) ) ))
+(assert (forall ((?x1 list))
+                (! (=> (is_cons ?x1) (= ?x1 (cons (car ?x1) (cdr ?x1)))) :pattern ((is_cons ?x1)(cdr ?x1)) ) ))
+
+(declare-fun is_null (list) Bool)
+(assert (= (is_null null) true))
+
+(assert (forall ((?x1 list))
+                (! (=> (is_null ?x1) (= (car ?x1) (node null))) :pattern ((is_null ?x1)(car ?x1)) )  ))
+(assert (forall ((?x1 list))
+                (! (=> (is_null ?x1) (= (cdr ?x1) null)) :pattern ((is_null ?x1)(cdr ?x1)) ) ))
+
+(assert (forall ((?x1 list))
+                (! (=> (is_null ?x1) (= ?x1 null)) :pattern ((is_null ?x1)) ) ))
+
+;;; directrr
+(assert (forall ((?x1 tree) (?x2 list))
+                (! (= (is_cons (cons ?x1 ?x2)) true) :pattern ((is_cons (cons ?x1 ?x2))) ) ))
+(assert (forall ((?x1 tree) (?x2 list))
+                (! (= (is_null (cons ?x1 ?x2)) false) :pattern ((is_null (cons ?x1 ?x2))) ) ))
+
+
+
+;;;;;;;;;;;;;;;;;;;;
+;; distinct
+(assert (forall ((?x1 list))
+                (! (=> (is_null ?x1) (not (is_cons ?x1)) ) :pattern ((is_null ?x1)) ) ))
+(assert (forall ((?x1 list))
+                (! (=> (is_cons ?x1) (not (is_null ?x1)) ) :pattern ((is_cons ?x1)) ) ))
+(assert (forall ((?x1 list))
+                (! (=> (not (is_null ?x1)) (is_cons ?x1) ) :pattern ((is_null ?x1)) ) ))
+(assert (forall ((?x1 list))
+                (! (=> (not (is_cons ?x1)) (is_null ?x1) ) :pattern ((is_cons ?x1)) ) ))
+
+;;;;;;;;;;;;;;;;;;;
+;; case-split
+(assert (forall ((?x1 list))
+            (!  (or (is_null ?x1) (is_cons ?x1)) :pattern ((car ?x1)) ) ))
+(assert (forall ((?x1 list))
+            (! (or (is_null ?x1) (is_cons ?x1)) :pattern ((cdr ?x1)) ) ))
+
+;;;;;;;;;;;;;;;
+;; tree
+
+;;;;;;;;;;;;;;;;
+;; injective
+
+(declare-fun inj4 (tree) list)
+(assert (forall ((?x1 list))
+                (! (= (inj4 (node ?x1)) ?x1) :pattern ((node ?x1)) ) ))
+
+(declare-fun inj5 (tree) nat)
+(assert (forall ((?x1 nat))
+                (!  (= (inj5 (leaf ?x1)) ?x1) :pattern ((leaf ?x1)) )  ))
+
+
+;;;;;;;;;;;;;;;;;;;;
+;; projection
+
+(declare-fun children (tree) list)
+(assert (forall ((?x1 list))
+                (! (= (children (node ?x1)) ?x1) :pattern ((children (node ?x1))) ) ))
+(assert (forall ((?x1 nat))
+                (! (= (children (leaf ?x1)) null) :pattern ((children (leaf ?x1))) ) ))
+
+
+(declare-fun data (tree) nat)
+(assert (forall ((?x1 nat))
+                (! (= (data (leaf ?x1)) ?x1) :pattern ((data (leaf ?x1))) ) ))
+(assert (forall ((?x1 list))
+                (! (= (data (node ?x1)) zero) :pattern ((data (node ?x1))) ) ))
+
+;;;;;;;;;;;;;;;;;;;
+;; test
+(declare-fun is_node (tree) Bool)
+(assert (forall ((?x1 list))
+                (! (= (is_node (node ?x1)) true) :pattern ((node ?x1)) )  ))
+
+(assert (forall ((?x1 tree))
+                (! (=> (is_node ?x1) (= ?x1 (node (children ?x1)))) :pattern ((is_node ?x1)(children ?x1)) ) ))
+
+(assert (forall ((?x1 tree))
+                (! (=> (is_node ?x1) (= (data ?x1) zero)) :pattern ((is_node ?x1)(data ?x1)) ) ))
+
+
+(declare-fun is_leaf (tree) Bool)
+(assert (forall ((?x1 nat))
+                (! (=> true (= (is_leaf (leaf ?x1)) true)) :pattern ((leaf ?x1)) ) ))
+
+(assert (forall ((?x1 tree))
+                (! (=> (is_leaf ?x1) (= ?x1 (leaf (data ?x1)))) :pattern ((is_leaf ?x1)(data ?x1)) ) ))
+(assert (forall ((?x1 tree))
+                (! (=> (is_leaf ?x1) (= (children ?x1) null)) :pattern ((is_leaf ?x1)(children ?x1)) ) ))
+
+;;; directrr
+(assert (forall ((?x1 list))
+                (! (= (is_node (node ?x1)) true) :pattern ((is_node (node ?x1))) ) ))
+(assert (forall ((?x1 list))
+                (! (= (is_leaf (node ?x1)) false) :pattern ((is_leaf (node ?x1))) ) ))
+(assert (forall ((?x1 nat))
+                (! (= (is_leaf (leaf ?x1)) true) :pattern (is_leaf (leaf ?x1)) ) ))
+(assert (forall ((?x1 nat))
+                (! (= (is_node (leaf ?x1)) false) :pattern ((is_node (leaf ?x1))) ) ))
+
+
+;;;;;;;;;;;;;;;;;;;;
+;; distinct
+(assert (forall ((?x1 tree))
+                (! (=> (is_node ?x1) (not (is_leaf ?x1)) ) :pattern ((is_node ?x1)) ) ))
+(assert (forall ((?x1 tree))
+                (! (=> (is_leaf ?x1) (not (is_node ?x1)) ) :pattern ((is_leaf ?x1)) ) ))
+(assert (forall ((?x1 tree))
+                (! (=> (not (is_node ?x1)) (is_leaf ?x1) ) :pattern ((is_node ?x1)) ) ))
+(assert (forall ((?x1 tree))
+                (! (=> (not (is_leaf ?x1)) (is_node ?x1) ) :pattern ((is_leaf ?x1)) ) ))
+
+;;;;;;;;;;;;;;;;;;;
+;; case-split
+(assert (forall ((?x1 tree))
+                (!  (or (is_node ?x1) (is_leaf ?x1)) :pattern ((children ?x1)) ) ))
+
+(assert (forall ((?x1 tree))
+                (! (or (is_node ?x1) (is_leaf ?x1)) :pattern ((data ?x1)) )  ))
+
+
+;;;;;;;;;;;;;;;;;;
+;; non-cyclic
+(declare-fun size_list (list) Real)
+(declare-fun size_tree (tree) Real)
+(assert (forall ((?x1 tree) (?x2 list))
+                (! (and (> (size_list (cons ?x1 ?x2)) (size_tree ?x1)) (> (size_list (cons ?x1 ?x2)) (size_list ?x2))) :pattern ((cons ?x1 ?x2)) ) ))
+(assert (forall ((?x1 list))
+                (! (> (size_tree (node ?x1)) (size_list ?x1)) :pattern ((node ?x1)) )  ))
+(assert (forall ((?x1 nat))
+                (! (> (size_tree (leaf ?x1)) (size_nat ?x1)) :pattern ((leaf ?x1)) ) ))
index 7c7663b17aad520c9ed6652bfcd12da10eef8f52..41cc61c9ed5c3705bbb9ea6976ec3bcc52f0fef1 100644 (file)
 
 (assert (= (length nil) 0))
 
-(assert (forall ((?e Int) (?l list)) (! (= (length (cons ?e ?l)) (+ 1 (length ?l))) :rewrite-rule)))
+;; (assert (forall ((?e Int) (?l list)) (! (= (length (cons ?e ?l)) (+ 1 (length ?l))) :rewrite-rule)))
+
+(assert-rewrite ((?e Int) (?l list)) () (length (cons ?e ?l)) (+ 1 (length ?l)) ())
 
 (declare-fun gen_cons (Int list) list)
 
-(assert (forall ((?n Int) (?l list)) (! (=> (= ?n 0) (= (gen_cons ?n ?l) ?l)) :rewrite-rule)))
+(assert-rewrite ((?n Int) (?l list)) (= ?n 0) (gen_cons ?n ?l) (?l) ())
 
-(assert (forall ((?n Int) (?l list)) (! (=> (> ?n 0) (= (gen_cons ?n ?l)
-        (gen_cons (- ?n 1) (cons 1 ?l)))) :rewrite-rule)))
+(assert-rewrite ((?n Int) (?l list)) (> ?n 0) (gen_cons ?n ?l)
+              (gen_cons (- ?n 1) (cons 1 ?l)) ())
 
 (declare-fun n () Int)
 
diff --git a/test/regress/regress0/rewriterules/native_arrays.smt2 b/test/regress/regress0/rewriterules/native_arrays.smt2
new file mode 100644 (file)
index 0000000..1be1316
--- /dev/null
@@ -0,0 +1,34 @@
+;; This example can't be done if we don't access the EqualityEngine of
+;; the theory of arrays
+
+(set-logic AUFLIA)
+(set-info :status unsat)
+
+(declare-sort Index 0)
+(declare-sort Element 0)
+
+;;A dumb predicate for a simple example
+(declare-fun P (Element) Bool)
+
+(assert-rewrite ((?i1 Index) (?i2 Index) (?e Element) (?a (Array Index Element))) ()
+                (P (select (store ?a ?i1 ?e) ?i2)) true () )
+
+(declare-fun a1 () (Array Index Element))
+(declare-fun a2 () (Array Index Element))
+(declare-fun a3 () (Array Index Element))
+(declare-fun i1 () Index)
+(declare-fun i2 () Index)
+(declare-fun e1 () Element)
+
+(assert (not (=>  (or (= a1 (store a2 i1 e1)) (= a1 (store a3 i1 e1))) (P (select a1 i2)) )))
+(check-sat)
+(exit)
+
+
+;; (declare-fun a1 () (Array Index Element))
+;; (declare-fun a2 () (Array Index Element))
+;; (declare-fun i1 () Index)
+;; (assert (= (store a1 i1 (select a2 i1)) (store a2 i1 (select a1 i1))))
+;; (assert (not (= a1 a2)))
+;; (check-sat)
+;; (exit)
diff --git a/test/regress/regress0/rewriterules/native_datatypes.smt2 b/test/regress/regress0/rewriterules/native_datatypes.smt2
new file mode 100644 (file)
index 0000000..f5d53e3
--- /dev/null
@@ -0,0 +1,33 @@
+;; Same than length.smt2 but the nil case is not a rewrite rule
+;; So here the rewrite rules have no guards length
+
+(set-info :status unsat)
+
+(declare-datatypes (
+(nat  (succ (pred nat)) (zero ) )
+(list  (cons (car nat)(cdr list)) (nil ) )
+
+))
+
+
+;;define length
+(declare-fun length (list) nat)
+
+(assert (= (length nil) zero))
+
+(assert (forall ((?e nat) (?l list)) (! (= (length (cons ?e ?l)) (succ (length ?l))) :rewrite-rule)))
+
+(declare-fun gen_cons (nat list) list)
+
+(assert (forall ((?l list)) (! (= (gen_cons zero ?l) ?l) :rewrite-rule)))
+
+(assert (forall ((?n nat) (?l list)) (! (= (gen_cons (succ ?n) ?l)
+        (gen_cons ?n (cons zero ?l))) :rewrite-rule)))
+
+(declare-fun n () nat)
+
+(assert (not (= (length (gen_cons (succ (succ zero)) nil)) (succ (succ zero)))))
+
+(check-sat)
+
+(exit)
diff --git a/test/regress/regress0/rewriterules/native_datatypes2.smt2 b/test/regress/regress0/rewriterules/native_datatypes2.smt2
new file mode 100644 (file)
index 0000000..4a719fb
--- /dev/null
@@ -0,0 +1,35 @@
+;; Same than length.smt2 but the nil case is not a rewrite rule
+;; So here the rewrite rules have no guards length
+
+(set-info :status unsat)
+
+(declare-datatypes (
+(nat  (succ (pred nat)) (zero ) )
+(list  (cons (car nat)(cdr list)) (nil ) )
+
+))
+
+
+;;define length
+(declare-fun length (list) nat)
+
+(assert (= (length nil) zero))
+
+(assert-rewrite ((?e nat) (?l list)) () (length (cons ?e ?l)) (succ (length ?l)) () )
+(assert-propagation ((?l list)) ((= (length ?l) zero)) () (= ?l nil) (((length ?l))) )
+;(assert-propagation ((?l list)) () () (= ?l nil) (((= (length ?l) 0))) )
+
+(declare-fun gen_cons (nat list) list)
+
+(assert-rewrite ((?l list)) () (gen_cons zero ?l) ?l () )
+
+(assert-rewrite ((?n nat) (?l list)) () (gen_cons (succ ?n) ?l) (gen_cons ?n (cons zero ?l)) () )
+
+(declare-fun l1 () list)
+(declare-fun l2 () list)
+
+(assert (not (=> (= (length l1) zero) (= l1 nil))))
+
+(check-sat)
+
+(exit)
diff --git a/test/regress/regress0/rewriterules/reachability_back_to_the_future.smt2 b/test/regress/regress0/rewriterules/reachability_back_to_the_future.smt2
new file mode 100644 (file)
index 0000000..7cd6173
--- /dev/null
@@ -0,0 +1,54 @@
+;; Back to the Future ... Shuvendu K.Lhiri, Shaz Qadeer
+(set-logic AUFLIA)
+(set-info :status unsat)
+
+(declare-sort elt 0)
+
+(declare-fun f (elt) elt)
+(declare-fun Rf (elt elt elt) Bool)
+
+;;eq
+(assert-propagation ((?x elt)) () () (or (= ?x ?x) (not (= ?x ?x))) ((?x)) )
+;; reflexive
+(assert-propagation ((?x elt)) () () (Rf ?x ?x ?x) ((?x)) )
+;; step
+(assert-propagation ((?x elt)) () () (Rf ?x (f ?x) (f ?x)) (((f ?x))) )
+;; reach
+(assert-propagation ((?x1 elt)(?x2 elt)) () ((Rf ?x1 ?x2 ?x2)) (or (= ?x1 ?x2) (Rf ?x1 (f ?x1) ?x2)) (((f ?x1))) )
+;; cycle
+(assert-propagation ((?x1 elt)(?x2 elt)) ((= (f ?x1) ?x1)) ((Rf ?x1 ?x2 ?x2)) (= ?x1 ?x2) (((f ?x1))) )
+;; sandwich
+(assert-propagation ((?x1 elt)(?x2 elt)) () ((Rf ?x1 ?x2 ?x1)) (= ?x1 ?x2) () )
+;; order1
+(assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3))
+                    (or (Rf ?x1 ?x2 ?x3) (Rf ?x1 ?x3 ?x2)) () )
+;; order2
+(assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x1 ?x2 ?x3))
+                    (and (Rf ?x1 ?x2 ?x2) (Rf ?x2 ?x3 ?x3)) () )
+;; transitive1
+(assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x1 ?x2 ?x2)(Rf ?x2 ?x3 ?x3))
+                    (Rf ?x1 ?x3 ?x3) () )
+;; transitive2
+(assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x0 ?x1 ?x2)(Rf ?x1 ?x3 ?x2))
+                    (and (Rf ?x0 ?x1 ?x3) (Rf ?x0 ?x3 ?x2)) () )
+;;transitive3
+(assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x0 ?x1 ?x2)(Rf ?x0 ?x3 ?x1))
+                    (and (Rf ?x0 ?x3 ?x2) (Rf ?x3 ?x1 ?x2)) () )
+
+(declare-fun e1 () elt)
+(declare-fun e2 () elt)
+(declare-fun e3 () elt)
+(declare-fun e4 () elt)
+
+
+;; (assert (=> (Rf e1 e2 e3) (Rf e1 (f e1) (f e1)) ))
+
+;; (assert (=> (Rf e1 e2 e3) (Rf e1 e3 e3) ))
+
+;; (assert (=> (Rf e1 e2 e3) (or (= e1 e3) (Rf e1 (f e1) e3)) ))
+
+(assert (not (=> (and (not (= e1 e2)) (Rf e1 e2 e3)) (Rf e1 (f e1) e3) )))
+
+
+(check-sat)
+(exit)
\ No newline at end of file
diff --git a/test/regress/regress0/rewriterules/reachability_back_to_the_future_extended.smt2 b/test/regress/regress0/rewriterules/reachability_back_to_the_future_extended.smt2
new file mode 100644 (file)
index 0000000..955c810
--- /dev/null
@@ -0,0 +1,72 @@
+;; Back to the Future ... Shuvendu K.Lhiri, Shaz Qadeer
+(set-logic AUFLIA)
+(set-info :status unsat)
+
+(declare-sort elt 0)
+
+(declare-fun f (elt) elt)
+(declare-fun Rf (elt elt elt) Bool)
+
+;;eq
+(assert-propagation ((?x elt)) () () (or (= ?x ?x) (not (= ?x ?x))) ((?x)) )
+;; reflexive
+(assert-propagation ((?x elt)) () () (Rf ?x ?x ?x) ((?x)) )
+;; step
+(assert-propagation ((?x elt)) () () (Rf ?x (f ?x) (f ?x)) (((f ?x))) )
+
+;; reach
+(assert-propagation ((?x1 elt)(?x2 elt)) () ((Rf ?x1 ?x2 ?x2)) (or (= ?x1 ?x2) (Rf ?x1 (f ?x1) ?x2)) (((f ?x1))) )
+;; reach extended
+(assert-propagation ((?x1 elt)(?x2 elt)) ((not (= ?x1 ?x2))(Rf ?x1 ?x2 ?x2)) () (Rf ?x1 (f ?x1) ?x2) (((Rf ?x1 (f ?x1) ?x2))) )
+;; reach extended
+(assert-propagation ((?x1 elt)(?x2 elt)) ((not (Rf ?x1 (f ?x1) ?x2))(Rf ?x1 ?x2 ?x2)) () (= ?x1 ?x2) (((Rf ?x1 (f ?x1) ?x2))) )
+
+;; cycle
+(assert-propagation ((?x1 elt)(?x2 elt)) ((= (f ?x1) ?x1)) ((Rf ?x1 ?x2 ?x2)) (= ?x1 ?x2) (((f ?x1))) )
+;; sandwich
+(assert-propagation ((?x1 elt)(?x2 elt)) () ((Rf ?x1 ?x2 ?x1)) (= ?x1 ?x2) () )
+;; order1
+(assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3))
+                    (or (Rf ?x1 ?x2 ?x3) (Rf ?x1 ?x3 ?x2)) () )
+;; order1 extended
+(assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)(not (Rf ?x1 ?x3 ?x2))) ()
+                    (Rf ?x1 ?x2 ?x3) (((Rf ?x1 ?x2 ?x3))) )
+;; order1 extended
+(assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)(not (Rf ?x1 ?x2 ?x3))) ()
+                    (Rf ?x1 ?x3 ?x2) (((Rf ?x1 ?x3 ?x2))) )
+
+;; order2
+(assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x1 ?x2 ?x3))
+                    (and (Rf ?x1 ?x2 ?x2) (Rf ?x2 ?x3 ?x3)) () )
+;; transitive1
+(assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x1 ?x2 ?x2)(Rf ?x2 ?x3 ?x3))
+                    (Rf ?x1 ?x3 ?x3) () )
+;; transitive2
+(assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x0 ?x1 ?x2)(Rf ?x1 ?x3 ?x2))
+                    (and (Rf ?x0 ?x1 ?x3) (Rf ?x0 ?x3 ?x2)) () )
+;;transitive3
+(assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x0 ?x1 ?x2)(Rf ?x0 ?x3 ?x1))
+                    (and (Rf ?x0 ?x3 ?x2) (Rf ?x3 ?x1 ?x2)) () )
+
+(declare-fun e1 () elt)
+(declare-fun e2 () elt)
+(declare-fun e3 () elt)
+(declare-fun e4 () elt)
+
+
+(assert (and (hack e1) (hack e2) (hack e3) (hack e4) (hack (f e1))))
+
+
+;; (assert (=> (Rf e1 e2 e3) (Rf e1 (f e1) (f e1)) ))
+
+;; (assert (=> (Rf e1 e2 e3) (Rf e1 e3 e3) ))
+
+;; (assert (=> (Rf e1 e2 e3) (or (= e1 e3) (Rf e1 (f e1) e3)) ))
+
+;;(assert (not (=> (and (not (= e1 e2)) (Rf e1 e2 e3)) (Rf e1 (f e1) e3) )))
+
+(assert (and (not (= e1 e2)) (Rf e1 e2 e3) (not (Rf e1 (f e1) e3)) ))
+
+
+(check-sat)
+(exit)
\ No newline at end of file
diff --git a/test/regress/regress0/rewriterules/reachability_bbttf_eT_arrays.smt2 b/test/regress/regress0/rewriterules/reachability_bbttf_eT_arrays.smt2
new file mode 100644 (file)
index 0000000..b706953
--- /dev/null
@@ -0,0 +1,332 @@
+;; Back to the Future ... Shuvendu K.Lhiri, Shaz Qadeer
+(set-logic AUFLIA)
+(set-info :status unsat)
+
+(declare-sort elt 0)
+(define-sort mem () (Array elt elt))
+
+(declare-fun R (mem elt elt elt) Bool)
+
+;; reflexive
+(assert-propagation ((?m mem)(?x elt)) () () (R ?m ?x ?x ?x) ((?m ?x)) )
+;; step
+(assert-propagation ((?m mem)(?x elt)) () () (R ?m ?x (select ?m ?x) (select ?m ?x)) (((select ?m ?x))) )
+;; (assert-propagation ((?x elt)) () () (Rf ?x (f ?x) (f ?x)) (((Rf ?x (f ?x) (f ?x)))) )
+;; (assert-propagation ((?x elt)) () () (=> true (Rf ?x (f ?x) (f ?x))) (((f ?x))) )
+
+;; reach
+(assert-propagation ((?m mem)(?x1 elt)(?x2 elt)) () ((R ?m ?x1 ?x2 ?x2)) (or (= ?x1 ?x2) (R ?m ?x1 (select ?m ?x1) ?x2)) (((select ?m ?x1))) )
+;; ;; reach extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)) ((not (= ?x1 ?x2))(Rf ?x1 ?x2 ?x2)) () (Rf ?x1 (f ?x1) ?x2) (((Rf ?x1 (f ?x1) ?x2))) )
+;; ;; reach extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)) ((not (Rf ?x1 (f ?x1) ?x2))(Rf ?x1 ?x2 ?x2)) () (= ?x1 ?x2) (((Rf ?x1 (f ?x1) ?x2))) )
+
+;; cycle
+(assert-propagation ((?m mem)(?x1 elt)(?x2 elt)) ((= (select ?m ?x1) ?x1)) ((R ?m ?x1 ?x2 ?x2)) (= ?x1 ?x2) (((select ?m ?x1))) )
+;; (assert-propagation ((?x1 elt)(?x2 elt)) ((= (f ?x1) ?x1)) ((Rf ?x1 ?x2 ?x2)) (= ?x1 ?x2) () )
+
+;; (assert-propagation ((?x1 elt)(?x2 elt)) () () (=> (and (= (f ?x1) ?x1) (Rf ?x1 ?x2 ?x2)) (= ?x1 ?x2)) (((Rf ?x1 ?x2 ?x2)(f ?x1))) )
+
+;; sandwich
+(assert-propagation ((?m mem)(?x1 elt)(?x2 elt)) () ((R ?m ?x1 ?x2 ?x1)) (= ?x1 ?x2) () )
+;; (assert-propagation ((?x1 elt)(?x2 elt)) () () (=> (Rf ?x1 ?x2 ?x1) (= ?x1 ?x2)) (((Rf ?x1 ?x2 ?x1))) )
+
+;; order1
+(assert-propagation ((?m mem)(?x1 elt)(?x2 elt)(?x3 elt)) ()
+                    ((R ?m ?x1 ?x2 ?x2)(R ?m ?x1 ?x3 ?x3)) (or (R ?m ?x1 ?x2 ?x3) (R ?m ?x1 ?x3 ?x2)) () )
+
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) () ()
+;;                     (=> (and (Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)) (or (Rf ?x1 ?x2 ?x3) (Rf ?x1 ?x3 ?x2))) (((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3))) )
+
+;; ;; order1 extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)(not (Rf ?x1 ?x3 ?x2))) ()
+;;                     (Rf ?x1 ?x2 ?x3) (((Rf ?x1 ?x2 ?x3))) )
+;; ;; order1 extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)(not (Rf ?x1 ?x2 ?x3))) ()
+;;                     (Rf ?x1 ?x3 ?x2) (((Rf ?x1 ?x3 ?x2))) )
+;; ;; order1 extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)(not (Rf ?x1 ?x3 ?x2))) ()
+;;                     (Rf ?x1 ?x2 ?x3) (((Rf ?x1 ?x3 ?x2))) )
+;; ;; order1 extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)(not (Rf ?x1 ?x2 ?x3))) ()
+;;                     (Rf ?x1 ?x3 ?x2) (((Rf ?x1 ?x2 ?x3))) )
+;; ;; order1 extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)(not (Rf ?x1 ?x3 ?x2))) ()
+;;                     (Rf ?x1 ?x2 ?x3) (((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3))) )
+;; ;; order1 extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)(not (Rf ?x1 ?x2 ?x3))) ()
+;;                     (Rf ?x1 ?x3 ?x2) (((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3))) )
+
+;; order2
+(assert-propagation ((?m mem)(?x1 elt)(?x2 elt)(?x3 elt)) () ((R ?m ?x1 ?x2 ?x3))
+                    (and (R ?m ?x1 ?x2 ?x2) (R ?m ?x2 ?x3 ?x3)) () )
+;; transitive1
+(assert-propagation ((?m mem)(?x1 elt)(?x2 elt)(?x3 elt)) () ((R ?m ?x1 ?x2 ?x2)(R ?m ?x2 ?x3 ?x3))
+                    (R ?m ?x1 ?x3 ?x3) () )
+;; ;; transitive1 extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) () ((not (Rf ?x1 ?x3 ?x3))(Rf ?x2 ?x3 ?x3))
+;;                     (not (Rf ?x1 ?x2 ?x2)) () )
+;; ;; transitive1 extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x1 ?x2 ?x2)(not (Rf ?x1 ?x3 ?x3)))
+;;                     (not (Rf ?x2 ?x3 ?x3)) () )
+
+;;transitive2
+(assert-propagation ((?m mem)(?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ((R ?m ?x0 ?x1 ?x2)(R ?m ?x1 ?x3 ?x2))
+                    (and (R ?m ?x0 ?x1 ?x3) (R ?m ?x0 ?x3 ?x2)) () )
+
+;; (assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ()
+;;                     (=> (and (Rf ?x0 ?x1 ?x2)(Rf ?x1 ?x3 ?x2))
+;;                         (and (Rf ?x0 ?x1 ?x3) (Rf ?x0 ?x3 ?x2)))
+;;                     (((Rf ?x0 ?x1 ?x2)(Rf ?x1 ?x3 ?x2))) )
+
+;; ;; transitive2 extended
+;; (assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ((not (Rf ?x0 ?x1 ?x3))(Rf ?x1 ?x3 ?x2))
+;;                     (not (Rf ?x0 ?x1 ?x2)) (((Rf ?x0 ?x1 ?x2))) )
+;; ;; transitive2 extended
+;; (assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x0 ?x1 ?x2)(not (Rf ?x0 ?x1 ?x3)))
+;;                     (not (Rf ?x1 ?x3 ?x2)) (((Rf ?x1 ?x3 ?x2))) )
+;; ;; transitive2 extended
+;; (assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ((not (Rf ?x0 ?x3 ?x2))(Rf ?x1 ?x3 ?x2))
+;;                     (not (Rf ?x0 ?x1 ?x2)) (((Rf ?x0 ?x1 ?x2))) )
+;; ;; transitive2 extended
+;; (assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x0 ?x1 ?x2)(not (Rf ?x0 ?x3 ?x2)))
+;;                     (not (Rf ?x1 ?x3 ?x2)) (((Rf ?x1 ?x3 ?x2))) )
+
+;; ;;transitive3
+(assert-propagation ((?m mem)(?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ((R ?m ?x0 ?x1 ?x2)(R ?m ?x0 ?x3 ?x1))
+                    (and (R ?m ?x0 ?x3 ?x2) (R ?m ?x3 ?x1 ?x2)) () )
+
+;; (assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ()
+;;                     (=> (and (Rf ?x0 ?x1 ?x2)(Rf ?x0 ?x3 ?x1))
+;;                         (and (Rf ?x0 ?x3 ?x2) (Rf ?x3 ?x1 ?x2))) (((Rf ?x0 ?x1 ?x2)(Rf ?x0 ?x3 ?x1))) )
+
+
+(declare-fun next () mem)
+
+(declare-fun e1 () elt)
+(declare-fun e2 () elt)
+(declare-fun e3 () elt)
+(declare-fun e4 () elt)
+
+
+
+(declare-fun R_avoid (mem elt elt elt) Bool)
+
+(assert-rewrite ((?m mem)(?x0 elt)(?x1 elt)(?exc elt)) () (R_avoid ?m ?x0 ?x1 ?exc)
+                 (or (R ?m ?x0 ?x1 ?exc) (and (R ?m ?x0 ?x1 ?x1) (not (R ?m ?x0 ?exc ?exc)))) () )
+
+
+;; Identity of Back to the future p175
+(assert-rewrite ((?p elt)(?q elt)(?u elt)(?v elt)(?w elt)(?m mem)) () (R (store ?m ?p ?q) ?u ?v ?w)
+                (or (and (R ?m ?u ?v ?w) (R_avoid ?m ?u ?w ?p) )
+                    (and (not (= ?p ?w)) (R_avoid ?m ?u ?p ?w) (R ?m ?u ?v ?p) (R_avoid ?m ?q ?w ?p) )
+                    (and (not (= ?p ?w)) (R_avoid ?m ?u ?p ?w) (R ?m ?q ?v ?w) (R_avoid ?m ?q ?w ?p) ) )
+                ()
+)
+
+
+
+(declare-fun join (mem elt elt) elt)
+
+(declare-fun null () elt)
+(assert (= (select next null) null))
+
+(assert-propagation ((?m mem)(?x elt)(?y elt)(?z elt)) () ((R ?m ?x ?z ?z)(R ?m ?y ?z ?z)) (R ?m ?x (join ?m ?x ?y) ?z) (((join ?m ?x ?y))) )
+(assert-propagation ((?m mem)(?x elt)(?y elt)) () () (or (and (R ?m ?x (join ?m ?x ?y) (join ?m ?x ?y)) (R ?m ?y (join ?m ?x ?y) (join ?m ?x ?y))) (= (join ?m ?x ?y) null))  (((join ?m ?x ?y))) )
+
+;;extended join
+(assert-propagation ((?m mem)(?x elt)(?y elt)(?z elt)) () ((R ?m ?x ?z (join ?m ?x ?y))(R ?m ?y ?z (join ?m ?x ?y))) (= ?z (join ?m ?x ?y)) () )
+
+
+(assert-propagation ((?p elt)(?q elt)(?m mem)(?u elt)(?v elt)) () ()
+                    (= (join (store ?m ?p ?q) ?u ?v)
+                       (let ((jp (join ?m ?u ?v)))
+                         ;; In ?m: ?u ?v have a nearest point of junction (join ?m ?u ?v)
+                         (ite (and (R ?m ?u jp jp) (R ?m ?v jp jp))
+                              ;; The modification is in the ?u branch
+                              (ite (R ?m ?u ?p jp)
+                                   ;; we can go by the new path and the new path doesn't cycle
+                                   (ite (and (R (store ?m ?p ?q) ?u ?p ?q) (R (store ?m ?p ?q) ?q (join ?m ?q ?v) (join ?m ?q ?v)))
+                                        (join ?m ?q ?v)
+                                   ;; we can't
+                                        null
+                                   )
+                              ;; The modification is in the ?v branch
+                              (ite (R ?m ?v ?p jp)
+                                   ;; we can go by the new path and the new path doesn't cycle
+                                   (ite (and (R (store ?m ?p ?q) ?v ?p ?q) (R (store ?m ?p ?q) ?q (join ?m ?u ?q) (join ?m ?u ?q)))
+                                        (join ?m ?u ?q)
+                                   ;; we can't
+                                        null
+                                   )
+                              ;; The modification is not before the point of junction
+                                   (join ?m ?u ?v)
+                              ))
+                         ;; In ?m: ?u ?v doens't have a point of junction
+                              ;;The modification is accesible from ?u
+                              (ite (R ?m ?u ?p ?p) (join ?m ?q ?v)
+                              ;;The modification is accesible from ?v
+                                   (ite (R ?m ?v ?p ?p) (join ?m ?u ?q)
+                              ;;The modification is accesible neither from ?u neither from ?v
+                                        (join ?m ?u ?v)
+                                   )
+                              )
+                         )
+                       ))
+                    (((join (store ?m ?p ?q) ?u ?v)))
+                    )
+
+(declare-fun next2 () mem)
+
+;; === Example 0 ===
+;; (assert (not (=>
+;;               (and (not (= e1 e2))
+;;                    (R next e1 e2 e3))
+;;               (R next e1 (select next e1) e3))
+;; ))
+
+;;================
+;;Thomas' example1 x,e1 y,e2 z,e3 y',e4
+;;================
+;; (assert (not (=>
+;;               (and (R next e1 e2 e3)
+;;                    (not (= e2 e3))
+;;                    (= e4 (select next e2)))
+;;               (R next e1 e4 e3))
+;; ))
+
+
+;;===================
+;; ;;Thomas' example2
+;;===================
+
+;; (assert (not (=>
+;;               (and (R next e1 null null)
+;;                    (= (join next e1 e2) null)
+;;                    (= next2 (store next e2 e1))
+;;                    )
+;;               (R next2 e1 null null)
+;;               )
+;;              )
+;;         )
+
+
+;;================
+;;Thomas' example3
+;;================
+(assert (not (=> (and (= (join next e1 e2) null)
+                      (R next e2 null null)
+                      (not (= e2 null))
+                      (= next2 (store next e2 e1))
+                      (= e3 e2)
+                      (= e4 (select next e2))
+                      )
+                 (= (join next2 e3 e4) null)
+                 )
+             )
+        )
+
+;; ==== for debugging example 3 ====
+;; ;;case to consider
+;; ;;(assert (or (not (R next e1 null null)) (R next e1 null null)))
+
+;; ;;first case to consider
+;; ;;(assert (R next e1 null null))
+
+;; ;;second case to consider
+;; ;; (assert (not (R next e1 null null)))
+
+
+;; ;;hyp
+;; (assert (= (join next e1 e2) null))
+;; (assert (R next e2 null null))
+;; (assert (not (= e2 null)))
+;; (assert (= next2 (store next e2 e1)))
+;; (assert (= e3 e2))
+;; (assert (= e4 (select next e2)))
+
+;; ;; help
+;; ;; have a join point
+;; ;; (assert (R next e2 e4 e4))
+;; ;; (assert (R next e4 e4 e4))
+
+;; ;; (assert (R next e2 (join next e2 e4) e4))
+;; ;; (assert (not (R next e4 e2 e2)))
+
+;; ;; (assert (not (= e2 (join next e2 e4))));;  slow with efficient (/axioms)
+
+;; ;; (assert (= e4 (join next e2 e4))) ;; unprovable with efficient (/axioms)
+;; ;; in e2 branch
+;; ;; (assert (not (R next e4 e2 null))) ;; 
+;; ;; the auxillary join
+;; ;; (assert (= (join next2 e1 e4) null))
+
+
+;; ;;to prove
+;; (assert (not (= (join next2 e3 e4) null)))
+
+
+;;====================
+;; ;;Thomas' example wrong sat?
+;;====================
+
+;; (assert (not (=> (and
+;;                   (= (join next e1 e2) null)
+;;                   (R next e2 null null)
+;;                   (not (= e2 null))
+;;                   (= next2 (store next e2 e1))
+;;                   )
+;;                  (= (join next2 e1 e2) null)
+;;                  )
+;;              )
+;;         )
+
+;;====================
+;; ;;example4 sat
+;;====================
+
+;; (assert (not (=> (and
+;;                   (= (join next e1 e2) null)
+;;                   (R next e2 null null) (not (= e2 null))
+;;                   )
+;; (not (R next e2 e2 e2))
+;; )))
+
+
+;;====================
+;;example5 unsat
+;;====================
+
+;; (assert (and
+;;          ;; (= (join e1 e2) null)
+;;          (= (select next (select next e1)) e1)
+;;          (R next e1 e2 e2)
+;;          (not (= e2 e1))
+;;          (not (= e2 (select next e1)))
+;;          )
+;; )
+
+;;====================
+;; ;; example 6 unsat
+;;====================
+
+;; ;; join is the nearest junction point
+;; (assert (and (not (= e3 (join next e1 e2)))
+;;              (R next e1 e3 (join next e1 e2))
+;;              (R next e2 e3 (join next e1 e2))
+;; ))
+
+
+;;====================
+;; example7 unsat
+;;====================
+
+;; (assert (R next e1 e2 (select next e1)))
+;; (assert (not (= e1 e2)))
+;; (assert (not (= e2 (select next e1))))
+
+
+
+(check-sat)
+(exit)
+
diff --git a/test/regress/regress0/rewriterules/reachability_bttf_ext_Thomas.smt2 b/test/regress/regress0/rewriterules/reachability_bttf_ext_Thomas.smt2
new file mode 100644 (file)
index 0000000..9210323
--- /dev/null
@@ -0,0 +1,211 @@
+;; Back to the Future ... Shuvendu K.Lhiri, Shaz Qadeer
+(set-logic AUFLIA)
+(set-info :status unsat)
+
+(declare-sort elt 0)
+
+(declare-fun f (elt) elt)
+(declare-fun Rf (elt elt elt) Bool)
+
+;; reflexive
+;;(assert-propagation ((?x elt)) () () (Rf ?x ?x ?x) ((?x)) )
+;; step
+(assert-propagation ((?x elt)) () () (Rf ?x (f ?x) (f ?x)) (((f ?x))) )
+;; (assert-propagation ((?x elt)) () () (Rf ?x (f ?x) (f ?x)) (((Rf ?x (f ?x) (f ?x)))) )
+;; (assert-propagation ((?x elt)) () () (=> true (Rf ?x (f ?x) (f ?x))) (((f ?x))) )
+
+;; reach
+(assert-propagation ((?x1 elt)(?x2 elt)) () ((Rf ?x1 ?x2 ?x2)) (or (= ?x1 ?x2) (Rf ?x1 (f ?x1) ?x2)) (((f ?x1))) )
+;; ;; reach extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)) ((not (= ?x1 ?x2))(Rf ?x1 ?x2 ?x2)) () (Rf ?x1 (f ?x1) ?x2) (((Rf ?x1 (f ?x1) ?x2))) )
+;; ;; reach extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)) ((not (Rf ?x1 (f ?x1) ?x2))(Rf ?x1 ?x2 ?x2)) () (= ?x1 ?x2) (((Rf ?x1 (f ?x1) ?x2))) )
+
+;; cycle
+(assert-propagation ((?x1 elt)(?x2 elt)) ((= (f ?x1) ?x1)) ((Rf ?x1 ?x2 ?x2)) (= ?x1 ?x2) (((f ?x1))) )
+;; (assert-propagation ((?x1 elt)(?x2 elt)) ((= (f ?x1) ?x1)) ((Rf ?x1 ?x2 ?x2)) (= ?x1 ?x2) () )
+
+;; (assert-propagation ((?x1 elt)(?x2 elt)) () () (=> (and (= (f ?x1) ?x1) (Rf ?x1 ?x2 ?x2)) (= ?x1 ?x2)) (((Rf ?x1 ?x2 ?x2)(f ?x1))) )
+
+;; sandwich
+(assert-propagation ((?x1 elt)(?x2 elt)) () ((Rf ?x1 ?x2 ?x1)) (= ?x1 ?x2) () )
+;; (assert-propagation ((?x1 elt)(?x2 elt)) () () (=> (Rf ?x1 ?x2 ?x1) (= ?x1 ?x2)) (((Rf ?x1 ?x2 ?x1))) )
+
+;; order1
+(assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) ()
+                    ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)) (or (Rf ?x1 ?x2 ?x3) (Rf ?x1 ?x3 ?x2)) () )
+
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) () ()
+;;                     (=> (and (Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)) (or (Rf ?x1 ?x2 ?x3) (Rf ?x1 ?x3 ?x2))) (((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3))) )
+
+;; ;; order1 extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)(not (Rf ?x1 ?x3 ?x2))) ()
+;;                     (Rf ?x1 ?x2 ?x3) (((Rf ?x1 ?x2 ?x3))) )
+;; ;; order1 extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)(not (Rf ?x1 ?x2 ?x3))) ()
+;;                     (Rf ?x1 ?x3 ?x2) (((Rf ?x1 ?x3 ?x2))) )
+;; ;; order1 extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)(not (Rf ?x1 ?x3 ?x2))) ()
+;;                     (Rf ?x1 ?x2 ?x3) (((Rf ?x1 ?x3 ?x2))) )
+;; ;; order1 extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)(not (Rf ?x1 ?x2 ?x3))) ()
+;;                     (Rf ?x1 ?x3 ?x2) (((Rf ?x1 ?x2 ?x3))) )
+;; ;; order1 extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)(not (Rf ?x1 ?x3 ?x2))) ()
+;;                     (Rf ?x1 ?x2 ?x3) (((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3))) )
+;; ;; order1 extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) ((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3)(not (Rf ?x1 ?x2 ?x3))) ()
+;;                     (Rf ?x1 ?x3 ?x2) (((Rf ?x1 ?x2 ?x2)(Rf ?x1 ?x3 ?x3))) )
+
+;; order2
+(assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x1 ?x2 ?x3))
+                    (and (Rf ?x1 ?x2 ?x2) (Rf ?x2 ?x3 ?x3)) () )
+;; transitive1
+(assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x1 ?x2 ?x2)(Rf ?x2 ?x3 ?x3))
+                    (Rf ?x1 ?x3 ?x3) () )
+;; ;; transitive1 extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) () ((not (Rf ?x1 ?x3 ?x3))(Rf ?x2 ?x3 ?x3))
+;;                     (not (Rf ?x1 ?x2 ?x2)) () )
+;; ;; transitive1 extended
+;; (assert-propagation ((?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x1 ?x2 ?x2)(not (Rf ?x1 ?x3 ?x3)))
+;;                     (not (Rf ?x2 ?x3 ?x3)) () )
+
+;;transitive2
+(assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x0 ?x1 ?x2)(Rf ?x1 ?x3 ?x2))
+                    (and (Rf ?x0 ?x1 ?x3) (Rf ?x0 ?x3 ?x2)) () )
+
+;; (assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ()
+;;                     (=> (and (Rf ?x0 ?x1 ?x2)(Rf ?x1 ?x3 ?x2))
+;;                         (and (Rf ?x0 ?x1 ?x3) (Rf ?x0 ?x3 ?x2)))
+;;                     (((Rf ?x0 ?x1 ?x2)(Rf ?x1 ?x3 ?x2))) )
+
+;; ;; transitive2 extended
+;; (assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ((not (Rf ?x0 ?x1 ?x3))(Rf ?x1 ?x3 ?x2))
+;;                     (not (Rf ?x0 ?x1 ?x2)) (((Rf ?x0 ?x1 ?x2))) )
+;; ;; transitive2 extended
+;; (assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x0 ?x1 ?x2)(not (Rf ?x0 ?x1 ?x3)))
+;;                     (not (Rf ?x1 ?x3 ?x2)) (((Rf ?x1 ?x3 ?x2))) )
+;; ;; transitive2 extended
+;; (assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ((not (Rf ?x0 ?x3 ?x2))(Rf ?x1 ?x3 ?x2))
+;;                     (not (Rf ?x0 ?x1 ?x2)) (((Rf ?x0 ?x1 ?x2))) )
+;; ;; transitive2 extended
+;; (assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x0 ?x1 ?x2)(not (Rf ?x0 ?x3 ?x2)))
+;;                     (not (Rf ?x1 ?x3 ?x2)) (((Rf ?x1 ?x3 ?x2))) )
+
+;; ;;transitive3
+(assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ((Rf ?x0 ?x1 ?x2)(Rf ?x0 ?x3 ?x1))
+                    (and (Rf ?x0 ?x3 ?x2) (Rf ?x3 ?x1 ?x2)) () )
+
+;; (assert-propagation ((?x0 elt)(?x1 elt)(?x2 elt)(?x3 elt)) () ()
+;;                     (=> (and (Rf ?x0 ?x1 ?x2)(Rf ?x0 ?x3 ?x1))
+;;                         (and (Rf ?x0 ?x3 ?x2) (Rf ?x3 ?x1 ?x2))) (((Rf ?x0 ?x1 ?x2)(Rf ?x0 ?x3 ?x1))) )
+
+
+(declare-fun e1 () elt)
+(declare-fun e2 () elt)
+(declare-fun e3 () elt)
+(declare-fun e4 () elt)
+
+
+;;Example0
+;;(assert (not (=> (and (not (= e1 e2)) (Rf e1 e2 e3)) (Rf e1 (f e1) e3))) )
+
+;;Thomas' example1 x,e1 y,e2 z,e3 y',e4
+;;(assert (not (=> (and (Rf e1 e2 e3) (not (= e2 e3)) (= e4 (f e2))) (Rf e1 e4 e3))))
+
+(declare-fun Rf_avoid (elt elt elt) Bool)
+
+;; (assert-rewrite ((?x0 elt)(?x1 elt)(?exc elt)) () (Rf_avoid ?x0 ?x1 ?exc)
+;;                  (or (Rf ?x0 ?x1 ?exc) (and (Rf ?x0 ?x1 ?x1) (not (Rf ?x0 ?exc ?exc)))) () )
+
+(declare-fun null () elt)
+(assert (= (f null) null))
+
+(declare-fun join (elt elt) elt)
+
+;; (assert-propagation ((?x elt)(?y elt)(?z elt)) () ((Rf ?x ?z ?z)(Rf ?y ?z ?z)) (Rf ?x (join ?x ?y) ?z) (((join ?x ?y))) )
+;; (assert-propagation ((?x elt)(?y elt)) () () (or (and (Rf ?x (join ?x ?y) (join ?x ?y)) (Rf ?y (join ?x ?y) (join ?x ?y))) (= (join ?x ?y) null))  (((join ?x ?y))) )
+
+;;Thomas' example2
+;; (assert (not (=> (and (Rf e1 null null) (= (join e1 e2) null)
+;; ;; (next' == upd(next, e, e1)
+;; )
+;; ;; (reach(next', e1, null) )
+;; (or (and (Rf e1 null null) (Rf_avoid e1 null e2) )
+;;     (and (not (= e2 null)) (Rf_avoid e1 e2 null) (Rf e1 null e2) (Rf_avoid e1 null e2) )
+;;     (and (not (= e2 null)) (Rf_avoid e1 e2 null) (Rf e1 null null) (Rf_avoid e1 null e2) ) )
+;; )))
+
+
+;;Thomas' example3
+;; join(next, first, e) == null &&
+;; reach(next, e, null) &&
+;; e != null &&
+;; next' == upd(next, e, first) &&
+;; first' == e &&
+;; e' == sel (next, e)
+;; ==>
+;; join(next', first', e') == null 
+
+
+;;Thomas' example3
+(assert(not
+        (=>
+         (and
+          ;; (= (join e1 e2) null)
+          (Rf e2 null null)
+          (not (= e2 null)))
+         ;; (next' == upd(next, e2, e1)
+         ;;join(next',e1,e2) == null
+(or (and (not (Rf (f e2) e2 e2)) (not (Rf e1 e2 e2) ))
+;;    (and (Rf (f e2) e2 e2) (not (Rf e1 e1 e1) ))
+    (and (Rf e1 e2 e2) (not (Rf (f e2) e1 e1)) )
+)
+;; (or
+;;  (and (not (Rf e1 e2 e2)) (not (Rf e2 e2 e2)))
+;;  (and (Rf e1 e2 e2) (not (Rf e2 e1 e1)))
+;;  (and (Rf e2 e2 e2) (not (Rf e1 e1 e1)))
+;; )
+)))
+
+
+
+;; ;;Thomas' example wrong sat?
+;; (assert (not (=> (and
+;;                   (= (join e1 e2) null)
+;;                   (Rf e2 null null) (not (= e2 null)))
+;; ;; (next' == upd(next, e2, e1)
+;; ;;join(next',e1,e2) == null
+;; (not (Rf e2 e2 e2))
+;; ;; (or
+;; ;;  (and (not (Rf e1 e2 e2)) (not (Rf e2 e2 e2)))
+;; ;;  (and (Rf e1 e2 e2) (not (Rf e2 e1 e1)))
+;; ;;  (and (Rf e2 e2 e2) (not (Rf e1 e1 e1)))
+;; ;; )
+;; )))
+
+;; ;;example4
+;; (assert (not (=> (and
+;;                   (= (join e1 e2) null)
+;;                   (Rf e2 null null) (not (= e2 null))
+;;                   )
+;; (not (Rf e2 e2 e2))
+;; )))
+
+
+;; ;;example5
+;; (assert (and
+;;          ;; (= (join e1 e2) null)
+;;          (= (f (f e1)) e1)
+;;          (Rf e1 e2 e2)
+;;          (not (= e2 e1))
+;;          (not (= e2 (f e1)))
+;;          )
+;; )
+
+
+
+
+(check-sat)
+(exit)
+
diff --git a/test/regress/regress0/rewriterules/relation.smt2 b/test/regress/regress0/rewriterules/relation.smt2
new file mode 100644 (file)
index 0000000..a327a90
--- /dev/null
@@ -0,0 +1,27 @@
+(set-logic AUFLIA)
+(set-info :status unsat)
+
+;; don't use a datatypes for currently focusing in uf
+(declare-sort elt 0)
+
+(declare-fun R (elt elt) Bool)
+
+;; reflexive
+(assert-rewrite ((x elt)) () (R x x) true ())
+
+;; transitive
+(assert-propagation ((x elt) (y elt) (z elt)) () ((R x y) (R y z)) (R x z) ())
+
+;; anti-symmetric
+(assert-propagation ((x elt) (y elt)) () ((R x y) (R y x)) (= x y) ())
+
+(declare-fun e1 () elt)
+(declare-fun e2 () elt)
+(declare-fun e3 () elt)
+(declare-fun e4 () elt)
+
+(assert (not (=> (and (R e1 e2) (R e2 e3) (R e3 e4) (R e4 e1)) (= e1 e4))))
+
+(check-sat)
+
+(exit)
\ No newline at end of file
index 65dc23a10b82146491c74a04972b8144194fc752..1b397ef5b40eb916f9e8920c592548e76bfc4b43 100644 (file)
 ;; inter
 
 (declare-fun inter (set set)  set)
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (=> (in ?s (inter ?t1 ?t2)) (and (in ?s ?t1) (in ?s ?t2))) :rewrite-rule)))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set)) ()
+                  ((in ?s (inter ?t1 ?t2))) (and (in ?s ?t1) (in ?s ?t2)) ())
 
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (! (=> (not (in ?s ?t1)) (not (in ?s (inter ?t1 ?t2)))) :pattern ((inter ?t1 ?t2)) ) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s ?t1))) (not (in ?s (inter ?t1 ?t2))) (((inter ?t1 ?t2))) )
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (! (=> (not (in ?s ?t2)) (not (in ?s (inter ?t1 ?t2)))) :pattern ((inter ?t1 ?t2)) ) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s ?t2))) (not (in ?s (inter ?t1 ?t2))) (((inter ?t1 ?t2))) )
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (=> (and (not (in ?s (inter ?t1 ?t2)))  (in ?s ?t1)) (not (in ?s ?t2))) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s (inter ?t1 ?t2))) (in ?s ?t1)) (not (in ?s ?t2)) () )
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (=> (and (not (in ?s (inter ?t1 ?t2)))  (in ?s ?t2)) (not (in ?s ?t1))) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s (inter ?t1 ?t2))) (in ?s ?t2)) (not (in ?s ?t1)) ())
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (! (=> (and (in ?s ?t1)  (in ?s ?t2)) (in ?s (inter ?t1 ?t2))) :pattern ((inter ?t1 ?t2)) ) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s ?t1) (in ?s ?t2)) (in ?s (inter ?t1 ?t2)) (((inter ?t1 ?t2))) )
 
 ;;;;;;;;;;;;;;;;;
 ;; union
 
 (declare-fun union (set set)  set)
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (=> (not (in ?s (union ?t1 ?t2))) (and (not (in ?s ?t1)) (not (in ?s ?t2)))) :rewrite-rule)))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s (union ?t1 ?t2)))) (and (not (in ?s ?t1)) (not (in ?s ?t2))) ())
 
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s ?t1)) (in ?s (union ?t1 ?t2)) (((union ?t1 ?t2))))
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (! (=> (in ?s ?t1) (in ?s (union ?t1 ?t2))) :pattern ((union ?t1 ?t2)) ) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s ?t2)) (in ?s (union ?t1 ?t2)) (((union ?t1 ?t2))))
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (! (=> (in ?s ?t2) (in ?s (union ?t1 ?t2))) :pattern ((union ?t1 ?t2)) ) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s (union ?t1 ?t2)) (not (in ?s ?t1))) (in ?s ?t2) ())
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (=> (and (in ?s (union ?t1 ?t2))  (not (in ?s ?t1))) (in ?s ?t2)) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s (union ?t1 ?t2)) (not (in ?s ?t2))) (in ?s ?t1) ())
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (=> (and (in ?s (union ?t1 ?t2))  (not (in ?s ?t2))) (in ?s ?t1)) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s ?t1)) (not (in ?s ?t2))) (not (in ?s (union ?t1 ?t2))) (((union ?t1 ?t2))))
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (! (=> (and (not (in ?s ?t1))  (not (in ?s ?t2))) (not (in ?s (union ?t1 ?t2)))) :pattern ((union ?t1 ?t2)) ) :rewrite-rule) ))
+;;;;;;;;;;;;;;;;;;;;
+;; diff
+
+(declare-fun diff (set set)  set)
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s (diff ?t1 ?t2))) (and (in ?s ?t1) (not (in ?s ?t2))) ())
+
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s ?t1))) (not (in ?s (diff ?t1 ?t2))) (((diff ?t1 ?t2))) )
+
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s ?t2)) (not (in ?s (diff ?t1 ?t2))) (((diff ?t1 ?t2))))
+
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s (diff ?t1 ?t2))) (in ?s ?t1)) (in ?s ?t2) ())
+
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s (diff ?t1 ?t2))) (not (in ?s ?t2))) (not (in ?s ?t1)) ())
+
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s ?t1) (not (in ?s ?t2))) (in ?s (diff ?t1 ?t2)) (((diff ?t1 ?t2))) )
 
 ;;;;;;;;;;;;;;;;
 ;;sing
 
 (declare-fun sing (elt)  set)
-(assert (forall ((?s elt))
-                (! (! (=> true (in ?s (sing ?s))) :pattern ((sing ?s)) ) :rewrite-rule) ))
-
-(assert (forall ((?s elt) (?t1 elt))
-                (! (=> true (=> (in ?s (sing ?t1)) (= ?s ?t1))) :rewrite-rule) ))
-
-(assert (forall ((?s elt) (?t1 elt))
-                (! (=> (not (in ?s (sing ?t1))) (not (= ?s ?t1))) :rewrite-rule) ))
+(assert-propagation ((?s elt))
+                  () () (in ?s (sing ?s)) (((sing ?s))) )
 
+(assert-propagation ((?s elt) (?t1 elt))
+                  () ((in ?s (sing ?t1))) (= ?s ?t1) ())
 
+(assert-propagation ((?s elt) (?t1 elt))
+                  () ((not (in ?s (sing ?t1)))) (not (= ?s ?t1)) ())
 
 ;;;;;;;;;;;;;;;;;;;
-;; fullfiling
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (=> (in ?s (union ?t1 ?t2)) (or (in ?s ?t1) (not (in ?s ?t1)))) :rewrite-rule)))
+;; fullfiling runned at Full effort
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s (union ?t1 ?t2))) (or (in ?s ?t1) (not (in ?s ?t1))) ())
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (! (=> (in ?s ?t1) (or (in ?s ?t2) (not (in ?s ?t2)))) :pattern ((inter ?t1 ?t2))) :rewrite-rule)))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s ?t1)) (or (in ?s ?t2) (not (in ?s ?t2))) (((inter ?t1 ?t2))))
 
-(assert (forall ((?t1 set) (?t2 set)) (! (=> (not (= ?t1 ?t2)) (exists ((?e elt)) (or (and (in ?e ?t1) (not (in ?e ?t2))) (and (not (in ?e ?t1)) (in ?e ?t2))))) :rewrite-rule)))
+(assert-propagation ((?t1 set) (?t2 set))
+                  () ((not (= ?t1 ?t2))) (exists ((?e elt)) (or (and (in ?e ?t1) (not (in ?e ?t2))) (and (not (in ?e ?t1)) (in ?e ?t2)))) ())
+
+;;;;;;;;;;;;;;;;;;;
+;; shortcut
+(declare-fun subset (set set) Bool)
+(assert-reduction ((?t1 set) (?t2 set))
+                () ((subset ?t1 ?t2)) (= (union ?t1 ?t2) ?t2) ())
 
 (declare-fun e () elt)
 (declare-fun t1 () set)
index 07e9f96434329305026ce8d0166220b4ef189312..55050ac1a44d734bb22cfa04d880fa48d230344f 100644 (file)
 
 (declare-fun in (elt set) Bool)
 
+
 ;;;;;;;;;;;;;;;;;;;;
 ;; inter
 
 (declare-fun inter (set set)  set)
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (=> (in ?s (inter ?t1 ?t2)) (and (in ?s ?t1) (in ?s ?t2))) :rewrite-rule)))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set)) ()
+                  ((in ?s (inter ?t1 ?t2))) (and (in ?s ?t1) (in ?s ?t2)) ())
 
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (! (=> (not (in ?s ?t1)) (not (in ?s (inter ?t1 ?t2)))) :pattern ((inter ?t1 ?t2)) ) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s ?t1))) (not (in ?s (inter ?t1 ?t2))) (((inter ?t1 ?t2))) )
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (! (=> (not (in ?s ?t2)) (not (in ?s (inter ?t1 ?t2)))) :pattern ((inter ?t1 ?t2)) ) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s ?t2))) (not (in ?s (inter ?t1 ?t2))) (((inter ?t1 ?t2))) )
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (=> (and (not (in ?s (inter ?t1 ?t2)))  (in ?s ?t1)) (not (in ?s ?t2))) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s (inter ?t1 ?t2))) (in ?s ?t1)) (not (in ?s ?t2)) () )
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (=> (and (not (in ?s (inter ?t1 ?t2)))  (in ?s ?t2)) (not (in ?s ?t1))) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s (inter ?t1 ?t2))) (in ?s ?t2)) (not (in ?s ?t1)) ())
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (! (=> (and (in ?s ?t1)  (in ?s ?t2)) (in ?s (inter ?t1 ?t2))) :pattern ((inter ?t1 ?t2)) ) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s ?t1) (in ?s ?t2)) (in ?s (inter ?t1 ?t2)) (((inter ?t1 ?t2))) )
 
 ;;;;;;;;;;;;;;;;;
 ;; union
 
 (declare-fun union (set set)  set)
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (=> (not (in ?s (union ?t1 ?t2))) (and (not (in ?s ?t1)) (not (in ?s ?t2)))) :rewrite-rule)))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s (union ?t1 ?t2)))) (and (not (in ?s ?t1)) (not (in ?s ?t2))) ())
+
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s ?t1)) (in ?s (union ?t1 ?t2)) (((union ?t1 ?t2))))
+
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s ?t2)) (in ?s (union ?t1 ?t2)) (((union ?t1 ?t2))))
+
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s (union ?t1 ?t2)) (not (in ?s ?t1))) (in ?s ?t2) ())
+
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s (union ?t1 ?t2)) (not (in ?s ?t2))) (in ?s ?t1) ())
+
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s ?t1)) (not (in ?s ?t2))) (not (in ?s (union ?t1 ?t2))) (((union ?t1 ?t2))))
 
+;;;;;;;;;;;;;;;;;;;;
+;; diff
+
+(declare-fun diff (set set)  set)
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s (diff ?t1 ?t2))) (and (in ?s ?t1) (not (in ?s ?t2))) ())
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (! (=> (in ?s ?t1) (in ?s (union ?t1 ?t2))) :pattern ((union ?t1 ?t2)) ) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s ?t1))) (not (in ?s (diff ?t1 ?t2))) (((diff ?t1 ?t2))) )
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (! (=> (in ?s ?t2) (in ?s (union ?t1 ?t2))) :pattern ((union ?t1 ?t2)) ) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s ?t2)) (not (in ?s (diff ?t1 ?t2))) (((diff ?t1 ?t2))))
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (=> (and (in ?s (union ?t1 ?t2))  (not (in ?s ?t1))) (in ?s ?t2)) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s (diff ?t1 ?t2))) (in ?s ?t1)) (in ?s ?t2) ())
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (=> (and (in ?s (union ?t1 ?t2))  (not (in ?s ?t2))) (in ?s ?t1)) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((not (in ?s (diff ?t1 ?t2))) (not (in ?s ?t2))) (not (in ?s ?t1)) ())
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (! (=> (and (not (in ?s ?t1))  (not (in ?s ?t2))) (not (in ?s (union ?t1 ?t2)))) :pattern ((union ?t1 ?t2)) ) :rewrite-rule) ))
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s ?t1) (not (in ?s ?t2))) (in ?s (diff ?t1 ?t2)) (((diff ?t1 ?t2))) )
 
 ;;;;;;;;;;;;;;;;
 ;;sing
 
 (declare-fun sing (elt)  set)
-(assert (forall ((?s elt))
-                (! (! (=> true (in ?s (sing ?s))) :pattern ((sing ?s)) ) :rewrite-rule) ))
-
-(assert (forall ((?s elt) (?t1 elt))
-                (! (=> true (=> (in ?s (sing ?t1)) (= ?s ?t1))) :rewrite-rule) ))
-
-(assert (forall ((?s elt) (?t1 elt))
-                (! (=> (not (in ?s (sing ?t1))) (not (= ?s ?t1))) :rewrite-rule) ))
+(assert-propagation ((?s elt))
+                  () () (in ?s (sing ?s)) (((sing ?s))) )
 
+(assert-propagation ((?s elt) (?t1 elt))
+                  () ((in ?s (sing ?t1))) (= ?s ?t1) ())
 
+(assert-propagation ((?s elt) (?t1 elt))
+                  () ((not (in ?s (sing ?t1)))) (not (= ?s ?t1)) ())
 
 ;;;;;;;;;;;;;;;;;;;
-;; fullfiling
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (=> (in ?s (union ?t1 ?t2)) (or (in ?s ?t1) (not (in ?s ?t1)))) :rewrite-rule)))
+;; fullfiling runned at Full effort
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s (union ?t1 ?t2))) (or (in ?s ?t1) (not (in ?s ?t1))) ())
+
+(assert-propagation ((?s elt) (?t1 set) (?t2 set))
+                  () ((in ?s ?t1)) (or (in ?s ?t2) (not (in ?s ?t2))) (((inter ?t1 ?t2))))
 
-(assert (forall ((?s elt) (?t1 set) (?t2 set))
-                (! (! (=> (in ?s ?t1) (or (in ?s ?t2) (not (in ?s ?t2)))) :pattern ((inter ?t1 ?t2))) :rewrite-rule)))
+(assert-propagation ((?t1 set) (?t2 set))
+                  () ((not (= ?t1 ?t2))) (exists ((?e elt)) (or (and (in ?e ?t1) (not (in ?e ?t2))) (and (not (in ?e ?t1)) (in ?e ?t2)))) ())
 
-;; (assert (forall ((?t1 set) (?t2 set)) (! (=> (not (= ?t1 ?t2)) (exists ((?e elt)) (or (and (in ?e ?t1) (not (in ?e ?t2))) (and (not (in ?e ?t1)) (in ?e ?t2))))) )))
+;;;;;;;;;;;;;;;;;;;
+;; shortcut
+(declare-fun subset (set set) Bool)
+(assert-reduction ((?t1 set) (?t2 set))
+                () ((subset ?t1 ?t2)) (= (union ?t1 ?t2) ?t2) ())
 
 (declare-fun e () elt)
 (declare-fun t1 () set)
diff --git a/test/regress/regress0/rewriterules/simulate_rewritting.smt2 b/test/regress/regress0/rewriterules/simulate_rewritting.smt2
new file mode 100644 (file)
index 0000000..d1d88a5
--- /dev/null
@@ -0,0 +1,24 @@
+;; A new fast tableau-base ... Domenico Cantone et Calogero G.Zarba
+(set-logic AUFLIA)
+(set-info :status sat)
+
+(declare-sort elt1 0)
+(declare-sort elt2 0)
+
+(declare-fun g (elt2) Bool)
+
+(declare-fun p (elt1 elt1) Bool)
+(declare-fun f (elt2) elt1)
+(declare-fun c1 () elt1)
+(declare-fun c2 () elt1)
+
+(assert (forall ((?e elt2)) (! (=> (g ?e) (= (f ?e) c2)) :rewrite-rule)))
+(assert (forall ((?e elt2)) (! (=> (g ?e) (= (f ?e) c1)) :rewrite-rule)))
+
+(declare-fun e () elt2)
+
+(assert (not (=> (g e) (=> (p c1 c2) (p (f e) (f e)))) ))
+
+(check-sat)
+
+(exit)
diff --git a/test/regress/regress0/rewriterules/test_efficient_ematching.smt2 b/test/regress/regress0/rewriterules/test_efficient_ematching.smt2
new file mode 100644 (file)
index 0000000..e91ef36
--- /dev/null
@@ -0,0 +1,35 @@
+(set-logic AUFLIA)
+(set-info :status unsat)
+
+;; don't use a datatypes for currently focusing in uf
+(declare-sort elt 0)
+
+(declare-fun R (elt elt) Bool)
+
+;; reflexive
+(assert-rewrite ((x elt)) () (R x x) true ())
+
+;; transitive
+(assert-propagation ((x elt) (y elt) (z elt)) () ((R x y) (R y z)) (R x z) ())
+
+;; anti-symmetric
+(assert-propagation ((x elt) (y elt)) () ((R x y) (R y x)) (= x y) ())
+
+(declare-fun f (elt) elt)
+(assert-propagation ((x elt)(y elt)) () ((R (f x) (f y))) (R x y) ())
+
+
+(declare-fun e1 () elt)
+(declare-fun e2 () elt)
+(declare-fun e3 () elt)
+(declare-fun e4 () elt)
+(declare-fun e5 () elt)
+
+(assert (not (=> (and (R e1 e2) (R e3 (f e4)) (R e4 e5)
+                      (or (and (= e3 (f e2)) (= e4 e1))
+                          (and (= e4 e2) (= e5 e1)) )
+        ) (= e1 e2))))
+
+(check-sat)
+
+(exit)
\ No newline at end of file