Compute term indices lazily in TermDb. Optimization for qcf to recognize irrelevant...
authorajreynol <andrew.j.reynolds@gmail.com>
Thu, 5 May 2016 23:44:47 +0000 (18:44 -0500)
committerajreynol <andrew.j.reynolds@gmail.com>
Thu, 5 May 2016 23:44:56 +0000 (18:44 -0500)
24 files changed:
proofs/lfsc_checker/check.cpp
proofs/lfsc_checker/expr.cpp
proofs/lfsc_checker/expr.h
proofs/lfsc_checker/main.cpp
proofs/signatures/th_bv_bitblast.plf
src/options/options_handler.cpp
src/options/quantifiers_modes.cpp
src/options/quantifiers_modes.h
src/options/quantifiers_options
src/parser/smt2/Smt2.g
src/parser/smt2/smt2.cpp
src/theory/quantifiers/conjecture_generator.cpp
src/theory/quantifiers/inst_propagator.cpp
src/theory/quantifiers/inst_propagator.h
src/theory/quantifiers/inst_strategy_e_matching.cpp
src/theory/quantifiers/quant_conflict_find.cpp
src/theory/quantifiers/quant_conflict_find.h
src/theory/quantifiers/quantifiers_rewriter.cpp
src/theory/quantifiers/term_database.cpp
src/theory/quantifiers/term_database.h
src/theory/quantifiers_engine.cpp
src/theory/quantifiers_engine.h
test/regress/regress0/sygus/Makefile.am
test/regress/regress0/sygus/strings-small.sy [new file with mode: 0644]

index c96791aeb8c4cd9237ec5cb85b0b21929c4ba963..22e326cdae86a89f9ff4a8d685dfda61b31831d8 100644 (file)
@@ -24,7 +24,7 @@ int colnum = 1;
 const char *filename = 0;
 FILE *curfile = 0;
 
-//#define USE_HASH_MAPS
+//#define USE_HASH_MAPS  //AJR: deprecated
 
 symmap2 progs;
 std::vector< Expr* > ascHoles;
index ae0e495314a9aff21c2e7ed2f25738dab3898b0f..5cb774fbf0fa3d01c70adc8c84ba5c6f58ac6907 100644 (file)
@@ -34,7 +34,6 @@ bool destroy_progs = false;
     Expr *r = rr;          \
     int ref = r->data >> 9; \
     ref = ref - 1; \
-    r->debugrefcnt(ref,DEC); \
     if (ref == 0) {  \
       _e = r;            \
       goto start_destroy; \
@@ -43,6 +42,7 @@ bool destroy_progs = false;
       r->data = (ref << 9) | (r->data & 511); \
   } while(0)
 
+//removed from below "ref = ref -1;":   r->debugrefcnt(ref,DEC);
 
 void Expr::destroy(Expr *_e, bool dec_kids) {
  start_destroy:
index 32a62ab3310b8e9e8758785c28d93e50114ae30e..5a505a3d99c3626a8ceb6c018082e6e1c18036de 100644 (file)
@@ -8,9 +8,9 @@
 #include <map>
 #include "chunking_memory_management.h"
 
-#define USE_FLAT_APP
+#define USE_FLAT_APP  //AJR: off deprecated
 #define MARKVAR_32
-#define DEBUG_SYM_NAMES
+//#define DEBUG_SYM_NAMES
 //#define DEBUG_SYMS
 
 // Expr class
@@ -66,7 +66,6 @@ protected:
 
   enum { INC, DEC, CREATE };
   void debugrefcnt(int ref, int what) {
-#ifdef DEBUG_REFCNT
     std::cout << "[";
     debug();
     switch(what) {
@@ -83,10 +82,6 @@ protected:
     char tmp[10];
     sprintf(tmp,"%d",ref);
     std::cout << tmp << "]\n";
-#else
-    (void)ref;
-    (void)what;
-#endif
   }
 
   Expr(int _class, int _op)
@@ -114,14 +109,18 @@ public:
     //   std::cout << " " << ref << std::endl;
     //}
     ref = ref<4194303 ? ref + 1 : ref;
+#ifdef DEBUG_REFCNT    
     debugrefcnt(ref,INC);
+#endif
     data = (ref << 9) | (data & 511);
   }
   static void destroy(Expr *, bool);
   inline void dec(bool dec_kids = true) {
     int ref = getrefcnt();
     ref = ref - 1;
+#ifdef DEBUG_REFCNT    
     debugrefcnt(ref,DEC);
+#endif
     if (ref == 0)
       destroy(this,dec_kids);
     else
@@ -131,10 +130,10 @@ public:
   //must pass statType (the expr representing "type") to this function
   bool isType( Expr* statType );
 
-  inline bool isDatatype() {
+  inline bool isDatatype() const {
     return getclass() == SYMS_EXPR || getop() == MPZ || getop() == MPQ;
   }
-  inline bool isArithTerm() {
+  inline bool isArithTerm() const {
     return getop() == ADD || getop() == NEG;
   }
 
@@ -188,13 +187,17 @@ public:
   CExpr(int _op) : Expr(CEXPR, _op), kids() {
     kids = new Expr *[1];
     kids[0] = 0;
+#ifdef DEBUG_REFCNT    
     debugrefcnt(1,CREATE);
+#endif
   }
   CExpr(int _op, Expr *e1) : Expr(CEXPR, _op), kids() {
     kids = new Expr *[2];
     kids[0] = e1;
     kids[1] = 0;
+#ifdef DEBUG_REFCNT    
     debugrefcnt(1,CREATE);
+#endif
   }
   CExpr(int _op, Expr *e1, Expr *e2)
     : Expr(CEXPR, _op), kids() {
@@ -202,7 +205,9 @@ public:
     kids[0] = e1;
     kids[1] = e2;
     kids[2] = 0;
+#ifdef DEBUG_REFCNT    
     debugrefcnt(1,CREATE);
+#endif
   }
   CExpr(int _op, Expr *e1, Expr *e2, Expr *e3)
     : Expr(CEXPR, _op), kids() {
@@ -211,7 +216,9 @@ public:
     kids[1] = e2;
     kids[2] = e3;
     kids[3] = 0;
+#ifdef DEBUG_REFCNT    
     debugrefcnt(1,CREATE);
+#endif
   }
   CExpr(int _op, Expr *e1, Expr *e2, Expr *e3, Expr *e4)
     : Expr(CEXPR, _op), kids() {
@@ -221,7 +228,9 @@ public:
     kids[2] = e3;
     kids[3] = e4;
     kids[4] = 0;
+#ifdef DEBUG_REFCNT    
     debugrefcnt(1,CREATE);
+#endif
   }
   CExpr(int _op, const std::vector<Expr *> &_kids) 
     : Expr(CEXPR, _op), kids() {
@@ -230,13 +239,17 @@ public:
     for (i = 0; i < iend; i++)
       kids[i] = _kids[i];
     kids[i] = 0;
+#ifdef DEBUG_REFCNT    
     debugrefcnt(1,CREATE);
+#endif
   }
 
   // _kids must be null-terminated.
   CExpr(int _op, bool dummy, Expr **_kids) : Expr(CEXPR, _op), kids(_kids) {
     (void)dummy;
+#ifdef DEBUG_REFCNT    
     debugrefcnt(1,CREATE);
+#endif
   }
 
   Expr *whr();
@@ -253,7 +266,9 @@ class IntExpr : public Expr {
   }
   IntExpr(mpz_t _n) : Expr(INT_EXPR, 0), n() {
     mpz_init_set(n,_n);
+#ifdef DEBUG_REFCNT    
     debugrefcnt(1,CREATE);
+#endif
   }
   IntExpr(signed long int _n ) : Expr(INT_EXPR, 0), n() {
     mpz_init_set_si( n, _n );
@@ -271,7 +286,9 @@ class RatExpr : public Expr {
   RatExpr(mpq_t _n) : Expr(RAT_EXPR, 0), n() {
     mpq_init( n );
     mpq_set(n,_n);
+#ifdef DEBUG_REFCNT   
     debugrefcnt(1,CREATE);
+#endif
     mpq_canonicalize( n );
   }
   RatExpr(signed long int _n1, unsigned long int _n2 ) : Expr(RAT_EXPR, 0), n() {
@@ -290,15 +307,19 @@ class SymExpr : public Expr {
     : Expr(theclass, 0), val(0)
   {   
     (void)_s;
+#ifdef DEBUG_REFCNT   
     if (theclass == SYM_EXPR)
       debugrefcnt(1,CREATE);
+#endif
   }
   SymExpr(const SymExpr &e, int theclass = SYM_EXPR) 
     : Expr(theclass, 0), val(0)
   {
     (void)e;
+#ifdef DEBUG_REFCNT   
     if (theclass == SYM_EXPR)
       debugrefcnt(1,CREATE);
+#endif
   }
 #ifdef MARKVAR_32
 private:
@@ -317,12 +338,16 @@ class SymSExpr : public SymExpr {
   SymSExpr(std::string _s, int theclass = SYMS_EXPR) 
     : SymExpr(_s, theclass), s(_s)
   {
+#ifdef DEBUG_REFCNT   
     debugrefcnt(1,CREATE);
+#endif
   }
   SymSExpr(const SymSExpr &e, int theclass = SYMS_EXPR) 
     : SymExpr(e, theclass), s(e.s)
   { 
+#ifdef DEBUG_REFCNT   
     debugrefcnt(1,CREATE);
+#endif
   }
 };
 
@@ -338,7 +363,9 @@ public:
 #ifdef DEBUG_HOLE_NAMES
     id = next_id++;
 #endif
+#ifdef DEBUG_REFCNT   
     debugrefcnt(1,CREATE);
+#endif
   }
   Expr *val; // may be set during subst(), defeq(), and clone().
 };
index 80f36e69fbff290e88225d7477fe55d670bc1c58..1d8ba58095dac75fa4b0b96e2d7ea0724d09319c 100644 (file)
@@ -133,6 +133,7 @@ int main(int argc, char **argv) {
   a.files.clear();
 #endif
 
+  std::cout << "Proof checked successfully!" << std::endl << std::endl;
   std::cout << "time = " << (int)clock() - check_time << std::endl;
   std::cout << "sym count = " << SymExpr::symmCount << std::endl;
   std::cout << "marked count = " << Expr::markedCount << std::endl;
index 8e8c518575800d4bb5a8b58847addc35dc097868..580b54418599e518b9fd891ac1319653cd65e78a 100644 (file)
                   (bbltn (fail bblt))
                   ((bbltc bi b') (bbltc (xor (xor ai bi) (bblast_bvadd_carry a' b' carry))
                                         (bblast_bvadd a' b' carry)))))))
-                               
+
+
+(program reverse_help ((x bblt) (acc bblt)) bblt
+(match x
+       (bbltn acc)
+       ((bbltc xi x') (reverse_help x' (bbltc xi acc)))))
+
+
+(program reverseb ((x bblt)) bblt
+        (reverse_help x bbltn))
+
+
+; AJR: use this version?
+;(program bblast_bvadd_2h ((a bblt) (b bblt) (carry formula)) bblt
+;(match a
+;  ( bbltn (match b (bbltn bbltn) (default (fail bblt))))
+;  ((bbltc ai a') (match b 
+;       (bbltn (fail bblt))
+;                 ((bbltc bi b') 
+;                   (let carry' (or (and ai bi) (and (xor ai bi) carry))
+;                   (bbltc (xor (xor ai bi) carry)
+;                                          (bblast_bvadd_2h a' b' carry'))))))))
+
+;(program bblast_bvadd_2 ((a bblt) (b bblt) (carry formula)) bblt
+;(let ar (reverseb a) ;; reverse a and b so that we can build the circuit 
+;(let br (reverseb b) ;; from the least significant bit up
+;(let ret (bblast_bvadd_2h ar br carry)
+;  (reverseb ret)))))
                                
 (declare bv_bbl_bvadd (! n mpz
                       (! x (term (BitVec n))
                           
 ;; shift add multiplier
 
-(program reverse_help ((x bblt) (acc bblt)) bblt
-(match x
-       (bbltn acc)
-       ((bbltc xi x') (reverse_help x' (bbltc xi acc)))))
-
-
-(program reverseb ((x bblt)) bblt
-        (reverse_help x bbltn))
-
 ;; (program concat ((a bblt) (b bblt)) bblt
 ;;   (match a (bbltn b)
 ;;        ((bbltc ai a') (bbltc ai (concat a' b)))))
index a2809bd6778b0f1307fbc27f41bffd376503c492..7d41ae862f9805ad32e62e12e46958851df115e2 100644 (file)
@@ -254,15 +254,21 @@ last-call\n\
 const std::string OptionsHandler::s_literalMatchHelp = "\
 Literal match modes currently supported by the --literal-match option:\n\
 \n\
-none (default)\n\
+none \n\
 + Do not use literal matching.\n\
 \n\
-predicate\n\
-+ Consider the phase requirements of predicate literals when applying heuristic\n\
-  quantifier instantiation.  For example, the trigger P( x ) in the quantified \n\
-  formula forall( x ). ( P( x ) V ~Q( x ) ) will only be matched with ground\n\
-  terms P( t ) where P( t ) is in the equivalence class of false, and likewise\n\
-  Q( x ) with Q( s ) where Q( s ) is in the equivalence class of true.\n\
+use (default)\n\
++ Consider phase requirements of triggers conservatively. For example, the\n\
+  trigger P( x ) in forall( x ). ( P( x ) V ~Q( x ) ) will not be matched with\n\
+  terms in the equivalence class of true, and likewise Q( x ) will not be matched\n\
+  terms in the equivalence class of false. Extends to equality.\n\
+\n\
+agg-predicate \n\
++ Consider phase requirements aggressively for predicates. In the above example,\n\
+  only match P( x ) with terms that are in the equivalence class of false.\n\
+\n\
+agg \n\
++ Consider the phase requirements aggressively for all triggers.\n\
 \n\
 ";
 
@@ -506,10 +512,12 @@ void OptionsHandler::checkInstWhenMode(std::string option, theory::quantifiers::
 theory::quantifiers::LiteralMatchMode OptionsHandler::stringToLiteralMatchMode(std::string option, std::string optarg) throw(OptionException) {
   if(optarg ==  "none") {
     return theory::quantifiers::LITERAL_MATCH_NONE;
-  } else if(optarg ==  "predicate") {
-    return theory::quantifiers::LITERAL_MATCH_PREDICATE;
-  } else if(optarg ==  "equality") {
-    return theory::quantifiers::LITERAL_MATCH_EQUALITY;
+  } else if(optarg ==  "use") {
+    return theory::quantifiers::LITERAL_MATCH_USE;
+  } else if(optarg ==  "agg-predicate") {
+    return theory::quantifiers::LITERAL_MATCH_AGG_PREDICATE;
+  } else if(optarg ==  "agg") {
+    return theory::quantifiers::LITERAL_MATCH_AGG;
   } else if(optarg ==  "help") {
     puts(s_literalMatchHelp.c_str());
     exit(1);
@@ -520,9 +528,7 @@ theory::quantifiers::LiteralMatchMode OptionsHandler::stringToLiteralMatchMode(s
 }
 
 void OptionsHandler::checkLiteralMatchMode(std::string option, theory::quantifiers::LiteralMatchMode mode) throw(OptionException) {
-  if(mode == theory::quantifiers::LITERAL_MATCH_EQUALITY) {
-    throw OptionException(std::string("Mode equality for ") + option + " is not supported in this release.");
-  }
+
 }
 
 theory::quantifiers::MbqiMode OptionsHandler::stringToMbqiMode(std::string option, std::string optarg) throw(OptionException) {
index a58120974cb60bce8dd7fbacf984e29813f587f8..e2cd78de5d7f09b99e17a2f3fb5b9cbea53733c7 100644 (file)
@@ -46,11 +46,14 @@ std::ostream& operator<<(std::ostream& out, theory::quantifiers::LiteralMatchMod
   case theory::quantifiers::LITERAL_MATCH_NONE:
     out << "LITERAL_MATCH_NONE";
     break;
-  case theory::quantifiers::LITERAL_MATCH_PREDICATE:
-    out << "LITERAL_MATCH_PREDICATE";
+  case theory::quantifiers::LITERAL_MATCH_USE:
+    out << "LITERAL_MATCH_USE";
     break;
-  case theory::quantifiers::LITERAL_MATCH_EQUALITY:
-    out << "LITERAL_MATCH_EQUALITY";
+  case theory::quantifiers::LITERAL_MATCH_AGG_PREDICATE:
+    out << "LITERAL_MATCH_AGG_PREDICATE";
+    break;
+  case theory::quantifiers::LITERAL_MATCH_AGG:
+    out << "LITERAL_MATCH_AGG";
     break;
   default:
     out << "LiteralMatchMode!UNKNOWN";
index 5749da972bbc55a88b1aaaf61702e28fb392592e..b4b9abdaf76feea0348d79a2d89b53cc99c1c512 100644 (file)
@@ -44,10 +44,12 @@ enum InstWhenMode {
 enum LiteralMatchMode {
   /** Do not consider polarity of patterns */
   LITERAL_MATCH_NONE,
-  /** Consider polarity of boolean predicates only */
-  LITERAL_MATCH_PREDICATE,
-  /** Consider polarity of boolean predicates, as well as equalities */
-  LITERAL_MATCH_EQUALITY,
+  /** Conservatively consider polarity of patterns */
+  LITERAL_MATCH_USE,
+  /** Aggressively consider polarity of Boolean predicates */
+  LITERAL_MATCH_AGG_PREDICATE,
+  /** Aggressively consider polarity of all terms */
+  LITERAL_MATCH_AGG,
 };
 
 enum MbqiMode {
index f69a8df8b6edc8e3abc2962fae18209f6895054a..9fef0295eb10686e54606c7367b018d7b0d2316c 100644 (file)
@@ -120,7 +120,7 @@ option fullSaturateQuantRd --full-saturate-quant-rd bool :default true
 option fullSaturateInst --fs-inst bool :default false
  interleave full saturate instantiation with other techniques
 
-option literalMatchMode --literal-matching=MODE CVC4::theory::quantifiers::LiteralMatchMode :default CVC4::theory::quantifiers::LITERAL_MATCH_NONE :include "options/quantifiers_modes.h" :handler stringToLiteralMatchMode :predicate checkLiteralMatchMode
+option literalMatchMode --literal-matching=MODE CVC4::theory::quantifiers::LiteralMatchMode :default CVC4::theory::quantifiers::LITERAL_MATCH_USE :include "options/quantifiers_modes.h" :handler stringToLiteralMatchMode :predicate checkLiteralMatchMode
  choose literal matching mode
 
 ### finite model finding options
index 38163c579c8ac1936608a7922bacf268a7219a3d..c28d23eacc0b4bb8529caae32401e5a36333ac3f 100644 (file)
@@ -760,7 +760,9 @@ sygusCommand returns [CVC4::Command* cmd = NULL]
         body = EXPR_MANAGER->mkExpr(kind::EXISTS, EXPR_MANAGER->mkExpr(kind::BOUND_VAR_LIST, PARSER_STATE->getSygusVars()), body);
         Debug("parser-sygus") << "...constructed exists " << body << std::endl;   
       }
-      body = EXPR_MANAGER->mkExpr(kind::FORALL, EXPR_MANAGER->mkExpr(kind::BOUND_VAR_LIST, PARSER_STATE->getSygusFunSymbols()), body, sygusAttr);
+      if( !PARSER_STATE->getSygusFunSymbols().empty() ){
+        body = EXPR_MANAGER->mkExpr(kind::FORALL, EXPR_MANAGER->mkExpr(kind::BOUND_VAR_LIST, PARSER_STATE->getSygusFunSymbols()), body, sygusAttr);
+      }
       Debug("parser-sygus") << "...constructed forall " << body << std::endl;   
       Command* c = new SetUserAttributeCommand("sygus", sygusVar);
       c->setMuted(true);
@@ -791,6 +793,7 @@ sygusGTerm[CVC4::SygusGTerm& sgt, std::string& fun]
   std::string sname;
   std::vector< Expr > let_vars;
   bool readingLet = false;
+  std::string s;
 }
   : LPAREN_TOK
     //read operator
@@ -890,6 +893,12 @@ sygusGTerm[CVC4::SygusGTerm& sgt, std::string& fun]
       sgt.d_name = AntlrInput::tokenText($BINARY_LITERAL);
       sgt.d_gterm_type = SygusGTerm::gterm_op;
     }
+  | str[s,false]
+    { Debug("parser-sygus") << "Sygus grammar " << fun << " : string literal \"" << s << "\"" << std::endl;
+      sgt.d_expr = MK_CONST( ::CVC4::String(s) );
+      sgt.d_name = s;
+      sgt.d_gterm_type = SygusGTerm::gterm_op;
+    }
   | symbol[name,CHECK_NONE,SYM_VARIABLE] ( SYGUS_ENUM_CONS_TOK symbol[name2,CHECK_NONE,SYM_VARIABLE] { readEnum = true; } )?
     { if( readEnum ){
         name = name + "__Enum__" + name2;
@@ -2773,7 +2782,7 @@ STRING_LITERAL_2_0
  * will be part of the token text.  Use the str[] parser rule instead.
  */
 STRING_LITERAL_2_5
-  : { PARSER_STATE->v2_5() }?=>
+  : { PARSER_STATE->v2_5() || PARSER_STATE->sygus() }?=>
     '"' (~('"') | '""')* '"'
   ;
 
index ebad905832e68a9bcbc4963412b143883f3df93c..2da44152af888d911cb267034488bcbd32bdc209 100644 (file)
@@ -350,6 +350,8 @@ void Smt2::setLogic(std::string name) {
       name = "UFLIRA";
     } else if(name == "BV") {
       name = "UFBV";
+    } else if(name == "SLIA") {
+      name = "UFSLIA";
     } else if(name == "ALL_SUPPORTED") {
       //no change
     } else {
index fa71f0132a13a95af7b7e79a6fa5725fe51a3b7b..f4eb67d7486d9ca7cd681c795b35bbdb58ed3807 100644 (file)
@@ -1572,7 +1572,6 @@ bool TermGenerator::getNextMatch( TermGenEnv * s, TNode eqc, std::map< TypeNode,
         if( d_match_status_child_num==0 ){
           //initial binding
           TNode f = s->getTgFunc( d_typ, d_status_num );
-          //std::map< TNode, TermArgTrie >::iterator it = s->getTermDatabase()->d_func_map_eqc_trie[f].d_data.find( eqc );
           Assert( !eqc.isNull() );
           TermArgTrie * tat = s->getTermDatabase()->getTermArgTrie( eqc, f );
           if( tat ){
@@ -1726,9 +1725,9 @@ void TermGenEnv::collectSignatureInformation() {
   d_func_kind.clear();
   d_func_args.clear();
   TypeNode tnull;
-  for( std::map< Node, TermArgTrie >::iterator it = getTermDatabase()->d_func_map_trie.begin(); it != getTermDatabase()->d_func_map_trie.end(); ++it ){
-    if( getTermDatabase()->getNumGroundTerms( it->first )>0 ){
-      Node nn = getTermDatabase()->getGroundTerm( it->first, 0 );
+  for( std::map< Node, std::vector< Node > >::iterator it = getTermDatabase()->d_op_map.begin(); it != getTermDatabase()->d_op_map.end(); ++it ){
+    if( !it->second.empty() ){
+      Node nn = it->second[0];
       Trace("sg-rel-sig-debug") << "Check in signature : " << nn << std::endl;
       if( d_cg->isHandledTerm( nn ) && nn.getKind()!=APPLY_SELECTOR_TOTAL && !nn.getType().isBoolean() ){
         bool do_enum = true;
@@ -1750,7 +1749,7 @@ void TermGenEnv::collectSignatureInformation() {
           d_typ_tg_funcs[nn.getType()].push_back( it->first );
           d_tg_func_param[it->first] = ( nn.getMetaKind() == kind::metakind::PARAMETERIZED );
           Trace("sg-rel-sig") << "Will enumerate function applications of : " << it->first << ", #args = " << d_func_args[it->first].size() << ", kind = " << nn.getKind() << std::endl;
-          getTermDatabase()->computeUfEqcTerms( it->first );
+          //getTermDatabase()->computeUfEqcTerms( it->first );
         }
       }
       Trace("sg-rel-sig-debug") << "Done check in signature : " << nn << std::endl;
index 1dc6f6d50f3401502a039044898b939e75e770c8..41c9c40c8e97c42d4ffc1ec9e7880e9c8991fb01 100644 (file)
@@ -34,6 +34,7 @@ bool EqualityQueryInstProp::reset( Theory::Effort e ) {
   d_uf.clear();
   d_uf_exp.clear();
   d_diseq_list.clear();
+  d_uf_func_map_trie.clear();
   return true;
 }
 
@@ -103,7 +104,7 @@ TNode EqualityQueryInstProp::getCongruentTerm( Node f, std::vector< TNode >& arg
   if( !t.isNull() ){
     return t;
   }else{
-    return d_func_map_trie[f].existsTerm( args );
+    return d_uf_func_map_trie[f].existsTerm( args );
   }
 }
 
@@ -168,6 +169,21 @@ bool EqualityQueryInstProp::areDisequalExp( Node a, Node b, std::vector< Node >&
   }
 }
 
+TNode EqualityQueryInstProp::getCongruentTermExp( Node f, std::vector< TNode >& args, std::vector< Node >& exp ) {
+  TNode t = d_qe->getTermDatabase()->getCongruentTerm( f, args );
+  if( !t.isNull() ){
+    return t;
+  }else{
+    TNode tt = d_uf_func_map_trie[f].existsTerm( args );
+    if( !tt.isNull() ){
+      //TODO?
+      return tt;
+    }else{
+      return tt;
+    }
+  }
+}
+
 Node EqualityQueryInstProp::getUfRepresentative( Node a, std::vector< Node >& exp ) {
   Assert( exp.empty() );
   std::map< Node, Node >::iterator it = d_uf.find( a );
@@ -279,11 +295,13 @@ int EqualityQueryInstProp::setEqual( Node& a, Node& b, bool pol, std::vector< No
       Assert( d_uf_exp[ar].empty() );
       Assert( d_uf_exp[br].empty() );
 
+      //registerUfTerm( ar );
       d_uf[ar] = br;
       merge_exp( d_uf_exp[ar], exp_a );
       merge_exp( d_uf_exp[ar], exp_b );
       merge_exp( d_uf_exp[ar], reason );
 
+      //registerUfTerm( br );
       d_uf[br] = br;
       d_uf_exp[br].clear();
 
@@ -316,6 +334,25 @@ int EqualityQueryInstProp::setEqual( Node& a, Node& b, bool pol, std::vector< No
   }
 }
 
+void EqualityQueryInstProp::registerUfTerm( TNode n ) {
+  if( d_uf.find( n )==d_uf.end() ){
+    if( !getEngine()->hasTerm( n ) ){
+      TNode f = d_qe->getTermDatabase()->getMatchOperator( n );
+      if( !f.isNull() ){
+        std::vector< TNode > args;
+        for( unsigned i=0; i<n.getNumChildren(); i++ ){
+          if( !getEngine()->hasTerm( n[i] ) ){
+            return;
+          }else{
+            args.push_back( n[i] );
+          }
+        }
+        d_uf_func_map_trie[f].addTerm( n, args );
+      }
+    }
+  }
+}
+
 //void EqualityQueryInstProp::addArgument( std::vector< Node >& args, std::vector< Node >& props, Node n, bool is_prop, bool pol ) {
 void EqualityQueryInstProp::addArgument( Node n, std::vector< Node >& args, std::vector< Node >& watch, bool is_watch ) {
   if( is_watch ){
@@ -573,6 +610,7 @@ bool InstPropagator::reset( Theory::Effort e ) {
   d_watch_list.clear();
   d_update_list.clear();
   d_relevant_inst.clear();
+  d_has_relevant_inst = false;
   return d_qy.reset( e );
 }
 
@@ -607,7 +645,31 @@ bool InstPropagator::notifyInstantiation( unsigned quant_e, Node q, Node lem, st
     return !d_conflict;
   }else{
     Assert( false );
-    return true;
+    return false;
+  }
+}
+
+void InstPropagator::filterInstantiations() {
+  if( d_has_relevant_inst ){
+    //now, inform quantifiers engine which instances should be retracted
+    Trace("qip-prop-debug") << "...remove instantiation ids : ";
+    for( std::map< unsigned, InstInfo >::iterator it = d_ii.begin(); it != d_ii.end(); ++it ){
+      if( !it->second.d_q.isNull() ){
+        if( d_relevant_inst.find( it->first )==d_relevant_inst.end() ){
+          if( !d_qe->removeInstantiation( it->second.d_q, it->second.d_lem, it->second.d_terms ) ){
+            Trace("qip-warn") << "WARNING : did not remove instantiation id " << it->first << std::endl;
+            Assert( false );
+          }else{
+            Trace("qip-prop-debug") << it->first << " ";
+          }
+        }else{
+          //mark the quantified formula as relevant
+          d_qe->markRelevant( it->second.d_q );
+        }
+      }
+    }
+    Trace("qip-prop-debug") << std::endl;
+    Trace("quant-engine-conflict") << "-----> InstPropagator::" << ( d_conflict ? "conflict" : "propagate" ) << " with " << d_relevant_inst.size() << " instances." << std::endl;
   }
 }
 
@@ -720,10 +782,12 @@ void InstPropagator::propagate( Node a, Node b, bool pol, std::vector< Node >& e
   }
   if( pol ){
     if( status==EqualityQueryInstProp::STATUS_MERGED_KNOWN ){
+      Trace("qip-rlv-propagate") << "Relevant propagation : " << a << ( pol ? " == " : " != " ) << b << std::endl;
       Assert( d_qy.getEngine()->hasTerm( a ) );
       Assert( d_qy.getEngine()->hasTerm( b ) );
       Trace("qip-prop-debug") << "...equality between known terms." << std::endl;
       addRelevantInstances( exp, "qip-propagate" );
+      //d_has_relevant_inst = true;
     }
     Trace("qip-prop-debug") << "...merged representatives " << a << " and " << b << std::endl;
     for( unsigned i=0; i<2; i++ ){
@@ -750,27 +814,7 @@ void InstPropagator::conflict( std::vector< Node >& exp ) {
   d_conflict = true;
   d_relevant_inst.clear();
   addRelevantInstances( exp, "qip-propagate" );
-
-  //now, inform quantifiers engine which instances should be retracted
-  Trace("qip-prop-debug") << "...remove instantiation ids : ";
-  for( std::map< unsigned, InstInfo >::iterator it = d_ii.begin(); it != d_ii.end(); ++it ){
-    if( !it->second.d_q.isNull() ){
-      if( d_relevant_inst.find( it->first )==d_relevant_inst.end() ){
-        if( !d_qe->removeInstantiation( it->second.d_q, it->second.d_lem, it->second.d_terms ) ){
-          Trace("qip-warn") << "WARNING : did not remove instantiation id " << it->first << std::endl;
-          Assert( false );
-        }else{
-          Trace("qip-prop-debug") << it->first << " ";
-        }
-      }else{
-        //mark the quantified formula as relevant
-        d_qe->markRelevant( it->second.d_q );
-      }
-    }
-  }
-  Trace("qip-prop-debug") << std::endl;
-  //will interupt the quantifiers engine
-  Trace("quant-engine-conflict") << "-----> InstPropagator::conflict with " << exp.size() << " instances." << std::endl;
+  d_has_relevant_inst = true;
 }
 
 bool InstPropagator::cacheConclusion( unsigned id, Node body, int prop_index ) {
index 61aa8257fe516af39c685c38fbf8f9ece36dc337..6201cf1528974c32df40dd2f78c1da7cb81e27c6 100644 (file)
@@ -64,9 +64,11 @@ public:
   bool areEqualExp( Node a, Node b, std::vector< Node >& exp );
   /** returns true is a and b are disequal in the current context */
   bool areDisequalExp( Node a, Node b, std::vector< Node >& exp );
+  /** get congruent term */
+  TNode getCongruentTermExp( Node f, std::vector< TNode >& args, std::vector< Node >& exp );
 private:
   /** term index */
-  std::map< Node, TermArgTrie > d_func_map_trie;
+  std::map< Node, TermArgTrie > d_uf_func_map_trie;
   /** union find for terms beyond what is stored in equality engine */
   std::map< Node, Node > d_uf;
   std::map< Node, std::vector< Node > > d_uf_exp;
@@ -75,6 +77,8 @@ private:
   std::map< Node, std::map< Node, std::vector< Node > > > d_diseq_list;
   /** add arg */
   void addArgument( Node n, std::vector< Node >& args, std::vector< Node >& watch, bool is_watch );
+  /** register term */
+  void registerUfTerm( TNode n );
 public:
   enum {
     STATUS_CONFLICT,
@@ -110,10 +114,13 @@ private:
     virtual bool notifyInstantiation( unsigned quant_e, Node q, Node lem, std::vector< Node >& terms, Node body ) {
       return d_ip.notifyInstantiation( quant_e, q, lem, terms, body );
     }
+    virtual void filterInstantiations() { d_ip.filterInstantiations(); }
   };
   InstantiationNotifyInstPropagator d_notify;
   /** notify instantiation method */
   bool notifyInstantiation( unsigned quant_e, Node q, Node lem, std::vector< Node >& terms, Node body );
+  /** remove instance ids */
+  void filterInstantiations();  
   /** allocate instantiation */
   unsigned allocateInstantiation( Node q, Node lem, std::vector< Node >& terms, Node body );
   /** equality query */
@@ -142,6 +149,7 @@ private:
   std::vector< unsigned > d_update_list;
   /** relevant instances */
   std::map< unsigned, bool > d_relevant_inst;
+  bool d_has_relevant_inst;
 private:
   bool update( unsigned id, InstInfo& i, bool firstTime = false );
   void propagate( Node a, Node b, bool pol, std::vector< Node >& exp );
index d58bbcf3a17302550acc2043976d9d6562a7ff4a..7bc51dc50e25e4cf1a6273575ae94282766c14d9 100644 (file)
@@ -332,19 +332,30 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
         unsigned num_fv = tinfo[pat].d_fv.size();
         Trace("auto-gen-trigger-debug") << "...required polarity for " << pat << " is " << rpol << ", eq=" << rpoleq << std::endl;
         if( rpol!=0 ){
+          Assert( rpol==1 || rpol==-1 );
           if( Trigger::isRelationalTrigger( pat ) ){
             pat = rpol==-1 ? pat.negate() : pat;
           }else{
             Assert( Trigger::isAtomicTrigger( pat ) );
             if( pat.getType().isBoolean() && rpoleq.isNull() ){
-              pat = NodeManager::currentNM()->mkNode( IFF, pat, NodeManager::currentNM()->mkConst( rpol==-1 ) ).negate();
+              if( options::literalMatchMode()==LITERAL_MATCH_USE ){
+                pat = NodeManager::currentNM()->mkNode( IFF, pat, NodeManager::currentNM()->mkConst( rpol==-1 ) ).negate();
+              }else if( options::literalMatchMode()!=LITERAL_MATCH_NONE ){
+                pat = NodeManager::currentNM()->mkNode( IFF, pat, NodeManager::currentNM()->mkConst( rpol==1 ) );
+              }
             }else{
               Assert( !rpoleq.isNull() );
               if( rpol==-1 ){
-                //all equivalence classes except rpoleq
-                pat = NodeManager::currentNM()->mkNode( EQUAL, pat, rpoleq ).negate();
+                if( options::literalMatchMode()!=LITERAL_MATCH_NONE ){
+                  //all equivalence classes except rpoleq
+                  pat = NodeManager::currentNM()->mkNode( EQUAL, pat, rpoleq ).negate();
+                }
               }else if( rpol==1 ){
-                //all equivalence classes that are not disequal to rpoleq TODO
+                if( options::literalMatchMode()==LITERAL_MATCH_AGG ){
+                  //only equivalence class rpoleq
+                  pat = NodeManager::currentNM()->mkNode( EQUAL, pat, rpoleq );
+                }
+                //all equivalence classes that are not disequal to rpoleq TODO?
               }
             }
           }
index 52563978f9afa02e6671c41e393c413258c94145..1365feda9d343c505057bf2bf8168f2d02d23d55 100644 (file)
@@ -119,7 +119,7 @@ void QuantInfo::initialize( QuantConflictFind * p, Node q, Node qn ) {
     //}
     //get all variables that are always relevant
     std::map< TNode, bool > visited;
-    getPropagateVars( vars, q[1], false, visited );
+    getPropagateVars( p, vars, q[1], false, visited );
     for( unsigned j=0; j<vars.size(); j++ ){
       Node v = vars[j];
       TNode f = p->getTermDatabase()->getMatchOperator( v );
@@ -140,7 +140,7 @@ void QuantInfo::initialize( QuantConflictFind * p, Node q, Node qn ) {
   }
 }
 
-void QuantInfo::getPropagateVars( std::vector< TNode >& vars, TNode n, bool pol, std::map< TNode, bool >& visited ){
+void QuantInfo::getPropagateVars( QuantConflictFind * p, std::vector< TNode >& vars, TNode n, bool pol, std::map< TNode, bool >& visited ){
   std::map< TNode, bool >::iterator itv = visited.find( n );
   if( itv==visited.end() ){
     visited[n] = true;
@@ -149,6 +149,12 @@ void QuantInfo::getPropagateVars( std::vector< TNode >& vars, TNode n, bool pol,
     if( d_var_num.find( n )!=d_var_num.end() ){
       Assert( std::find( vars.begin(), vars.end(), n )==vars.end() );
       vars.push_back( n );
+      TNode f = p->getTermDatabase()->getMatchOperator( n );
+      if( !f.isNull() ){
+        if( std::find( p->d_func_rel_dom[f].begin(), p->d_func_rel_dom[f].end(), d_q )==p->d_func_rel_dom[f].end() ){
+          p->d_func_rel_dom[f].push_back( d_q );
+        }
+      } 
     }else if( MatchGen::isHandledBoolConnective( n ) ){
       Assert( n.getKind()!=IMPLIES );
       QuantPhaseReq::getEntailPolarity( n, 0, true, pol, rec, newPol );
@@ -156,7 +162,7 @@ void QuantInfo::getPropagateVars( std::vector< TNode >& vars, TNode n, bool pol,
     Trace("qcf-opt-debug") << "getPropagateVars " << n << ", pol = " << pol << ", rec = " << rec << std::endl;
     if( rec ){
       for( unsigned i=0; i<n.getNumChildren(); i++ ){
-        getPropagateVars( vars, n[i], pol, visited );
+        getPropagateVars( p, vars, n[i], pol, visited );
       }
     }
   }
@@ -238,7 +244,7 @@ void QuantInfo::flatten( Node n, bool beneathQuant ) {
 }
 
 
-void QuantInfo::reset_round( QuantConflictFind * p ) {
+bool QuantInfo::reset_round( QuantConflictFind * p ) {
   for( unsigned i=0; i<d_match.size(); i++ ){
     d_match[i] = TNode::null();
     d_match_term[i] = TNode::null();
@@ -246,6 +252,7 @@ void QuantInfo::reset_round( QuantConflictFind * p ) {
   d_vars_set.clear();
   d_curr_var_deq.clear();
   d_tconstraints.clear();
+  
   //add built-in variable constraints
   for( unsigned r=0; r<2; r++ ){
     for( std::map< int, std::vector< Node > >::iterator it = d_var_constraint[r].begin();
@@ -263,7 +270,7 @@ void QuantInfo::reset_round( QuantConflictFind * p ) {
           d_mg->d_children.clear();
           d_mg->d_n = NodeManager::currentNM()->mkConst( true );
           d_mg->d_type = MatchGen::typ_ground;
-          return;
+          return false;
         }
       }
     }
@@ -274,6 +281,7 @@ void QuantInfo::reset_round( QuantConflictFind * p ) {
   }
   //now, reset for matching
   d_mg->reset( p, false, this );
+  return true;
 }
 
 int QuantInfo::getCurrentRepVar( int v ) {
@@ -1283,11 +1291,14 @@ void MatchGen::reset( QuantConflictFind * p, bool tgt, QuantInfo * qi ) {
     }
   }else if( d_type==typ_var ){
     Assert( isHandledUfTerm( d_n ) );
-    Node f = getMatchOperator( p, d_n );
+    TNode f = getMatchOperator( p, d_n );
     Debug("qcf-match-debug") << "       reset: Var will match operators of " << f << std::endl;
     TermArgTrie * qni = p->getTermDatabase()->getTermArgTrie( Node::null(), f );
     if( qni!=NULL ){
       d_qn.push_back( qni );
+    }else{
+      //inform irrelevant quantifiers
+      p->setIrrelevantFunction( f );
     }
     d_matched_basis = false;
   }else if( d_type==typ_tsym || d_type==typ_tconstraint ){
@@ -2013,6 +2024,18 @@ void QuantConflictFind::reset_round( Theory::Effort level ) {
   d_needs_computeRelEqr = true;
 }
 
+void QuantConflictFind::setIrrelevantFunction( TNode f ) {
+  if( d_irr_func.find( f )==d_irr_func.end() ){
+    d_irr_func[f] = true;
+    std::map< TNode, std::vector< Node > >::iterator it = d_func_rel_dom.find( f );
+    if( it != d_func_rel_dom.end()){
+      for( unsigned j=0; j<it->second.size(); j++ ){
+        d_irr_quant[it->second[j]] = true;
+      }
+    }
+  }
+}
+
 /** check */
 void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
   if( quant_e==QuantifiersEngine::QEFFORT_CONFLICT ){
@@ -2035,14 +2058,9 @@ void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
       }
       computeRelevantEqr();
 
-      //determine order for quantified formulas
-      std::vector< Node > qorder;
-      for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
-        Node q = d_quantEngine->getModel()->getAssertedQuantifier( i, true );
-        if( d_quantEngine->hasOwnership( q, this ) ){
-          qorder.push_back( q );
-        }
-      }
+      d_irr_func.clear();
+      d_irr_quant.clear();
+
       if( Trace.isOn("qcf-debug") ){
         Trace("qcf-debug") << std::endl;
         debugPrint("qcf-debug");
@@ -2053,80 +2071,83 @@ void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
       for( short e = effort_conflict; e<=end_e; e++ ){
         d_effort = e;
         Trace("qcf-check") << "Checking quantified formulas at effort " << e << "..." << std::endl;
-        for( unsigned j=0; j<qorder.size(); j++ ){
-          Node q = qorder[j];
-          QuantInfo * qi = &d_qinfo[q];
-
-          Assert( d_qinfo.find( q )!=d_qinfo.end() );
-          if( qi->matchGeneratorIsValid() ){
-            Trace("qcf-check") << "Check quantified formula ";
-            debugPrintQuant("qcf-check", q);
-            Trace("qcf-check") << " : " << q << "..." << std::endl;
-
-            Trace("qcf-check-debug") << "Reset round..." << std::endl;
-            qi->reset_round( this );
-            //try to make a matches making the body false
-            Trace("qcf-check-debug") << "Get next match..." << std::endl;
-            while( qi->getNextMatch( this ) ){
-              Trace("qcf-inst") << "*** Produced match at effort " << e << " : " << std::endl;
-              qi->debugPrintMatch("qcf-inst");
-              Trace("qcf-inst") << std::endl;
-              if( !qi->isMatchSpurious( this ) ){
-                std::vector< int > assigned;
-                if( qi->completeMatch( this, assigned ) ){
-                  std::vector< Node > terms;
-                  qi->getMatch( terms );
-                  bool tcs = qi->isTConstraintSpurious( this, terms );
-                  if( !tcs ){
-                    //for debugging
-                    if( Debug.isOn("qcf-check-inst") ){
-                      Node inst = d_quantEngine->getInstantiation( q, terms );
-                      Debug("qcf-check-inst") << "Check instantiation " << inst << "..." << std::endl;
-                      Assert( !getTermDatabase()->isEntailed( inst, true ) );
-                      Assert( getTermDatabase()->isEntailed( inst, false ) || e>effort_conflict );
-                    }
-                    if( d_quantEngine->addInstantiation( q, terms ) ){
-                      Trace("qcf-check") << "   ... Added instantiation" << std::endl;
-                      Trace("qcf-inst") << "*** Was from effort " << e << " : " << std::endl;
-                      qi->debugPrintMatch("qcf-inst");
-                      Trace("qcf-inst") << std::endl;
-                      ++addedLemmas;
-                      if( e==effort_conflict ){
-                        d_quantEngine->markRelevant( q );
-                        ++(d_statistics.d_conflict_inst);
-                        if( options::qcfAllConflict() ){
-                          isConflict = true;
+        for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+          Node q = d_quantEngine->getModel()->getAssertedQuantifier( i, true );
+          if( d_quantEngine->hasOwnership( q, this ) && d_irr_quant.find( q )==d_irr_quant.end() ){
+            QuantInfo * qi = &d_qinfo[q];
+
+            Assert( d_qinfo.find( q )!=d_qinfo.end() );
+            if( qi->matchGeneratorIsValid() ){
+              Trace("qcf-check") << "Check quantified formula ";
+              debugPrintQuant("qcf-check", q);
+              Trace("qcf-check") << " : " << q << "..." << std::endl;
+
+              Trace("qcf-check-debug") << "Reset round..." << std::endl;
+              if( qi->reset_round( this ) ){
+                //try to make a matches making the body false
+                Trace("qcf-check-debug") << "Get next match..." << std::endl;
+                while( qi->getNextMatch( this ) ){
+                  Trace("qcf-inst") << "*** Produced match at effort " << e << " : " << std::endl;
+                  qi->debugPrintMatch("qcf-inst");
+                  Trace("qcf-inst") << std::endl;
+                  if( !qi->isMatchSpurious( this ) ){
+                    std::vector< int > assigned;
+                    if( qi->completeMatch( this, assigned ) ){
+                      std::vector< Node > terms;
+                      qi->getMatch( terms );
+                      bool tcs = qi->isTConstraintSpurious( this, terms );
+                      if( !tcs ){
+                        //for debugging
+                        if( Debug.isOn("qcf-check-inst") ){
+                          Node inst = d_quantEngine->getInstantiation( q, terms );
+                          Debug("qcf-check-inst") << "Check instantiation " << inst << "..." << std::endl;
+                          Assert( !getTermDatabase()->isEntailed( inst, true ) );
+                          Assert( getTermDatabase()->isEntailed( inst, false ) || e>effort_conflict );
+                        }
+                        if( d_quantEngine->addInstantiation( q, terms ) ){
+                          Trace("qcf-check") << "   ... Added instantiation" << std::endl;
+                          Trace("qcf-inst") << "*** Was from effort " << e << " : " << std::endl;
+                          qi->debugPrintMatch("qcf-inst");
+                          Trace("qcf-inst") << std::endl;
+                          ++addedLemmas;
+                          if( e==effort_conflict ){
+                            d_quantEngine->markRelevant( q );
+                            ++(d_statistics.d_conflict_inst);
+                            if( options::qcfAllConflict() ){
+                              isConflict = true;
+                            }else{
+                              d_conflict.set( true );
+                            }
+                            break;
+                          }else if( e==effort_prop_eq ){
+                            d_quantEngine->markRelevant( q );
+                            ++(d_statistics.d_prop_inst);
+                          }
                         }else{
-                          d_conflict.set( true );
+                          Trace("qcf-inst") << "   ... Failed to add instantiation" << std::endl;
+                          //this should only happen if the algorithm generates the same propagating instance twice this round
+                          //in this case, break to avoid exponential behavior
+                          break;
                         }
-                        break;
-                      }else if( e==effort_prop_eq ){
-                        d_quantEngine->markRelevant( q );
-                        ++(d_statistics.d_prop_inst);
+                      }else{
+                        Trace("qcf-inst") << "   ... Spurious instantiation (match is T-inconsistent)" << std::endl;
                       }
+                      //clean up assigned
+                      qi->revertMatch( this, assigned );
+                      d_tempCache.clear();
                     }else{
-                      Trace("qcf-inst") << "   ... Failed to add instantiation" << std::endl;
-                      //this should only happen if the algorithm generates the same propagating instance twice this round
-                      //in this case, break to avoid exponential behavior
-                      break;
+                      Trace("qcf-inst") << "   ... Spurious instantiation (cannot assign unassigned variables)" << std::endl;
                     }
                   }else{
-                    Trace("qcf-inst") << "   ... Spurious instantiation (match is T-inconsistent)" << std::endl;
+                    Trace("qcf-inst") << "   ... Spurious instantiation (match is inconsistent)" << std::endl;
                   }
-                  //clean up assigned
-                  qi->revertMatch( this, assigned );
-                  d_tempCache.clear();
-                }else{
-                  Trace("qcf-inst") << "   ... Spurious instantiation (cannot assign unassigned variables)" << std::endl;
                 }
-              }else{
-                Trace("qcf-inst") << "   ... Spurious instantiation (match is inconsistent)" << std::endl;
+                Trace("qcf-check") << "Done, conflict = " << d_conflict << std::endl;
+                if( d_conflict ){
+                  break;
+                }
               }
             }
-            Trace("qcf-check") << "Done, conflict = " << d_conflict << std::endl;
-            if( d_conflict ){
-              break;
-            }
           }
         }
         if( addedLemmas>0 ){
@@ -2157,17 +2178,9 @@ void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
 void QuantConflictFind::computeRelevantEqr() {
   if( d_needs_computeRelEqr ){
     d_needs_computeRelEqr = false;
-    Trace("qcf-check") << "Compute relevant equalities..." << std::endl;
-    //d_uf_terms.clear();
-    //d_eqc_uf_terms.clear();
+    Trace("qcf-check") << "Compute relevant equivalence classes..." << std::endl;
     d_eqcs.clear();
-    //d_arg_reps.clear();
-    //double clSet = 0;
-    //if( Trace.isOn("qcf-opt") ){
-    //  clSet = double(clock())/double(CLOCKS_PER_SEC);
-    //}
 
-    //now, store matches
     eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( getEqualityEngine() );
     while( !eqcs_i.isFinished() ){
       Node r = (*eqcs_i);
index 16f6b6a1b634b44785e2cb12edb723e8c32e7c5d..974495269bdf7866c433499e7890b4ebd27b3d0f 100644 (file)
@@ -117,7 +117,7 @@ private: //for completing match
   std::vector< int > d_una_eqc_count;
   //optimization: track which arguments variables appear under UF terms in
   std::map< int, std::map< TNode, std::vector< unsigned > > > d_var_rel_dom;
-  void getPropagateVars( std::vector< TNode >& vars, TNode n, bool pol, std::map< TNode, bool >& visited );
+  void getPropagateVars( QuantConflictFind * p, std::vector< TNode >& vars, TNode n, bool pol, std::map< TNode, bool >& visited );
   //optimization: number of variables set, to track when we can stop
   std::map< int, bool > d_vars_set;
   std::map< Node, bool > d_ground_terms;
@@ -156,7 +156,7 @@ public:
   }
 
   Node d_q;
-  void reset_round( QuantConflictFind * p );
+  bool reset_round( QuantConflictFind * p );
 public:
   //initialize
   void initialize( QuantConflictFind * p, Node q, Node qn );
@@ -195,6 +195,11 @@ private:
   std::map< Kind, Node > d_zero;
   //for storing nodes created during t-constraint solving (prevents memory leaks)
   std::vector< Node > d_tempCache;
+  //optimization: list of quantifiers that depend on ground function applications
+  std::map< TNode, std::vector< Node > > d_func_rel_dom;
+  std::map< TNode, bool > d_irr_func;
+  std::map< Node, bool > d_irr_quant;
+  void setIrrelevantFunction( TNode f );
 private:
   std::map< Node, Node > d_op_node;
   int d_fid_count;
index 2f7864831b83ee1d3d8ba06de6112ac288465828..6963f7e62714893b982f669980eb4c8561631d5d 100644 (file)
@@ -187,7 +187,6 @@ RewriteResponse QuantifiersRewriter::preRewrite(TNode in) {
     std::vector< Node > args;
     Node body = in;
     bool doRewrite = false;
-    bool firstTime = true;
     while( body.getNumChildren()==2 && body.getKind()==body[1].getKind() ){
       for( unsigned i=0; i<body[0].getNumChildren(); i++ ){
         args.push_back( body[0][i] );
@@ -197,8 +196,11 @@ RewriteResponse QuantifiersRewriter::preRewrite(TNode in) {
     }
     if( doRewrite ){
       std::vector< Node > children;
+      for( unsigned i=0; i<body[0].getNumChildren(); i++ ){
+        args.push_back( body[0][i] );
+      }      
       children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST,args) );
-      children.push_back( body );
+      children.push_back( body[1] );
       Node n = NodeManager::currentNM()->mkNode( in.getKind(), children );
       if( in!=n ){
         Trace("quantifiers-pre-rewrite") << "*** pre-rewrite " << in << std::endl;
index b143286cc29be94a554143aeeb99269d05a61dc3..61c02d3ace9bfa884e6ec2e20d6467b024289607 100644 (file)
@@ -163,6 +163,10 @@ void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant, bool wi
         //if this is an atomic trigger, consider adding it
         if( inst::Trigger::isAtomicTrigger( n ) ){
           Trace("term-db") << "register term in db " << n << std::endl;
+          if( options::finiteModelFind() ){
+            computeModelBasisArgAttribute( n );
+          }
+          
           Node op = getMatchOperator( n );
           d_op_map[op].push_back( n );
           added.insert( n );
@@ -222,7 +226,86 @@ void TermDb::computeUfEqcTerms( TNode f ) {
   }
 }
 
+void TermDb::computeUfTerms( TNode f ) {
+  if( d_op_nonred_count.find( f )==d_op_nonred_count.end() ){
+    d_op_nonred_count[ f ] = 0;
+    std::map< Node, std::vector< Node > >::iterator it = d_op_map.find( f );
+    if( it!=d_op_map.end() ){
+      eq::EqualityEngine* ee = d_quantEngine->getMasterEqualityEngine();
+      Trace("term-db-debug") << "Adding terms for operator " << f << std::endl;
+      for( unsigned i=0; i<it->second.size(); i++ ){
+        Node n = it->second[i];
+        //to be added to term index, term must be relevant, and exist in EE
+        if( hasTermCurrent( n ) && ee->hasTerm( n ) ){
+          if( isTermActive( n ) ){
+            computeArgReps( n );
+
+            Trace("term-db-debug") << "Adding term " << n << " with arg reps : ";
+            for( unsigned i=0; i<d_arg_reps[n].size(); i++ ){
+              Trace("term-db-debug") << d_arg_reps[n][i] << " ";
+              if( std::find( d_func_map_rel_dom[f][i].begin(), 
+                             d_func_map_rel_dom[f][i].end(), d_arg_reps[n][i] ) == d_func_map_rel_dom[f][i].end() ){
+                d_func_map_rel_dom[f][i].push_back( d_arg_reps[n][i] );
+              }
+            }
+            Trace("term-db-debug") << std::endl;
+            Trace("term-db-debug") << "  and value : " << ee->getRepresentative( n ) << std::endl;
+            Node at = d_func_map_trie[ f ].addOrGetTerm( n, d_arg_reps[n] );
+            Trace("term-db-debug2") << "...add term returned " << at << std::endl;
+            if( at!=n && ee->areEqual( at, n ) ){
+              setTermInactive( n );
+              Trace("term-db-debug") << n << " is redundant." << std::endl;
+              //congruentCount++;
+            }else{
+              if( at!=n && ee->areDisequal( at, n, false ) ){
+                std::vector< Node > lits;
+                lits.push_back( NodeManager::currentNM()->mkNode( at.getType().isBoolean() ? IFF : EQUAL, at, n ) );
+                for( unsigned i=0; i<at.getNumChildren(); i++ ){
+                  if( at[i]!=n[i] ){
+                    lits.push_back( NodeManager::currentNM()->mkNode( at[i].getType().isBoolean() ? IFF : EQUAL, at[i], n[i] ).negate() );
+                  }
+                }
+                Node lem = lits.size()==1 ? lits[0] : NodeManager::currentNM()->mkNode( OR, lits );
+                if( Trace.isOn("term-db-lemma") ){
+                  Trace("term-db-lemma") << "Disequal congruent terms : " << at << " " << n << "!!!!" << std::endl;
+                  if( !d_quantEngine->getTheoryEngine()->needCheck() ){
+                    Trace("term-db-lemma") << "  all theories passed with no lemmas." << std::endl;
+                  }
+                  Trace("term-db-lemma") << "  add lemma : " << lem << std::endl;
+                }
+                d_quantEngine->addLemma( lem );
+                d_consistent_ee = false;
+                return;
+              }
+              //nonCongruentCount++;
+              d_op_nonred_count[ f ]++;
+            }
+          }else{
+            Trace("term-db-debug") << n << " is already redundant." << std::endl;
+            //congruentCount++;
+            //alreadyCongruentCount++;
+          }
+        }else{
+          Trace("term-db-debug") << n << " is not relevant." << std::endl;
+          //nonRelevantCount++;
+        }
+      }
+      
+      /*
+      if( Trace.isOn("term-db-index") ){
+        Trace("term-db-index") << "Term index for " << f << " : " << std::endl;
+        Trace("term-db-index") << "- " << it->first << std::endl;
+        d_func_map_trie[ f ].debugPrint("term-db-index", it->second[0]);
+        Trace("term-db-index") << "Non-Congruent/Congruent/Non-Relevant = ";
+        Trace("term-db-index") << nonCongruentCount << " / " << congruentCount << " (" << alreadyCongruentCount << ") / " << nonRelevantCount << std::endl; 
+      }
+      */
+    }
+  }
+}
+
 bool TermDb::inRelevantDomain( TNode f, unsigned i, TNode r ) {
+  computeUfTerms( f );
   Assert( d_quantEngine->getTheoryEngine()->getMasterEqualityEngine()->getRepresentative( r )==r );
   std::map< Node, std::map< unsigned, std::vector< Node > > >::iterator it = d_func_map_rel_dom.find( f );
   if( it != d_func_map_rel_dom.end() ){
@@ -584,10 +667,10 @@ void TermDb::presolve() {
 }
 
 bool TermDb::reset( Theory::Effort effort ){
-  int nonCongruentCount = 0;
-  int congruentCount = 0;
-  int alreadyCongruentCount = 0;
-  int nonRelevantCount = 0;
+  //int nonCongruentCount = 0;
+  //int congruentCount = 0;
+  //int alreadyCongruentCount = 0;
+  //int nonRelevantCount = 0;
   d_op_nonred_count.clear();
   d_arg_reps.clear();
   d_func_map_trie.clear();
@@ -642,71 +725,16 @@ bool TermDb::reset( Theory::Effort effort ){
     }
   }
 
+/*
   //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 ){
-    d_op_nonred_count[ it->first ] = 0;
-    Trace("term-db-debug") << "Adding terms for operator " << it->first << std::endl;
-    for( unsigned i=0; i<it->second.size(); i++ ){
-      Node n = it->second[i];
-      //to be added to term index, term must be relevant, and exist in EE
-      if( hasTermCurrent( n ) && ee->hasTerm( n ) ){
-        if( isTermActive( n ) ){
-          if( options::finiteModelFind() ){
-            computeModelBasisArgAttribute( n );
-          }
-          computeArgReps( n );
-
-          Trace("term-db-debug") << "Adding term " << n << " with arg reps : ";
-          for( unsigned i=0; i<d_arg_reps[n].size(); i++ ){
-            Trace("term-db-debug") << d_arg_reps[n][i] << " ";
-            if( std::find( d_func_map_rel_dom[it->first][i].begin(), 
-                           d_func_map_rel_dom[it->first][i].end(), d_arg_reps[n][i] ) == d_func_map_rel_dom[it->first][i].end() ){
-              d_func_map_rel_dom[it->first][i].push_back( d_arg_reps[n][i] );
-            }
-          }
-          Trace("term-db-debug") << std::endl;
-          Trace("term-db-debug") << "  and value : " << ee->getRepresentative( n ) << std::endl;
-          Node at = d_func_map_trie[ it->first ].addOrGetTerm( n, d_arg_reps[n] );
-          Trace("term-db-debug2") << "...add term returned " << at << std::endl;
-          if( at!=n && ee->areEqual( at, n ) ){
-            setTermInactive( n );
-            Trace("term-db-debug") << n << " is redundant." << std::endl;
-            congruentCount++;
-          }else{
-            if( at!=n && ee->areDisequal( at, n, false ) ){
-              std::vector< Node > lits;
-              lits.push_back( NodeManager::currentNM()->mkNode( at.getType().isBoolean() ? IFF : EQUAL, at, n ) );
-              for( unsigned i=0; i<at.getNumChildren(); i++ ){
-                if( at[i]!=n[i] ){
-                  lits.push_back( NodeManager::currentNM()->mkNode( at[i].getType().isBoolean() ? IFF : EQUAL, at[i], n[i] ).negate() );
-                }
-              }
-              Node lem = lits.size()==1 ? lits[0] : NodeManager::currentNM()->mkNode( OR, lits );
-              if( Trace.isOn("term-db-lemma") ){
-                Trace("term-db-lemma") << "Disequal congruent terms : " << at << " " << n << "!!!!" << std::endl;
-                if( !d_quantEngine->getTheoryEngine()->needCheck() ){
-                  Trace("term-db-lemma") << "  all theories passed with no lemmas." << std::endl;
-                }
-                Trace("term-db-lemma") << "  add lemma : " << lem << std::endl;
-              }
-              d_quantEngine->addLemma( lem );
-              d_consistent_ee = false;
-              return false;
-            }
-            nonCongruentCount++;
-            d_op_nonred_count[ it->first ]++;
-          }
-        }else{
-          Trace("term-db-debug") << n << " is already redundant." << std::endl;
-          congruentCount++;
-          alreadyCongruentCount++;
-        }
-      }else{
-        Trace("term-db-debug") << n << " is not relevant." << std::endl;
-        nonRelevantCount++;
-      }
+    computeUfTerms( it->first );
+    if( !d_consistent_ee ){
+      return false;
     }
   }
+*/  
+  /*
   Trace("term-db-stats") << "TermDb: Reset" << std::endl;
   Trace("term-db-stats") << "Non-Congruent/Congruent/Non-Relevant = ";
   Trace("term-db-stats") << nonCongruentCount << " / " << congruentCount << " (" << alreadyCongruentCount << ") / " << nonRelevantCount << std::endl;
@@ -719,10 +747,12 @@ bool TermDb::reset( Theory::Effort effort ){
       }
     }
   }
+  */
   return true;
 }
 
 TermArgTrie * TermDb::getTermArgTrie( Node f ) {
+  computeUfTerms( f );
   std::map< Node, TermArgTrie >::iterator itut = d_func_map_trie.find( f );
   if( itut!=d_func_map_trie.end() ){
     return &itut->second;
@@ -751,11 +781,18 @@ TermArgTrie * TermDb::getTermArgTrie( Node eqc, Node f ) {
 }
 
 TNode TermDb::getCongruentTerm( Node f, Node n ) {
-  computeArgReps( n );
-  return d_func_map_trie[f].existsTerm( d_arg_reps[n] );
+  computeUfTerms( f );
+  std::map< Node, TermArgTrie >::iterator itut = d_func_map_trie.find( f );
+  if( itut!=d_func_map_trie.end() ){
+    computeArgReps( n );
+    return itut->second.existsTerm( d_arg_reps[n] );
+  }else{
+    return TNode::null();
+  }
 }
 
 TNode TermDb::getCongruentTerm( Node f, std::vector< TNode >& args ) {
+  computeUfTerms( f );
   return d_func_map_trie[f].existsTerm( args );
 }
 
index 004292622c368501d2b7294b5ea7057a265ce168..684b6cf833a3d55bb5d0836e4026a3aa1b376818 100644 (file)
@@ -248,6 +248,8 @@ public:
   void computeArgReps( TNode n );
   /** compute uf eqc terms */
   void computeUfEqcTerms( TNode f );
+  /** compute uf terms */
+  void computeUfTerms( TNode f );
   /** in relevant domain */
   bool inRelevantDomain( TNode f, unsigned i, TNode r );
   /** evaluate a term under a substitution.  Return representative in EE if possible.
@@ -271,7 +273,7 @@ public:
   Node getEligibleTermInEqc( TNode r );
   /** is inst closure */
   bool isInstClosure( Node r );
-
+  
 //for model basis
 private:
   //map from types to model basis terms
index 2451036f145652ab67ec1b770e246e7b24e4dd4d..12edb5277c0f7b6878bd6dc28de940c416859ed4 100644 (file)
@@ -353,7 +353,7 @@ void QuantifiersEngine::check( Theory::Effort e ){
   std::vector< QuantifiersModule* > qm;
   if( d_model->checkNeeded() ){
     needsCheck = needsCheck || e>=Theory::EFFORT_LAST_CALL;  //always need to check at or above last call
-    for( int i=0; i<(int)d_modules.size(); i++ ){
+    for( unsigned i=0; i<d_modules.size(); i++ ){
       if( d_modules[i]->needsCheck( e ) ){
         qm.push_back( d_modules[i] );
         needsCheck = true;
@@ -396,6 +396,12 @@ void QuantifiersEngine::check( Theory::Effort e ){
       } 
       d_recorded_inst.clear();
     }
+    
+    double clSet = 0;
+    if( Trace.isOn("quant-engine") ){
+      clSet = double(clock())/double(CLOCKS_PER_SEC);
+      Trace("quant-engine") << ">>>>> Quantifiers Engine Round, effort = " << e << " <<<<<" << std::endl;
+    }
 
     if( Trace.isOn("quant-engine-debug") ){
       Trace("quant-engine-debug") << "Quantifiers Engine check, level = " << e << std::endl;
@@ -456,7 +462,6 @@ void QuantifiersEngine::check( Theory::Effort e ){
     flushLemmas();
     if( d_hasAddedLemma ){
       return;
-
     }
 
     if( e==Theory::EFFORT_LAST_CALL ){
@@ -548,6 +553,13 @@ void QuantifiersEngine::check( Theory::Effort e ){
         }
       }
     }
+    if( Trace.isOn("quant-engine") ){
+      double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
+      Trace("quant-engine") << "Finished quantifiers engine, total time = " << (clSet2-clSet);
+      Trace("quant-engine") << ", added lemma = " << d_hasAddedLemma;
+      Trace("quant-engine") << std::endl;
+    }
+    
     Trace("quant-engine-debug2") << "Finished quantifiers engine check." << std::endl;
   }else{
     Trace("quant-engine-debug2") << "Quantifiers Engine does not need check." << std::endl;
@@ -567,7 +579,7 @@ void QuantifiersEngine::check( Theory::Effort e ){
       }
     }
     if( setIncomplete ){
-      Trace("quant-engine-debug") << "Set incomplete flag." << std::endl;
+      Trace("quant-engine") << "Set incomplete flag." << std::endl;
       getOutputChannel().setIncomplete();
     }
     //output debug stats
@@ -646,8 +658,6 @@ bool QuantifiersEngine::registerQuantifier( Node f ){
         d_modules[i]->registerQuantifier( f );
       }
       Node ceBody = d_term_db->getInstConstantBody( f );
-      //generate the phase requirements
-      //d_phase_reqs[f] = new QuantPhaseReq( ceBody, true );
       //also register it with the strong solver
       //if( options::finiteModelFind() ){
       //  ((uf::TheoryUF*)d_te->theoryOf( THEORY_UF ))->getStrongSolver()->registerQuantifier( f );
@@ -1209,9 +1219,19 @@ quantifiers::UserPatMode QuantifiersEngine::getInstUserPatMode() {
 
 void QuantifiersEngine::flushLemmas(){
   if( !d_lemmas_waiting.empty() ){
+    //filter based on notify classes
+    if( !d_inst_notify.empty() ){
+      unsigned prev_lem_sz = d_lemmas_waiting.size();
+      for( unsigned j=0; j<d_inst_notify.size(); j++ ){
+        d_inst_notify[j]->filterInstantiations();
+      }  
+      if( prev_lem_sz!=d_lemmas_waiting.size() ){
+        Trace("quant-engine") << "...filtered instances : " << d_lemmas_waiting.size() << " / " << prev_lem_sz << std::endl;
+      }
+    }
     //take default output channel if none is provided
     d_hasAddedLemma = true;
-    for( int i=0; i<(int)d_lemmas_waiting.size(); i++ ){
+    for( unsigned i=0; i<d_lemmas_waiting.size(); i++ ){
       Trace("qe-lemma") << "Lemma : " << d_lemmas_waiting[i] << std::endl;
       getOutputChannel().lemma( d_lemmas_waiting[i], false, true );
     }
index 4c7cb4a2f2c7c2a856bd99c9b99bc01e50d1fdea..60666c4a9988fa16d59456444bb8e7c78b3cbead 100644 (file)
@@ -48,6 +48,7 @@ class InstantiationNotify {
 public:
   InstantiationNotify(){}
   virtual bool notifyInstantiation( unsigned quant_e, Node q, Node lem, std::vector< Node >& terms, Node body ) = 0;
+  virtual void filterInstantiations() = 0;
 };
 
 namespace quantifiers {
index 2ca807662ce719b1accf670870a2f49bffdc4f7c..8c847be60e9ef16bcaf33e708473ebcad3655589 100644 (file)
@@ -48,7 +48,8 @@ TESTS = commutative.sy \
         clock-inc-tuple.sy \
         dt-test-ns.sy \
         no-mention.sy \
-        max2-univ.sy
+        max2-univ.sy \
+        strings-small.sy
 
 # sygus tests currently taking too long for make regress
 EXTRA_DIST = $(TESTS) \
diff --git a/test/regress/regress0/sygus/strings-small.sy b/test/regress/regress0/sygus/strings-small.sy
new file mode 100644 (file)
index 0000000..bc559f9
--- /dev/null
@@ -0,0 +1,35 @@
+; EXPECT: unsat
+; COMMAND-LINE: --cegqi-si --no-dump-synth
+(set-logic SLIA)
+(synth-fun f ((firstname String) (lastname String)) String
+((Start String (ntString))
+
+(ntString String (
+firstname 
+lastname 
+" "
+(str.++ ntString ntString)))
+
+(ntInt Int (
+0 
+1 
+2
+(+ ntInt ntInt)
+(- ntInt ntInt)
+(str.len ntString)
+(str.to.int ntString)
+(str.indexof ntString ntString ntInt)))
+
+(ntBool Bool (
+true 
+false
+(str.prefixof ntString ntString)
+(str.suffixof ntString ntString)
+(str.contains ntString ntString)))
+
+))
+
+(constraint (= (f "Nancy" "FreeHafer") "Nancy FreeHafer"))
+
+(check-synth)
+