Fix related to parametric sorts whose interpretation is finite due to uninterpreted...
authorajreynol <andrew.j.reynolds@gmail.com>
Mon, 23 May 2016 19:28:29 +0000 (14:28 -0500)
committerajreynol <andrew.j.reynolds@gmail.com>
Mon, 23 May 2016 19:28:29 +0000 (14:28 -0500)
12 files changed:
src/expr/datatype.cpp
src/expr/datatype.h
src/expr/type_node.cpp
src/expr/type_node.h
src/theory/datatypes/theory_datatypes.cpp
src/theory/datatypes/type_enumerator.cpp
src/theory/datatypes/type_enumerator.h
src/theory/quantifiers/quant_split.cpp
src/theory/term_registration_visitor.cpp
src/theory/theory_model.cpp
test/regress/regress0/fmf/Makefile.am
test/regress/regress0/fmf/sc-crash-052316.smt2 [new file with mode: 0644]

index d14ac26d40034576e76afe93c4493fe5ae652bb3..001f38a79499916f95006b0af072ec2d2cdfca57 100644 (file)
@@ -297,7 +297,7 @@ bool Datatype::isFinite() const throw(IllegalArgumentException) {
   return true;
 }
 
-bool Datatype::isUFinite() const throw(IllegalArgumentException) {
+bool Datatype::isInterpretedFinite() const throw(IllegalArgumentException) {
   PrettyCheckArgument(isResolved(), this, "this datatype is not yet resolved");
   // we're using some internals, so we have to set up this library context
   ExprManagerScope ems(d_self);
@@ -310,7 +310,7 @@ bool Datatype::isUFinite() const throw(IllegalArgumentException) {
   self.setAttribute(DatatypeUFiniteComputedAttr(), true);
   self.setAttribute(DatatypeUFiniteAttr(), false);
   for(const_iterator i = begin(), i_end = end(); i != i_end; ++i) {
-    if(! (*i).isUFinite()) {
+    if(! (*i).isInterpretedFinite()) {
       return false;
     }
   }
@@ -850,7 +850,7 @@ bool DatatypeConstructor::isFinite() const throw(IllegalArgumentException) {
   return true;
 }
 
-bool DatatypeConstructor::isUFinite() const throw(IllegalArgumentException) {
+bool DatatypeConstructor::isInterpretedFinite() const throw(IllegalArgumentException) {
   PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
   // we're using some internals, so we have to set up this library context
   ExprManagerScope ems(d_constructor);
@@ -859,18 +859,9 @@ bool DatatypeConstructor::isUFinite() const throw(IllegalArgumentException) {
   if(self.getAttribute(DatatypeUFiniteComputedAttr())) {
     return self.getAttribute(DatatypeUFiniteAttr());
   }
-  bool success = true;
   for(const_iterator i = begin(), i_end = end(); i != i_end; ++i) {
-    Type t = (*i).getRangeType();
-    if( t.isDatatype() ){
-      const Datatype& dt = ((DatatypeType)t).getDatatype();
-      if( !dt.isUFinite() ){
-        success = false;
-      }
-    }else if(!t.isSort() && !t.getCardinality().isFinite()) {
-      success = false;
-    }
-    if(!success ){
+    TypeNode t = TypeNode::fromType( (*i).getRangeType() );
+    if(!t.isInterpretedFinite()) {
       self.setAttribute(DatatypeUFiniteComputedAttr(), true);
       self.setAttribute(DatatypeUFiniteAttr(), false);
       return false;
index 1197b4a3bd045f95743e1f661b49a38266326d01..dfd893fe8288b789923a7a4bd272e6e9435251b4 100644 (file)
@@ -342,7 +342,7 @@ public:
    * uninterpreted sorts are finite.  This function can
    * only be called for resolved constructors.
    */
-  bool isUFinite() const throw(IllegalArgumentException);
+  bool isInterpretedFinite() const throw(IllegalArgumentException);
 
   /**
    * Returns true iff this Datatype constructor has already been
@@ -634,7 +634,7 @@ public:
    * datatype is  not well-founded, this function  returns false.  The
    * Datatype must be resolved or an exception is thrown.
    */
-  bool isUFinite() const throw(IllegalArgumentException);
+  bool isInterpretedFinite() const throw(IllegalArgumentException);
 
   /**
    * Return true iff this datatype is well-founded (there exist ground
index 5d672e6ac782fbc603435ab08b6eecbca606b6ed..dc2370bead5bf2b52a8f45516fb85415a7588bb0 100644 (file)
@@ -21,6 +21,7 @@
 #include "expr/type_properties.h"
 #include "options/base_options.h"
 #include "options/expr_options.h"
+#include "options/quantifiers_options.h"
 
 using namespace std;
 
@@ -64,6 +65,26 @@ Cardinality TypeNode::getCardinality() const {
   return kind::getCardinality(*this);
 }
 
+bool TypeNode::isInterpretedFinite() const {
+  if( getCardinality().isFinite() ){
+    return true;
+  }else{
+    if( options::finiteModelFind() ){
+      if( isSort() ){
+        return true;
+      }else if( isDatatype() || isParametricDatatype() ){
+        const Datatype& dt = getDatatype();
+        return dt.isInterpretedFinite();
+      }else if( isArray() ){
+        return getArrayIndexType().isInterpretedFinite() && getArrayConstituentType().isInterpretedFinite();
+      }else if( isSet() ) {
+        return getSetElementType().isInterpretedFinite();
+      }
+    }
+    return false;
+  }
+}
+
 bool TypeNode::isWellFounded() const {
   return kind::isWellFounded(*this);
 }
index cfb61a0855d4bdbd03c3e3fb6ef65726d9745a30..46fdaa143b3f7ebd37229cd2c9c710dd7e7da0a5 100644 (file)
@@ -419,6 +419,13 @@ public:
    * @return a finite or infinite cardinality
    */
   Cardinality getCardinality() const;
+  
+  /**
+   * Is this type interpreted as being finite.
+   * If finite model finding is enabled, this assumes all uninterpreted sorts 
+   *   are interpreted as finite.
+   */
+  bool isInterpretedFinite() const;
 
   /**
    * Returns whether this type is well-founded.
index 0100f1833f19bc533e867f658d0eb43aa9af9f50..95d704a0e19055d662d7876e7e9d2b98aec74f30 100644 (file)
@@ -191,7 +191,7 @@ void TheoryDatatypes::check(Effort e) {
           if( !hasLabel( eqc, n ) ){
             Trace("datatypes-debug") << "No constructor..." << std::endl;
             const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
-            Trace("datatypes-debug") << "Datatype " << dt << " is " << dt.isFinite() << " " << dt.isUFinite() << " " << dt.isRecursiveSingleton() << std::endl;
+            Trace("datatypes-debug") << "Datatype " << dt << " is " << dt.isFinite() << " " << dt.isInterpretedFinite() << " " << dt.isRecursiveSingleton() << std::endl;
             bool continueProc = true;
             if( dt.isRecursiveSingleton() ){
               Trace("datatypes-debug") << "Check recursive singleton..." << std::endl;
@@ -252,7 +252,7 @@ void TheoryDatatypes::check(Effort e) {
                   if( consIndex==-1 ){
                     consIndex = j;
                   }
-                  if( options::finiteModelFind() ? !dt[ j ].isUFinite() : !dt[ j ].isFinite() ) {
+                  if( !dt[ j ].isInterpretedFinite() ) {
                     if( !eqc || !eqc->d_selectors ){
                       needSplit = false;
                     }
@@ -1497,7 +1497,7 @@ void TheoryDatatypes::collectModelInfo( TheoryModel* m, bool fullModel ){
         if( neqc.isNull() ){
           for( unsigned i=0; i<pcons.size(); i++ ){
             //must try the infinite ones first
-            bool cfinite = options::finiteModelFind() ? dt[ i ].isUFinite() : dt[ i ].isFinite();
+            bool cfinite = dt[ i ].isInterpretedFinite();
             if( pcons[i] && (r==1)==cfinite ){
               neqc = DatatypesRewriter::getInstCons( eqc, dt, i );
               //for( unsigned j=0; j<neqc.getNumChildren(); j++ ){
index 6c1155237595c799449d95f6024d68c5f475d232..c0539743f79ad78b48943564291cd8a531cb7077 100644 (file)
@@ -172,7 +172,7 @@ Node DatatypesEnumerator::getTermEnum( TypeNode tn, unsigned i ){
    Debug("dt-enum") << "datatype is " << d_type << std::endl;
    Debug("dt-enum") << "properties : " << d_datatype.isCodatatype() << " " << d_datatype.isRecursiveSingleton();
    Debug("dt-enum") << " " << d_datatype.isFinite() << std::endl;
-   Debug("dt-enum") << " " << d_datatype.isUFinite() << std::endl;
+   Debug("dt-enum") << " " << d_datatype.isInterpretedFinite() << std::endl;
 
    if( d_datatype.isCodatatype() && hasCyclesDt( d_datatype ) ){
      //start with uninterpreted constant
index bbfd951b3cc57f8fef2f789c0407072567477f7a..8473b5d69153964f32e93f10b92703e9a08c1a2a 100644 (file)
@@ -159,7 +159,7 @@ public:
       }
       if( d_ctor>=d_has_debruijn+d_datatype.getNumConstructors() ){
         //try next size limit as long as new terms were generated at last size, or other cases
-        if( prevSize==d_size_limit || ( d_size_limit==0 && d_datatype.isCodatatype() ) || ( options::finiteModelFind() ? !d_datatype.isUFinite() : !d_datatype.isFinite() ) ){
+        if( prevSize==d_size_limit || ( d_size_limit==0 && d_datatype.isCodatatype() ) || !d_datatype.isInterpretedFinite() ){
           d_size_limit++;
           d_ctor = d_zeroCtor;
           for( unsigned i=0; i<d_sel_sum.size(); i++ ){
index 9fb943e5ee9ebc76a7d7489f4bf9ac09383435cc..5aff1a848a50520e6f192d8d8c1c76c6854620b7 100644 (file)
@@ -48,11 +48,11 @@ void QuantDSplit::preRegisterQuantifier( Node q ) {
       }else{
         int score = -1;
         if( options::quantDynamicSplit()==quantifiers::QUANT_DSPLIT_MODE_AGG ){
-          score = dt.isUFinite() ? 1 : -1;
+          score = dt.isInterpretedFinite() ? 1 : -1;
         }else if( options::quantDynamicSplit()==quantifiers::QUANT_DSPLIT_MODE_DEFAULT ){
-          score = dt.isUFinite() ? 1 : -1;
+          score = dt.isInterpretedFinite() ? 1 : -1;
         }
-        Trace("quant-dsplit-debug") << "Datatype " << dt.getName() << " is score " << score << " (" << dt.isUFinite() << " " << dt.isFinite() << ")" << std::endl;
+        Trace("quant-dsplit-debug") << "Datatype " << dt.getName() << " is score " << score << " (" << dt.isInterpretedFinite() << " " << dt.isFinite() << ")" << std::endl;
         if( score>max_score ){
           max_index = i;
           max_score = score;
index 830e7f8096922f1c75e1e96b3a80e4b8ebdd0e89..6b268805ac8426b1c6a79804c658638bad95a983 100644 (file)
@@ -64,14 +64,8 @@ bool PreRegisterVisitor::alreadyVisited(TNode current, TNode parent) {
       TypeNode type = current.getType();
       typeTheoryId = Theory::theoryOf(type);
       if (typeTheoryId != currentTheoryId) {
-        if (options::finiteModelFind() && type.isSort()) {
-          // We're looking for finite models
+        if (type.isInterpretedFinite()) {
           useType = true;
-        } else {
-          Cardinality card = type.getCardinality();
-          if (card.isFinite()) {
-            useType = true;
-          }
         }
       }
     }
@@ -130,14 +124,8 @@ void PreRegisterVisitor::visit(TNode current, TNode parent) {
       TypeNode type = current.getType();
       typeTheoryId = Theory::theoryOf(type);
       if (typeTheoryId != currentTheoryId) {
-        if (options::finiteModelFind() && type.isSort()) {
-          // We're looking for finite models
+        if (type.isInterpretedFinite()) {
           useType = true;
-        } else {
-          Cardinality card = type.getCardinality();
-          if (card.isFinite()) {
-            useType = true;
-          }
         }
       }
     }
@@ -222,14 +210,8 @@ bool SharedTermsVisitor::alreadyVisited(TNode current, TNode parent) const {
       TypeNode type = current.getType();
       typeTheoryId = Theory::theoryOf(type);
       if (typeTheoryId != currentTheoryId) {
-        if (options::finiteModelFind() && type.isSort()) {
-          // We're looking for finite models
+        if (type.isInterpretedFinite()) {
           useType = true;
-        } else {
-          Cardinality card = type.getCardinality();
-          if (card.isFinite()) {
-            useType = true;
-          }
         }
       }
     }
@@ -244,14 +226,8 @@ bool SharedTermsVisitor::alreadyVisited(TNode current, TNode parent) const {
       TypeNode type = current.getType();
       typeTheoryId = Theory::theoryOf(type);
       if (typeTheoryId != currentTheoryId) {
-        if (options::finiteModelFind() && type.isSort()) {
-          // We're looking for finite models
+        if (type.isInterpretedFinite()) {
           useType = true;
-        } else {
-          Cardinality card = type.getCardinality();
-          if (card.isFinite()) {
-            useType = true;
-          }
         }
       }
     }
@@ -297,14 +273,8 @@ void SharedTermsVisitor::visit(TNode current, TNode parent) {
       TypeNode type = current.getType();
       typeTheoryId = Theory::theoryOf(type);
       if (typeTheoryId != currentTheoryId) {
-        if (options::finiteModelFind() && type.isSort()) {
-          // We're looking for finite models
+        if (type.isInterpretedFinite()) {
           useType = true;
-        } else {
-          Cardinality card = type.getCardinality();
-          if (card.isFinite()) {
-            useType = true;
-          }
         }
       }
     }
index fa7e497e2e9760f33ebd16679075da5d5d60189a..6889d100200d39b644230c086a8077bd7e786dbe 100644 (file)
@@ -832,6 +832,7 @@ void TheoryEngineModelBuilder::buildModel(Model* m, bool fullModel)
           Assert(!t.isBoolean() || (*i2).getKind() == kind::APPLY_UF);
           Node n;
           if (t.getCardinality().isInfinite()) {
+          // if (!t.isInterpretedFinite()) {
             bool success;
             do{
               Trace("model-builder-debug") << "Enumerate term of type " << t << std::endl;
index 575aa4159d6b9883b5e63b962edc8cc74cac276b..6e1c6e91859744b26f4949fbe866172a3d61b6e7 100644 (file)
@@ -55,7 +55,8 @@ TESTS =       \
        datatypes-ufinite-nested.smt2 \
        ForElimination-scala-9.smt2 \
        agree466.smt2 \
-       LeftistHeap.scala-8-ncm.smt2
+       LeftistHeap.scala-8-ncm.smt2 \
+       sc-crash-052316.smt2
 
 EXTRA_DIST = $(TESTS)
 
diff --git a/test/regress/regress0/fmf/sc-crash-052316.smt2 b/test/regress/regress0/fmf/sc-crash-052316.smt2
new file mode 100644 (file)
index 0000000..2fc86cb
--- /dev/null
@@ -0,0 +1,35 @@
+; COMMAND-LINE: --finite-model-find
+; EXPECT: unsat
+  (set-logic ALL_SUPPORTED)
+  (set-info :status unsat)
+  (declare-sort g_ 0)
+  (declare-fun __nun_card_witness_0_ () g_)
+  (declare-sort f_ 0)
+  (declare-fun __nun_card_witness_1_ () f_)
+  (declare-sort e_ 0)
+  (declare-fun __nun_card_witness_2_ () e_)
+(declare-datatypes ()
+ ((prod1_ (Pair1_ (_select_Pair1__0 e_) (_select_Pair1__1 f_)))))
+  (declare-sort d_ 0)
+  (declare-fun __nun_card_witness_3_ () d_)
+  (declare-sort c_ 0)
+  (declare-fun __nun_card_witness_4_ () c_)
+  (declare-sort b_ 0)
+  (declare-fun __nun_card_witness_5_ () b_)
+  (declare-sort a_ 0)
+  (declare-fun __nun_card_witness_6_ () a_)
+(declare-datatypes ()
+ ((prod_ (Pair_ (_select_Pair__0 a_) (_select_Pair__1 b_)))))
+  (declare-fun f1_ (prod_ c_ d_ prod1_) g_)
+  (declare-fun g1_ (prod_) c_)
+  (declare-fun h_ (prod_ d_) prod1_)
+  (declare-fun nun_sk_0_ () prod_)
+(declare-fun nun_sk_1_ (c_) d_)
+  (assert
+   (not
+    (exists ((v/72 c_))
+     (exists ((x/73 prod1_))
+      (= (f1_ nun_sk_0_ v/72 (nun_sk_1_ v/72) x/73)
+       (f1_ nun_sk_0_ (g1_ nun_sk_0_) (nun_sk_1_ v/72)
+        (h_ nun_sk_0_ (nun_sk_1_ v/72))))))))
+(check-sat)