Refactor setIncomplete in quantifiers.
authorajreynol <andrew.j.reynolds@gmail.com>
Thu, 15 Sep 2016 15:43:28 +0000 (10:43 -0500)
committerajreynol <andrew.j.reynolds@gmail.com>
Thu, 15 Sep 2016 15:43:28 +0000 (10:43 -0500)
20 files changed:
src/theory/quantifiers/ambqi_builder.cpp
src/theory/quantifiers/ambqi_builder.h
src/theory/quantifiers/full_model_check.cpp
src/theory/quantifiers/full_model_check.h
src/theory/quantifiers/inst_strategy_cbqi.cpp
src/theory/quantifiers/inst_strategy_cbqi.h
src/theory/quantifiers/instantiation_engine.cpp
src/theory/quantifiers/instantiation_engine.h
src/theory/quantifiers/local_theory_ext.h
src/theory/quantifiers/model_builder.cpp
src/theory/quantifiers/model_builder.h
src/theory/quantifiers/model_engine.cpp
src/theory/quantifiers/model_engine.h
src/theory/quantifiers/quant_split.cpp
src/theory/quantifiers/quant_split.h
src/theory/quantifiers/quant_util.cpp
src/theory/quantifiers/quant_util.h
src/theory/quantifiers/rewrite_engine.cpp
src/theory/quantifiers/rewrite_engine.h
src/theory/quantifiers_engine.cpp

index 97116dee4661bcf7f6d848aca118607afe57abc1..2ccc17e55ddf67fc779a67498e31e7b3b13ef0fd 100644 (file)
@@ -836,7 +836,7 @@ void AbsMbqiBuilder::processBuildModel(TheoryModel* m, bool fullModel) {
 //--------------------model checking---------------------------------------
 
 //do exhaustive instantiation
-bool AbsMbqiBuilder::doExhaustiveInstantiation( FirstOrderModel * fm, Node q, int effort ) {
+int AbsMbqiBuilder::doExhaustiveInstantiation( FirstOrderModel * fm, Node q, int effort ) {
   Trace("ambqi-check") << "Exhaustive instantiation " << q << " " << effort << std::endl;
   if (effort==0) {
     FirstOrderModelAbs * fma = fm->asFirstOrderModelAbs();
@@ -868,9 +868,10 @@ bool AbsMbqiBuilder::doExhaustiveInstantiation( FirstOrderModel * fm, Node q, in
       d_addedLemmas += lem;
       Trace("ambqi-inst-debug") << "...Total : " << d_addedLemmas << std::endl;
     }
-    return quantValid;
+    return quantValid ? 1 : 0;
+  }else{
+    return 1;
   }
-  return true;
 }
 
 bool AbsMbqiBuilder::doCheck( FirstOrderModelAbs * m, TNode q, AbsDef & ad, TNode n ) {
index 3669d38b7312ebfa54f76065ba8228a34bf73bbc..0adaef63880ca596564bcae1b4e81ac703e4c3d8 100644 (file)
@@ -93,7 +93,7 @@ public:
   //process build model
   void processBuildModel(TheoryModel* m, bool fullModel);
   //do exhaustive instantiation
-  bool doExhaustiveInstantiation( FirstOrderModel * fm, Node q, int effort );
+  int doExhaustiveInstantiation( FirstOrderModel * fm, Node q, int effort );
 };
 
 }
index be608aeaa2a95c58694b24552c85ae97f0029623..72057e7341024dc8f29a364e92adc44aade0ff97 100644 (file)
@@ -589,7 +589,7 @@ void FullModelChecker::debugPrint(const char * tr, Node n, bool dispStar) {
 }
 
 
-bool FullModelChecker::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) {
+int FullModelChecker::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) {
   Trace("fmc") << "Full model check " << f << ", effort = " << effort << "..." << std::endl;
   Assert( !d_qe->inConflict() );
   if( optUseModel() ){
@@ -723,15 +723,15 @@ bool FullModelChecker::doExhaustiveInstantiation( FirstOrderModel * fm, Node f,
           if( temp.addEntry(fmfmc, d_quant_models[f].d_cond[j], d_quant_models[f].d_value[j] ) ){
             if( !exhaustiveInstantiate(fmfmc, f, d_quant_models[f].d_cond[j], j ) ){
               //something went wrong, resort to exhaustive instantiation
-              return false;
+              return 0;
             }
           }
         }
       }
     }
-    return true;
+    return 1;
   }else{
-    return false;
+    return 0;
   }
 }
 
index 411b7a5ebe4ceb61b246622fc3c623a48cffe89a..7d21b4185f306940dcfafd4a492e5cfdd2d98d66 100644 (file)
@@ -139,7 +139,7 @@ public:
   void debugPrintCond(const char * tr, Node n, bool dispStar = false);
   void debugPrint(const char * tr, Node n, bool dispStar = false);
 
-  bool doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort );
+  int doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort );
 
   Node getFunctionValue(FirstOrderModelFmc * fm, Node op, const char* argPrefix );
 
index 82f45916cc674dcf9f1b05e54d7d6fbe5e1a6703..9ee62964ba79cb6d29c1dd862da0e1cbd3680764 100644 (file)
@@ -285,6 +285,15 @@ bool InstStrategyCbqi::checkComplete() {
   }
 }
 
+bool InstStrategyCbqi::checkCompleteFor( Node q ) {
+  std::map< Node, int >::iterator it = d_do_cbqi.find( q );
+  if( it!=d_do_cbqi.end() ){
+    return it->second>0;
+  }else{
+    return false;
+  }
+}
+
 Node InstStrategyCbqi::getIdMarkedQuantNode( Node n, std::map< Node, Node >& visited ){
   std::map< Node, Node >::iterator it = visited.find( n );
   if( it==visited.end() ){
@@ -334,7 +343,7 @@ Node InstStrategyCbqi::getIdMarkedQuantNode( Node n, std::map< Node, Node >& vis
 
 void InstStrategyCbqi::preRegisterQuantifier( Node q ) {
   if( d_quantEngine->getOwner( q )==NULL && doCbqi( q ) ){
-    if( !options::cbqiAll() ){
+    if( d_do_cbqi[q]==2 ){
       //take full ownership of the quantified formula
       d_quantEngine->setOwner( q, this );
       
@@ -512,43 +521,49 @@ int InstStrategyCbqi::hasNonCbqiVariable( Node q ){
 }
 
 bool InstStrategyCbqi::doCbqi( Node q ){
-  std::map< Node, bool >::iterator it = d_do_cbqi.find( q );
+  std::map< Node, int >::iterator it = d_do_cbqi.find( q );
   if( it==d_do_cbqi.end() ){
-    bool ret = true;
+    int ret = 2;
     if( !d_quantEngine->getTermDatabase()->isQAttrQuantElim( q ) ){
       //if has an instantiation pattern, don't do it
       if( q.getNumChildren()==3 && options::eMatching() && options::userPatternsQuant()!=USER_PAT_MODE_IGNORE ){
         for( unsigned i=0; i<q[2].getNumChildren(); i++ ){
           if( q[2][i].getKind()==INST_PATTERN ){
-            ret = false;
+            ret = 0;
           }
         }
       }
-      if( ret ){
-        if( options::cbqiAll() ){
-          ret = true;
-        }else{
-          //if quantifier has a non-handled variable, then do not use cbqi
-          //if quantifier has an APPLY_UF term, then do not use cbqi
-          //Node cb = d_quantEngine->getTermDatabase()->getInstConstantBody( q );
-          int ncbqiv = hasNonCbqiVariable( q );
-          if( ncbqiv==1 ){
-            //all variables imply this will be handled regardless of body (e.g. for EPR)
-            ret = true;
-          }else if( ncbqiv==0 ){
-            std::map< Node, bool > visited;
-            ret = !hasNonCbqiOperator( q[1], visited );
-          }else{
-            ret = false;
+      if( ret!=0 ){
+        //if quantifier has a non-handled variable, then do not use cbqi
+        //if quantifier has an APPLY_UF term, then do not use cbqi unless EPR
+        int ncbqiv = hasNonCbqiVariable( q );
+        if( ncbqiv==0 || ncbqiv==1 ){
+          std::map< Node, bool > visited;
+          if( hasNonCbqiOperator( q[1], visited ) ){
+            if( ncbqiv==1 ){
+              //all variables are fully handled, this implies this will be handlable regardless of body (e.g. for EPR)
+              //  so, try but not exclusively
+              ret = 1;
+            }else{
+              //cannot be handled
+              ret = 0;
+            }
           }
+        }else{
+          // unhandled variable type
+          ret = 0;
+        }
+        if( ret==0 && options::cbqiAll() ){
+          //try but not exclusively
+          ret = 1;
         }
       }
     }
     Trace("cbqi-quant") << "doCbqi " << q << " returned " << ret << std::endl;
     d_do_cbqi[q] = ret;
-    return ret;
+    return ret!=0;
   }else{
-    return it->second;
+    return it->second!=0;
   }
 }
 
index 18f4f4a310acf27625242d94c3f44fdf106ff730..eab2677471c3d01254bfead5e3fae910655b47db 100644 (file)
@@ -48,8 +48,8 @@ protected:
   std::map< Node, bool > d_active_quant;
   /** whether we have instantiated quantified formulas */
   //NodeSet d_added_inst;
-  /** whether to do cbqi for this quantified formula */
-  std::map< Node, bool > d_do_cbqi;
+  /** whether to do cbqi for this quantified formula 0 : no, 2 : yes, 1 : yes but not exclusively, -1 : heuristically */
+  std::map< Node, int > d_do_cbqi;
   /** register ce lemma */
   bool registerCbqiLemma( Node q );
   virtual void registerCounterexampleLemma( Node q, Node lem );
@@ -103,6 +103,7 @@ public:
   void reset_round( Theory::Effort e );
   void check( Theory::Effort e, unsigned quant_e );
   bool checkComplete();
+  bool checkCompleteFor( Node q );
   void preRegisterQuantifier( Node q );
   void registerQuantifier( Node q );
   /** get next decision request */
index db597d03133754a477652bd4cc7486224b88c51d..f46d08f08ce165889b6eb4dae68dc8c9363f231d 100644 (file)
@@ -151,19 +151,9 @@ void InstantiationEngine::check( Theory::Effort e, unsigned quant_e ){
   }
 }
 
-bool InstantiationEngine::checkComplete() {
-  if( !options::finiteModelFind() ){
-    for( unsigned i=0; i<d_quants.size(); i++ ){
-      if( isIncomplete( d_quants[i] ) ){
-        return false;
-      }
-    }
-  }
-  return true;
-}
-
-bool InstantiationEngine::isIncomplete( Node q ) {
-  return true;
+bool InstantiationEngine::checkCompleteFor( Node q ) {
+  //TODO?
+  return false;
 }
 
 void InstantiationEngine::preRegisterQuantifier( Node q ) {
index d2b3740a1c4d76db59e4a50839af45f6f0040ac0..79963cb4580e4a25ee668901906e6fa605d4e45b 100644 (file)
@@ -78,7 +78,7 @@ public:
   bool needsCheck( Theory::Effort e );
   void reset_round( Theory::Effort e );
   void check( Theory::Effort e, unsigned quant_e );
-  bool checkComplete();
+  bool checkCompleteFor( Node q );
   void preRegisterQuantifier( Node q );
   void registerQuantifier( Node q );
   Node explain(TNode n){ return Node::null(); }
index 94abf3c90a34bbd936622c92c6faf71cdd37c269..04a6bc9c810b3130d9a22d1482683c618555c78b 100644 (file)
@@ -66,6 +66,8 @@ public:
   void check( Theory::Effort e, unsigned quant_e );
   /* Called for new quantifiers */
   void registerQuantifier( Node q ) {}
+  /* check complete */
+  bool checkComplete() { return !d_wasInvoked; }
   void assertNode( Node n ) {}
   /** Identify this module (for debugging, dynamic configuration, etc..) */
   std::string identify() const { return "LtePartialInst"; }
index 7bbe061080b88144bee524d58856a10fe63b0b6a..b30c2addb171c42ab5c4c2a2d7e9c050cb53fc7b 100644 (file)
@@ -391,7 +391,7 @@ bool QModelBuilderIG::isTermActive( Node n ){
 
 
 //do exhaustive instantiation
-bool QModelBuilderIG::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) {
+int QModelBuilderIG::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) {
   if( optUseModel() ){
     RepSetIterator riter( d_qe, &(d_qe->getModel()->d_rep_set) );
     if( riter.setQuantifier( f ) ){
@@ -470,10 +470,9 @@ bool QModelBuilderIG::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, i
       }
     }
     //if the iterator is incomplete, we will return unknown instead of sat if no instantiations are added this round
-    d_incomplete_check = riter.isIncomplete();
-    return true;
+    return riter.isIncomplete() ? -1 : 1;
   }else{
-    return false;
+    return 0;
   }
 }
 
index e4f9529a81ab861d9e49ef38d43f36bd2436ce87..9b89e5ef68f8992f8dba33ecf92fe26d4910e7e5 100644 (file)
@@ -38,13 +38,14 @@ public:
   virtual ~QModelBuilder() throw() {}
   // is quantifier active?
   virtual bool isQuantifierActive( Node f );
-  //do exhaustive instantiation
-  virtual bool doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) { return false; }
+  //do exhaustive instantiation  
+  // 0 :  failed, but resorting to true exhaustive instantiation may work
+  // >0 : success
+  // <0 : failed
+  virtual int doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) { return false; }
   //whether to construct model
   virtual bool optUseModel();
   /** number of lemmas generated while building model */
-  //is the exhaustive instantiation incomplete?
-  bool d_incomplete_check;
   int d_addedLemmas;
   int d_triedLemmas;
   /** exist instantiation ? */
@@ -142,7 +143,7 @@ public:
   // is quantifier active?
   bool isQuantifierActive( Node f );
   //do exhaustive instantiation
-  bool doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort );
+  int doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort );
 
   //temporary stats
   int d_numQuantSat;
index 7658f2b6bf50003c5097b1601865540141055d9b..7f560b74c9f295df6c58e95e296838938e3d6ee5 100644 (file)
@@ -99,7 +99,7 @@ void ModelEngine::check( Theory::Effort e, unsigned quant_e ){
     }
 
     if( addedLemmas==0 ){
-      Trace("model-engine-debug") << "No lemmas added, incomplete = " << d_incomplete_check << std::endl;
+      Trace("model-engine-debug") << "No lemmas added, incomplete = " << ( d_incomplete_check || !d_incomplete_quants.empty() ) << std::endl;
       //CVC4 will answer SAT or unknown
       if( Trace.isOn("fmf-consistent") ){
         Trace("fmf-consistent") << std::endl;
@@ -113,6 +113,10 @@ bool ModelEngine::checkComplete() {
   return !d_incomplete_check;
 }
 
+bool ModelEngine::checkCompleteFor( Node q ) {
+  return std::find( d_incomplete_quants.begin(), d_incomplete_quants.end(), q )==d_incomplete_quants.end();
+}
+
 void ModelEngine::registerQuantifier( Node f ){
   if( Trace.isOn("fmf-warn") ){
     bool canHandle = true;
@@ -195,17 +199,18 @@ int ModelEngine::checkModel(){
   // FMC uses two sub-effort levels
   int e_max = options::mbqiMode()==MBQI_FMC || options::mbqiMode()==MBQI_FMC_INTERVAL ? 2 : ( options::mbqiMode()==MBQI_TRUST ? 0 : 1 );
   for( int e=0; e<e_max; e++) {
+    d_incomplete_quants.clear();
     for( unsigned i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
-      Node f = fm->getAssertedQuantifier( i, true );
-      Trace("fmf-exh-inst") << "-> Exhaustive instantiate " << f << ", effort = " << e << "..." << std::endl;
+      Node q = fm->getAssertedQuantifier( i, true );
+      Trace("fmf-exh-inst") << "-> Exhaustive instantiate " << q << ", effort = " << e << "..." << std::endl;
       //determine if we should check this quantifier
-      if( considerQuantifiedFormula( f ) ){
-        exhaustiveInstantiate( f, e );
+      if( considerQuantifiedFormula( q ) ){
+        exhaustiveInstantiate( q, e );
         if( d_quantEngine->inConflict() || ( optOneQuantPerRound() && d_addedLemmas>0 ) ){
           break;
         }
       }else{
-        Trace("fmf-exh-inst") << "-> Inactive : " << f << std::endl;
+        Trace("fmf-exh-inst") << "-> Inactive : " << q << std::endl;
       }
     }
     if( d_addedLemmas>0 ){
@@ -260,12 +265,16 @@ void ModelEngine::exhaustiveInstantiate( Node f, int effort ){
   quantifiers::QModelBuilder * mb = d_quantEngine->getModelBuilder();
   mb->d_triedLemmas = 0;
   mb->d_addedLemmas = 0;
-  mb->d_incomplete_check = false;
-  if( mb->doExhaustiveInstantiation( d_quantEngine->getModel(), f, effort ) ){
-    Trace("fmf-exh-inst") << "-> Builder determined instantiation(s)." << std::endl;
+  int retEi = mb->doExhaustiveInstantiation( d_quantEngine->getModel(), f, effort );
+  if( retEi!=0 ){
+    if( retEi<0 ){
+      Trace("fmf-exh-inst") << "-> Builder determined complete instantiation was impossible." << std::endl;
+      d_incomplete_quants.push_back( f );
+    }else{
+      Trace("fmf-exh-inst") << "-> Builder determined instantiation(s)." << std::endl;
+    }
     d_triedLemmas += mb->d_triedLemmas;
     d_addedLemmas += mb->d_addedLemmas;
-    d_incomplete_check = d_incomplete_check || mb->d_incomplete_check;
     d_statistics.d_mbqi_inst_lemmas += mb->d_addedLemmas;
   }else{
     if( Trace.isOn("fmf-exh-inst-debug") ){
@@ -309,7 +318,9 @@ void ModelEngine::exhaustiveInstantiate( Node f, int effort ){
       Trace("fmf-exh-inst") << "...exhaustive instantiation did set, incomplete=" << riter.isIncomplete() << "..." << std::endl;
     }
     //if the iterator is incomplete, we will return unknown instead of sat if no instantiations are added this round
-    d_incomplete_check = d_incomplete_check || riter.isIncomplete();
+    if( riter.isIncomplete() ){
+      d_incomplete_quants.push_back( f );
+    }
   }
 }
 
index 12f18aa08248bbddec1b0b9f6bfcd6665c1da749..8575792b499087c745d3a6be074ba766d91297a0 100644 (file)
@@ -42,6 +42,8 @@ private:
   //temporary statistics
   //is the exhaustive instantiation incomplete?
   bool d_incomplete_check;
+  // set of quantified formulas for which check was incomplete
+  std::vector< Node > d_incomplete_quants;
   int d_addedLemmas;
   int d_triedLemmas;
   int d_totalLemmas;
@@ -54,6 +56,7 @@ public:
   void reset_round( Theory::Effort e );
   void check( Theory::Effort e, unsigned quant_e );
   bool checkComplete();
+  bool checkCompleteFor( Node q );
   void registerQuantifier( Node f );
   void assertNode( Node f );
   Node explain(TNode n){ return Node::null(); }
index 35b3e1f9e751ab103df4999edc496bd59d7ed79e..df85331354c08f8ace53ccc5bcfb3bc3347ca337 100644 (file)
@@ -73,6 +73,11 @@ bool QuantDSplit::needsCheck( Theory::Effort e ) {
   return e>=Theory::EFFORT_FULL && !d_quant_to_reduce.empty();
 }
 
+bool QuantDSplit::checkCompleteFor( Node q ) {
+  // true if we split q
+  return d_added_split.find( q )!=d_added_split.end();
+}
+
 /* Call during quantifier engine's check */
 void QuantDSplit::check( Theory::Effort e, unsigned quant_e ) {
   //add lemmas ASAP (they are a reduction)
index d3682499859e0611e1ac5a8099bd4581f9accf9f..3e3b088142db9fb1f388ef63f2afa5ac5e1f2202 100644 (file)
@@ -43,6 +43,7 @@ public:
   /* Called for new quantifiers */
   void registerQuantifier( Node q ) {}
   void assertNode( Node n ) {}
+  bool checkCompleteFor( Node q );
   /** Identify this module (for debugging, dynamic configuration, etc..) */
   std::string identify() const { return "QuantDSplit"; }
 };
index c3ddfacff1c13e796330df453a73230dec78ddc0..f4284a8ab96c1bca61174441bea78824aa9e834d 100644 (file)
@@ -429,7 +429,7 @@ void QuantEPR::registerNode( Node n, std::map< int, std::map< Node, bool > >& vi
         for( unsigned i=0; i<n[0].getNumChildren(); i++ ){
           TypeNode tn = n[0][i].getType();
           if( d_non_epr.find( tn )==d_non_epr.end() ){
-            Trace("quant-epr") << "Sort " << tn << " is non-EPR because of nested quantification." << std::endl;
+            Trace("quant-epr") << "Sort " << tn << " is non-EPR because of nested or possible existential quantification." << std::endl;
             d_non_epr[tn] = true;
           }
         }
index d8e57b1cacbab6749d2fadb529ca574083f24614..3ff21aa6e003b4e6f89081638141295a47ed6390 100644 (file)
@@ -51,8 +51,10 @@ public:
   virtual void reset_round( Theory::Effort e ){}
   /* Call during quantifier engine's check */
   virtual void check( Theory::Effort e, unsigned quant_e ) = 0;
-  /* check was complete (e.g. no lemmas implies a model) */
+  /* check was complete, return false if there is no way to answer "SAT", true if maybe can answer "SAT" */
   virtual bool checkComplete() { return true; }
+  /* check was complete for quantified formula q (e.g. no lemmas implies a model) */
+  virtual bool checkCompleteFor( Node q ) { return false; }
   /* Called for new quantified formulas */
   virtual void preRegisterQuantifier( Node q ) { }
   /* Called for new quantifiers after owners are finalized */
index 3add7a9d7bfdd705d513677f10fae283a6f5ef14..a2a2e99c674e6bab1de3f36801f3bbd044a5ebc6 100644 (file)
@@ -295,6 +295,11 @@ void RewriteEngine::assertNode( Node n ) {
 
 }
 
+bool RewriteEngine::checkCompleteFor( Node q ) { 
+  // by semantics of rewrite rules, saturation -> SAT 
+  return std::find( d_rr_quant.begin(), d_rr_quant.end(), q )!=d_rr_quant.end();
+}
+
 Node RewriteEngine::getInstConstNode( Node n, Node q ) {
   std::map< Node, Node >::iterator it = d_inst_const_node[q].find( n );
   if( it==d_inst_const_node[q].end() ){
index 8d0678724e02baf67dc62e4c3cb4f6a2d7854b41..ef3337e537997a2141e5a7b6dddc63d4ebf59755 100644 (file)
@@ -56,6 +56,7 @@ public:
   void check( Theory::Effort e, unsigned quant_e );
   void registerQuantifier( Node f );
   void assertNode( Node n );
+  bool checkCompleteFor( Node q );
   /** Identify this module */
   std::string identify() const { return "RewriteEngine"; }
 };
index e48c6eafe8c4ff1af6bba477b362f6e05b37f2f1..fbfdb856e283fefb991adfff9ca5369f0766ac45 100644 (file)
@@ -219,7 +219,6 @@ void QuantifiersEngine::finishInit(){
     d_sg_gen = new quantifiers::ConjectureGenerator( this, c );
     d_modules.push_back( d_sg_gen );
   }
-  //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 );
@@ -395,13 +394,6 @@ void QuantifiersEngine::check( Theory::Effort e ){
   d_conflict = false;
   d_hasAddedLemma = false;
   bool setIncomplete = false;
-  if( e==Theory::EFFORT_LAST_CALL ){
-    //sources of incompleteness
-    if( d_lte_part_inst && d_lte_part_inst->wasInvoked() ){
-      Trace("quant-engine-debug") << "Set incomplete due to LTE partial instantiation." << std::endl;
-      setIncomplete = true;
-    }
-  }
   bool usedModelBuilder = false;
 
   Trace("quant-engine-debug2") << "Quantifiers Engine call to check, level = " << e << ", needsCheck=" << needsCheck << std::endl;
@@ -544,20 +536,49 @@ void QuantifiersEngine::check( Theory::Effort e ){
           }
         }else if( quant_e==QEFFORT_MODEL ){
           if( e==Theory::EFFORT_LAST_CALL ){
+            //sources of incompleteness
             if( !d_recorded_inst.empty() ){
+              Trace("quant-engine-debug") << "Set incomplete due to recorded instantiations." << std::endl;
               setIncomplete = true;
             }
             //if we have a chance not to set incomplete
             if( !setIncomplete ){
               setIncomplete = false;
               //check if we should set the incomplete flag
-              for( unsigned i=0; i<qm.size(); i++ ){
-                if( !qm[i]->checkComplete() ){
-                  Trace("quant-engine-debug") << "Set incomplete because " << qm[i]->identify().c_str() << " was incomplete." << std::endl;
+              for( unsigned i=0; i<d_modules.size(); i++ ){
+                if( !d_modules[i]->checkComplete() ){
+                  Trace("quant-engine-debug") << "Set incomplete because " << d_modules[i]->identify().c_str() << " was incomplete." << std::endl;
                   setIncomplete = true;
                   break;
                 }
               }
+              if( !setIncomplete ){
+                //look at individual quantified formulas, one module must claim completeness for each one
+                for( unsigned i=0; i<d_model->getNumAssertedQuantifiers(); i++ ){
+                  bool hasCompleteM = false;
+                  Node q = d_model->getAssertedQuantifier( i );
+                  QuantifiersModule * qmd = getOwner( q );
+                  if( qmd!=NULL ){
+                    hasCompleteM = qmd->checkCompleteFor( q );
+                  }else{
+                    for( unsigned j=0; j<d_modules.size(); j++ ){
+                      if( d_modules[j]->checkCompleteFor( q ) ){
+                        qmd = d_modules[j];
+                        hasCompleteM = true;
+                        break;
+                      }
+                    }
+                  }
+                  if( !hasCompleteM ){
+                    Trace("quant-engine-debug") << "Set incomplete because " << q << " was not fully processed." << std::endl;
+                    setIncomplete = true;
+                    break;
+                  }else{
+                    Assert( qmd!=NULL );
+                    Trace("quant-engine-debug2") << "Complete for " << q << " due to " << qmd->identify().c_str() << std::endl;
+                  }
+                }
+              }
             }
             //if setIncomplete = false, we will answer SAT, otherwise we will run at quant_e QEFFORT_LAST_CALL
             if( !setIncomplete ){