Better combination of UF with cbqi, refactor quantifiers intialization.
authorajreynol <andrew.j.reynolds@gmail.com>
Wed, 4 Nov 2015 09:41:49 +0000 (10:41 +0100)
committerajreynol <andrew.j.reynolds@gmail.com>
Wed, 4 Nov 2015 09:42:01 +0000 (10:42 +0100)
16 files changed:
src/theory/quantifiers/ceg_instantiator.cpp
src/theory/quantifiers/inst_strategy_cbqi.cpp
src/theory/quantifiers/instantiation_engine.cpp
src/theory/quantifiers/instantiation_engine.h
src/theory/quantifiers/options
src/theory/quantifiers/quant_conflict_find.cpp
src/theory/quantifiers/quantifiers_rewriter.cpp
src/theory/quantifiers/quantifiers_rewriter.h
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/fmf/Makefile.am
test/regress/regress0/fmf/krs-sat.smt2 [new file with mode: 0644]
test/regress/regress0/quantifiers/Makefile.am
test/regress/regress0/quantifiers/ari056.smt2 [new file with mode: 0644]

index 5ae8905d1b032de6c7a45c08a6420a7ae324bdf9..3e69a616a55880ddc93585c2a854ccdcd38e7c9e 100644 (file)
@@ -292,9 +292,9 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
       std::vector< Node > mbp_vts_coeff[2][2];
       std::vector< Node > mbp_lit[2];
       //std::vector< MbpBounds > mbp_bounds[2];
-      unsigned rmax = Theory::theoryOf( pv )==Theory::theoryOf( pv.getType() ) ? 1 : 2;
-      for( unsigned r=0; r<rmax; r++ ){
-        TheoryId tid = r==0 ? Theory::theoryOf( pv ) : Theory::theoryOf( pv.getType() );
+      //unsigned rmax = Theory::theoryOf( pv )==Theory::theoryOf( pv.getType() ) ? 1 : 2;
+      for( unsigned r=0; r<2; r++ ){
+        TheoryId tid = r==0 ? Theory::theoryOf( pvtn ) : THEORY_UF;
         Trace("cbqi-inst-debug2") << "  look at assertions of " << tid << std::endl;
         std::map< TheoryId, std::vector< Node > >::iterator ita = d_curr_asserts.find( tid );
         if( ita!=d_curr_asserts.end() ){
@@ -303,7 +303,7 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
             Trace("cbqi-inst-debug2") << "  look at " << lit << std::endl;
             Node atom = lit.getKind()==NOT ? lit[0] : lit;
             bool pol = lit.getKind()!=NOT;
-            if( tid==THEORY_ARITH ){
+            if( pvtn.isReal() ){
               //arithmetic inequalities and disequalities
               if( atom.getKind()==GEQ || ( atom.getKind()==EQUAL && !pol ) ){
                 Assert( atom[0].getType().isInteger() || atom[0].getType().isReal() );
@@ -614,7 +614,7 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
 
     //[4] resort to using value in model
     // do so if we are in effort=1, or if the variable is boolean, or if we are solving for a subfield of a datatype
-    if( effort>0 || pvtn.isBoolean() || !curr_var.empty() ){
+    if( ( effort>0 || pvtn.isBoolean() || !curr_var.empty() ) && !pvtn.isSort() ){
       Node mv = getModelValue( pv );
       Node pv_coeff_m;
       Trace("cbqi-inst-debug") << "[4] " << i << "...try model value " << mv << std::endl;
@@ -976,14 +976,10 @@ Node CegInstantiator::applySubstitution( TypeNode tn, Node n, std::vector< Node
 }
 
 Node CegInstantiator::getModelBasedProjectionValue( Node e, Node t, bool isLower, Node c, Node me, Node mt, Node theta, Node inf_coeff, Node delta_coeff ) {
-  /*
-  if( e.getType().isInteger() && !t.getType().isInteger() ){
-    //TODO : round up/down this bound?
-    return Node::null();
-  }
-  */
   Node val = t;
   Trace("cbqi-bound2") << "Value : " << val << std::endl;
+  Assert( !e.getType().isInteger() || t.getType().isInteger() );
+  Assert( !e.getType().isInteger() || mt.getType().isInteger() );
   //add rho value
   //get the value of c*e
   Node ceValue = me;
@@ -1005,7 +1001,7 @@ Node CegInstantiator::getModelBasedProjectionValue( Node e, Node t, bool isLower
     Node rho;
     //if( !mt.getType().isInteger() ){
       //round up/down
-      //mt = NodeManager::currentNM()->mkNode( 
+      //mt = NodeManager::currentNM()->mkNode(
     //}
     if( isLower ){
       rho = NodeManager::currentNM()->mkNode( MINUS, ceValue, mt );
@@ -1157,6 +1153,7 @@ void CegInstantiator::processAssertions() {
 
   //for each variable
   std::vector< TheoryId > tids;
+  tids.push_back(THEORY_UF);
   for( unsigned i=0; i<d_vars.size(); i++ ){
     Node pv = d_vars[i];
     TypeNode pvtn = pv.getType();
@@ -1389,8 +1386,8 @@ void CegInstantiator::registerCounterexampleLemma( std::vector< Node >& lems, st
       d_var_order_index.clear();
     }
   }
-  
-  //remove ITEs 
+
+  //remove ITEs
   IteSkolemMap iteSkolemMap;
   d_qe->getTheoryEngine()->getIteRemover()->run(lems, iteSkolemMap);
   Assert( d_aux_vars.empty() );
@@ -1466,7 +1463,7 @@ int CegInstantiator::isolate( Node pv, Node atom, Node & veq_c, Node & val, Node
         }
       }
     }
-    
+
     ires = QuantArith::isolate( pv, msum, veq_c, val, atom.getKind() );
     if( ires!=0 ){
       Node realPart;
@@ -1510,7 +1507,7 @@ int CegInstantiator::isolate( Node pv, Node atom, Node & veq_c, Node & val, Node
         Trace("cbqi-inst-debug") << "Isolate for mixed Int/Real : " << veq_c << " * " << pv << " " << atom.getKind() << " " << val << std::endl;
         Trace("cbqi-inst-debug") << "                 real part : " << realPart << std::endl;
         if( ires!=0 ){
-          val = Rewriter::rewrite( NodeManager::currentNM()->mkNode( ires==-1 ? PLUS : MINUS, 
+          val = Rewriter::rewrite( NodeManager::currentNM()->mkNode( ires==-1 ? PLUS : MINUS,
                                     NodeManager::currentNM()->mkNode( ires==-1 ? MINUS : PLUS, val, realPart ),
                                     NodeManager::currentNM()->mkNode( TO_INTEGER, realPart ) ) );
           Trace("cbqi-inst-debug") << "result : " << val << std::endl;
@@ -1521,6 +1518,6 @@ int CegInstantiator::isolate( Node pv, Node atom, Node & veq_c, Node & val, Node
     vts_coeff_inf = vts_coeff[0];
     vts_coeff_delta = vts_coeff[1];
   }
-    
+
   return ires;
 }
index 07de0a3d1aad7f2d9ec0724d6de9d42f4b672d4b..56d5022c4fc6866a04b54979d039a1ed59117f44 100644 (file)
@@ -34,7 +34,7 @@ using namespace CVC4::theory::arith;
 #define ARITH_INSTANTIATOR_USE_MINUS_DELTA
 
 InstStrategyCbqi::InstStrategyCbqi( QuantifiersEngine * qe ) : QuantifiersModule( qe ), d_added_cbqi_lemma( qe->getUserContext() ){
-  
+
 }
 
 bool InstStrategyCbqi::needsCheck( Theory::Effort e ) {
@@ -44,7 +44,7 @@ bool InstStrategyCbqi::needsCheck( Theory::Effort e ) {
 unsigned InstStrategyCbqi::needsModel( Theory::Effort e ) {
   for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
     Node q = d_quantEngine->getModel()->getAssertedQuantifier( i );
-    if( d_quantEngine->getOwner( q )==this && d_quantEngine->getModel()->isQuantifierActive( q ) ){
+    if( doCbqi( q ) && d_quantEngine->getModel()->isQuantifierActive( q ) ){
       return QuantifiersEngine::QEFFORT_STANDARD;
     }
   }
@@ -57,7 +57,7 @@ void InstStrategyCbqi::reset_round( Theory::Effort effort ) {
   for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
     Node q = d_quantEngine->getModel()->getAssertedQuantifier( i );
     //it is not active if it corresponds to a rewrite rule: we will process in rewrite engine
-    if( d_quantEngine->getOwner( q )==this ){
+    if( doCbqi( q ) ){
       if( !hasAddedCbqiLemma( q ) ){
         d_added_cbqi_lemma.insert( q );
         Trace("cbqi") << "Do cbqi for " << q << std::endl;
@@ -76,7 +76,7 @@ void InstStrategyCbqi::reset_round( Theory::Effort effort ) {
           Trace("cbqi") << "Counterexample lemma : " << lem << std::endl;
           registerCounterexampleLemma( q, lem );
         }
-      //set inactive the quantified formulas whose CE literals are asserted false  
+      //set inactive the quantified formulas whose CE literals are asserted false
       }else if( d_quantEngine->getModel()->isQuantifierActive( q ) ){
         Debug("cbqi-debug") << "Check quantified formula " << q << "..." << std::endl;
         Node cel = d_quantEngine->getTermDatabase()->getCounterexampleLiteral( q );
@@ -106,7 +106,7 @@ void InstStrategyCbqi::check( Theory::Effort e, unsigned quant_e ) {
       unsigned lastWaiting = d_quantEngine->getNumLemmasWaiting();
       for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
         Node q = d_quantEngine->getModel()->getAssertedQuantifier( i );
-        if( d_quantEngine->getOwner( q )==this && d_quantEngine->getModel()->isQuantifierActive( q ) ){
+        if( doCbqi( q ) && d_quantEngine->getModel()->isQuantifierActive( q ) ){
           process( q, e, ee );
         }
       }
@@ -127,13 +127,15 @@ bool InstStrategyCbqi::checkComplete() {
 
 void InstStrategyCbqi::preRegisterQuantifier( Node q ) {
   if( d_quantEngine->getOwner( q )==NULL && doCbqi( q ) ){
-    //take ownership of the quantified formula
-    d_quantEngine->setOwner( q, this );
+    if( !options::cbqiAll() && !options::cbqiSplx() ){
+      //take full ownership of the quantified formula
+      d_quantEngine->setOwner( q, this );
+    }
   }
 }
 
 void InstStrategyCbqi::registerQuantifier( Node q ) {
-  
+
 }
 
 void InstStrategyCbqi::registerCounterexampleLemma( Node q, Node lem ){
index 2785ad128fb1a64f44aad29cc8c6d2618328c336..49f561234f7b2e408322c1fc9834b128515382a3 100644 (file)
@@ -30,16 +30,7 @@ using namespace CVC4::theory::quantifiers;
 using namespace CVC4::theory::inst;
 
 InstantiationEngine::InstantiationEngine( QuantifiersEngine* qe ) :
-QuantifiersModule( qe ), d_isup(NULL), d_i_ag(NULL){
-
-}
-
-InstantiationEngine::~InstantiationEngine() {
-  delete d_i_ag;
-  delete d_isup;
-}
-
-void InstantiationEngine::finishInit(){
+QuantifiersModule( qe ){
   if( options::eMatching() ){
     //these are the instantiation strategies for E-matching
     //user-provided patterns
@@ -51,9 +42,18 @@ void InstantiationEngine::finishInit(){
     //auto-generated patterns
     d_i_ag = new InstStrategyAutoGenTriggers( d_quantEngine );
     d_instStrategies.push_back( d_i_ag );
+  }else{
+    d_isup = NULL;
+    d_i_ag = NULL;
   }
 }
 
+InstantiationEngine::~InstantiationEngine() {
+  delete d_i_ag;
+  delete d_isup;
+}
+
+
 void InstantiationEngine::presolve() {
   for( unsigned i=0; i<d_instStrategies.size(); ++i ){
     d_instStrategies[i]->presolve();
index bc1199588f5a1a303ecfec46b7b9df98747c20e9..4a990ff6ba51e28988c1ed0f6863d6eb9d64d1ad 100644 (file)
@@ -74,8 +74,6 @@ private:
 public:
   InstantiationEngine( QuantifiersEngine* qe );
   ~InstantiationEngine();
-  /** initialize */
-  void finishInit();
   void presolve();
   bool needsCheck( Theory::Effort e );
   void reset_round( Theory::Effort e );
index a60f5af78376399aa299f3534fe127067d28c704..2578d0b7f2b0464b69f0a66cce32dd5fd57e03eb 100644 (file)
@@ -31,8 +31,10 @@ option dtVarExpandQuant --dt-var-exp-quant bool :default true
 #ite lift mode for quantified formulas
 option iteLiftQuant --ite-lift-quant=MODE CVC4::theory::quantifiers::IteLiftQuantMode :default CVC4::theory::quantifiers::ITE_LIFT_QUANT_MODE_SIMPLE :include "theory/quantifiers/modes.h" :read-write :handler CVC4::theory::quantifiers::stringToIteLiftQuantMode :handler-include "theory/quantifiers/options_handlers.h"
  ite lifting mode for quantified formulas
-option iteCondVarSplitQuant --ite-cond-var-split-quant bool :default true
- split variables occurring as conditions of ITE in quantifiers
+option condVarSplitQuant --cond-var-split-quant bool :default true
+ split quantified formulas that lead to variable eliminations
+option condVarSplitQuantAgg --cond-var-split-agg-quant bool :default false
+ aggressive split quantified formulas that lead to variable eliminations
 option iteDtTesterSplitQuant --ite-dtt-split-quant bool :read-write :default false
  split ites with dt testers as conditions
 # Whether to CNF quantifier bodies
index a1af1313df4382ee662d689591fb3fa0616add7e..26b598413198b579f88ef1e0d8bacd1f42226ca7 100644 (file)
@@ -624,7 +624,7 @@ bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assign
   }
 
   if( !d_unassigned.empty() && ( success || doContinue ) ){
-    Trace("qcf-check") << "Assign to unassigned..." << std::endl;
+    Trace("qcf-check") << "Assign to unassigned (" << d_unassigned.size() << ")..." << std::endl;
     do {
       if( doFail ){
         Trace("qcf-check-unassign") << "Failure, try again..." << std::endl;
@@ -702,6 +702,7 @@ bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assign
         }
       }
     }while( success && isMatchSpurious( p ) );
+    Trace("qcf-check") << "done assigning." << std::endl;
   }
   if( success ){
     for( unsigned i=0; i<d_unassigned.size(); i++ ){
@@ -2113,7 +2114,9 @@ void QuantConflictFind::computeRelevantEqr() {
             itt->second.push_back( r );
           }
         }else{
-          d_eqcs[rtn].push_back( r );
+          if( !options::cbqi() || !TermDb::hasInstConstAttr( r ) ){
+            d_eqcs[rtn].push_back( r );
+          }
         }
       }
       ++eqcs_i;
index e911b0dc4116787f5fb63733a87501cd8bde4cac..8954082697721dfa010b9144a0127f9665b73126 100644 (file)
@@ -648,62 +648,111 @@ Node QuantifiersRewriter::computeProcessTerms( Node body, bool hasPol, bool pol,
   }
 }
 
-Node QuantifiersRewriter::computeProcessIte( Node body ){
-  if( body.getKind()==ITE ){
-    if( options::iteDtTesterSplitQuant() ){
-      Trace("quantifiers-rewrite-ite-debug") << "DTT split : " << body << std::endl;
-      std::map< Node, Node > pcons;
-      std::map< Node, std::map< int, Node > > ncons;
-      std::vector< Node > conj;
-      computeDtTesterIteSplit( body, pcons, ncons, conj );
-      Assert( !conj.empty() );
-      if( conj.size()>1 ){
-        Trace("quantifiers-rewrite-ite") << "*** Split ITE (datatype tester) " << body << " into : " << std::endl;
-        for( unsigned i=0; i<conj.size(); i++ ){
-          Trace("quantifiers-rewrite-ite") << "   " << conj[i] << std::endl;
+
+bool QuantifiersRewriter::isConditionalVariableElim( Node n, int pol ){
+  if( n.getKind()==NOT ){
+    return isConditionalVariableElim( n[0], -pol );
+  }else if( ( n.getKind()==AND && pol>=0 ) || ( n.getKind()==OR && pol<=0 ) ){
+    pol = n.getKind()==AND ? 1 : -1;
+    for( unsigned i=0; i<n.getNumChildren(); i++ ){
+      if( isConditionalVariableElim( n[i], pol ) ){
+        return true;
+      }
+    }
+  }else if( n.getKind()==EQUAL ){
+    for( unsigned i=0; i<2; i++ ){
+      if( n[i].getKind()==BOUND_VARIABLE ){
+        if( !TermDb::containsTerm( n[1-i], n[i] ) ){
+          return true;
         }
-        return NodeManager::currentNM()->mkNode( AND, conj );
       }
     }
-    if( options::iteCondVarSplitQuant() ){
-      Trace("quantifiers-rewrite-ite-debug") << "Conditional var eq split " << body << std::endl;
+  }else if( n.getKind()==BOUND_VARIABLE ){
+    return true;
+  }
+  return false;
+}
+
+Node QuantifiersRewriter::computeProcessIte( Node body, Node ipl ){
+  if( options::iteDtTesterSplitQuant() && body.getKind()==ITE ){
+    Trace("quantifiers-rewrite-ite-debug") << "DTT split : " << body << std::endl;
+    std::map< Node, Node > pcons;
+    std::map< Node, std::map< int, Node > > ncons;
+    std::vector< Node > conj;
+    computeDtTesterIteSplit( body, pcons, ncons, conj );
+    Assert( !conj.empty() );
+    if( conj.size()>1 ){
+      Trace("quantifiers-rewrite-ite") << "*** Split ITE (datatype tester) " << body << " into : " << std::endl;
+      for( unsigned i=0; i<conj.size(); i++ ){
+        Trace("quantifiers-rewrite-ite") << "   " << conj[i] << std::endl;
+      }
+      return NodeManager::currentNM()->mkNode( AND, conj );
+    }
+  }
+  if( options::condVarSplitQuant() ){
+    if( body.getKind()==ITE || ( body.getKind()==IFF && options::condVarSplitQuantAgg() && !TermDb::isFunDefAnnotation( ipl ) ) ){
+      Trace("quantifiers-rewrite-debug") << "Conditional var elim split " << body << "?" << std::endl;
       bool do_split = false;
-      for( unsigned r=0; r<2; r++ ){
-        //check if there is a variable elimination
-        Node b = r==0 ? body[0] : body[0].negate();
-        QuantPhaseReq qpr( b );
-        Trace("quantifiers-rewrite-ite-debug") << "phase req " << body[0] << " #: " << qpr.d_phase_reqs.size() << std::endl;
-        for( std::map< Node, bool >::iterator it = qpr.d_phase_reqs.begin(); it != qpr.d_phase_reqs.end(); ++it ){
-          Trace("quantifiers-rewrite-ite-debug") << "phase req " << it->first << " -> " << it->second << std::endl;
-          if( it->second ){
-            if( it->first.getKind()==EQUAL ){
-              for( unsigned i=0; i<2; i++ ){
-                if( it->first[i].getKind()==BOUND_VARIABLE ){
-                  unsigned j = i==0 ? 1 : 0;
-                  if( !TermDb::containsTerm( it->first[j], it->first[i] ) ){
-                    do_split = true;
-                    break;
-                  }
-                }
+      unsigned index_max = body.getKind()==ITE ? 0 : 1;
+      for( unsigned index=0; index<=index_max; index++ ){
+        if( isConditionalVariableElim( body[index] ) ){
+          do_split = true;
+          break;
+        }
+      }
+      if( do_split ){
+        Node pos;
+        Node neg;
+        if( body.getKind()==ITE ){
+          pos = NodeManager::currentNM()->mkNode( OR, body[0].negate(), body[1] );
+          neg = NodeManager::currentNM()->mkNode( OR, body[0], body[2] );
+        }else{
+          pos = NodeManager::currentNM()->mkNode( OR, body[0].negate(), body[1] );
+          neg = NodeManager::currentNM()->mkNode( OR, body[0], body[1].negate() );
+        }
+        Trace("quantifiers-rewrite-debug") << "*** Split (conditional variable eq) " << body << " into : " << std::endl;
+        Trace("quantifiers-rewrite-debug") << "   " << pos << std::endl;
+        Trace("quantifiers-rewrite-debug") << "   " << neg << std::endl;
+        return NodeManager::currentNM()->mkNode( AND, pos, neg );
+      }
+    }else if( body.getKind()==OR && options::condVarSplitQuantAgg() ){
+      std::vector< Node > bchildren;
+      std::vector< Node > nchildren;
+      for( unsigned i=0; i<body.getNumChildren(); i++ ){
+        bool split = false;
+        if( nchildren.empty() ){
+          if( body[i].getKind()==AND ){
+            std::vector< Node > children;
+            for( unsigned j=0; j<body[i].getNumChildren(); j++ ){
+              if( ( body[i][j].getKind()==NOT && body[i][j][0].getKind()==EQUAL && isConditionalVariableElim( body[i][j][0] ) ) ||
+                  body[i][j].getKind()==BOUND_VARIABLE ){
+                nchildren.push_back( body[i][j] );
+              }else{
+                children.push_back( body[i][j] );
               }
             }
-          }
-          if( do_split ){
-            break;
+            if( !nchildren.empty() ){
+              if( !children.empty() ){
+                nchildren.push_back( children.size()==1 ? children[0] : NodeManager::currentNM()->mkNode( AND, children ) );
+              }
+              split = true;
+            }
           }
         }
-        if( do_split ){
-          //bool cpol = (r==1);
-          Node pos = NodeManager::currentNM()->mkNode( OR, body[0].negate(), body[1] );
-          //pos = pos.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
-          //pos = Rewriter::rewrite( pos );
-          Node neg = NodeManager::currentNM()->mkNode( OR, body[0], body[2] );
-          Trace("quantifiers-rewrite-ite") << "*** Split ITE (conditional variable eq) " << body << " into : " << std::endl;
-          Trace("quantifiers-rewrite-ite") << "   " << pos << std::endl;
-          Trace("quantifiers-rewrite-ite") << "   " << neg << std::endl;
-          return NodeManager::currentNM()->mkNode( AND, pos, neg );
+        if( !split ){
+          bchildren.push_back( body[i] );
         }
       }
+      if( !nchildren.empty() ){
+        Trace("quantifiers-rewrite-debug") << "*** Split (conditional variable eq) " << body << " into : " << std::endl;
+        for( unsigned i=0; i<nchildren.size(); i++ ){
+          bchildren.push_back( nchildren[i] );
+          nchildren[i] = NodeManager::currentNM()->mkNode( OR, bchildren );
+          Trace("quantifiers-rewrite-debug") << "   " << nchildren[i] << std::endl;
+          bchildren.pop_back();
+        }
+        return NodeManager::currentNM()->mkNode( AND, nchildren );
+      }
     }
   }
   return body;
@@ -738,10 +787,9 @@ Node QuantifiersRewriter::computeVarElimination( Node body, std::vector< Node >&
           break;
         }
       }
-    }
-    else if( it->first.getKind()==APPLY_TESTER ){
+    }else if( it->first.getKind()==APPLY_TESTER ){
       if( options::dtVarExpandQuant() && it->second && it->first[0].getKind()==BOUND_VARIABLE ){
-        Trace("dt-var-expand") << "Expand datatype variable based on : " << it->first << std::endl;
+        Trace("var-elim-dt") << "Expand datatype variable based on : " << it->first << std::endl;
         std::vector< Node >::iterator ita = std::find( args.begin(), args.end(), it->first[0] );
         if( ita!=args.end() ){
           vars.push_back( it->first[0] );
@@ -760,11 +808,21 @@ Node QuantifiersRewriter::computeVarElimination( Node body, std::vector< Node >&
             newVars.push_back( v );
           }
           subs.push_back( NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, newChildren ) );
-          Trace("dt-var-expand") << "...apply substitution " << subs[0] << "/" << vars[0] << std::endl;
+          Trace("var-elim-dt") << "...apply substitution " << subs[0] << "/" << vars[0] << std::endl;
           args.erase( ita );
           args.insert( args.end(), newVars.begin(), newVars.end() );
         }
       }
+    }else if( it->first.getKind()==BOUND_VARIABLE ){
+      if( options::varElimQuant() ){
+        std::vector< Node >::iterator ita = std::find( args.begin(), args.end(), it->first );
+        if( ita!=args.end() ){
+          Trace("var-elim-bool") << "Variable eliminate : " << it->first << " in " << body << std::endl;
+          vars.push_back( it->first );
+          subs.push_back( NodeManager::currentNM()->mkConst( it->second ) );
+          args.erase( ita );
+        }
+      }
     }
   }
   if( !vars.empty() ){
@@ -1286,7 +1344,7 @@ bool QuantifiersRewriter::doOperation( Node f, bool isNested, int computeOption
     return true;
     //return options::iteLiftQuant()!=ITE_LIFT_QUANT_MODE_NONE || options::iteCondVarSplitQuant();
   }else if( computeOption==COMPUTE_PROCESS_ITE ){
-    return options::iteDtTesterSplitQuant() || options::iteCondVarSplitQuant();
+    return options::iteDtTesterSplitQuant() || options::condVarSplitQuant();
   }else if( computeOption==COMPUTE_PRENEX ){
     return options::prenexQuant()!=PRENEX_NONE && !options::aggressiveMiniscopeQuant();
   }else if( computeOption==COMPUTE_VAR_ELIMINATION ){
@@ -1332,7 +1390,7 @@ Node QuantifiersRewriter::computeOperation( Node f, bool isNested, int computeOp
         n = NodeManager::currentNM()->mkNode( OR, new_conds );
       }
     }else if( computeOption==COMPUTE_PROCESS_ITE ){
-      n = computeProcessIte( n );
+      n = computeProcessIte( n, ipl );
     }else if( computeOption==COMPUTE_PRENEX ){
       n = computePrenex( n, args, true );
     }else if( computeOption==COMPUTE_VAR_ELIMINATION ){
index 98a83b7de462acbf9ebb866b82fc31adb363696a..0ad79587a7f4450ae5919afc8f1e299c6c563665 100644 (file)
@@ -39,6 +39,7 @@ private:
   static void computeArgVec2( std::vector< Node >& args, std::vector< Node >& activeArgs, Node n, Node ipl );
   static Node computeClause( Node n );
   static void computeDtTesterIteSplit( Node n, std::map< Node, Node >& pcons, std::map< Node, std::map< int, Node > >& ncons, std::vector< Node >& conj );
+  static bool isConditionalVariableElim( Node n, int pol=0 );
 private:
   static Node computeElimSymbols( Node body );
   static Node computeMiniscoping( Node f, std::vector< Node >& args, Node body, Node ipl );
@@ -48,7 +49,7 @@ private:
   static Node computeProcessTerms( Node body, bool hasPol, bool pol, std::map< Node, bool >& currCond, int nCurrCond,
                                    std::map< Node, Node >& cache, std::map< Node, Node >& icache,
                                    std::vector< Node >& new_vars, std::vector< Node >& new_conds );
-  static Node computeProcessIte( Node body );
+  static Node computeProcessIte( Node body, Node ipl );
   static Node computeVarElimination( Node body, std::vector< Node >& args, Node& ipl );
   static Node computeCNF( Node body, std::vector< Node >& args, NodeBuilder<>& defs, bool forcePred );
   static Node computePrenex( Node body, std::vector< Node >& args, bool pol );
@@ -60,9 +61,9 @@ private:
     COMPUTE_AGGRESSIVE_MINISCOPING,
     COMPUTE_NNF,
     COMPUTE_PROCESS_TERMS,
-    COMPUTE_PROCESS_ITE,
     COMPUTE_PRENEX,
     COMPUTE_VAR_ELIMINATION,
+    COMPUTE_PROCESS_ITE,
     //COMPUTE_FLATTEN_ARGS_UF,
     //COMPUTE_CNF,
     COMPUTE_LAST
index bfeacf0444099682435fb2de23a5e26c021e14a0..e513666a40b819af769e6979d83d0189961d6679 100644 (file)
@@ -1599,9 +1599,23 @@ bool TermDb::isFunDef( Node q ) {
   return !getFunDefHead( q ).isNull();
 }
 
+bool TermDb::isFunDefAnnotation( Node ipl ) {
+  if( !ipl.isNull() ){
+    for( unsigned i=0; i<ipl.getNumChildren(); i++ ){
+      if( ipl[i].getKind()==INST_ATTRIBUTE ){
+        if( ipl[i][0].getAttribute(FunDefAttribute()) ){
+          return true;
+        }
+      }
+    }
+  }
+  return false;
+}
+
 Node TermDb::getFunDefHead( Node q ) {
   //&& ( q[1].getKind()==EQUAL || q[1].getKind()==IFF ) && q[1][0].getKind()==APPLY_UF &&
   if( q.getKind()==FORALL && q.getNumChildren()==3 ){
+
     for( unsigned i=0; i<q[2].getNumChildren(); i++ ){
       if( q[2][i].getKind()==INST_ATTRIBUTE ){
         if( q[2][i][0].getAttribute(FunDefAttribute()) ){
index 3e38897d165d54f2f8b2077788e202cb8833ad00..bc8851195829e2f055cfdb8942433e88c630b383 100644 (file)
@@ -147,13 +147,13 @@ public:
   /** constants */
   Node d_zero;
   Node d_one;
-  
+
   /** map from operators to ground terms for that operator */
   std::map< Node, std::vector< Node > > d_op_map;
   /** map from type nodes to terms of that type */
   std::map< TypeNode, std::vector< Node > > d_type_map;
-  
-  
+
+
   /** count number of non-redundant ground terms per operator */
   std::map< Node, int > d_op_nonred_count;
   /**mapping from UF terms to representatives of their arguments */
@@ -165,7 +165,7 @@ public:
   std::map< Node, bool > d_has_map;
   /** map from reps to a term in eqc in d_has_map */
   std::map< Node, Node > d_term_elig_eqc;
-  
+
 public:
   /** ground terms for operator */
   unsigned getNumGroundTerms( Node f );
@@ -204,7 +204,7 @@ public:
   Node getEligibleTermInEqc( TNode r );
   /** is inst closure */
   bool isInstClosure( Node r );
-  
+
 //for model basis
 private:
   //map from types to model basis terms
@@ -301,7 +301,7 @@ public:
   bool isClosedEnumerableType( TypeNode tn );
   // may complete
   bool mayComplete( TypeNode tn );
-  
+
 //for triggers
 private:
   /** helper function for compute var contains */
@@ -414,6 +414,8 @@ public: //general queries concerning quantified formulas wrt modules
   static Node getRewriteRule( Node q );
   /** is fun def */
   static bool isFunDef( Node q );
+  /** is fun def */
+  static bool isFunDefAnnotation( Node ipl );
   /** is sygus conjecture */
   static bool isSygusConjecture( Node q );
   /** is sygus conjecture */
index 41e560557a459019ca15fa1fd22759839912ba04..ba3dc9fb0450f1b28cab93091b809b6dcaa37988 100644 (file)
@@ -94,8 +94,6 @@ d_presolve_cache_wic(u){
   d_tr_trie = new inst::TriggerTrie;
   d_hasAddedLemma = false;
 
-  bool needsBuilder = false;
-  bool needsRelDom = false;
   Trace("quant-engine-debug") << "Initialize quantifiers engine." << std::endl;
   Trace("quant-engine-debug") << "Initialize model, mbqi : " << options::mbqiMode() << std::endl;
 
@@ -115,95 +113,145 @@ d_presolve_cache_wic(u){
     d_quant_rel = NULL;
   }
 
+  d_qcf = NULL;
+  d_sg_gen = NULL;
+  d_inst_engine = NULL;
+  d_i_cbqi = NULL;
+  d_model_engine = NULL;
+  d_bint = NULL;
+  d_rr_engine = NULL;
+  d_ceg_inst = NULL;
+  d_lte_part_inst = NULL;
+  d_alpha_equiv = NULL;
+  d_fun_def_engine = NULL;
+  d_uee = NULL;
+  d_fs = NULL;
+  d_rel_dom = NULL;
+  d_builder = NULL;
+
+  d_total_inst_count_debug = 0;
+  d_ierCounter = 0;
+  d_ierCounter_lc = 0;
+  //if any strategy called only on last call, use phase 3
+  d_inst_when_phase = options::cbqi() ? 3 : 2;
+}
+
+QuantifiersEngine::~QuantifiersEngine(){
+  delete d_builder;
+  delete d_rr_engine;
+  delete d_bint;
+  delete d_model_engine;
+  delete d_inst_engine;
+  delete d_qcf;
+  delete d_quant_rel;
+  delete d_rel_dom;
+  delete d_model;
+  delete d_tr_trie;
+  delete d_term_db;
+  delete d_eq_query;
+  delete d_sg_gen;
+  delete d_ceg_inst;
+  delete d_lte_part_inst;
+  delete d_fun_def_engine;
+  delete d_uee;
+  delete d_fs;
+  delete d_i_cbqi;
+}
+
+EqualityQueryQuantifiersEngine* QuantifiersEngine::getEqualityQuery() {
+  return d_eq_query;
+}
+
+context::Context* QuantifiersEngine::getSatContext(){
+  return d_te->theoryOf( THEORY_QUANTIFIERS )->getSatContext();
+}
+
+context::UserContext* QuantifiersEngine::getUserContext(){
+  return d_te->theoryOf( THEORY_QUANTIFIERS )->getUserContext();
+}
+
+OutputChannel& QuantifiersEngine::getOutputChannel(){
+  return d_te->theoryOf( THEORY_QUANTIFIERS )->getOutputChannel();
+}
+/** get default valuation for the quantifiers engine */
+Valuation& QuantifiersEngine::getValuation(){
+  return d_te->theoryOf( THEORY_QUANTIFIERS )->getValuation();
+}
+
+void QuantifiersEngine::finishInit(){
+  context::Context * c = getSatContext();
+  Trace("quant-engine-debug") << "QuantifiersEngine : finishInit " << std::endl;
+  bool needsBuilder = false;
+  bool needsRelDom = false;
   //add quantifiers modules
   if( options::quantConflictFind() || options::quantRewriteRules() ){
     d_qcf = new quantifiers::QuantConflictFind( this, c);
     d_modules.push_back( d_qcf );
-  }else{
-    d_qcf = NULL;
   }
   if( options::conjectureGen() ){
     d_sg_gen = new quantifiers::ConjectureGenerator( this, c );
     d_modules.push_back( d_sg_gen );
-  }else{
-    d_sg_gen = NULL;
   }
   //maintain invariant : either InstantiationEngine or ModelEngine must be in d_modules
   if( !options::finiteModelFind() || options::fmfInstEngine() ){
     d_inst_engine = new quantifiers::InstantiationEngine( this );
     d_modules.push_back(  d_inst_engine );
-  }else{
-    d_inst_engine = NULL;
   }
-  //counterexample-based instantiation (initialized during finishInit)
-  d_i_cbqi = NULL;
-  if( options::cbqi() && options::cbqiModel() ){
-    needsBuilder = true;
+  if( options::cbqi() ){
+    if( options::cbqiSplx() ){
+      d_i_cbqi = new quantifiers::InstStrategySimplex( (arith::TheoryArith*)getTheoryEngine()->theoryOf( THEORY_ARITH ), this );
+      d_modules.push_back( d_i_cbqi );
+    }else{
+      d_i_cbqi = new quantifiers::InstStrategyCegqi( this );
+      d_modules.push_back( d_i_cbqi );
+      if( options::cbqiModel() ){
+        needsBuilder = true;
+      }
+    }
   }
   //finite model finding
   if( options::finiteModelFind() ){
     if( options::fmfBoundInt() ){
       d_bint = new quantifiers::BoundedIntegers( c, this );
       d_modules.push_back( d_bint );
-    }else{
-      d_bint = NULL;
     }
     d_model_engine = new quantifiers::ModelEngine( c, this );
     d_modules.push_back( d_model_engine );
     needsBuilder = true;
-  }else{
-    d_model_engine = NULL;
-    d_bint = NULL;
   }
   if( options::quantRewriteRules() ){
     d_rr_engine = new quantifiers::RewriteEngine( c, this );
     d_modules.push_back(d_rr_engine);
-  }else{
-    d_rr_engine = NULL;
   }
   if( options::ceGuidedInst() ){
     d_ceg_inst = new quantifiers::CegInstantiation( this, c );
     d_modules.push_back( d_ceg_inst );
     needsBuilder = true;
-  }else{
-    d_ceg_inst = NULL;
   }
   if( options::ltePartialInst() ){
     d_lte_part_inst = new quantifiers::LtePartialInst( this, c );
     d_modules.push_back( d_lte_part_inst );
-  }else{
-    d_lte_part_inst = NULL;
   }
   if( options::quantAlphaEquiv() ){
     d_alpha_equiv = new quantifiers::AlphaEquivalence( this );
-  }else{
-    d_alpha_equiv = NULL;
   }
   //if( options::funDefs() ){
   //  d_fun_def_engine = new quantifiers::FunDefEngine( this, c );
   //  d_modules.push_back( d_fun_def_engine );
-  //}else{
-  d_fun_def_engine = NULL;
   //}
   if( options::quantEqualityEngine() ){
     d_uee = new quantifiers::QuantEqualityEngine( this, c );
     d_modules.push_back( d_uee );
-  }else{
-    d_uee = NULL;
   }
   //full saturation : instantiate from relevant domain, then arbitrary terms
   if( options::fullSaturateQuant() || options::fullSaturateInst() ){
     d_fs = new quantifiers::FullSaturation( this );
     d_modules.push_back( d_fs );
     needsRelDom = true;
-  }else{
-    d_fs = NULL;
   }
 
   if( needsRelDom ){
     d_rel_dom = new quantifiers::RelevantDomain( this, d_model );
-  }else{
-    d_rel_dom = NULL;
   }
 
   if( needsBuilder ){
@@ -219,74 +267,8 @@ d_presolve_cache_wic(u){
       Trace("quant-engine-debug") << "...make default model builder." << std::endl;
       d_builder = new quantifiers::QModelBuilderDefault( c, this );
     }
-  }else{
-    d_builder = NULL;
   }
 
-  d_total_inst_count_debug = 0;
-  d_ierCounter = 0;
-  d_ierCounter_lc = 0;
-}
-
-QuantifiersEngine::~QuantifiersEngine(){
-  delete d_builder;
-  delete d_rr_engine;
-  delete d_bint;
-  delete d_model_engine;
-  delete d_inst_engine;
-  delete d_qcf;
-  delete d_quant_rel;
-  delete d_rel_dom;
-  delete d_model;
-  delete d_tr_trie;
-  delete d_term_db;
-  delete d_eq_query;
-  delete d_sg_gen;
-  delete d_ceg_inst;
-  delete d_lte_part_inst;
-  delete d_fun_def_engine;
-  delete d_uee;
-  delete d_fs;
-  delete d_i_cbqi;
-}
-
-EqualityQueryQuantifiersEngine* QuantifiersEngine::getEqualityQuery() {
-  return d_eq_query;
-}
-
-context::Context* QuantifiersEngine::getSatContext(){
-  return d_te->theoryOf( THEORY_QUANTIFIERS )->getSatContext();
-}
-
-context::Context* QuantifiersEngine::getUserContext(){
-  return d_te->theoryOf( THEORY_QUANTIFIERS )->getUserContext();
-}
-
-OutputChannel& QuantifiersEngine::getOutputChannel(){
-  return d_te->theoryOf( THEORY_QUANTIFIERS )->getOutputChannel();
-}
-/** get default valuation for the quantifiers engine */
-Valuation& QuantifiersEngine::getValuation(){
-  return d_te->theoryOf( THEORY_QUANTIFIERS )->getValuation();
-}
-
-void QuantifiersEngine::finishInit(){
-  Trace("quant-engine-debug") << "QuantifiersEngine : finishInit " << std::endl;
-  //counterexample-based quantifier instantiation
-  if( options::cbqi() ){
-    if( options::cbqiSplx() ){
-      d_i_cbqi = new quantifiers::InstStrategySimplex( (arith::TheoryArith*)getTheoryEngine()->theoryOf( THEORY_ARITH ), this );
-      d_modules.push_back( d_i_cbqi );
-    }else{
-      d_i_cbqi = new quantifiers::InstStrategyCegqi( this );
-      d_modules.push_back( d_i_cbqi );
-    }
-  }else{
-    d_i_cbqi = NULL;
-  }
-  for( int i=0; i<(int)d_modules.size(); i++ ){
-    d_modules[i]->finishInit();
-  }
 }
 
 QuantifiersModule * QuantifiersEngine::getOwner( Node q ) {
@@ -717,7 +699,7 @@ bool QuantifiersEngine::addInstantiationInternal( Node f, std::vector< Node >& v
     d_temp_inst_debug[f]++;
     d_total_inst_count_debug++;
     Trace("inst") << "*** Instantiate " << f << " with " << std::endl;
-    for( int i=0; i<(int)terms.size(); i++ ){
+    for( unsigned i=0; i<terms.size(); i++ ){
       if( Trace.isOn("inst") ){
         Trace("inst") << "   " << terms[i];
         if( Trace.isOn("inst-debug") ){
@@ -725,22 +707,20 @@ bool QuantifiersEngine::addInstantiationInternal( Node f, std::vector< Node >& v
         }
         Trace("inst") << std::endl;
       }
-      Assert( terms[i].getType().isSubtypeOf( f[0][i].getType() ) );
-    }
-    if( options::cbqiSplx() ){
-      for( int i=0; i<(int)terms.size(); i++ ){
-        if( quantifiers::TermDb::hasInstConstAttr(terms[i]) ){
+      if( options::cbqi() ){
+        if( quantifiers::TermDb::getInstConstAttr(terms[i])==f ){
           Trace("inst")<< "***& Bad Instantiate " << f << " with " << std::endl;
-          for( int i=0; i<(int)terms.size(); i++ ){
+          for( unsigned i=0; i<terms.size(); i++ ){
             Trace("inst") << "   " << terms[i] << std::endl;
           }
           Unreachable("Bad instantiation");
         }
       }
+      Assert( terms[i].getType().isSubtypeOf( f[0][i].getType() ) );
     }
     if( options::instMaxLevel()!=-1 ){
       uint64_t maxInstLevel = 0;
-      for( int i=0; i<(int)terms.size(); i++ ){
+      for( unsigned i=0; i<terms.size(); i++ ){
         if( terms[i].hasAttribute(InstLevelAttribute()) ){
           if( terms[i].getAttribute(InstLevelAttribute())>maxInstLevel ){
             maxInstLevel = terms[i].getAttribute(InstLevelAttribute());
@@ -1017,9 +997,9 @@ bool QuantifiersEngine::getInstWhenNeedsCheck( Theory::Effort e ) {
   }else if( options::instWhenMode()==quantifiers::INST_WHEN_FULL_DELAY ){
     performCheck = ( e >= Theory::EFFORT_FULL ) && !getTheoryEngine()->needCheck();
   }else if( options::instWhenMode()==quantifiers::INST_WHEN_FULL_LAST_CALL ){
-    performCheck = ( ( e==Theory::EFFORT_FULL && d_ierCounter%2==0 ) || e==Theory::EFFORT_LAST_CALL );
+    performCheck = ( ( e==Theory::EFFORT_FULL && d_ierCounter%d_inst_when_phase==0 ) || e==Theory::EFFORT_LAST_CALL );
   }else if( options::instWhenMode()==quantifiers::INST_WHEN_FULL_DELAY_LAST_CALL ){
-    performCheck = ( ( e==Theory::EFFORT_FULL && !getTheoryEngine()->needCheck() && d_ierCounter%2==0 ) || e==Theory::EFFORT_LAST_CALL );
+    performCheck = ( ( e==Theory::EFFORT_FULL && !getTheoryEngine()->needCheck() && d_ierCounter%d_inst_when_phase==0 ) || e==Theory::EFFORT_LAST_CALL );
   }else if( options::instWhenMode()==quantifiers::INST_WHEN_LAST_CALL ){
     performCheck = ( e >= Theory::EFFORT_LAST_CALL );
   }else{
index 57214988541c1494d6a8273a0e369d87c28b0d2b..bbf3fad61d9648a9e4f21987dab2fc81c7df8413 100644 (file)
@@ -53,8 +53,6 @@ public:
   virtual ~QuantifiersModule(){}
   //get quantifiers engine
   QuantifiersEngine* getQuantifiersEngine() { return d_quantEngine; }
-  /** initialize */
-  virtual void finishInit() {}
   /** presolve */
   virtual void presolve() {}
   /* whether this module needs to check this round */
@@ -201,6 +199,7 @@ private:
   /** inst round counters */
   int d_ierCounter;
   int d_ierCounter_lc;
+  int d_inst_when_phase;
   /** has presolve been called */
   context::CDO< bool > d_presolve;
   /** presolve cache */
@@ -220,7 +219,7 @@ public:
   /** get default sat context for quantifiers engine */
   context::Context* getSatContext();
   /** get default sat context for quantifiers engine */
-  context::Context* getUserContext();
+  context::UserContext* getUserContext();
   /** get default output channel for the quantifiers engine */
   OutputChannel& getOutputChannel();
   /** get default valuation for the quantifiers engine */
index 9d6df2796bcc8607381343d657378ed494ad6b63..bb85e62b307f103d4e35329ffaba20e9e81865de 100644 (file)
@@ -40,7 +40,8 @@ TESTS =       \
        fib-core.smt2 \
        fore19-exp2-core.smt2 \
        with-ind-104-core.smt2 \
-       syn002-si-real-int.smt2
+       syn002-si-real-int.smt2 \
+       krs-sat.smt2
 
 
 EXTRA_DIST = $(TESTS)
diff --git a/test/regress/regress0/fmf/krs-sat.smt2 b/test/regress/regress0/fmf/krs-sat.smt2
new file mode 100644 (file)
index 0000000..22d9e44
--- /dev/null
@@ -0,0 +1,16 @@
+; COMMAND-LINE: --finite-model-find
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(set-info :status sat)
+(declare-sort $$unsorted 0)
+(declare-fun cowlNothing ($$unsorted) Bool)
+(declare-fun cowlThing ($$unsorted) Bool)
+(declare-fun xsd_integer ($$unsorted) Bool)
+(declare-fun xsd_string ($$unsorted) Bool)
+(declare-fun is () $$unsorted)
+(assert (and (forall ((X $$unsorted)) (cowlThing X) ) (forall ((X $$unsorted)) (not (cowlNothing X)) )))
+(assert (forall ((X $$unsorted)) (= (xsd_string X) (not (xsd_integer X))) ))
+(assert (and (forall ((X $$unsorted)) (or (not (cowlThing X)) (= X is)) ) (cowlThing is)))
+(assert (cowlThing is))
+(assert (and (forall ((X $$unsorted)) (cowlThing X) ) (forall ((X $$unsorted)) (not (cowlNothing X)) ) (forall ((X $$unsorted)) (or (not (cowlThing X)) (= X is)) )))
+(check-sat)
index 89dcc0a2688ea86a5a8d726de0aab82428077f77..e6b0a59fc7e243b3a21fe3d4edd87704cfe8a83d 100644 (file)
@@ -59,8 +59,9 @@ TESTS =       \
        floor.smt2 \
        array-unsat-simp3.smt2 \
        mix-simp.smt2 \
-       mix-coeff.smt2  \
-       mix-match.smt2
+       mix-coeff.smt2 \
+       mix-match.smt2 \
+       ari056.smt2
 
 
 # regression can be solved with --finite-model-find --fmf-inst-engine
diff --git a/test/regress/regress0/quantifiers/ari056.smt2 b/test/regress/regress0/quantifiers/ari056.smt2
new file mode 100644 (file)
index 0000000..ed4d2bf
--- /dev/null
@@ -0,0 +1,4 @@
+(set-logic UFNIRA)
+(set-info :status unsat)
+(assert (forall ((X Int)) (= X 12) ))
+(check-sat)