Support for separation logic + EPR. Refactor preprocessing of sep.nil, only allow...
authorajreynol <andrew.j.reynolds@gmail.com>
Fri, 9 Sep 2016 19:14:09 +0000 (14:14 -0500)
committerajreynol <andrew.j.reynolds@gmail.com>
Fri, 9 Sep 2016 19:14:09 +0000 (14:14 -0500)
43 files changed:
src/options/quantifiers_options
src/options/sep_options
src/smt/smt_engine.cpp
src/theory/quantifiers_engine.cpp
src/theory/sep/theory_sep.cpp
src/theory/sep/theory_sep.h
test/regress/regress0/sep/Makefile.am
test/regress/regress0/sep/chain-int.smt2
test/regress/regress0/sep/crash1220.smt2
test/regress/regress0/sep/dispose-list-4-init.smt2
test/regress/regress0/sep/dup-nemp.smt2
test/regress/regress0/sep/emp2-quant-unsat.smt2 [new file with mode: 0644]
test/regress/regress0/sep/loop-1220.smt2
test/regress/regress0/sep/nemp.smt2
test/regress/regress0/sep/nspatial-simp.smt2
test/regress/regress0/sep/pto-01.smt2
test/regress/regress0/sep/pto-02.smt2
test/regress/regress0/sep/pto-04.smt2
test/regress/regress0/sep/sep-01.smt2
test/regress/regress0/sep/sep-02.smt2
test/regress/regress0/sep/sep-03.smt2
test/regress/regress0/sep/sep-find2.smt2
test/regress/regress0/sep/sep-neg-1refine.smt2
test/regress/regress0/sep/sep-neg-nstrict.smt2
test/regress/regress0/sep/sep-neg-nstrict2.smt2
test/regress/regress0/sep/sep-neg-simple.smt2
test/regress/regress0/sep/sep-neg-swap.smt2
test/regress/regress0/sep/sep-nterm-again.smt2
test/regress/regress0/sep/sep-nterm-val-model.smt2
test/regress/regress0/sep/sep-plus1.smt2
test/regress/regress0/sep/sep-simp-unc.smt2
test/regress/regress0/sep/sep-simp-unsat-emp.smt2
test/regress/regress0/sep/simple-neg-sat.smt2
test/regress/regress0/sep/split-find-unsat-w-emp.smt2
test/regress/regress0/sep/split-find-unsat.smt2
test/regress/regress0/sep/wand-0526-sat.smt2
test/regress/regress0/sep/wand-crash.smt2
test/regress/regress0/sep/wand-false.smt2
test/regress/regress0/sep/wand-nterm-simp.smt2
test/regress/regress0/sep/wand-nterm-simp2.smt2
test/regress/regress0/sep/wand-simp-sat.smt2
test/regress/regress0/sep/wand-simp-sat2.smt2
test/regress/regress0/sep/wand-simp-unsat.smt2

index 462995becb22b65b3b412d3699e81a1ce715cc9a..606e33d757931eea1cdef931464d5b7b50e3d684 100644 (file)
@@ -310,7 +310,7 @@ option cbqiInnermost --cbqi-innermost bool :read-write :default true
 option cbqiNestedQE --cbqi-nested-qe bool :default false
  process nested quantified formulas with quantifier elimination in counterexample-based quantifier instantiation
  
-option quantEpr --quant-epr bool :default false
+option quantEpr --quant-epr bool :default false :read-write
  infer whether in effectively propositional fragment, use for cbqi
  
 ### local theory extensions options 
index 043355bdafb3033fefc40d1831ea2cd4d72aeff3..fecf4401e614f1376376cf52cfd257f5936c167c 100644 (file)
@@ -12,8 +12,6 @@ option sepExp --sep-exp bool :default false
  experimental flag for sep
 option sepMinimalRefine --sep-min-refine bool :default false
  only add refinement lemmas for minimal (innermost) assertions
-option sepPreciseBound --sep-prec-bound bool :default false
- calculate precise bounds for labels
 option sepDisequalC --sep-deq-c bool :default true
  assume cardinality elements are distinct
 
index 9c88381130a0409b3d26d95b1d531a60dbe98285..93e62f79d86b4f4a8b0a922ef8036c9989fc6167 100644 (file)
@@ -1690,6 +1690,7 @@ void SmtEngine::setDefaults() {
     //disable modes not supported by incremental
     options::sortInference.set( false );
     options::ufssFairnessMonotone.set( false );
+    options::quantEpr.set( false );
   }
   if( d_logic.hasCardinalityConstraints() ){
     //must have finite model finding on
index 316357ef2ef191ba8bc42815ed8c249ac5def7ea..7c1fd82d3deecc780a776177be1fd0f6672fbfc4 100644 (file)
@@ -19,6 +19,7 @@
 #include "smt/smt_statistics_registry.h"
 #include "theory/arrays/theory_arrays.h"
 #include "theory/datatypes/theory_datatypes.h"
+#include "theory/sep/theory_sep.h"
 #include "theory/quantifiers/alpha_equivalence.h"
 #include "theory/quantifiers/ambqi_builder.h"
 #include "theory/quantifiers/bounded_integers.h"
@@ -113,11 +114,8 @@ QuantifiersEngine::QuantifiersEngine(context::Context* c, context::UserContext*
   }
 
   if( options::quantEpr() ){
-    if( !options::incrementalSolving() ){
-      d_qepr = new QuantEPR;
-    }else{
-      d_qepr = NULL;
-    }
+    Assert( !options::incrementalSolving() );
+    d_qepr = new QuantEPR;
   }else{
     d_qepr = NULL;
   }
@@ -367,6 +365,9 @@ void QuantifiersEngine::ppNotifyAssertions( std::vector< Node >& assertions ) {
       }
     }
     if( d_qepr!=NULL ){
+      //must handle sources of other new constants e.g. separation logic
+      //FIXME: cleanup
+      ((sep::TheorySep*)getTheoryEngine()->theoryOf( THEORY_SEP ))->initializeBounds();
       d_qepr->finishInit(); 
     }
   }
index 8ab92368a8a69381e9f187683c1eb2d874032728..eefc0e779fb7936619ff7292c1d01876fa3e0dc3 100644 (file)
@@ -26,6 +26,7 @@
 #include "smt/logic_exception.h"
 #include "theory/quantifiers_engine.h"
 #include "theory/quantifiers/term_database.h"
+#include "options/quantifiers_options.h"
 
 using namespace std;
 
@@ -45,6 +46,7 @@ TheorySep::TheorySep(context::Context* c, context::UserContext* u, OutputChannel
 {
   d_true = NodeManager::currentNM()->mkConst<bool>(true);
   d_false = NodeManager::currentNM()->mkConst<bool>(false);
+  d_bounds_init = false;
   
   // The kinds we are treating as function application in congruence
   d_equalityEngine.addFunctionKind(kind::SEP_PTO);
@@ -126,43 +128,6 @@ void TheorySep::explain(TNode literal, std::vector<TNode>& assumptions) {
   }
 }
 
-void TheorySep::preRegisterTermRec(TNode t, std::map< TNode, bool >& visited ) {
-  if( visited.find( t )==visited.end() ){
-    visited[t] = true;
-    Trace("sep-prereg-debug") << "Preregister : " << t << std::endl;
-    if( t.getKind()==kind::SEP_NIL ){
-      Trace("sep-prereg") << "Preregister nil : " << t << std::endl;
-      //per type, all nil variable references are equal
-      TypeNode tn = t.getType();
-      std::map< TypeNode, Node >::iterator it = d_nil_ref.find( tn );
-      if( it==d_nil_ref.end() ){
-        Trace("sep-prereg") << "...set as reference." << std::endl;
-        setNilRef( tn, t );
-      }else{
-        Node nr = it->second;
-        Trace("sep-prereg") << "...reference is " << nr << "." << std::endl;
-        if( t!=nr ){
-          if( d_reduce.find( t )==d_reduce.end() ){
-            d_reduce.insert( t );
-            Node lem = NodeManager::currentNM()->mkNode( tn.isBoolean() ? kind::IFF : kind::EQUAL, t, nr );
-            Trace("sep-lemma") << "Sep::Lemma: nil ref eq : " << lem << std::endl;
-            d_out->lemma( lem );
-          }
-        }
-      }
-    }else{
-      for( unsigned i=0; i<t.getNumChildren(); i++ ){
-        preRegisterTermRec( t[i], visited );
-      }
-    }
-  }
-}
-
-void TheorySep::preRegisterTerm(TNode term){
-  std::map< TNode, bool > visited;
-  preRegisterTermRec( term, visited );
-}
-
 
 void TheorySep::propagate(Effort e){
 
@@ -234,14 +199,12 @@ void TheorySep::computeCareGraph() {
 /////////////////////////////////////////////////////////////////////////////
 
 
-void TheorySep::collectModelInfo( TheoryModel* m, bool fullModel )
-{
+void TheorySep::collectModelInfo( TheoryModel* m, bool fullModel ){
   // Send the equality engine information to the model
   m->assertEqualityEngine( &d_equalityEngine );
 }
 
-void TheorySep::postProcessModel(TheoryModel* m) {
+void TheorySep::postProcessModel( TheoryModel* m ){
   Trace("sep-model") << "Printing model for TheorySep..." << std::endl;
   
   std::vector< Node > sep_children;
@@ -253,11 +216,9 @@ void TheorySep::postProcessModel(TheoryModel* m) {
     Assert( d_loc_to_data_type.find( it->first )!=d_loc_to_data_type.end() );
     Trace("sep-model") << "Model for heap, type = " << it->first << " with data type " << d_loc_to_data_type[it->first] << " : " << std::endl;
     TypeEnumerator te_range( d_loc_to_data_type[it->first] );
-    //m->d_comment_str << "Model for heap, type = " << it->first << " : " << std::endl;
     computeLabelModel( it->second, d_tmodel );
     if( d_label_model[it->second].d_heap_locs_model.empty() ){
       Trace("sep-model") << "  [empty]" << std::endl;
-      //m->d_comment_str << "  [empty]" << std::endl;
     }else{
       for( unsigned j=0; j<d_label_model[it->second].d_heap_locs_model.size(); j++ ){
         Assert( d_label_model[it->second].d_heap_locs_model[j].getKind()==kind::SINGLETON );
@@ -266,20 +227,17 @@ void TheorySep::postProcessModel(TheoryModel* m) {
         Assert( l.isConst() );
         pto_children.push_back( l );
         Trace("sep-model") << " " << l << " -> ";
-        //m->d_comment_str << "  " << l << " -> ";
         if( d_pto_model[l].isNull() ){
           Trace("sep-model") << "_";
           //m->d_comment_str << "_";
           pto_children.push_back( *te_range );
         }else{
           Trace("sep-model") << d_pto_model[l];
-          //m->d_comment_str << d_pto_model[l];
           Node vpto = d_valuation.getModel()->getRepresentative( d_pto_model[l] );
           Assert( vpto.isConst() );
           pto_children.push_back( vpto );
         }
         Trace("sep-model") << std::endl;
-        //m->d_comment_str << std::endl;
         sep_children.push_back( NodeManager::currentNM()->mkNode( kind::SEP_PTO, pto_children ) );
       }
     }
@@ -288,8 +246,6 @@ void TheorySep::postProcessModel(TheoryModel* m) {
     m_neq = NodeManager::currentNM()->mkNode( nil.getType().isBoolean() ? kind::IFF : kind::EQUAL, nil, vnil );
     Trace("sep-model") << "sep.nil = " << vnil << std::endl;
     Trace("sep-model") << std::endl;
-    //m->d_comment_str << "sep.nil = " << vnil << std::endl;
-    //m->d_comment_str << std::endl;
     if( sep_children.empty() ){
       TypeEnumerator te_domain( it->first );
       m_heap = NodeManager::currentNM()->mkNode( kind::SEP_EMP, *te_domain );
@@ -299,8 +255,6 @@ void TheorySep::postProcessModel(TheoryModel* m) {
       m_heap = NodeManager::currentNM()->mkNode( kind::SEP_STAR, sep_children );
     }
     m->setHeapModel( m_heap, m_neq );
-    //m->d_comment_str << m->d_sep_heap << std::endl;
-    //m->d_comment_str << m->d_sep_nil_eq << std::endl;
   }
   Trace("sep-model") << "Finished printing model for TheorySep." << std::endl;
 }
@@ -314,10 +268,17 @@ void TheorySep::presolve() {
   Trace("sep-pp") << "Presolving" << std::endl;
   //TODO: cleanup if incremental?
   
-  //we must preregister all instances of sep.nil to ensure they are made equal
-  for( unsigned i=0; i<d_pp_nils.size(); i++ ){
-    std::map< TNode, bool > visited;
-    preRegisterTermRec( d_pp_nils[i], visited );
+  for( std::map< TypeNode, std::vector< Node > >::iterator it = d_pp_nils.begin(); it != d_pp_nils.end(); ++it ){
+    Trace("sep-pp") << it->second.size() << " nil references of type " << it->first << std::endl;
+    if( !it->second.empty() ){
+      setNilRef( it->first, it->second[0] );
+      //ensure all instances of sep.nil are made equal
+      for( unsigned i=1; i<it->second.size(); i++ ){
+        Node lem = NodeManager::currentNM()->mkNode( it->first.isBoolean() ? kind::IFF : kind::EQUAL, it->second[i], it->second[0] );
+        Trace("sep-lemma") << "Sep::Lemma: nil ref eq : " << lem << std::endl;
+        d_out->lemma( lem );
+      }
+    }
   }
   d_pp_nils.clear();
 }
@@ -392,28 +353,6 @@ void TheorySep::check(Effort e) {
               TypeNode tn = getReferenceType( s_atom );
               Assert( d_reference_bound.find( tn )!=d_reference_bound.end() );
               c_lems.push_back( NodeManager::currentNM()->mkNode( kind::SUBSET, s_lbl, d_reference_bound[tn] ) );
-              if( options::sepPreciseBound() ){
-                //more precise bound
-                Trace("sep-bound") << "Propagate Bound(" << s_lbl << ") = ";
-                Assert( d_lbl_reference_bound.find( s_lbl )!=d_lbl_reference_bound.end() );
-                for( unsigned j=0; j<d_lbl_reference_bound[s_lbl].size(); j++ ){
-                  Trace("sep-bound") << d_lbl_reference_bound[s_lbl][j] << " ";
-                }
-                Trace("sep-bound") << std::endl << "  to children of " << s_atom << std::endl;
-                //int rb_start = 0;
-                for( unsigned j=0; j<s_atom.getNumChildren(); j++ ){
-                  Node c_lbl = getLabel( s_atom, j, s_lbl );
-                  std::vector< Node > bound_loc;
-                  bound_loc.insert( bound_loc.end(), d_references[s_atom][j].begin(), d_references[s_atom][j].end() );
-                  //carry all locations for now
-                  bound_loc.insert( bound_loc.end(), d_lbl_reference_bound[s_lbl].begin(), d_lbl_reference_bound[s_lbl].end() );
-                  //Trace("sep-bound") << std::endl;
-                  Node bound_v = mkUnion( tn, bound_loc );
-                  Trace("sep-bound") << "  ...bound value : " << bound_v << std::endl;
-                  children.push_back( NodeManager::currentNM()->mkNode( kind::SUBSET, c_lbl, bound_v ) );
-                }     
-                Trace("sep-bound") << "Done propagate Bound(" << s_lbl << ")" << std::endl;        
-              }
               std::vector< Node > labels;
               getLabelChildren( s_atom, s_lbl, children, labels );
               Node empSet = NodeManager::currentNM()->mkConst(EmptySet(s_lbl.getType().toType()));
@@ -845,10 +784,10 @@ TypeNode TheorySep::getDataType( Node n ) {
 
 //must process assertions at preprocess so that quantified assertions are processed properly
 void TheorySep::ppNotifyAssertions( std::vector< Node >& assertions ) {
-  //dummy sort in case heap loc/data is unconstrained
   d_pp_nils.clear();
   std::map< Node, bool > visited;
   for( unsigned i=0; i<assertions.size(); i++ ){
+    Trace("sep-pp") << "Process assertion : " << assertions[i] << std::endl;
     processAssertion( assertions[i], visited );
   }
   //if data type is unconstrained, assume a fresh uninterpreted sort
@@ -865,8 +804,9 @@ void TheorySep::processAssertion( Node n, std::map< Node, bool >& visited ) {
   if( visited.find( n )==visited.end() ){
     visited[n] = true;
     if( n.getKind()==kind::SEP_NIL ){
-      if( std::find( d_pp_nils.begin(), d_pp_nils.end(), n )==d_pp_nils.end() ){
-        d_pp_nils.push_back( n );
+      TypeNode tn = n.getType();
+      if( std::find( d_pp_nils[tn].begin(), d_pp_nils[tn].end(), n )==d_pp_nils[tn].end() ){
+        d_pp_nils[tn].push_back( n );
       }
     }else if( n.getKind()==kind::SEP_PTO || n.getKind()==kind::SEP_STAR || n.getKind()==kind::SEP_WAND || n.getKind()==kind::SEP_EMP ){
       //get the reference type (will compute d_type_references)
@@ -887,7 +827,7 @@ TypeNode TheorySep::computeReferenceType( Node atom, int& card, int index ) {
   std::map< int, TypeNode >::iterator it = d_reference_type[atom].find( index );
   if( it==d_reference_type[atom].end() ){
     card = 0;
-    TypeNode tn;      
+    TypeNode tn;
     if( index==-1 && ( atom.getKind()==kind::SEP_STAR || atom.getKind()==kind::SEP_WAND ) ){
       for( unsigned i=0; i<atom.getNumChildren(); i++ ){
         int cardc = 0;
@@ -947,7 +887,13 @@ TypeNode TheorySep::computeReferenceType2( Node atom, int& card, int index, Node
       TypeNode tn1 = n[0].getType();
       TypeNode tn2 = n[1].getType();
       if( quantifiers::TermDb::hasBoundVarAttr( n[0] ) ){
-        d_reference_bound_invalid[tn1] = true;
+        if( options::quantEpr() && n[0].getKind()==kind::BOUND_VARIABLE ){
+          // still valid : bound on heap models will include Herbrand universe of n[0].getType()
+          d_reference_bound_fv[tn1] = true;
+        }else{
+          d_reference_bound_invalid[tn1] = true;
+          Trace("sep-bound") << "reference cannot be bound (due to quantified pto)." << std::endl;
+        }
       }else{
         if( std::find( d_references[atom][index].begin(), d_references[atom][index].end(), n[0] )==d_references[atom][index].end() ){
           d_references[atom][index].push_back( n[0] );
@@ -976,6 +922,14 @@ TypeNode TheorySep::computeReferenceType2( Node atom, int& card, int index, Node
       }
       visited[n] = card;
       return tn;
+    }else if( n.getKind()==kind::SEP_NIL ){
+      TypeNode tn = n.getType();
+      TypeNode tnd;
+      registerRefDataTypes( tn, tnd, n );
+      if( std::find( d_pp_nils[tn].begin(), d_pp_nils[tn].end(), n )==d_pp_nils[tn].end() ){
+        d_pp_nils[tn].push_back( n );
+      }
+      return tn;
     }else{
       card = 0;
       TypeNode otn;
@@ -998,6 +952,12 @@ TypeNode TheorySep::computeReferenceType2( Node atom, int& card, int index, Node
 }
 
 void TheorySep::registerRefDataTypes( TypeNode tn1, TypeNode tn2, Node atom ){
+  //separation logic is effectively enabled when we find at least one spatial constraint occurs in the input
+  if( options::incrementalSolving() ){
+    std::stringstream ss;
+    ss << "ERROR: cannot use separation logic in incremental mode." << std::endl;
+    throw LogicException(ss.str());
+  }
   std::map< TypeNode, TypeNode >::iterator itt = d_loc_to_data_type.find( tn1 );
   if( itt==d_loc_to_data_type.end() ){
     if( !d_loc_to_data_type.empty() ){
@@ -1035,9 +995,55 @@ void TheorySep::registerRefDataTypes( TypeNode tn1, TypeNode tn2, Node atom ){
   }
 }
 
+void TheorySep::initializeBounds() {
+  if( !d_bounds_init ){
+    Trace("sep-bound")  << "Initialize sep bounds..." << std::endl;
+    d_bounds_init = true;
+    for( std::map< TypeNode, TypeNode >::iterator it = d_loc_to_data_type.begin(); it != d_loc_to_data_type.end(); ++it ){
+      TypeNode tn = it->first;
+      Trace("sep-bound")  << "Initialize bounds for " << tn << "..." << std::endl;
+      QuantEPR * qepr = getLogicInfo().isQuantified() ? getQuantifiersEngine()->getQuantEPR() : NULL;
+      //if pto had free variable reference      
+      if( d_reference_bound_invalid.find( tn )==d_reference_bound_invalid.end() ){
+        if( d_reference_bound_fv.find( tn )!=d_reference_bound_fv.end() ){
+          //include Herbrand universe of tn
+          if( qepr && qepr->isEPR( tn ) ){
+            for( unsigned j=0; j<qepr->d_consts[tn].size(); j++ ){
+              Node k = qepr->d_consts[tn][j];
+              if( std::find( d_type_references[tn].begin(), d_type_references[tn].end(), k )==d_type_references[tn].end() ){
+                d_type_references[tn].push_back( k );
+              }
+            }
+          }else{
+            d_reference_bound_invalid[tn] = true;
+            Trace("sep-bound") << "reference cannot be bound (due to non-EPR variable)." << std::endl;
+          }
+        }
+      }
+      unsigned n_emp = 0;
+      if( d_reference_bound_invalid.find( tn )==d_reference_bound_invalid.end() ){ 
+        n_emp = d_card_max[tn]>d_card_max[TypeNode::null()] ? d_card_max[tn] : d_card_max[TypeNode::null()];  
+      }else if( d_type_references[tn].empty() ){
+        //must include at least one constant
+        n_emp = 1;
+      }
+      Trace("sep-bound") << "Constructing " << n_emp << " cardinality constants." << std::endl;
+      for( unsigned r=0; r<n_emp; r++ ){
+        Node e = NodeManager::currentNM()->mkSkolem( "e", tn, "cardinality bound element for seplog" );
+        d_type_references_card[tn].push_back( e );
+        //must include this constant back into EPR handling
+        if( qepr && qepr->isEPR( tn ) ){
+          qepr->d_consts[tn].push_back( e );
+        }
+      }
+    }
+  }
+}
+
 Node TheorySep::getBaseLabel( TypeNode tn ) {
   std::map< TypeNode, Node >::iterator it = d_base_label.find( tn );
   if( it==d_base_label.end() ){
+    initializeBounds();
     Trace("sep") << "Make base label for " << tn << std::endl;
     std::stringstream ss;
     ss << "__Lb";
@@ -1051,35 +1057,45 @@ Node TheorySep::getBaseLabel( TypeNode tn ) {
     ss2 << "__Lu";
     d_reference_bound[tn] = NodeManager::currentNM()->mkSkolem( ss2.str(), ltn, "" );
     d_type_references_all[tn].insert( d_type_references_all[tn].end(), d_type_references[tn].begin(), d_type_references[tn].end() );
+
+    //check whether monotonic (elements can be added to tn without effecting satisfiability)
+    bool tn_is_monotonic = true;
+    if( tn.isSort() ){
+      //TODO: use monotonicity inference
+      tn_is_monotonic = !getLogicInfo().isQuantified();
+    }else{
+      tn_is_monotonic = tn.getCardinality().isInfinite();
+    }
     //add a reference type for maximum occurrences of empty in a constraint
-    unsigned n_emp = d_card_max[tn]>d_card_max[TypeNode::null()] ? d_card_max[tn] : d_card_max[TypeNode::null()];
-    for( unsigned r=0; r<n_emp; r++ ){
-      Node e = NodeManager::currentNM()->mkSkolem( "e", tn, "cardinality bound element for seplog" );
-      //d_type_references_all[tn].push_back( NodeManager::currentNM()->mkSkolem( "e", NodeManager::currentNM()->mkRefType(tn) ) );
-      if( options::sepDisequalC() ){
+    if( options::sepDisequalC() && tn_is_monotonic ){
+      for( unsigned r=0; r<d_type_references_card[tn].size(); r++ ){
+        Node e = d_type_references_card[tn][r];
         //ensure that it is distinct from all other references so far
         for( unsigned j=0; j<d_type_references_all[tn].size(); j++ ){
           Node eq = NodeManager::currentNM()->mkNode( e.getType().isBoolean() ? kind::IFF : kind::EQUAL, e, d_type_references_all[tn][j] );
           d_out->lemma( eq.negate() );
         }
+        d_type_references_all[tn].push_back( e );
       }
-      d_type_references_all[tn].push_back( e );
-      d_lbl_reference_bound[d_base_label[tn]].push_back( e );
+    }else{
+      //break symmetries TODO
+    
+      d_type_references_all[tn].insert( d_type_references_all[tn].end(), d_type_references_card[tn].begin(), d_type_references_card[tn].end() );
     }
-    //construct bound
-    d_reference_bound_max[tn] = mkUnion( tn, d_type_references_all[tn] );
-    Trace("sep-bound") << "overall bound for " << d_base_label[tn] << " : " << d_reference_bound_max[tn] << std::endl;
+    Assert( !d_type_references_all[tn].empty() );
+    
+    if( d_reference_bound_invalid.find( tn )==d_reference_bound_invalid.end() ){      
+      //construct bound
+      d_reference_bound_max[tn] = mkUnion( tn, d_type_references_all[tn] );
+      Trace("sep-bound") << "overall bound for " << d_base_label[tn] << " : " << d_reference_bound_max[tn] << std::endl;
 
-    if( d_reference_bound_invalid.find( tn )==d_reference_bound_invalid.end() ){
       Node slem = NodeManager::currentNM()->mkNode( kind::SUBSET, d_reference_bound[tn], d_reference_bound_max[tn] );
       Trace("sep-lemma") << "Sep::Lemma: reference bound for " << tn << " : " << slem << std::endl;
       d_out->lemma( slem );
-    }else{
-      Trace("sep-bound") << "reference cannot be bound (possibly due to quantified pto)." << std::endl;
+      //slem = NodeManager::currentNM()->mkNode( kind::SUBSET, d_base_label[tn], d_reference_bound_max[tn] );
+      //Trace("sep-lemma") << "Sep::Lemma: base reference bound for " << tn << " : " << slem << std::endl;
+      //d_out->lemma( slem );
     }
-    //slem = NodeManager::currentNM()->mkNode( kind::SUBSET, d_base_label[tn], d_reference_bound_max[tn] );
-    //Trace("sep-lemma") << "Sep::Lemma: base reference bound for " << tn << " : " << slem << std::endl;
-    //d_out->lemma( slem );
     
     //assert that nil ref is not in base label
     Node nr = getNilRef( tn );
@@ -1373,7 +1389,6 @@ void TheorySep::computeLabelModel( Node lbl, std::map< Node, Node >& tmodel ) {
         Assert( false );
       }
     }
-    //end hack
     for( unsigned j=0; j<d_label_model[lbl].d_heap_locs_model.size(); j++ ){
       Node u = d_label_model[lbl].d_heap_locs_model[j];
       Assert( u.getKind()==kind::SINGLETON );
@@ -1387,7 +1402,8 @@ void TheorySep::computeLabelModel( Node lbl, std::map< Node, Node >& tmodel ) {
         //TypeNode tn = u.getType().getRefConstituentType();
         TypeNode tn = u.getType();
         Trace("sep-process") << "WARNING: could not find symbolic term in model for " << u << ", cref type " << tn << std::endl;
-        Assert( d_type_references_all.find( tn )!=d_type_references_all.end() && !d_type_references_all[tn].empty() );
+        Assert( d_type_references_all.find( tn )!=d_type_references_all.end() );
+        Assert( !d_type_references_all[tn].empty() );
         tt = d_type_references_all[tn][0];
       }else{
         tt = itm->second;
index 32aa065b773f06139f547e349a849b5cbe9c0835..4f60c5781fed949e738a0b68704dc4b2ce36cc1c 100644 (file)
@@ -51,7 +51,10 @@ class TheorySep : public Theory {
   /** True node for predicates = false */
   Node d_false;
   
-  std::vector< Node > d_pp_nils;
+  //whether bounds have been initialized
+  bool d_bounds_init;
+  
+  std::map< TypeNode, std::vector< Node > > d_pp_nils;
 
   Node mkAnd( std::vector< TNode >& assumptions );
 
@@ -88,10 +91,8 @@ class TheorySep : public Theory {
   /** Explain why this literal is true by adding assumptions */
   void explain(TNode literal, std::vector<TNode>& assumptions);
 
-  void preRegisterTermRec(TNode t, std::map< TNode, bool >& visited );
   public:
 
-  void preRegisterTerm(TNode t);
   void propagate(Effort e);
   Node explain(TNode n);
 
@@ -220,11 +221,11 @@ class TheorySep : public Theory {
   std::map< TypeNode, Node > d_reference_bound;
   std::map< TypeNode, Node > d_reference_bound_max;
   std::map< TypeNode, bool > d_reference_bound_invalid;
+  std::map< TypeNode, bool > d_reference_bound_fv;
   std::map< TypeNode, std::vector< Node > > d_type_references;
+  std::map< TypeNode, std::vector< Node > > d_type_references_card;
   std::map< TypeNode, std::vector< Node > > d_type_references_all;
   std::map< TypeNode, unsigned > d_card_max;
-  //bounds for labels
-  std::map< Node, std::vector< Node > > d_lbl_reference_bound;
   //for empty argument
   std::map< TypeNode, Node > d_emp_arg;
   //map from ( atom, label, child index ) -> label
@@ -299,6 +300,7 @@ public:
     return &d_equalityEngine;
   }
 
+  void initializeBounds();
 };/* class TheorySep */
 
 }/* CVC4::theory::sep namespace */
index 6078bfa19b160b6c8b787cfc25fd05b5a90f64b1..7bcd700bdb4ac94dba936f621cf6e39ebaeb97b0 100644 (file)
@@ -56,7 +56,8 @@ TESTS =       \
   fmf-nemp-2.smt2 \
   trees-1.smt2 \
   wand-false.smt2 \
-  dup-nemp.smt2
+  dup-nemp.smt2 \
+  emp2-quant-unsat.smt2
 
 
 FAILING_TESTS =
index d3245e33fa5a7c18947e9a3f4e498c703cc3fb3b..ebe52fa4643817dcff60ed38cb32686f53d7735d 100644 (file)
@@ -1,4 +1,4 @@
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
 
 (declare-const x Int)
index a0fc5a187d6fb6744a7dbf87c717275853f49faa..f68434f33026e1fc7eac8df429eabf088d2c77a3 100755 (executable)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
 
 (declare-const x Int)
index 766354cd952bf7b86fdf6c8762384ae9fe5c3eb4..b3e2088b1404680f18db39ac26608ea3868d4b42 100644 (file)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 
 (declare-sort Loc 0)
 
index 00956112846bab08170ef8406a1bb6887dde4e19..98348f617aec6028f158f5f4bbf82986e05b49e9 100644 (file)
@@ -1,4 +1,4 @@
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
 (declare-sort Loc 0)
 (declare-const l Loc)
diff --git a/test/regress/regress0/sep/emp2-quant-unsat.smt2 b/test/regress/regress0/sep/emp2-quant-unsat.smt2
new file mode 100644 (file)
index 0000000..52d99d8
--- /dev/null
@@ -0,0 +1,12 @@
+; COMMAND-LINE: --quant-epr
+; EXPECT: unsat
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+(declare-sort U 0)
+(declare-fun u () U)
+
+(assert (sep (not (emp u)) (not (emp u))))
+
+(assert (forall ((x U) (y U)) (= x y)))
+
+(check-sat)
index 2981606d80e94c786198ef4a3f2521a1944ded72..b857aec2af35657b52641bb67732f44232c46055 100644 (file)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
 
 (declare-const x Int)
index e1e21dd100e4d9aae2e8dd665f4a1e15b32b1490..a0766a7e01b305687c75eacd781d9f1af027ae3a 100644 (file)
@@ -1,5 +1,5 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (assert (not (emp 0)))
 (check-sat)
index 0c93719c9ab0ff7888fbb3a94361eb4aef5002c7..c807757d126cfd870c6a3a0387bed5798760da44 100755 (executable)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
 (declare-fun x () Int)
 
index b0dece248d72062ee670573939ad4b0936d414e4..28ed5c47b71730eb8b35b77a476bea2081a88a13 100644 (file)
@@ -1,4 +1,4 @@
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
 
 (declare-const x Int)
index f0b6d2dee0e3ca7caab7d00fdf75892f304def94..ab1cea0c86b05c81d81fb4ece89a6c5d69397d34 100644 (file)
@@ -1,4 +1,4 @@
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
 
 
index 1734c93bbddddba499570586f8443870fd95a5c5..9b0afda7a7063032725bb9ef990022f52727b0be 100644 (file)
@@ -1,4 +1,4 @@
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
 
 (declare-const x1 Int)
index c3330f036b8c584508ea4f81b22e80af58983d07..a93fc4db88b1c268364ff1988fdd75c320c5fb2d 100644 (file)
@@ -1,4 +1,4 @@
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
 
 (declare-const x Int)
index 403bcf077675103893406eb43238b14040b402d2..6f190d9643df6953b018691c88254b6907abba65 100644 (file)
@@ -1,4 +1,4 @@
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
 
 (declare-const x Int)
index 427c44b507f833225e8d87188ee6686d4604064e..8dce5acc72b9813c44e293996e6d34490a817c68 100644 (file)
@@ -1,4 +1,4 @@
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
 
 (declare-const x Int)
index 26a27eb22f7e86d46bb81013eab4e1e4b8a28c9e..356f866c186acebecb4093327001447a2b196675 100644 (file)
@@ -1,4 +1,4 @@
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
 
 (declare-const x1 Int)
index 8ddbdd05fff6f9c4c95ade79a03a5c162fbbaf57..ab12c64615ec21efe903263f8f2270d5532a1058 100644 (file)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
 
 (declare-const x Int)
index 1a69336a8cb739af6b95dc95b0534c6ffb667316..425e5ce3c2b87e486a4b822d4ac55bcdcf7c2e86 100644 (file)
@@ -1,4 +1,4 @@
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
 
 (declare-const x Int)
index e71e6a51a73a1333b65edc78a253dd1f8e4a0d52..7ada6ff068f418a5291d09590ce67ea449d477ac 100644 (file)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
 
 (declare-const x Int)
index 191e7527f3235f3fca9e98e032e591c972fa648b..7b6fc69e9ae1877e997c914377b7e6e8bfa2036a 100644 (file)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
 
 (declare-const x Int)
index f89a9c0ac86b5e8e22892cac689e92c7550f4ac2..53f890b0df8a3ff74f2efd8fca08551a3b1e9214 100644 (file)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
 
 (declare-const x Int)
index 9b4afe36a8b736e9520d0d8453265ce1b9b14e2c..3e595b5e9f6361cb693182b44a177930871c5d34 100644 (file)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
 
 (declare-const x Int)
index 0178134cb14263864f38557e34e4a76b726c44a3..d4fb0fd5279562144380fc1ecbb82f001aa12a4d 100644 (file)
@@ -1,4 +1,4 @@
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
 
 (declare-const x Int)
index 772acd981f914554ad17b16455e2082d1d6cd15d..9522e2420a50527d2f8e69e967e58c68489c56bf 100644 (file)
@@ -1,4 +1,4 @@
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
 
 (declare-const x Int)
index 6cdf51294c68c937296f6e25ecab417c52d438ca..cedbb53eb8cdd95c2f9a4d255c22ec2980a0ae3f 100755 (executable)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
 (declare-sort U 0)
 (declare-fun x () U)
index fb58b9d105a35ab0741e423c1150e9580fbf7fea..9239fb770a3ff130bfc9dd5873ec3c342a8d72d5 100644 (file)
@@ -1,4 +1,4 @@
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
 
 (declare-sort U 0)
index 0c0b6a9a3c6744e51f60c48c4543a7e30b1e4a65..70927ad82468b20bc4d1e4db3fa114da7f4d460c 100644 (file)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
 
 (declare-const x Int)
index ed3187a9657116ee5a07fedb989dc7a71539490f..10e509e05630e09fbf24e40542028eeaabcfbdbc 100644 (file)
@@ -1,4 +1,4 @@
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
 
 (declare-const x Int)
index 1731174faee5c31526ee642c01b3d0061f9211a1..1a9e76a8a0de6367fbff711de5381b68b49caa7a 100644 (file)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: unsat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
 
 (declare-const x Int)
index 0c0ee72adf4a717ccf8f6b1eb5fbc5c7748ccfad..fa0aab5912192aab0432ae7da4651d7aa3981277 100644 (file)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (declare-fun x () Int)
 (declare-fun y () Int)
 (declare-fun u () Int)
index 9b48713236dfffb258c014cfa3b4bfca232653b6..1d799c8c9acefe779cc47f42228ad96e2c8c9ece 100644 (file)
@@ -1,5 +1,5 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (assert (wand (emp 0) (emp 0)))
 (check-sat)
index 642c0a8aa41e6efac488d64d8f4100607df1a3d6..65500f775703d44e316120da53b667fb37148335 100644 (file)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
 (declare-fun x () Int)
 (assert (wand (pto x x) false))
index e8ee4252c14aa7ed77a976dcf8bcf3585f3126e1..0db7330d1bdc4b4666025ed082d6abf50823b701 100644 (file)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (declare-fun x () Int)
 (assert (wand (emp x) (pto x 3)))
 (check-sat)
index c317e87364fd1aa57fbd5a8cf30d372968ab31d6..cce0f79e39817837b5aed5216b96612aa193226c 100644 (file)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
 (declare-fun x () Int)
 (assert (wand (pto x 1) (emp x)))
index df4bfa6d8f3e6e365b523e85790e94c9185f2537..120683f7472457738300ab227fdebfa3082f3761 100755 (executable)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (declare-fun x () Int)
 (assert (wand (pto x 1) (pto x 1)))
 (check-sat)
index 059e91317d7b3504748665e8e08c9cc01c8f7fbc..c684d16ad52928ea7b319c89256f148f0f58db97 100755 (executable)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
 (declare-fun x () Int)
 (assert (wand (pto x 1) (pto x 3)))
index 95bc85537f6cd1b1b0b32866e895a90d72ae6052..c9851661ad4eb7000145f5493d866599c7646d52 100755 (executable)
@@ -1,6 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: unsat
-(set-logic ALL_SUPPORTED)
+(set-logic QF_ALL_SUPPORTED)
 (declare-fun x () Int)
 (assert (wand (pto x 1) (pto x 3)))
 (assert (emp x))