Fix for collectModelInfo related to finite types + preregistration. Generalize previo...
authorajreynol <andrew.j.reynolds@gmail.com>
Fri, 3 Mar 2017 22:17:24 +0000 (16:17 -0600)
committerajreynol <andrew.j.reynolds@gmail.com>
Fri, 3 Mar 2017 22:17:24 +0000 (16:17 -0600)
src/theory/datatypes/theory_datatypes.cpp
src/theory/datatypes/theory_datatypes.h
src/theory/sep/theory_sep.cpp
src/theory/sets/theory_sets_private.cpp
src/theory/strings/theory_strings.cpp
src/theory/uf/theory_uf.cpp
test/regress/regress0/sets/Makefile.am
test/regress/regress0/sets/abt-te-exh2.smt2 [new file with mode: 0644]

index b66cb15ff8cf40cc7c660bba35302b1523d3e342..d285f292ad9fabee7da22e62c513f3db50800fee 100644 (file)
@@ -173,7 +173,7 @@ void TheoryDatatypes::check(Effort e) {
         return;
       }
     }while( d_addedFact );
-
+  
     //check for splits
     Trace("datatypes-debug") << "Check for splits " << e << endl;
     do {
@@ -183,6 +183,7 @@ void TheoryDatatypes::check(Effort e) {
       eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &d_equalityEngine );
       while( !eqcs_i.isFinished() ){
         Node n = (*eqcs_i);
+        //TODO : avoid irrelevant (pre-registered but not asserted) terms here?
         TypeNode tn = n.getType();
         if( tn.isDatatype() ){
           Trace("datatypes-debug") << "Process equivalence class " << n << std::endl;
@@ -1414,9 +1415,15 @@ void TheoryDatatypes::collectModelInfo( TheoryModel* m, bool fullModel ){
   Trace("dt-model") << std::endl;
   printModelDebug( "dt-model" );
   Trace("dt-model") << std::endl;
+  
+  set<Node> termSet;
+  
+  // Compute terms appearing in assertions and shared terms, and in inferred equalities
+  getRelevantTerms(termSet);
 
   //combine the equality engine
-  m->assertEqualityEngine( &d_equalityEngine );
+  m->assertEqualityEngine( &d_equalityEngine, &termSet );
+  
 
   //get all constructors
   eq::EqClassesIterator eqccs_i = eq::EqClassesIterator( &d_equalityEngine );
@@ -1426,18 +1433,22 @@ void TheoryDatatypes::collectModelInfo( TheoryModel* m, bool fullModel ){
   while( !eqccs_i.isFinished() ){
     Node eqc = (*eqccs_i);
     //for all equivalence classes that are datatypes
-    if( eqc.getType().isDatatype() ){
-      EqcInfo* ei = getOrMakeEqcInfo( eqc );
-      if( ei && !ei->d_constructor.get().isNull() ){
-        Node c = ei->d_constructor.get();
-        cons.push_back( c );
-        eqc_cons[ eqc ] = c;
-      }else{
-        //if eqc contains a symbol known to datatypes (a selector), then we must assign
-        //should assign constructors to EQC if they have a selector or a tester
-        bool shouldConsider = ( ei && ei->d_selectors ) || hasTester( eqc );
-        if( shouldConsider ){
-          nodes.push_back( eqc );
+    if( termSet.find( eqc )==termSet.end() ){
+      Trace("dt-cmi-debug") << "Irrelevant eqc : " << eqc << std::endl;
+    }else{
+      if( eqc.getType().isDatatype() ){
+        EqcInfo* ei = getOrMakeEqcInfo( eqc );
+        if( ei && !ei->d_constructor.get().isNull() ){
+          Node c = ei->d_constructor.get();
+          cons.push_back( c );
+          eqc_cons[ eqc ] = c;
+        }else{
+          //if eqc contains a symbol known to datatypes (a selector), then we must assign
+          //should assign constructors to EQC if they have a selector or a tester
+          bool shouldConsider = ( ei && ei->d_selectors ) || hasTester( eqc );
+          if( shouldConsider ){
+            nodes.push_back( eqc );
+          }
         }
       }
     }
@@ -1456,54 +1467,6 @@ void TheoryDatatypes::collectModelInfo( TheoryModel* m, bool fullModel ){
     const Datatype& dt = ((DatatypeType)tt).getDatatype();
     if( !d_equalityEngine.hasTerm( eqc ) ){
       Assert( false );
-      /*
-      if( !dt.isCodatatype() ){
-        Trace("dt-cmi") << "NOTICE : Datatypes: need to assign constructor for " << eqc << std::endl;
-        Trace("dt-cmi") << "   Type : " << eqc.getType() << std::endl;
-        TypeNode tn = eqc.getType();
-        //if it is infinite, make sure it is fresh
-        //  this ensures that the term that this is an argument of is distinct.
-        if( eqc.getType().getCardinality().isInfinite() ){
-          std::map< TypeNode, int >::iterator it = typ_enum_map.find( tn );
-          int teIndex;
-          if( it==typ_enum_map.end() ){
-            teIndex = (int)typ_enum.size();
-            typ_enum_map[tn] = teIndex;
-            typ_enum.push_back( TypeEnumerator(tn) );
-          }else{
-            teIndex = it->second;
-          }
-          bool success;
-          do{
-            success = true;
-            Assert( !typ_enum[teIndex].isFinished() );
-            neqc = *typ_enum[teIndex];
-            Trace("dt-cmi-debug") << "Try " << neqc << " ... " << std::endl;
-            ++typ_enum[teIndex];
-            for( unsigned i=0; i<cons.size(); i++ ){
-              //check if it is modulo equality the same
-              if( cons[i].getOperator()==neqc.getOperator() ){
-                bool diff = false;
-                for( unsigned j=0; j<cons[i].getNumChildren(); j++ ){
-                  if( !m->areEqual( cons[i][j], neqc[j] ) ){
-                    diff = true;
-                    break;
-                  }
-                }
-                if( !diff ){
-                  Trace("dt-cmi-debug") << "...Already equivalent modulo equality to " << cons[i] << std::endl;
-                  success = false;
-                  break;
-                }
-              }
-            }
-          }while( !success );
-        }else{
-          TypeEnumerator te(tn);
-          neqc = *te;
-        }
-      }
-      */
     }else{
       Trace("dt-cmi") << "NOTICE : Datatypes: no constructor in equivalence class " << eqc << std::endl;
       Trace("dt-cmi") << "   Type : " << eqc.getType() << std::endl;
@@ -2186,6 +2149,34 @@ bool TheoryDatatypes::checkClashModEq( TNode n1, TNode n2, std::vector< Node >&
   return false;
 }
 
+void TheoryDatatypes::getRelevantTerms( std::set<Node>& termSet ) {
+  // Compute terms appearing in assertions and shared terms
+  computeRelevantTerms(termSet);
+  
+  //also include non-singleton equivalence classes
+  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &d_equalityEngine );
+  while( !eqcs_i.isFinished() ){
+    TNode r = (*eqcs_i);
+    bool addedFirst = false;
+    Node first;
+    eq::EqClassIterator eqc_i = eq::EqClassIterator( r, &d_equalityEngine );
+    while( !eqc_i.isFinished() ){
+      TNode n = (*eqc_i);
+      if( first.isNull() ){
+        first = n;
+      }else{
+        if( !addedFirst ){
+          addedFirst = true;
+          termSet.insert( first );
+        }
+        termSet.insert( n );
+      }
+      ++eqc_i;
+    }
+    ++eqcs_i;
+  }
+}
+
 std::pair<bool, Node> TheoryDatatypes::entailmentCheck(TNode lit, const EntailmentCheckParameters* params, EntailmentCheckSideEffects* out) {
   Trace("dt-entail") << "Check entailed : " << lit << std::endl;
   Node atom = lit.getKind()==NOT ? lit[0] : lit;
index 49c45590c96956dfb3345e640a61c16c08129724..770c3a9d4250633718fb4f8a07467a0e09a4c71e 100644 (file)
@@ -310,6 +310,8 @@ private:
   bool mustCommunicateFact( Node n, Node exp );
   /** check clash mod eq */
   bool checkClashModEq( TNode n1, TNode n2, std::vector< Node >& exp, std::vector< std::pair< TNode, TNode > >& deq_cand );
+  /** get relevant terms */
+  void getRelevantTerms( std::set<Node>& termSet );
 private:
   //equality queries
   bool hasTerm( TNode a );
index 81afc0da256787f2650f029bee7eb90da30f6a26..4f31f10b5a9f5231d0c5bd1ee4ddb11ed5a04d9c 100644 (file)
@@ -201,8 +201,13 @@ void TheorySep::computeCareGraph() {
 
 
 void TheorySep::collectModelInfo( TheoryModel* m, bool fullModel ){
+  set<Node> termSet;
+
+  // Compute terms appearing in assertions and shared terms
+  computeRelevantTerms(termSet);
+
   // Send the equality engine information to the model
-  m->assertEqualityEngine( &d_equalityEngine );
+  m->assertEqualityEngine( &d_equalityEngine, &termSet );
 }
 
 void TheorySep::postProcessModel( TheoryModel* m ){
index 7d2bbf3d12529e601ba6745780cb0ab84053be0c..e78575791690929dcd3f0fcdb9d5c521f0483fc1 100644 (file)
@@ -506,7 +506,6 @@ void TheorySetsPrivate::fullEffortCheck(){
     d_sentLemma = false;
     d_addedFact = false;
     d_set_eqc.clear();
-    d_set_eqc_relevant.clear();
     d_set_eqc_list.clear();
     d_eqc_emptyset.clear();
     d_eqc_singleton.clear();
@@ -532,9 +531,6 @@ void TheorySetsPrivate::fullEffortCheck(){
       if( tn.isSet() ){
         isSet = true;
         d_set_eqc.push_back( eqc );
-        if( d_equalityEngine.isTriggerTerm(eqc, THEORY_SETS) ){
-          d_set_eqc_relevant[eqc] = true;
-        }
       }
       Trace("sets-eqc") << "[" << eqc << "] : ";
       eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &d_equalityEngine );
@@ -551,7 +547,6 @@ void TheorySetsPrivate::fullEffortCheck(){
             if( pindex!=-1  ){
               if( d_pol_mems[pindex][s].find( x )==d_pol_mems[pindex][s].end() ){
                 d_pol_mems[pindex][s][x] = n;
-                d_set_eqc_relevant[s] = true;
                 Trace("sets-debug2") << "Membership[" << x << "][" << s << "] : " << n << ", pindex = " << pindex << std::endl;
               }
               if( d_members_index[s].find( x )==d_members_index[s].end() ){
@@ -579,8 +574,6 @@ void TheorySetsPrivate::fullEffortCheck(){
           }else{
             Node r1 = d_equalityEngine.getRepresentative( n[0] );
             Node r2 = d_equalityEngine.getRepresentative( n[1] );
-            d_set_eqc_relevant[r1] = true;
-            d_set_eqc_relevant[r2] = true;
             if( d_bop_index[n.getKind()][r1].find( r2 )==d_bop_index[n.getKind()][r1].end() ){
               d_bop_index[n.getKind()][r1][r2] = n;
               d_op_list[n.getKind()].push_back( n );
@@ -601,7 +594,6 @@ void TheorySetsPrivate::fullEffortCheck(){
             //TODO: extend approach for this case
           }
           Node r = d_equalityEngine.getRepresentative( n[0] );
-          d_set_eqc_relevant[r] = true;
           if( d_eqc_to_card_term.find( r )==d_eqc_to_card_term.end() ){
             d_eqc_to_card_term[ r ] = n;
             registerCardinalityTerm( n[0], lemmas );
@@ -1740,14 +1732,18 @@ EqualityStatus TheorySetsPrivate::getEqualityStatus(TNode a, TNode b) {
 
 
 void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel) {
-  Trace("sets") << "Set collect model info" << std::endl;
+  Trace("sets-model") << "Set collect model info" << std::endl;
+  set<Node> termSet;
+  // Compute terms appearing in assertions and shared terms
+  d_external.computeRelevantTerms(termSet);
+  
   // Assert equalities and disequalities to the model
-  m->assertEqualityEngine(&d_equalityEngine);
+  m->assertEqualityEngine(&d_equalityEngine,&termSet);
   
   std::map< Node, Node > mvals;
   for( int i=(int)(d_set_eqc.size()-1); i>=0; i-- ){
     Node eqc = d_set_eqc[i];
-    if( d_set_eqc_relevant.find( eqc )==d_set_eqc_relevant.end() ){
+    if( termSet.find( eqc )==termSet.end() ){
       Trace("sets-model") << "* Do not assign value for " << eqc << " since is not relevant." << std::endl;
     }else{
       std::vector< Node > els;
index 09cc3cb3b663878453c98d89f21aa4e07c02753e..45a6a93d19db55a335ae43f6aa386bf0a7b00efe 100644 (file)
@@ -442,7 +442,16 @@ void TheoryStrings::presolve() {
 void TheoryStrings::collectModelInfo( TheoryModel* m, bool fullModel ) {
   Trace("strings-model") << "TheoryStrings : Collect model info, fullModel = " << fullModel << std::endl;
   Trace("strings-model") << "TheoryStrings : assertEqualityEngine." << std::endl;
+  
+  //AJR : no use doing this since we cannot preregister terms with finite types that don't belong to strings.
+  //      change this if we generalize to sequences.
+  //set<Node> termSet;
+  // Compute terms appearing in assertions and shared terms
+  //computeRelevantTerms(termSet);
+  //m->assertEqualityEngine( &d_equalityEngine, &termSet );
+  
   m->assertEqualityEngine( &d_equalityEngine );
+  
   // Generate model
   std::vector< Node > nodes;
   getEquivalenceClasses( nodes );
index e4a3ac78c95e76c1b16799b653b29dea0ddc9d1e..35aee53050fa446602c8c48cd3b2a7742858444b 100644 (file)
@@ -246,7 +246,12 @@ Node TheoryUF::explain(TNode literal, eq::EqProof* pf) {
 }
 
 void TheoryUF::collectModelInfo( TheoryModel* m, bool fullModel ){
-  m->assertEqualityEngine( &d_equalityEngine );
+  set<Node> termSet;
+
+  // Compute terms appearing in assertions and shared terms
+  computeRelevantTerms(termSet);
+
+  m->assertEqualityEngine( &d_equalityEngine, &termSet );
   // if( fullModel ){
   //   std::map< TypeNode, TypeEnumerator* > type_enums;
   //   //must choose proper representatives
index 62f8665ec65bbd72d01ba0a489bee6e92bbdf1f9..f4f921c43e2b04c009f049e11fd78e753f212d9c 100644 (file)
@@ -73,8 +73,8 @@ TESTS =       \
        card-6.smt2 \
        card-7.smt2 \
        abt-min.smt2 \
-       abt-te-exh.smt2
-
+       abt-te-exh.smt2 \
+       abt-te-exh2.smt2
 
 EXTRA_DIST = $(TESTS)
 
diff --git a/test/regress/regress0/sets/abt-te-exh2.smt2 b/test/regress/regress0/sets/abt-te-exh2.smt2
new file mode 100644 (file)
index 0000000..9ff80e1
--- /dev/null
@@ -0,0 +1,24 @@
+; COMMAND-LINE: --finite-model-find
+; EXPECT: sat
+(set-logic ALL)
+(declare-sort Atom 0)
+
+(declare-fun p ((Set Atom) (Set Atom)) (Set Atom))
+(declare-fun j ((Set Atom) (Set Atom)) (Set Atom))
+(declare-fun k ((Set Atom) (Set Atom)) (Set Atom))
+(declare-fun d ((Set Atom) (Set Atom)) (Set Atom))
+
+(declare-fun a () (Set Atom))
+(declare-fun n () Atom)
+(declare-fun v () Atom)
+
+(assert (forall ((b Atom) (c Atom)) 
+(or 
+(member v (k (singleton n) (j (singleton b) a)))
+(= (as emptyset (Set Atom)) (d (j (singleton b) a) (singleton n)))
+)
+)
+)
+
+(check-sat)
+