Fix bug related to quantifiers + incremental, thanks John Backes for the bug report...
authorajreynol <andrew.j.reynolds@gmail.com>
Tue, 15 Sep 2015 08:39:29 +0000 (10:39 +0200)
committerajreynol <andrew.j.reynolds@gmail.com>
Tue, 15 Sep 2015 08:39:29 +0000 (10:39 +0200)
src/theory/quantifiers/conjecture_generator.cpp
src/theory/quantifiers/term_database.cpp
src/theory/quantifiers/term_database.h
src/theory/quantifiers_engine.cpp
src/theory/quantifiers_engine.h
src/theory/theory_model.cpp
src/theory/theory_model.h
test/regress/regress0/push-pop/Makefile.am
test/regress/regress0/push-pop/bug-fmf-fun-skolem.smt2 [new file with mode: 0644]

index 3cf60310039ad3bf06e94c19e371a502cd74df2d..896cf5dffe731dc61eaa1045ad3265cefea89d43 100644 (file)
@@ -1048,7 +1048,7 @@ void ConjectureGenerator::getEnumerateUfTerm( Node n, unsigned num, std::vector<
     for( unsigned i=0; i<n.getNumChildren(); i++ ){
       vec.push_back( 0 );
       TypeNode tn = n[i].getType();
-      if( TermDb::isClosedEnumerableType( tn ) ){
+      if( getTermDatabase()->isClosedEnumerableType( tn ) ){
         types.push_back( tn );
       }else{
         return;
index d076c6510065e48dd7551c0917281653c4d4cc3b..bb35ac4cda3e483c1fd120b5ab983435062bde6e 100644 (file)
@@ -418,7 +418,7 @@ bool TermDb::mayComplete( TypeNode tn ) {
   std::map< TypeNode, bool >::iterator it = d_may_complete.find( tn );
   if( it==d_may_complete.end() ){
     bool mc = false;
-    if( !tn.isArray() && tn.getCardinality().isFinite() && !tn.getCardinality().isLargeFinite() ){
+    if( isClosedEnumerableType( tn ) && tn.getCardinality().isFinite() && !tn.getCardinality().isLargeFinite() ){
       Node card = NodeManager::currentNM()->mkConst( Rational(tn.getCardinality().getFiniteCardinality()) );
       Node oth = NodeManager::currentNM()->mkConst( Rational(1000) );
       Node eq = NodeManager::currentNM()->mkNode( LEQ, card, oth );
@@ -964,7 +964,19 @@ Node TermDb::getEnumerateTerm( TypeNode tn, unsigned index ) {
 }
 
 bool TermDb::isClosedEnumerableType( TypeNode tn ) {
-  return !tn.isArray() && !tn.isSort() && !tn.isCodatatype();
+  std::map< TypeNode, bool >::iterator it = d_typ_closed_enum.find( tn );
+  if( it==d_typ_closed_enum.end() ){
+    bool ret = true;
+    if( tn.isArray() || tn.isSort() || tn.isCodatatype() ){
+      ret = false;
+    }else{
+      //TODO: all subfields must be closed enumerable?
+    }
+    d_typ_closed_enum[tn] = ret;
+    return ret;
+  }else{
+    return it->second;
+  }
 }
 
 Node TermDb::getFreeVariableForInstConstant( Node n ){
index fb80cb8a8be8aadbaf8e1e05beafccf13a6db644..7c136a1867d4757d2c02b6d6f71ffa484176a1df 100644 (file)
@@ -279,11 +279,13 @@ private:
   //type enumerators
   std::map< TypeNode, unsigned > d_typ_enum_map;
   std::vector< TypeEnumerator > d_typ_enum;
+  // closed enumerable type cache
+  std::map< TypeNode, bool > d_typ_closed_enum;
 public:
   //get nth term for type
   Node getEnumerateTerm( TypeNode tn, unsigned index );
   //does this type have an enumerator that produces constants that are handled by ground theory solvers
-  static bool isClosedEnumerableType( TypeNode tn );
+  bool isClosedEnumerableType( TypeNode tn );
 
 //miscellaneous
 public:
index 1a5be5a575a84de230737aa2a98415ad66a4f3d1..23d46fd406047379c8f17147430a6d751f42b9d9 100644 (file)
@@ -80,7 +80,8 @@ quantifiers::TermDb * QuantifiersModule::getTermDatabase() {
 
 QuantifiersEngine::QuantifiersEngine(context::Context* c, context::UserContext* u, TheoryEngine* te):
 d_te( te ),
-d_lemmas_produced_c(u){
+d_lemmas_produced_c(u),
+d_skolemized(u){
   d_eq_query = new EqualityQueryQuantifiersEngine( this );
   d_term_db = new quantifiers::TermDb( c, u, this );
   d_tr_trie = new inst::TriggerTrie;
@@ -1000,13 +1001,14 @@ void QuantifiersEngine::getPhaseReqTerms( Node f, std::vector< Node >& nodes ){
 
 void QuantifiersEngine::printInstantiations( std::ostream& out ) {
   bool printed = false;
-  for( std::map< Node, bool >::iterator it = d_skolemized.begin(); it != d_skolemized.end(); ++it ){
+  for( BoolMap::iterator it = d_skolemized.begin(); it != d_skolemized.end(); ++it ){
+    Node q = (*it).first;
     printed = true;
-    out << "Skolem constants of " << it->first << " : " << std::endl;
+    out << "Skolem constants of " << q << " : " << std::endl;
     out << "  ( ";
-    for( unsigned i=0; i<d_term_db->d_skolem_constants[it->first].size(); i++ ){
+    for( unsigned i=0; i<d_term_db->d_skolem_constants[q].size(); i++ ){
       if( i>0 ){ out << ", "; }
-      out << d_term_db->d_skolem_constants[it->first][i];
+      out << d_term_db->d_skolem_constants[q][i];
     }
     out << " )" << std::endl;
     out << std::endl;
index 2658d09f0ba114a27de62ed3893c2dac15d6252b..cc8baa1c0165f65786a33cc31d95e95b26aeb4b9 100644 (file)
@@ -178,7 +178,7 @@ private:
   std::map< Node, inst::InstMatchTrie > d_inst_match_trie;
   std::map< Node, inst::CDInstMatchTrie* > d_c_inst_match_trie;
   /** quantifiers that have been skolemized */
-  std::map< Node, bool > d_skolemized;
+  BoolMap d_skolemized;
   /** term database */
   quantifiers::TermDb* d_term_db;
   /** all triggers will be stored in this trie */
index 5766a26c1c7ccc17c27fbfe41fb9c719d9a6f0fc..c4bc94bd2fd643a8d13bf99c6910d06dd80345c4 100644 (file)
@@ -236,35 +236,6 @@ Node TheoryModel::getDomainValue( TypeNode tn, std::vector< Node >& exclude ){
   return Node::null();
 }
 
-//FIXME: need to ensure that theory enumerators exist for each sort
-Node TheoryModel::getNewDomainValue( TypeNode tn ){
-  if( tn.isSort() ){
-    return Node::null();
-  }else{
-    TypeEnumerator te(tn);
-    while( !te.isFinished() ){
-      Node r = *te;
-      if(Debug.isOn("getNewDomainValue")) {
-        Debug("getNewDomainValue") << "getNewDomainValue( " << tn << ")" << endl;
-        Debug("getNewDomainValue") << "+ TypeEnumerator gave: " << r << endl;
-        Debug("getNewDomainValue") << "+ d_type_reps are:";
-        for(vector<Node>::const_iterator i = d_rep_set.d_type_reps[tn].begin();
-            i != d_rep_set.d_type_reps[tn].end();
-            ++i) {
-          Debug("getNewDomainValue") << " " << *i;
-        }
-        Debug("getNewDomainValue") << endl;
-      }
-      if( std::find(d_rep_set.d_type_reps[tn].begin(), d_rep_set.d_type_reps[tn].end(), r) ==d_rep_set.d_type_reps[tn].end() ) {
-        Debug("getNewDomainValue") << "+ it's new, so returning " << r << endl;
-        return r;
-      }
-      ++te;
-    }
-    return Node::null();
-  }
-}
-
 /** add substitution */
 void TheoryModel::addSubstitution( TNode x, TNode t, bool invalidateCache ){
   if( !d_substitutions.hasSubstitution( x ) ){
index 092b5e8c76e1529487501d46a2d74a2572932d3b..e023edadd6339297d77dc1d7179b2444cc3b816a 100644 (file)
@@ -72,11 +72,6 @@ public:
     *   This function returns a term in d_rep_set.d_type_reps[tn] but not in exclude
     */
   Node getDomainValue( TypeNode tn, std::vector< Node >& exclude );
-  /** get new domain value
-    *   This function returns a constant term of type tn that is not in d_rep_set.d_type_reps[tn]
-    *   If it cannot find such a node, it returns null.
-    */
-  Node getNewDomainValue( TypeNode tn );
 public:
   /** Adds a substitution from x to t. */
   void addSubstitution(TNode x, TNode t, bool invalidateCache = true);
index bcd8da228acca290e047138a2dc6c1624683ecdc..501e7b2c6375c6e70a5b5a29c3859858a86ced98 100644 (file)
@@ -40,7 +40,8 @@ BUG_TESTS = \
   quant-fun-proc.smt2 \
   quant-fun-proc-unmacro.smt2 \
   quant-fun-proc-unfd.smt2 \
-  bug654-dd.smt2
+  bug654-dd.smt2 \
+  bug-fmf-fun-skolem.smt2
 
 TESTS =        $(SMT_TESTS) $(SMT2_TESTS) $(CVC_TESTS) $(BUG_TESTS)
 
diff --git a/test/regress/regress0/push-pop/bug-fmf-fun-skolem.smt2 b/test/regress/regress0/push-pop/bug-fmf-fun-skolem.smt2
new file mode 100644 (file)
index 0000000..d5effc0
--- /dev/null
@@ -0,0 +1,25 @@
+; COMMAND-LINE: --incremental --fmf-fun
+(set-logic ALL_SUPPORTED)
+(declare-datatypes () ((Lst (cons (head Int) (tail Lst)) (nil))))
+(define-fun-rec sum ((l Lst)) Int (ite (is-nil l) 0 (+ (head l) (sum (tail l)))))
+
+(declare-fun input () Int)
+(declare-fun p () Bool)
+(declare-fun acc () Lst)
+(assert (and (= acc (ite (>= input 0) (cons input nil) nil))
+             (= p (>= (sum acc) 0))))
+
+
+; EXPECT: unsat
+(push 1)
+(assert (not p))
+(check-sat)
+(pop 1)
+
+; EXPECT: unsat
+(push 1)
+(assert (not p))
+(check-sat)
+(pop 1)
+
+