merged fmf-devel branch, includes support for SMT2 command get-value and (extended...
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Thu, 12 Jul 2012 18:30:15 +0000 (18:30 +0000)
committerAndrew Reynolds <andrew.j.reynolds@gmail.com>
Thu, 12 Jul 2012 18:30:15 +0000 (18:30 +0000)
87 files changed:
README.fmf-devel [new file with mode: 0644]
src/expr/command.cpp
src/expr/command.h
src/parser/cvc/Cvc.g
src/parser/smt/Smt.g
src/parser/smt2/Smt2.g
src/parser/tptp/tptp.h
src/printer/smt2/smt2_printer.cpp
src/smt/smt_engine.cpp
src/smt/smt_engine.h
src/theory/Makefile.am
src/theory/arith/theory_arith.cpp
src/theory/arith/theory_arith.h
src/theory/arith/theory_arith_instantiator.cpp
src/theory/arith/theory_arith_instantiator.h
src/theory/arrays/theory_arrays.cpp
src/theory/arrays/theory_arrays.h
src/theory/arrays/theory_arrays_instantiator.cpp
src/theory/arrays/theory_arrays_instantiator.h
src/theory/booleans/theory_bool.cpp
src/theory/booleans/theory_bool.h
src/theory/builtin/theory_builtin.cpp
src/theory/builtin/theory_builtin.h
src/theory/bv/theory_bv.cpp
src/theory/bv/theory_bv.h
src/theory/datatypes/theory_datatypes.cpp
src/theory/datatypes/theory_datatypes.h
src/theory/datatypes/theory_datatypes_instantiator.cpp
src/theory/datatypes/theory_datatypes_instantiator.h
src/theory/example/theory_uf_tim.h
src/theory/inst_match.cpp
src/theory/inst_match.h
src/theory/instantiator_default.cpp
src/theory/instantiator_default.h
src/theory/model.cpp [new file with mode: 0644]
src/theory/model.h [new file with mode: 0644]
src/theory/quantifiers/Makefile.am
src/theory/quantifiers/first_order_model.cpp [new file with mode: 0644]
src/theory/quantifiers/first_order_model.h [new file with mode: 0644]
src/theory/quantifiers/instantiation_engine.cpp
src/theory/quantifiers/instantiation_engine.h
src/theory/quantifiers/model_engine.cpp
src/theory/quantifiers/model_engine.h
src/theory/quantifiers/relevant_domain.cpp [new file with mode: 0644]
src/theory/quantifiers/relevant_domain.h [new file with mode: 0644]
src/theory/quantifiers/rep_set_iterator.cpp [new file with mode: 0644]
src/theory/quantifiers/rep_set_iterator.h [new file with mode: 0644]
src/theory/quantifiers/term_database.cpp [new file with mode: 0644]
src/theory/quantifiers/term_database.h [new file with mode: 0644]
src/theory/quantifiers/theory_quantifiers.cpp
src/theory/quantifiers/theory_quantifiers.h
src/theory/quantifiers/theory_quantifiers_instantiator.cpp
src/theory/quantifiers/theory_quantifiers_instantiator.h
src/theory/quantifiers_engine.cpp
src/theory/quantifiers_engine.h
src/theory/rewriterules/theory_rewriterules.cpp
src/theory/rewriterules/theory_rewriterules.h
src/theory/rewriterules/theory_rewriterules_rules.cpp
src/theory/shared_terms_database.h
src/theory/theory.cpp
src/theory/theory.h
src/theory/theory_engine.cpp
src/theory/theory_engine.h
src/theory/trigger.cpp
src/theory/trigger.h
src/theory/uf/Makefile.am
src/theory/uf/inst_strategy.cpp
src/theory/uf/inst_strategy.h
src/theory/uf/kinds
src/theory/uf/theory_uf.cpp
src/theory/uf/theory_uf.h
src/theory/uf/theory_uf_candidate_generator.cpp
src/theory/uf/theory_uf_instantiator.cpp
src/theory/uf/theory_uf_instantiator.h
src/theory/uf/theory_uf_model.cpp [new file with mode: 0644]
src/theory/uf/theory_uf_model.h [new file with mode: 0644]
src/theory/uf/theory_uf_strong_solver.cpp
src/theory/uf/theory_uf_strong_solver.h
src/theory/uf/theory_uf_type_rules.h
src/theory/valuation.cpp
src/theory/valuation.h
src/util/Makefile.am
src/util/dump.h
src/util/model.cpp [new file with mode: 0644]
src/util/model.h [new file with mode: 0644]
src/util/options.cpp
src/util/options.h

diff --git a/README.fmf-devel b/README.fmf-devel
new file mode 100644 (file)
index 0000000..e35bcab
--- /dev/null
@@ -0,0 +1 @@
+This branch is used for development of the finite model finding mode of CVC4.
index 8b7f1bfa4a81fab8060b4e1e2ab249c3555db5e3..5b889712d7dba1f798d17003c8839d0873899c73 100644 (file)
@@ -456,8 +456,9 @@ std::string DeclarationDefinitionCommand::getSymbol() const throw() {
 
 /* class DeclareFunctionCommand */
 
-DeclareFunctionCommand::DeclareFunctionCommand(const std::string& id, Type t) throw() :
+DeclareFunctionCommand::DeclareFunctionCommand(const std::string& id, Expr func, Type t) throw() :
   DeclarationDefinitionCommand(id),
+  d_func(func),
   d_type(t) {
 }
 
@@ -467,17 +468,18 @@ Type DeclareFunctionCommand::getType() const throw() {
 
 void DeclareFunctionCommand::invoke(SmtEngine* smtEngine) throw() {
   Dump("declarations") << *this;
+  smtEngine->addToModelFunction( d_func );
   d_commandStatus = CommandSuccess::instance();
 }
 
 Command* DeclareFunctionCommand::exportTo(ExprManager* exprManager,
                                           ExprManagerMapCollection& variableMap) {
-  return new DeclareFunctionCommand(d_symbol,
+  return new DeclareFunctionCommand(d_symbol, d_func.exportTo(exprManager, variableMap),
                                     d_type.exportTo(exprManager, variableMap));
 }
 
 Command* DeclareFunctionCommand::clone() const {
-  return new DeclareFunctionCommand(d_symbol, d_type);
+  return new DeclareFunctionCommand(d_symbol, d_func, d_type);
 }
 
 /* class DeclareTypeCommand */
@@ -498,6 +500,7 @@ Type DeclareTypeCommand::getType() const throw() {
 
 void DeclareTypeCommand::invoke(SmtEngine* smtEngine) throw() {
   Dump("declarations") << *this;
+  smtEngine->addToModelType( d_type );
   d_commandStatus = CommandSuccess::instance();
 }
 
@@ -762,6 +765,47 @@ Command* GetAssignmentCommand::clone() const {
   return c;
 }
 
+/* class GetModelCommand */
+
+GetModelCommand::GetModelCommand() throw() {
+}
+
+void GetModelCommand::invoke(SmtEngine* smtEngine) throw() {
+  try {
+    d_result = smtEngine->getModel();
+    d_smtEngine = smtEngine;
+    d_commandStatus = CommandSuccess::instance();
+  } catch(exception& e) {
+    d_commandStatus = new CommandFailure(e.what());
+  }
+}
+
+Model* GetModelCommand::getResult() const throw() {
+  return d_result;
+}
+
+void GetModelCommand::printResult(std::ostream& out) const throw() {
+  if(! ok()) {
+    this->Command::printResult(out);
+  } else {
+    d_smtEngine->printModel( out, d_result );
+  }
+}
+
+Command* GetModelCommand::exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap) {
+  GetModelCommand* c = new GetModelCommand();
+  c->d_result = d_result;
+  c->d_smtEngine = d_smtEngine;
+  return c;
+}
+
+Command* GetModelCommand::clone() const {
+  GetModelCommand* c = new GetModelCommand();
+  c->d_result = d_result;
+  c->d_smtEngine = d_smtEngine;
+  return c;
+}
+
 /* class GetProofCommand */
 
 GetProofCommand::GetProofCommand() throw() {
index 98046c2427c8c0298bae22d6081ded4761e3ac5a..123fe01826fec66807b4de4c1bac3395a425dba1 100644 (file)
@@ -37,6 +37,7 @@
 #include "util/sexpr.h"
 #include "util/datatype.h"
 #include "util/proof.h"
+#include "util/model.h"
 
 namespace CVC4 {
 
@@ -316,9 +317,10 @@ public:
 
 class CVC4_PUBLIC DeclareFunctionCommand : public DeclarationDefinitionCommand {
 protected:
+  Expr d_func;
   Type d_type;
 public:
-  DeclareFunctionCommand(const std::string& id, Type type) throw();
+  DeclareFunctionCommand(const std::string& id, Expr func, Type type) throw();
   ~DeclareFunctionCommand() throw() {}
   Type getType() const throw();
   void invoke(SmtEngine* smtEngine) throw();
@@ -462,6 +464,20 @@ public:
   Command* clone() const;
 };/* class GetAssignmentCommand */
 
+class CVC4_PUBLIC GetModelCommand : public Command {
+protected:
+  Model* d_result;
+  SmtEngine* d_smtEngine;
+public:
+  GetModelCommand() throw();
+  ~GetModelCommand() throw() {}
+  void invoke(SmtEngine* smtEngine) throw();
+  Model* getResult() const throw();
+  void printResult(std::ostream& out) const throw();
+  Command* exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap);
+  Command* clone() const;
+};/* class GetModelCommand */
+
 class CVC4_PUBLIC GetProofCommand : public Command {
 protected:
   Proof* d_result;
index 55e10724b2bc9a5ab7b8979490219650a89a1e5a..bbeee4f7f5aa7ebf470e0d39e48ba8505b2e192e 100644 (file)
@@ -922,9 +922,9 @@ declareVariables[CVC4::Command*& cmd, CVC4::Type& t, const std::vector<std::stri
             }
           } else {
             Debug("parser") << "  " << *i << " not declared" << std::endl;
-            PARSER_STATE->mkVar(*i, t);
+            Expr func = PARSER_STATE->mkVar(*i, t);
             if(topLevel) {
-              Command* decl = new DeclareFunctionCommand(*i, t);
+              Command* decl = new DeclareFunctionCommand(*i, func, t);
               seq->addCommand(decl);
             }
           }
index d44f7abcbd26cdd5f565e46f6f9975e1b3215513..429adee0a98e1d6bcbc72a028be0ac4a615bcb89 100644 (file)
@@ -470,8 +470,8 @@ functionDeclaration[CVC4::Command*& smt_command]
       } else {
         t = EXPR_MANAGER->mkFunctionType(sorts);
       }
-      PARSER_STATE->mkVar(name, t);
-      smt_command = new DeclareFunctionCommand(name, t);
+      Expr func = PARSER_STATE->mkVar(name, t);
+      smt_command = new DeclareFunctionCommand(name, func, t);
     }
   ;
 
@@ -490,8 +490,8 @@ predicateDeclaration[CVC4::Command*& smt_command]
       } else {
         t = EXPR_MANAGER->mkPredicateType(p_sorts);
       }
-      PARSER_STATE->mkVar(name, t);
-      smt_command = new DeclareFunctionCommand(name, t);
+      Expr func = PARSER_STATE->mkVar(name, t);
+      smt_command = new DeclareFunctionCommand(name, func, t);
     }
   ;
 
index 84d75ceac1ff23f085ad2a4c0c7de3b1ed28a4f4..577438d37f5cbf0338ebe9a73a90a1a9de3436eb 100644 (file)
@@ -240,8 +240,8 @@ command returns [CVC4::Command* cmd = NULL]
       if( sorts.size() > 0 ) {
         t = EXPR_MANAGER->mkFunctionType(sorts, t);
       }
-      PARSER_STATE->mkVar(name, t);
-      $cmd = new DeclareFunctionCommand(name, t); }
+      Expr func = PARSER_STATE->mkVar(name, t);
+      $cmd = new DeclareFunctionCommand(name, func, t); }
   | /* function definition */
     DEFINE_FUN_TOK { PARSER_STATE->checkThatLogicIsSet(); }
     symbol[name,CHECK_UNDECLARED,SYM_VARIABLE]
@@ -383,6 +383,9 @@ extendedCommand[CVC4::Command*& cmd]
     LPAREN_TOK ( LPAREN_TOK datatypeDef[dts] RPAREN_TOK )+ RPAREN_TOK
     { PARSER_STATE->popScope();
       cmd = new DatatypeDeclarationCommand(PARSER_STATE->mkMutualDatatypeTypes(dts)); }
+  | /* get model */
+    GET_MODEL_TOK { PARSER_STATE->checkThatLogicIsSet(); }
+    { cmd = new GetModelCommand; }      
   | ECHO_TOK
     ( simpleSymbolicExpr[sexpr]
       { std::stringstream ss;
@@ -1063,6 +1066,7 @@ POP_TOK : 'pop';
 
 // extended commands
 DECLARE_DATATYPES_TOK : 'declare-datatypes';
+GET_MODEL_TOK : 'get-model';
 ECHO_TOK : 'echo';
 
 // attributes
index e6231920d38d1b2aa7e72e03fbcc212434ff115e..ae4ad4e7f453cf0233d2575402ea1398e4fe7f9b 100644 (file)
@@ -70,11 +70,11 @@ public:
       //Conversion from rational to unsorted
       t = em->mkFunctionType(em->realType(), d_unsorted);
       d_rtu_op = em->mkVar("$$rtu",t);
-      preemptCommand(new DeclareFunctionCommand("$$rtu", t));
+      preemptCommand(new DeclareFunctionCommand("$$rtu", d_rtu_op, t));
       //Conversion from unsorted to rational
       t = em->mkFunctionType(d_unsorted, em->realType());
       d_utr_op = em->mkVar("$$utr",t);
-      preemptCommand(new DeclareFunctionCommand("$$utur", t));
+      preemptCommand(new DeclareFunctionCommand("$$utur", d_utr_op, t));
     }
     // Add the inverse in order to show that over the elements that
     // appear in the problem there is a bijection between unsorted and
@@ -98,11 +98,11 @@ public:
       //Conversion from string to unsorted
       t = em->mkFunctionType(em->stringType(), d_unsorted);
       d_stu_op = em->mkVar("$$stu",t);
-      preemptCommand(new DeclareFunctionCommand("$$stu", t));
+      preemptCommand(new DeclareFunctionCommand("$$stu", d_stu_op, t));
       //Conversion from unsorted to string
       t = em->mkFunctionType(d_unsorted, em->stringType());
       d_uts_op = em->mkVar("$$uts",t);
-      preemptCommand(new DeclareFunctionCommand("$$uts", t));
+      preemptCommand(new DeclareFunctionCommand("$$uts", d_uts_op, t));
     }
     // Add the inverse in order to show that over the elements that
     // appear in the problem there is a bijection between unsorted and
@@ -185,7 +185,7 @@ inline void Tptp::makeApplication(Expr & expr, std::string & name,
     } else {
       Type t = term ? d_unsorted : getExprManager()->booleanType();
       expr = mkVar(name,t,true); //levelZero
-      preemptCommand(new DeclareFunctionCommand(name, t));
+      preemptCommand(new DeclareFunctionCommand(name, expr, t));
     }
   } else { // Its an application
     if(isDeclared(name)){ //already appeared
@@ -195,7 +195,7 @@ inline void Tptp::makeApplication(Expr & expr, std::string & name,
       Type t = term ? d_unsorted : getExprManager()->booleanType();
       t = getExprManager()->mkFunctionType(sorts, t);
       expr = mkVar(name,t,true); //levelZero
-      preemptCommand(new DeclareFunctionCommand(name, t));
+      preemptCommand(new DeclareFunctionCommand(name, expr, t));
     }
     expr = getExprManager()->mkExpr(kind::APPLY_UF, expr, args);
   }
index e032a942644d1e967046a3827f36e7d722a05af6..7fa00a6e45c693f8a3be8fb8fb74c04eaf657f29 100644 (file)
@@ -126,8 +126,8 @@ void Smt2Printer::toStream(std::ostream& out, TNode n,
       const Integer& x = bv.getValue();
       unsigned n = bv.getSize();
       out << "(_ ";
-      out << "bv" << x <<" " << n; 
-      out << ")"; 
+      out << "bv" << x <<" " << n;
+      out << ")";
       // //out << "#b";
 
       // while(n-- > 0) {
@@ -307,6 +307,14 @@ void Smt2Printer::toStream(std::ostream& out, TNode n,
     // TODO user patterns
     break;
 
+  //function models
+  case kind::FUNCTION_MODEL:
+    break;
+  case kind::FUNCTION_CASE_SPLIT:
+    break;
+  case kind::FUNCTION_CASE:
+    out << "if ";
+    break;
   default:
     // fall back on however the kind prints itself; this probably
     // won't be SMT-LIB v2 compliant, but it will be clear from the
index 08e335717c2bae99a751194ba05d7289021471a9..4cccb8d10f09c0153a96deb348c3a0698efa35b0 100644 (file)
@@ -59,6 +59,7 @@
 #include "theory/theory_traits.h"
 #include "theory/logic_info.h"
 #include "util/ite_removal.h"
+#include "theory/model.h"
 
 using namespace std;
 using namespace CVC4;
@@ -743,7 +744,8 @@ void SmtEngine::setOption(const std::string& key, const SExpr& value)
     } else if(key == ":produce-unsat-cores") {
       throw BadOptionException();
     } else if(key == ":produce-models") {
-      throw BadOptionException();
+      //throw BadOptionException();
+      const_cast<Options*>( Options::s_current )->produceModels = true;
     } else if(key == ":produce-assignments") {
       throw BadOptionException();
     } else {
@@ -935,7 +937,7 @@ void SmtEnginePrivate::removeITEs() {
   for (unsigned i = 0; i < d_assertionsToCheck.size(); ++ i) {
     d_assertionsToCheck[i] = Rewriter::rewrite(d_assertionsToCheck[i]);
   }
-  
+
 }
 
 void SmtEnginePrivate::staticLearning() {
@@ -1467,7 +1469,7 @@ void SmtEnginePrivate::processAssertions() {
         expandDefinitions(d_assertionsToPreprocess[i], cache);
     }
   }
-    
+
   // Apply the substitutions we already have, and normalize
   Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
                     << "applying substitutions" << endl;
@@ -1766,16 +1768,15 @@ Expr SmtEngine::getValue(const Expr& e)
     throw ModalException(msg);
   }
   if(d_status.isNull() ||
-     d_status.asSatisfiabilityResult() != Result::SAT ||
+     d_status.asSatisfiabilityResult() == Result::UNSAT ||
      d_problemExtended) {
     const char* msg =
-      "Cannot get value unless immediately preceded by SAT/INVALID response.";
+      "Cannot get value unless immediately preceded by SAT/INVALID or UNKNOWN response.";
     throw ModalException(msg);
   }
-  if(type.isFunction() || type.isPredicate() ||
-     type.isKind() || type.isSortConstructor()) {
+  if(type.isKind() || type.isSortConstructor()) {
     const char* msg =
-      "Cannot get value of a function, predicate, or sort.";
+      "Cannot get value of a sort.";
     throw ModalException(msg);
   }
 
@@ -1786,10 +1787,14 @@ Expr SmtEngine::getValue(const Expr& e)
   n = Rewriter::rewrite(n);
 
   Trace("smt") << "--- getting value of " << n << endl;
-  Node resultNode = d_theoryEngine->getValue(n);
-
+  theory::TheoryModel* m = d_theoryEngine->getModel();
+  Node resultNode;
+  if( m ){
+    resultNode = m->getValue( n );
+  }
+  Trace("smt") << "--- got value " << n << " = " << resultNode << endl;
   // type-check the result we got
-  Assert(resultNode.isNull() || resultNode.getType() == n.getType());
+  Assert(resultNode.isNull() || resultNode.getType().isSubtypeOf( n.getType() ));
   return Expr(d_exprManager, new Node(resultNode));
 }
 
@@ -1835,11 +1840,11 @@ SExpr SmtEngine::getAssignment() throw(ModalException, AssertionException) {
     throw ModalException(msg);
   }
   if(d_status.isNull() ||
-     d_status.asSatisfiabilityResult() != Result::SAT ||
+     d_status.asSatisfiabilityResult() == Result::UNSAT  ||
      d_problemExtended) {
     const char* msg =
       "Cannot get the current assignment unless immediately "
-      "preceded by SAT/INVALID response.";
+      "preceded by SAT/INVALID or UNKNOWN response.";
     throw ModalException(msg);
   }
 
@@ -1859,7 +1864,11 @@ SExpr SmtEngine::getAssignment() throw(ModalException, AssertionException) {
     Node n = Rewriter::rewrite(*i);
 
     Trace("smt") << "--- getting value of " << n << endl;
-    Node resultNode = d_theoryEngine->getValue(n);
+    theory::TheoryModel* m = d_theoryEngine->getModel();
+    Node resultNode;
+    if( m ){
+      resultNode = m->getValue( n );
+    }
 
     // type-check the result we got
     Assert(resultNode.isNull() || resultNode.getType() == boolType);
@@ -1878,6 +1887,45 @@ SExpr SmtEngine::getAssignment() throw(ModalException, AssertionException) {
   return SExpr(sexprs);
 }
 
+
+void SmtEngine::addToModelType( Type& t ){
+  Trace("smt") << "SMT addToModelType(" << t << ")" << endl;
+  NodeManagerScope nms(d_nodeManager);
+  if( Options::current()->produceModels ) {
+    d_theoryEngine->getModel()->addDefineType( TypeNode::fromType( t ) );
+  }
+}
+
+void SmtEngine::addToModelFunction( Expr& e ){
+  Trace("smt") << "SMT addToModelFunction(" << e << ")" << endl;
+  NodeManagerScope nms(d_nodeManager);
+  if( Options::current()->produceModels ) {
+    d_theoryEngine->getModel()->addDefineFunction( e.getNode() );
+  }
+}
+
+
+Model* SmtEngine::getModel() throw(ModalException, AssertionException){
+  Trace("smt") << "SMT getModel()" << endl;
+  NodeManagerScope nms(d_nodeManager);
+
+  if(!Options::current()->produceModels) {
+    const char* msg =
+      "Cannot get value when produce-models options is off.";
+    throw ModalException(msg);
+  }
+  if(d_status.isNull() ||
+     d_status.asSatisfiabilityResult() == Result::UNSAT  ||
+     d_problemExtended) {
+    const char* msg =
+      "Cannot get the current model unless immediately "
+      "preceded by SAT/INVALID or UNKNOWN response.";
+    throw ModalException(msg);
+  }
+
+  return d_theoryEngine->getModel();
+}
+
 Proof* SmtEngine::getProof() throw(ModalException, AssertionException) {
   Trace("smt") << "SMT getProof()" << endl;
   NodeManagerScope nms(d_nodeManager);
@@ -2063,4 +2111,9 @@ StatisticsRegistry* SmtEngine::getStatisticsRegistry() const {
   return d_exprManager->d_nodeManager->getStatisticsRegistry();
 }
 
+void SmtEngine::printModel( std::ostream& out, Model* m ){
+  NodeManagerScope nms(d_nodeManager);
+  m->toStream(out);
+}
+
 }/* CVC4 namespace */
index ae9caf0eb90da1cbb210afb7eea763e7bfbd9e11..aef98d75b7b68d4eb2e8666e88f289cde6b8a85a 100644 (file)
@@ -29,6 +29,7 @@
 #include "expr/expr.h"
 #include "expr/expr_manager.h"
 #include "util/proof.h"
+#include "util/model.h"
 #include "smt/bad_option_exception.h"
 #include "smt/modal_exception.h"
 #include "smt/no_such_function_exception.h"
@@ -385,6 +386,25 @@ public:
    */
   SExpr getAssignment() throw(ModalException, AssertionException);
 
+  /**
+   * Add to Model Type.  This is used for recording which types should be reported
+   * during a get-model call.
+   */
+  void addToModelType( Type& t );
+
+  /**
+   * Add to Model Function.  This is used for recording which functions should be reported
+   * during a get-model call.
+   */
+  void addToModelFunction( Expr& e );
+
+  /**
+   * Get the model (only if immediately preceded by a SAT
+   * or INVALID query).  Only permitted if CVC4 was built with model
+   * support and produce-models is on.
+   */
+  Model* getModel() throw(ModalException, AssertionException);
+
   /**
    * Get the last proof (only if immediately preceded by an UNSAT
    * or VALID query).  Only permitted if CVC4 was built with proof
@@ -520,6 +540,11 @@ public:
     return d_status;
   }
 
+  /**
+   * print model function (need this?)
+   */
+  void printModel( std::ostream& out, Model* m );
+
 };/* class SmtEngine */
 
 }/* CVC4 namespace */
index 84af80035f8fb18ba93d456e037232116be25538..bca96f7d7d85bf9d07c679396f8116427e2a8172 100644 (file)
@@ -43,7 +43,9 @@ libtheory_la_SOURCES = \
        inst_match_impl.h \
        inst_match.cpp \
        trigger.h \
-       trigger.cpp
+       trigger.cpp \
+       model.h \
+       model.cpp 
 
 nodist_libtheory_la_SOURCES = \
        rewriter_tables.h \
index 390ac280b9ff392ffcbf5eed8501c71c03851a58..c68e9cf54f3ba0d464944682597e4ab6551f45f9 100644 (file)
@@ -40,6 +40,7 @@
 #include "theory/arith/constraint.h"
 #include "theory/arith/theory_arith.h"
 #include "theory/arith/normal_form.h"
+#include "theory/model.h"
 
 #include <stdint.h>
 
@@ -1464,12 +1465,12 @@ void TheoryArith::check(Effort effortLevel){
     d_qflraStatus = Result::UNSAT;
     if(previous == Result::SAT){
       ++d_statistics.d_revertsOnConflicts;
-      Debug("arith::bt") << "clearing here " << " " << newFacts << " " << previous << " " << d_qflraStatus  << endl; 
+      Debug("arith::bt") << "clearing here " << " " << newFacts << " " << previous << " " << d_qflraStatus  << endl;
       revertOutOfConflict();
       d_simplex.clearQueue();
     }else{
       ++d_statistics.d_commitsOnConflicts;
-      Debug("arith::bt") << "committing here " << " " << newFacts << " " << previous << " " << d_qflraStatus  << endl; 
+      Debug("arith::bt") << "committing here " << " " << newFacts << " " << previous << " " << d_qflraStatus  << endl;
       d_partialModel.commitAssignmentChanges();
       revertOutOfConflict();
     }
@@ -1492,7 +1493,7 @@ void TheoryArith::check(Effort effortLevel){
       ++d_statistics.d_nontrivialSatChecks;
     }
 
-    Debug("arith::bt") << "committing sap inConflit"  << " " << newFacts << " " << previous << " " << d_qflraStatus  << endl; 
+    Debug("arith::bt") << "committing sap inConflit"  << " " << newFacts << " " << previous << " " << d_qflraStatus  << endl;
     d_partialModel.commitAssignmentChanges();
     d_unknownsInARow = 0;
     if(Debug.isOn("arith::consistency")){
@@ -1503,7 +1504,7 @@ void TheoryArith::check(Effort effortLevel){
     ++d_unknownsInARow;
     ++(d_statistics.d_unknownChecks);
     Assert(!fullEffort(effortLevel));
-    Debug("arith::bt") << "committing unknown"  << " " << newFacts << " " << previous << " " << d_qflraStatus  << endl; 
+    Debug("arith::bt") << "committing unknown"  << " " << newFacts << " " << previous << " " << d_qflraStatus  << endl;
     d_partialModel.commitAssignmentChanges();
     d_statistics.d_maxUnknownsInARow.maxAssign(d_unknownsInARow);
     break;
@@ -1922,80 +1923,8 @@ DeltaRational TheoryArith::getDeltaValue(TNode n) {
   }
 }
 
-Node TheoryArith::getValue(TNode n) {
-  NodeManager* nodeManager = NodeManager::currentNM();
+void TheoryArith::collectModelInfo( TheoryModel* m ){
 
-  Assert(d_qflraStatus == Result::SAT);
-
-  switch(n.getKind()) {
-  case kind::VARIABLE: {
-    ArithVar var = d_arithvarNodeMap.asArithVar(n);
-
-    DeltaRational drat = d_partialModel.getAssignment(var);
-    const Rational& delta = d_partialModel.getDelta();
-    Debug("getValue") << n << " " << drat << " " << delta << endl;
-    return nodeManager->
-      mkConst( drat.getNoninfinitesimalPart() +
-               drat.getInfinitesimalPart() * delta );
-  }
-
-  case kind::EQUAL: // 2 args
-    return nodeManager->
-      mkConst( d_valuation.getValue(n[0]) == d_valuation.getValue(n[1]) );
-
-  case kind::PLUS: { // 2+ args
-    Rational value(0);
-    for(TNode::iterator i = n.begin(),
-            iend = n.end();
-          i != iend;
-          ++i) {
-      value += d_valuation.getValue(*i).getConst<Rational>();
-    }
-    return nodeManager->mkConst(value);
-  }
-
-  case kind::MULT: { // 2+ args
-    Rational value(1);
-    for(TNode::iterator i = n.begin(),
-            iend = n.end();
-          i != iend;
-          ++i) {
-      value *= d_valuation.getValue(*i).getConst<Rational>();
-    }
-    return nodeManager->mkConst(value);
-  }
-
-  case kind::MINUS: // 2 args
-    // should have been rewritten
-    Unreachable();
-
-  case kind::UMINUS: // 1 arg
-    // should have been rewritten
-    Unreachable();
-
-  case kind::DIVISION: // 2 args
-    return nodeManager->mkConst( d_valuation.getValue(n[0]).getConst<Rational>() /
-                                 d_valuation.getValue(n[1]).getConst<Rational>() );
-
-  case kind::LT: // 2 args
-    return nodeManager->mkConst( d_valuation.getValue(n[0]).getConst<Rational>() <
-                                 d_valuation.getValue(n[1]).getConst<Rational>() );
-
-  case kind::LEQ: // 2 args
-    return nodeManager->mkConst( d_valuation.getValue(n[0]).getConst<Rational>() <=
-                                 d_valuation.getValue(n[1]).getConst<Rational>() );
-
-  case kind::GT: // 2 args
-    return nodeManager->mkConst( d_valuation.getValue(n[0]).getConst<Rational>() >
-                                 d_valuation.getValue(n[1]).getConst<Rational>() );
-
-  case kind::GEQ: // 2 args
-    return nodeManager->mkConst( d_valuation.getValue(n[0]).getConst<Rational>() >=
-                                 d_valuation.getValue(n[1]).getConst<Rational>() );
-
-  default:
-    Unhandled(n.getKind());
-  }
 }
 
 bool TheoryArith::safeToReset() const {
index fd2925bf62037f58d207236dee1718fa14c4f501..35fcca4060310b0633d747add8764a94734610b5 100644 (file)
@@ -323,7 +323,7 @@ public:
   void propagate(Effort e);
   Node explain(TNode n);
 
-  Node getValue(TNode n);
+  void collectModelInfo( TheoryModel* m );
 
   void shutdown(){ }
 
index f1b870c52c3d1fb39013c97fce3d7fe8b538ca44..c4cb2f4935018ce011d30eac25d652e528ea9c49 100644 (file)
@@ -17,6 +17,7 @@
 #include "theory/arith/theory_arith_instantiator.h"
 #include "theory/arith/theory_arith.h"
 #include "theory/theory_engine.h"
+#include "theory/quantifiers/term_database.h"
 
 using namespace std;
 using namespace CVC4;
@@ -40,7 +41,7 @@ void InstStrategySimplex::processResetInstantiationRound( Theory::Effort effort
   d_counter++;
 }
 
-int InstStrategySimplex::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategySimplex::process( Node f, Theory::Effort effort, int e ){
   if( e<2 ){
     return STATUS_UNFINISHED;
   }else if( e==2 ){
@@ -99,7 +100,7 @@ int InstStrategySimplex::process( Node f, Theory::Effort effort, int e, int inst
 //
 //}
 //
-//int InstStrategySimplexUfMatch::process( Node f, int effort, int instLimit ){
+//int InstStrategySimplexUfMatch::process( Node f, int effort ){
 //  if( effort<2 ){
 //    return STATUS_UNFINISHED;
 //  }else if( effort==2 ){
@@ -120,7 +121,7 @@ int InstStrategySimplex::process( Node f, Theory::Effort effort, int e, int inst
 //        while( d_tableaux_ce_term_trigger[x]->getNextMatch() && !addedLemma ){
 //          InstMatch* m = d_tableaux_ce_term_trigger[x]->getCurrent();
 //          if( m->isComplete( f ) ){
-//            if( d_quantEngine->addInstantiation( f, m, true ) ){
+//            if( d_quantEngine->addInstantiation( f, m ) ){
 //              ++(d_th->d_statistics.d_instantiations_match_pure);
 //              ++(d_th->d_statistics.d_instantiations);
 //              addedLemma = true;
@@ -133,8 +134,8 @@ int InstStrategySimplex::process( Node f, Theory::Effort effort, int e, int inst
 //            //Debug("quant-arith") << std::endl;
 //            std::vector< Node > vars;
 //            std::vector< Node > matches;
-//            for( int i=0; i<d_quantEngine->getNumInstantiationConstants( f ); i++ ){
-//              Node ic = d_quantEngine->getInstantiationConstant( f, i );
+//            for( int i=0; i<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
+//              Node ic = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i );
 //              if( m->d_map[ ic ]!=Node::null() ){
 //                vars.push_back( ic );
 //                matches.push_back( m->d_map[ ic ] );
@@ -162,7 +163,7 @@ int InstStrategySimplex::process( Node f, Theory::Effort effort, int e, int inst
 //                ++(d_th->d_statistics.d_instantiations_match_var);
 //              }
 //            }else{
-//              if( d_quantEngine->addInstantiation( f, m, true ) ){
+//              if( d_quantEngine->addInstantiation( f, m ) ){
 //                addedLemma = true;
 //                ++(d_th->d_statistics.d_instantiations_match_no_var);
 //                ++(d_th->d_statistics.d_instantiations);
@@ -242,7 +243,7 @@ void InstantiatorTheoryArith::processResetInstantiationRound( Theory::Effort eff
   }
 }
 
-int InstantiatorTheoryArith::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstantiatorTheoryArith::process( Node f, Theory::Effort effort, int e ){
   Debug("quant-arith") << "Arith: Try to solve (" << effort << ") for " << f << "... " << std::endl;
   return InstStrategy::STATUS_UNKNOWN;
 }
@@ -316,11 +317,11 @@ void InstantiatorTheoryArith::debugPrint( const char* c ){
     Node f = d_quantEngine->getQuantifier( q );
     Debug(c) << f << std::endl;
     Debug(c) << "   Inst constants: ";
-    for( int i=0; i<(int)d_quantEngine->getNumInstantiationConstants( f ); i++ ){
+    for( int i=0; i<(int)d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
       if( i>0 ){
         Debug( c ) << ", ";
       }
-      Debug( c ) << d_quantEngine->getInstantiationConstant( f, i );
+      Debug( c ) << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i );
     }
     Debug(c) << std::endl;
     Debug(c) << "   Instantiation rows: ";
@@ -377,7 +378,7 @@ bool InstantiatorTheoryArith::doInstantiation2( Node f, Node term, ArithVar x, I
   //use as instantiation value for var
   m.d_map[ var ] = instVal;
   Debug("quant-arith") << "Add instantiation " << m << std::endl;
-  return d_quantEngine->addInstantiation( f, m, true );
+  return d_quantEngine->addInstantiation( f, m );
 }
 
 Node InstantiatorTheoryArith::getTableauxValue( Node n, bool minus_delta ){
index 3880a49a79a244aeb2f23fcc76a4ee0a8a0c8034..406478a2aebf2c179677cac4da82da651de83dac 100644 (file)
@@ -41,7 +41,7 @@ private:
   Node d_negOne;
   /** process functions */
   void processResetInstantiationRound( Theory::Effort effort );
-  int process( Node f, Theory::Effort effort, int e, int instLimit );
+  int process( Node f, Theory::Effort effort, int e );
 public:
   InstStrategySimplex( InstantiatorTheoryArith* th, QuantifiersEngine* ie );
   ~InstStrategySimplex(){}
@@ -56,7 +56,7 @@ public:
 //  /** trigger for instantiation rows */
 //  std::map< ArithVar, Trigger* > d_tableaux_ce_term_trigger;
 //public:
-//  InstStrategySimplexUfMatch( InstantiatorTheoryArith* th, QuantifiersEngine* ie ) : 
+//  InstStrategySimplexUfMatch( InstantiatorTheoryArith* th, QuantifiersEngine* ie ) :
 //      InstStrategy( ie ), d_th( th ){}
 //  ~InstStrategySimplexUfMatch(){}
 //  void resetInstantiationRound();
@@ -102,7 +102,7 @@ private:
   /**  reset instantiation */
   void processResetInstantiationRound( Theory::Effort effort );
   /** process at effort */
-  int process( Node f, Theory::Effort effort, int e, int instLimit );
+  int process( Node f, Theory::Effort effort, int e );
   /** add term to row */
   void addTermToRow( ArithVar x, Node n, Node& f, NodeBuilder<>& t );
   /** get delta for node */
index 460289439ad876a974314fb0f02a666a9ac982be..5add52d1f8148e52384dfb7cf3fe97146d0c9cbe 100644 (file)
@@ -24,6 +24,7 @@
 #include "theory/rewriter.h"
 #include "expr/command.h"
 #include "theory/arrays/theory_arrays_instantiator.h"
+#include "theory/model.h"
 
 using namespace std;
 
@@ -57,7 +58,7 @@ TheoryArrays::TheoryArrays(context::Context* c, context::UserContext* u, OutputC
   d_checkTimer("theory::arrays::checkTime"),
   d_ppEqualityEngine(u, "theory::arrays::TheoryArraysPP"),
   d_ppFacts(u),
-  //  d_ppCache(u),  
+  //  d_ppCache(u),
   d_literalsToPropagate(c),
   d_literalsToPropagateIndex(c, 0),
   d_isPreRegistered(c),
@@ -211,7 +212,7 @@ Node TheoryArrays::ppRewrite(TNode term) {
                 for (j = leftWrites - 1; j > i; --j) {
                   index_j = write_j[1];
                   if (!ppDisequal(index_i, index_j)) {
-                    Node hyp2(index_i.getType() == nm->booleanType()? 
+                    Node hyp2(index_i.getType() == nm->booleanType()?
                               index_i.iffNode(index_j) : index_i.eqNode(index_j));
                     hyp << hyp2.notNode();
                   }
@@ -623,27 +624,10 @@ void TheoryArrays::computeCareGraph()
 // MODEL GENERATION
 /////////////////////////////////////////////////////////////////////////////
 
-
-Node TheoryArrays::getValue(TNode n)
-{
-  // TODO: Implement this
-  NodeManager* nodeManager = NodeManager::currentNM();
-
-  switch(n.getKind()) {
-
-  case kind::VARIABLE:
-    Unhandled(kind::VARIABLE);
-
-  case kind::EQUAL: // 2 args
-    return nodeManager->
-      mkConst( d_valuation.getValue(n[0]) == d_valuation.getValue(n[1]) );
-
-  default:
-    Unhandled(n.getKind());
-  }
+void TheoryArrays::collectModelInfo( TheoryModel* m ){
+  m->assertEqualityEngine( &d_equalityEngine );
 }
 
-
 /////////////////////////////////////////////////////////////////////////////
 // NOTIFICATIONS
 /////////////////////////////////////////////////////////////////////////////
@@ -663,7 +647,7 @@ void TheoryArrays::presolve()
 void TheoryArrays::check(Effort e) {
   TimerStat::CodeTimer codeTimer(d_checkTimer);
 
-  while (!done() && !d_conflict) 
+  while (!done() && !d_conflict)
   {
     // Get all the assertions
     Assertion assertion = get();
@@ -1306,7 +1290,7 @@ void TheoryArrays::dischargeLemmas()
       d_equalityEngine.assertEquality(eq2, true, d_true);
       continue;
     }
-    
+
     Node lem = nm->mkNode(kind::OR, eq2_r, eq1_r);
 
     Trace("arrays-lem")<<"Arrays::addRowLemma adding "<<lem<<"\n";
index 25797dda333fa6802d8f99ddfaa169c0e5fb9cc3..6787f8ad89a7ffc97f8e1285133f94f4536a1b7e 100644 (file)
@@ -219,7 +219,7 @@ class TheoryArrays : public Theory {
   private:
   public:
 
-  Node getValue(TNode n);
+  void collectModelInfo( TheoryModel* m );
 
   /////////////////////////////////////////////////////////////////////////////
   // NOTIFICATIONS
@@ -346,6 +346,12 @@ class TheoryArrays : public Theory {
   void queueRowLemma(RowLemmaType lem);
   void dischargeLemmas();
 
+  public:
+
+  eq::EqualityEngine* getEqualityEngine() {
+    return &d_equalityEngine;
+  }
+
 };/* class TheoryArrays */
 
 }/* CVC4::theory::arrays namespace */
index 334d70eea8d405bd7281723138db998a749a8a01..2e446c57f81d1deb7a5114b437437f5e57f9b811 100644 (file)
@@ -51,6 +51,35 @@ void InstantiatorTheoryArrays::processResetInstantiationRound( Theory::Effort ef
 
 }
 
-int InstantiatorTheoryArrays::process( Node f, Theory::Effort effort, int e, int limitInst ){
+int InstantiatorTheoryArrays::process( Node f, Theory::Effort effort, int e ){
   return InstStrategy::STATUS_SAT;
 }
+
+bool InstantiatorTheoryArrays::hasTerm( Node a ){
+  return ((TheoryArrays*)d_th)->getEqualityEngine()->hasTerm( a );
+}
+
+bool InstantiatorTheoryArrays::areEqual( Node a, Node b ){
+  if( hasTerm( a ) && hasTerm( b ) ){
+    return ((TheoryArrays*)d_th)->getEqualityEngine()->areEqual( a, b );
+  }else{
+    return a==b;
+  }
+}
+
+bool InstantiatorTheoryArrays::areDisequal( Node a, Node b ){
+  if( hasTerm( a ) && hasTerm( b ) ){
+    return ((TheoryArrays*)d_th)->getEqualityEngine()->areDisequal( a, b, false );
+  }else{
+    return false;
+  }
+}
+
+Node InstantiatorTheoryArrays::getRepresentative( Node a ){
+  if( hasTerm( a ) ){
+    return ((TheoryArrays*)d_th)->getEqualityEngine()->getRepresentative( a );
+  }else{
+    return a;
+  }
+}
+
index 6a7c9c3eda3ebca208590ddf1685434cabd7dd02..ade43fdb02bca0bb6108b923c3236ca9f0956511 100644 (file)
@@ -32,7 +32,7 @@ protected:
   /** reset instantiation round */
   void processResetInstantiationRound( Theory::Effort effort );
   /** process quantifier */
-  int process( Node f, Theory::Effort effort, int e, int limitInst = 0 );
+  int process( Node f, Theory::Effort effort, int e );
 public:
   InstantiatorTheoryArrays(context::Context* c, QuantifiersEngine* ie, Theory* th);
   ~InstantiatorTheoryArrays() {}
@@ -42,6 +42,12 @@ public:
   void assertNode( Node assertion );
   /** identify */
   std::string identify() const { return std::string("InstantiatorTheoryArrays"); }
+public:
+  /** general queries about equality */
+  bool hasTerm( Node a );
+  bool areEqual( Node a, Node b );
+  bool areDisequal( Node a, Node b );
+  Node getRepresentative( Node a );
 };/* class Instantiatior */
 
 }
index 520adc228c79ca8e5865f4c4893aadb2eeb4c421..f096987db399c9095fd3b59189d2ca4f3305e0bb 100644 (file)
@@ -32,106 +32,8 @@ namespace CVC4 {
 namespace theory {
 namespace booleans {
 
-Node TheoryBool::getValue(TNode n) {
-  NodeManager* nodeManager = NodeManager::currentNM();
+void TheoryBool::collectModelInfo( TheoryModel* m ){
 
-  switch(n.getKind()) {
-  case kind::VARIABLE:
-    // case for Boolean vars is implemented in TheoryEngine (since it
-    // appeals to the PropEngine to get the value)
-    Unreachable();
-
-  case kind::EQUAL: // 2 args
-    // should be handled by IFF
-    Unreachable();
-
-  case kind::NOT: { // 1 arg
-    Node v = d_valuation.getValue(n[0]);
-    return v.isNull() ? Node::null() : nodeManager->mkConst(! v.getConst<bool>());
-  }
-
-  case kind::AND: { // 2+ args
-    bool foundNull = false;
-    for(TNode::iterator i = n.begin(),
-            iend = n.end();
-          i != iend;
-          ++i) {
-      Node v = d_valuation.getValue(*i);
-      if(v.isNull()) {
-        foundNull = true;
-      } else if(! v.getConst<bool>()) {
-        return nodeManager->mkConst(false);
-      }
-    }
-    return foundNull ? Node::null() : nodeManager->mkConst(true);
-  }
-
-  case kind::IFF: { // 2 args
-    Node v0 = d_valuation.getValue(n[0]);
-    Node v1 = d_valuation.getValue(n[1]);
-    if(v0.isNull() || v1.isNull()) {
-      return Node::null();
-    }
-    return nodeManager->mkConst( v0.getConst<bool>() == v1.getConst<bool>() );
-  }
-
-  case kind::IMPLIES: { // 2 args
-    Node v0 = d_valuation.getValue(n[0]);
-    Node v1 = d_valuation.getValue(n[1]);
-    if(v0.isNull() && v1.isNull()) {
-      return Node::null();
-    }
-    bool value = false;
-    if(! v0.isNull()) {
-      value = value || (! v0.getConst<bool>());
-    }
-    if(! v1.isNull()) {
-      value = value || v1.getConst<bool>();
-    }
-    return nodeManager->mkConst(value);
-  }
-
-  case kind::OR: { // 2+ args
-    bool foundNull = false;
-    for(TNode::iterator i = n.begin(),
-            iend = n.end();
-          i != iend;
-          ++i) {
-      Node v = d_valuation.getValue(*i);
-      if(v.isNull()) {
-        foundNull = true;
-      } else if(v.getConst<bool>()) {
-        return nodeManager->mkConst(true);
-      }
-    }
-    return foundNull ? Node::null() : nodeManager->mkConst(false);
-  }
-
-  case kind::XOR: { // 2 args
-    Node v0 = d_valuation.getValue(n[0]);
-    Node v1 = d_valuation.getValue(n[1]);
-    if(v0.isNull() || v1.isNull()) {
-      return Node::null();
-    }
-    return nodeManager->mkConst( v0.getConst<bool>() != v1.getConst<bool>() );
-  }
-
-  case kind::ITE: { // 3 args
-    // all ITEs should be gone except (bool,bool,bool) ones
-    Assert( n[1].getType() == nodeManager->booleanType() &&
-            n[2].getType() == nodeManager->booleanType() );
-    Node v0 = d_valuation.getValue(n[0]);
-    Node v1 = d_valuation.getValue(n[1]);
-    Node v2 = d_valuation.getValue(n[2]);
-    if(v0.isNull()) {
-      return v1 == v2 ? v1 : Node::null();
-    }
-    return nodeManager->mkConst( v0.getConst<bool>() ? v1.getConst<bool>() : v2.getConst<bool>() );
-  }
-
-  default:
-    Unhandled(n.getKind());
-  }
 }
 
 Theory::PPAssertStatus TheoryBool::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
index 40783a6ce694f1b5ce8726250c565d6d8168f79f..827b0ff5703873d5391e6fbc4b89011c796ae12e 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "theory/theory.h"
 #include "context/context.h"
+#include "theory/model.h"
 
 namespace CVC4 {
 namespace theory {
@@ -34,7 +35,7 @@ public:
     Theory(THEORY_BOOL, c, u, out, valuation, logicInfo, qe) {
   }
 
-  Node getValue(TNode n);
+  void collectModelInfo( TheoryModel* m );
 
   PPAssertStatus ppAssert(TNode in, SubstitutionMap& outSubstitutions);
 
index e955539d5361d19fa3264040eac839be0a54489d..fa176243cd69e603f80867141aba82a5bee844f6 100644 (file)
@@ -19,6 +19,7 @@
 #include "theory/builtin/theory_builtin.h"
 #include "theory/valuation.h"
 #include "expr/kind.h"
+#include "theory/model.h"
 
 using namespace std;
 
@@ -26,38 +27,8 @@ namespace CVC4 {
 namespace theory {
 namespace builtin {
 
-Node TheoryBuiltin::getValue(TNode n) {
-  switch(n.getKind()) {
+void TheoryBuiltin::collectModelInfo( TheoryModel* m ){
 
-  case kind::VARIABLE:
-    // no variables that the builtin theory is responsible for
-    Unreachable();
-
-  case kind::EQUAL: { // 2 args
-    // has to be an EQUAL over tuples, since all others should be
-    // handled elsewhere
-    Assert(n[0].getKind() == kind::TUPLE &&
-           n[1].getKind() == kind::TUPLE);
-    return NodeManager::currentNM()->
-      mkConst( getValue(n[0]) == getValue(n[1]) );
-  }
-
-  case kind::TUPLE: { // 2+ args
-    NodeBuilder<> nb(kind::TUPLE);
-    for(TNode::iterator i = n.begin(),
-          iend = n.end();
-        i != iend;
-        ++i) {
-      nb << d_valuation.getValue(*i);
-    }
-    return Node(nb);
-  }
-
-  default:
-    // all other "builtins" should have been rewritten away or handled
-    // by the valuation, or handled elsewhere.
-    Unhandled(n.getKind());
-  }
 }
 
 }/* CVC4::theory::builtin namespace */
index a13c69d9dd719debb44f91c0e35322cab44fe182..51bd7c75695790b75c6a6c174c9993610f068b1e 100644 (file)
@@ -31,7 +31,7 @@ class TheoryBuiltin : public Theory {
 public:
   TheoryBuiltin(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo, QuantifiersEngine* qe) :
     Theory(THEORY_BUILTIN, c, u, out, valuation, logicInfo, qe) {}
-  Node getValue(TNode n);
+  void collectModelInfo( TheoryModel* m );
   std::string identify() const { return std::string("TheoryBuiltin"); }
 };/* class TheoryBuiltin */
 
index 273b406e64be04ffe085ef86004f8e148ea63f86..da2dd77f68644cf7d65e7394ffd7c7b67d82ab67 100644 (file)
@@ -57,13 +57,13 @@ TheoryBV::Statistics::Statistics():
 {
   StatisticsRegistry::registerStat(&d_avgConflictSize);
   StatisticsRegistry::registerStat(&d_solveSubstitutions);
-  StatisticsRegistry::registerStat(&d_solveTimer); 
+  StatisticsRegistry::registerStat(&d_solveTimer);
 }
 
 TheoryBV::Statistics::~Statistics() {
   StatisticsRegistry::unregisterStat(&d_avgConflictSize);
   StatisticsRegistry::unregisterStat(&d_solveSubstitutions);
-  StatisticsRegistry::unregisterStat(&d_solveTimer); 
+  StatisticsRegistry::unregisterStat(&d_solveTimer);
 }
 
 void TheoryBV::preRegisterTerm(TNode node) {
@@ -75,7 +75,7 @@ void TheoryBV::preRegisterTerm(TNode node) {
   }
 
   d_bitblastSolver.preRegister(node);
-  d_equalitySolver.preRegister(node); 
+  d_equalitySolver.preRegister(node);
 }
 
 void TheoryBV::sendConflict() {
@@ -94,54 +94,40 @@ void TheoryBV::check(Effort e)
 {
   BVDebug("bitvector") << "TheoryBV::check(" << e << ")" << std::endl;
 
-  // if we are already in conflict just return the conflict 
+  // if we are already in conflict just return the conflict
   if (inConflict()) {
     sendConflict();
     return;
   }
-  
+
   // getting the new assertions
-  std::vector<TNode> new_assertions; 
+  std::vector<TNode> new_assertions;
   while (!done()) {
     Assertion assertion = get();
     TNode fact = assertion.assertion;
     new_assertions.push_back(fact);
-    BVDebug("bitvector-assertions") << "TheoryBV::check assertion " << fact << "\n"; 
+    BVDebug("bitvector-assertions") << "TheoryBV::check assertion " << fact << "\n";
   }
 
   if (!inConflict()) {
     // sending assertions to the equality solver first
     d_equalitySolver.addAssertions(new_assertions, e);
   }
-  
+
   if (!inConflict()) {
     // sending assertions to the bitblast solver
     d_bitblastSolver.addAssertions(new_assertions, e);
   }
-  
+
   if (inConflict()) {
     sendConflict();
   }
 }
 
+void TheoryBV::collectModelInfo( TheoryModel* m ){
 
-Node TheoryBV::getValue(TNode n) {
-  //NodeManager* nodeManager = NodeManager::currentNM();
-
-  switch(n.getKind()) {
-
-  case kind::VARIABLE:
-    Unhandled(kind::VARIABLE);
-
-  case kind::EQUAL: // 2 args
-    Unhandled(kind::VARIABLE);
-
-  default:
-    Unhandled(n.getKind());
-  }
 }
 
-
 void TheoryBV::propagate(Effort e) {
   BVDebug("bitvector") << indent() << "TheoryBV::propagate()" << std::endl;
 
@@ -166,14 +152,14 @@ void TheoryBV::propagate(Effort e) {
 Theory::PPAssertStatus TheoryBV::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
   switch(in.getKind()) {
   case kind::EQUAL:
-    
+
     if (in[0].getMetaKind() == kind::metakind::VARIABLE && !in[1].hasSubterm(in[0])) {
-      ++(d_statistics.d_solveSubstitutions); 
+      ++(d_statistics.d_solveSubstitutions);
       outSubstitutions.addSubstitution(in[0], in[1]);
       return PP_ASSERT_STATUS_SOLVED;
     }
     if (in[1].getMetaKind() == kind::metakind::VARIABLE && !in[0].hasSubterm(in[1])) {
-      ++(d_statistics.d_solveSubstitutions); 
+      ++(d_statistics.d_solveSubstitutions);
       outSubstitutions.addSubstitution(in[1], in[0]);
       return PP_ASSERT_STATUS_SOLVED;
     }
@@ -243,14 +229,14 @@ bool TheoryBV::storePropagation(TNode literal, SubTheory subtheory)
 
 
 void TheoryBV::explain(TNode literal, std::vector<TNode>& assumptions) {
-  // Ask the appropriate subtheory for the explanation 
+  // Ask the appropriate subtheory for the explanation
   if (propagatedBy(literal, SUB_EQUALITY)) {
     BVDebug("bitvector::explain") << "TheoryBV::explain(" << literal << "): EQUALITY" << std::endl;
-    d_equalitySolver.explain(literal, assumptions); 
+    d_equalitySolver.explain(literal, assumptions);
   } else {
     Assert(propagatedBy(literal, SUB_BITBLAST));
-    BVDebug("bitvector::explain") << "TheoryBV::explain(" << literal << ") : BITBLASTER" << std::endl;    
-    d_bitblastSolver.explain(literal, assumptions); 
+    BVDebug("bitvector::explain") << "TheoryBV::explain(" << literal << ") : BITBLASTER" << std::endl;
+    d_bitblastSolver.explain(literal, assumptions);
   }
 }
 
@@ -263,7 +249,7 @@ Node TheoryBV::explain(TNode node) {
   explain(node, assumptions);
   // this means that it is something true at level 0
   if (assumptions.size() == 0) {
-    return utils::mkTrue(); 
+    return utils::mkTrue();
   }
   // return the explanation
   Node explanation = mkAnd(assumptions);
@@ -274,9 +260,9 @@ Node TheoryBV::explain(TNode node) {
 
 void TheoryBV::addSharedTerm(TNode t) {
   Debug("bitvector::sharing") << indent() << "TheoryBV::addSharedTerm(" << t << ")" << std::endl;
-  d_sharedTermsSet.insert(t); 
+  d_sharedTermsSet.insert(t);
   if (!Options::current()->bitvectorEagerBitblast && d_useEqualityEngine) {
-    d_equalitySolver.addSharedTerm(t); 
+    d_equalitySolver.addSharedTerm(t);
   }
 }
 
index 761c11e3d21bc1e7fc77e8b8ae754ecc275e3bae..611927b2b699b2d8a58f47238904264001a8a6da 100644 (file)
@@ -57,10 +57,10 @@ public:
   void check(Effort e);
 
   void propagate(Effort e);
-  
+
   Node explain(TNode n);
 
-  Node getValue(TNode n);
+  void collectModelInfo( TheoryModel* m );
 
   std::string identify() const { return std::string("TheoryBV"); }
 
@@ -124,7 +124,7 @@ private:
   }
 
   void setConflict(Node conflict = Node::null()) {
-    d_conflict = true; 
+    d_conflict = true;
     d_conflictNode = conflict;
   }
 
@@ -136,8 +136,8 @@ private:
 
   friend class Bitblaster;
   friend class BitblastSolver;
-  friend class EqualitySolver; 
-  
+  friend class EqualitySolver;
+
 };/* class TheoryBV */
 
 }/* CVC4::theory::bv namespace */
index f9ef49c6b225d349e1b8d9984db8eb1ea4d07857..cb0f75c120167479ee56558bc46c58947167538f 100644 (file)
@@ -23,6 +23,7 @@
 #include "util/datatype.h"
 #include "util/Assert.h"
 #include "theory/datatypes/theory_datatypes_instantiator.h"
+#include "theory/model.h"
 
 #include <map>
 
@@ -94,6 +95,9 @@ void TheoryDatatypes::notifyCongruent(TNode lhs, TNode rhs) {
 
 void TheoryDatatypes::preRegisterTerm(TNode n) {
   Debug("datatypes-prereg") << "TheoryDatatypes::preRegisterTerm() " << n << endl;
+  if( n.getType().isDatatype() ){
+    d_preRegTerms.push_back( n );
+  }
 }
 
 
@@ -616,16 +620,11 @@ void TheoryDatatypes::updateSelectors( Node a ) {
   }
 }
 
-Node TheoryDatatypes::getValue(TNode n) {
-  NodeManager* nodeManager = NodeManager::currentNM();
-  switch(n.getKind()) {
-  case kind::VARIABLE:
-    Unhandled(kind::VARIABLE);
-  case kind::EQUAL: // 2 args
-    return nodeManager->
-      mkConst( d_valuation.getValue(n[0]) == d_valuation.getValue(n[1]) );
-  default:
-    Unhandled(n.getKind());
+void TheoryDatatypes::collectModelInfo( TheoryModel* m ){
+  //temporary
+  for( int i=0; i<(int)d_preRegTerms.size(); i++ ){
+    Node n = find( d_preRegTerms[i] );
+    m->assertEquality( n, d_preRegTerms[i], true );
   }
 }
 
@@ -1054,3 +1053,64 @@ bool TheoryDatatypes::searchForCycle( Node n, Node on,
   }
   return false;
 }
+
+bool TheoryDatatypes::hasTerm( Node a ){
+  return false;
+}
+
+bool TheoryDatatypes::areEqual( Node a, Node b ){
+  Node ar = find( a );
+  Node br = find( b );
+  if( ar==br ){
+    return true;
+  }else if( ar.getKind()==APPLY_CONSTRUCTOR && br.getKind()==APPLY_CONSTRUCTOR &&
+            ar.getOperator()==br.getOperator() ){
+    //for( int i=0; i<(int)ar.getNumChildren(); i++ ){
+    //  if( !areEqual( ar[0], br[0] ) ){
+    //    return false;
+    //  }
+    //}
+    //return true;
+    return false;
+  }else{
+    return false;
+  }
+}
+
+bool TheoryDatatypes::areDisequal( Node a, Node b ){
+  Node ar = find( a );
+  Node br = find( b );
+  if( ar==br ){
+    return false;
+  }else if( ar.getKind()==APPLY_CONSTRUCTOR && br.getKind()==APPLY_CONSTRUCTOR &&
+            ar.getOperator()!=br.getOperator() ){
+    return true;
+  }else{
+    EqLists::iterator deq_ia = d_disequalities.find( ar );
+    EqLists::iterator deq_ib = d_disequalities.find( br );
+    if( deq_ia!=d_disequalities.end() && deq_ib!=d_disequalities.end() ){
+      EqList* deq;
+      if( (*deq_ib).second->size()<(*deq_ia).second->size() ){
+        deq = (*deq_ib).second;
+      }else{
+        deq = (*deq_ia).second;
+      }
+      for(EqList::const_iterator i = deq->begin(); i != deq->end(); i++) {
+        TNode deqn = (*i);
+        TNode sp = find(deqn[0]);
+        TNode tp = find(deqn[1]);
+        if( sp==a && tp==b ){
+          return true;
+        }else if( sp==b && tp==a ){
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+}
+
+Node TheoryDatatypes::getRepresentative( Node a ){
+  return find( a );
+}
+
index 5a4135a3b98e804d4e4a16351b1346624d02c176..783c0ebc7efe67c0fcbd6605f9dfafae0da96a46 100644 (file)
@@ -142,6 +142,8 @@ private:
    */
   CongruenceClosureExplainer<CongruenceChannel, CONGRUENCE_OPERATORS_2 (kind::APPLY_CONSTRUCTOR, kind::APPLY_SELECTOR)> d_cce;
 
+  //temporary
+  std::vector< Node > d_preRegTerms;
 public:
   TheoryDatatypes(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo, QuantifiersEngine* qe);
   ~TheoryDatatypes();
@@ -150,7 +152,7 @@ public:
 
   void addSharedTerm(TNode t);
   void check(Effort e);
-  Node getValue(TNode n);
+  void collectModelInfo( TheoryModel* m );
   void shutdown() { }
   std::string identify() const { return std::string("TheoryDatatypes"); }
 
@@ -180,6 +182,12 @@ private:
   bool searchForCycle( Node n, Node on,
                        std::map< Node, bool >& visited,
                        NodeBuilder<>& explanation );
+public:
+  //equality queries
+  bool hasTerm( Node a );
+  bool areEqual( Node a, Node b );
+  bool areDisequal( Node a, Node b );
+  Node getRepresentative( Node a );
 };/* class TheoryDatatypes */
 
 inline bool TheoryDatatypes::hasConflict() {
index 6a32466e4c36504dbe1d4d676a997fff8b992b97..9495e4d48b0cec942a18785b1b2407c0361bbb38 100644 (file)
@@ -17,6 +17,7 @@
 #include "theory/datatypes/theory_datatypes_instantiator.h"
 #include "theory/datatypes/theory_datatypes.h"
 #include "theory/theory_engine.h"
+#include "theory/quantifiers/term_database.h"
 
 using namespace std;
 using namespace CVC4;
@@ -47,15 +48,15 @@ void InstantiatorTheoryDatatypes::processResetInstantiationRound( Theory::Effort
 }
 
 
-int InstantiatorTheoryDatatypes::process( Node f, Theory::Effort effort, int e, int limitInst ){
+int InstantiatorTheoryDatatypes::process( Node f, Theory::Effort effort, int e ){
   Debug("quant-datatypes") << "Datatypes: Try to solve (" << e << ") for " << f << "... " << std::endl;
   if( Options::current()->cbqi ){
     if( e<2 ){
       return InstStrategy::STATUS_UNFINISHED;
     }else if( e==2 ){
       InstMatch m;
-      for( int j = 0; j<(int)d_quantEngine->getNumInstantiationConstants( f ); j++ ){
-        Node i = d_quantEngine->getInstantiationConstant( f, j );
+      for( int j = 0; j<(int)d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); j++ ){
+        Node i = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );
         if( i.getType().isDatatype() ){
           Node n = getValueFor( i );
           Debug("quant-datatypes-debug") << "Value for " << i << " is " << n << std::endl;
@@ -142,10 +143,6 @@ Node InstantiatorTheoryDatatypes::getValueFor( Node n ){
   }
 }
 
-Node InstantiatorTheoryDatatypes::getRepresentative( Node n ){
-  return ((TheoryDatatypes*)d_th)->find( n );
-}
-
 InstantiatorTheoryDatatypes::Statistics::Statistics():
   d_instantiations("InstantiatorTheoryDatatypes::Instantiations_Total", 0)
 {
@@ -156,3 +153,18 @@ InstantiatorTheoryDatatypes::Statistics::~Statistics(){
   StatisticsRegistry::unregisterStat(&d_instantiations);
 }
 
+bool InstantiatorTheoryDatatypes::hasTerm( Node a ){
+  return ((TheoryDatatypes*)d_th)->hasTerm( a );
+}
+
+bool InstantiatorTheoryDatatypes::areEqual( Node a, Node b ){
+  return ((TheoryDatatypes*)d_th)->areEqual( a, b );
+}
+
+bool InstantiatorTheoryDatatypes::areDisequal( Node a, Node b ){
+  return ((TheoryDatatypes*)d_th)->areDisequal( a, b );
+}
+
+Node InstantiatorTheoryDatatypes::getRepresentative( Node a ){
+  return ((TheoryDatatypes*)d_th)->getRepresentative( a );
+}
index ab5703757283c16b6a047debe6b3e01efe974136..a080465af21483577c99b069c7d9dd9ac6f1b093 100644 (file)
@@ -42,11 +42,9 @@ private:
   /**  reset instantiation */
   void processResetInstantiationRound( Theory::Effort effort );
   /** process at effort */
-  int process( Node f, Theory::Effort effort, int e, int limitInst );
+  int process( Node f, Theory::Effort effort, int e );
   /** get value for */
   Node getValueFor( Node n );
-  /** get representative */
-  Node getRepresentative( Node n );
 
   class Statistics {
   public:
@@ -55,6 +53,12 @@ private:
     ~Statistics();
   };
   Statistics d_statistics;
+public:
+  /** general queries about equality */
+  bool hasTerm( Node a );
+  bool areEqual( Node a, Node b );
+  bool areDisequal( Node a, Node b );
+  Node getRepresentative( Node a );
 };/* class InstantiatiorTheoryDatatypes  */
 
 }
index 41e58349a8acdbdc77d9f04a0af8256766e53e66..5a6732bc4a198ceef648d4dbd8eefcbb5d762c83 100644 (file)
@@ -143,12 +143,11 @@ public:
   void explain(TNode n) {}
 
   /**
-   * Get a theory value.
+   * Get model
    *
-   * Overloads Node getValue(TNode n); from theory.h.
    * See theory/theory.h for more information about this method.
    */
-  Node getValue(TNode n) {
+  void collectModelInfo( TheoryModel* m ){
     Unimplemented("TheoryUFTim doesn't support model generation");
   }
 
index 32d6c958b7d33027ae741379874c087469c75d42..abcf5aa7fa0f567a2da35b4b8ce461743420690c 100644 (file)
 #include "theory/uf/theory_uf_instantiator.h"
 #include "theory/uf/theory_uf_candidate_generator.h"
 #include "theory/uf/equality_engine.h"
+#include "theory/quantifiers/model_engine.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/first_order_model.h"
+#include "theory/quantifiers/term_database.h"
 
 using namespace std;
 using namespace CVC4;
@@ -29,7 +33,8 @@ using namespace CVC4::theory;
 
 
 bool CandidateGenerator::isLegalCandidate( Node n ){
-  return !n.getAttribute(NoMatchAttribute()) && ( !Options::current()->cbqi || !n.hasAttribute(InstConstantAttribute()) );
+  return ( !n.getAttribute(NoMatchAttribute()) && ( !Options::current()->cbqi || !n.hasAttribute(InstConstantAttribute()) ) ) ||
+         ( Options::current()->finiteModelFind && n.hasAttribute(ModelBasisArgAttribute()) && n.getAttribute(ModelBasisArgAttribute())==1 );
 }
 
 void CandidateGeneratorQueue::addCandidate( Node n ) {
@@ -115,9 +120,9 @@ void InstMatch::debugPrint( const char* c ){
 }
 
 void InstMatch::makeComplete( Node f, QuantifiersEngine* qe ){
-  for( int i=0; i<(int)qe->d_inst_constants[f].size(); i++ ){
-    if( d_map.find( qe->d_inst_constants[f][i] )==d_map.end() ){
-      d_map[ qe->d_inst_constants[f][i] ] = qe->getFreeVariableForInstConstant( qe->d_inst_constants[f][i] );
+  for( int i=0; i<(int)qe->getTermDatabase()->d_inst_constants[f].size(); i++ ){
+    if( d_map.find( qe->getTermDatabase()->d_inst_constants[f][i] )==d_map.end() ){
+      d_map[ qe->getTermDatabase()->d_inst_constants[f][i] ] = qe->getTermDatabase()->getFreeVariableForInstConstant( qe->getTermDatabase()->d_inst_constants[f][i] );
     }
   }
 }
@@ -127,7 +132,7 @@ void InstMatch::makeInternal( QuantifiersEngine* qe ){
     if( Options::current()->cbqi && it->second.hasAttribute(InstConstantAttribute()) ){
       d_map[ it->first ] = qe->getEqualityQuery()->getInternalRepresentative( it->second );
       if( Options::current()->cbqi && it->second.hasAttribute(InstConstantAttribute()) ){
-        d_map[ it->first ] = qe->getFreeVariableForInstConstant( it->first );
+        d_map[ it->first ] = qe->getTermDatabase()->getFreeVariableForInstConstant( it->first );
       }
     }
   }
@@ -137,7 +142,7 @@ void InstMatch::makeRepresentative( QuantifiersEngine* qe ){
   for( std::map< Node, Node >::iterator it = d_map.begin(); it != d_map.end(); ++it ){
     d_map[ it->first ] = qe->getEqualityQuery()->getInternalRepresentative( it->second );
     if( Options::current()->cbqi && it->second.hasAttribute(InstConstantAttribute()) ){
-      d_map[ it->first ] = qe->getFreeVariableForInstConstant( it->first );
+      d_map[ it->first ] = qe->getTermDatabase()->getFreeVariableForInstConstant( it->first );
     }
   }
 }
@@ -154,7 +159,7 @@ void InstMatch::computeTermVec( QuantifiersEngine* qe, const std::vector< Node >
     if( it!=d_map.end() && !it->second.isNull() ){
       match.push_back( it->second );
     }else{
-      match.push_back( qe->getFreeVariableForInstConstant( vars[i] ) );
+      match.push_back( qe->getTermDatabase()->getFreeVariableForInstConstant( vars[i] ) );
     }
   }
 }
@@ -169,7 +174,7 @@ void InstMatch::computeTermVec( const std::vector< Node >& vars, std::vector< No
 void InstMatchTrie::addInstMatch2( QuantifiersEngine* qe, Node f, InstMatch& m, int index, ImtIndexOrder* imtio ){
   if( long(index)<long(f[0].getNumChildren()) && ( !imtio || long(index)<long(imtio->d_order.size()) ) ){
     int i_index = imtio ? imtio->d_order[index] : index;
-    Node n = m.d_map[ qe->getInstantiationConstant( f, i_index ) ];
+    Node n = m.d_map[ qe->getTermDatabase()->getInstantiationConstant( f, i_index ) ];
     d_data[n].addInstMatch2( qe, f, m, index+1, imtio );
   }
 }
@@ -180,7 +185,7 @@ bool InstMatchTrie::existsInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m
     return true;
   }else{
     int i_index = imtio ? imtio->d_order[index] : index;
-    Node n = m.d_map[ qe->getInstantiationConstant( f, i_index ) ];
+    Node n = m.d_map[ qe->getTermDatabase()->getInstantiationConstant( f, i_index ) ];
     std::map< Node, InstMatchTrie >::iterator it = d_data.find( n );
     if( it!=d_data.end() ){
       if( it->second.existsInstMatch( qe, f, m, modEq, index+1, imtio ) ){
@@ -190,7 +195,7 @@ bool InstMatchTrie::existsInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m
     if( modEq ){
       //check modulo equality if any other instantiation match exists
       if( ((uf::TheoryUF*)qe->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine()->hasTerm( n ) ){
-        eq::EqClassIterator eqc( qe->getEqualityQuery()->getRepresentative( n ),
+        eq::EqClassIterator eqc( ((uf::TheoryUF*)qe->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine()->getRepresentative( n ),
                                 ((uf::TheoryUF*)qe->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine() );
         while( !eqc.isFinished() ){
           Node en = (*eqc);
@@ -344,7 +349,9 @@ bool InstMatchGenerator::getMatch( Node t, InstMatch& m, QuantifiersEngine* qe )
   Debug("matching") << "Matching " << t << " against pattern " << d_match_pattern << " ("
                     << m.d_map.size() << ")" << ", " << d_children.size() << std::endl;
   Assert( !d_match_pattern.isNull() );
-  if( d_matchPolicy==MATCH_GEN_INTERNAL_ARITHMETIC ){
+  if( qe->d_optMatchIgnoreModelBasis && t.getAttribute(ModelBasisAttribute()) ){
+    return true;
+  }else if( d_matchPolicy==MATCH_GEN_INTERNAL_ARITHMETIC ){
     return getMatchArithmetic( t, m, qe );
   }else if( d_matchPolicy==MATCH_GEN_INTERNAL_ERROR ){
     return false;
@@ -421,7 +428,6 @@ bool InstMatchGenerator::getNextMatch2( InstMatch& m, QuantifiersEngine* qe, boo
     t = d_cg->getNextCandidate();
     //if t not null, try to fit it into match m
     if( !t.isNull() && t.getType()==d_match_pattern.getType() ){
-      //Assert( t.getType()==d_match_pattern.getType() );
       success = getMatch( t, m, qe );
     }
   }while( !success && !t.isNull() );
@@ -592,16 +598,16 @@ bool InstMatchGenerator::nonunifiable( TNode t0, const std::vector<Node> & vars)
   return false;
 }
 
-int InstMatchGenerator::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit, bool addSplits ){
+int InstMatchGenerator::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
   //now, try to add instantiation for each match produced
   int addedLemmas = 0;
   InstMatch m;
   while( getNextMatch( m, qe ) ){
     //m.makeInternal( d_quantEngine->getEqualityQuery() );
     m.add( baseMatch );
-    if( qe->addInstantiation( f, m, addSplits ) ){
+    if( qe->addInstantiation( f, m ) ){
       addedLemmas++;
-      if( instLimit>0 && addedLemmas==instLimit ){
+      if( qe->d_optInstLimitActive && qe->d_optInstLimit<=0 ){
         return addedLemmas;
       }
     }
@@ -706,29 +712,62 @@ void InstMatchGeneratorMulti::reset( Node eqc, QuantifiersEngine* qe ){
   }
 }
 
-void InstMatchGeneratorMulti::collectInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
-                                                     std::vector< IndexedTrie >& unique_var_tries,
-                                                     int trieIndex, int childIndex, int endChildIndex, bool modEq ){
+int InstMatchGeneratorMulti::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
+  int addedLemmas = 0;
+  Debug("smart-multi-trigger") << "Process smart multi trigger" << std::endl;
+  for( int i=0; i<(int)d_children.size(); i++ ){
+    Debug("smart-multi-trigger") << "Calculate matches " << i << std::endl;
+    std::vector< InstMatch > newMatches;
+    InstMatch m;
+    while( d_children[i]->getNextMatch( m, qe ) ){
+      m.makeRepresentative( qe );
+      newMatches.push_back( InstMatch( &m ) );
+      m.clear();
+    }
+    for( int j=0; j<(int)newMatches.size(); j++ ){
+      processNewMatch( qe, newMatches[j], i, addedLemmas );
+    }
+  }
+  return addedLemmas;
+}
+
+void InstMatchGeneratorMulti::processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas ){
+  //see if these produce new matches
+  d_children_trie[fromChildIndex].addInstMatch( qe, d_f, m, true );
+  //possibly only do the following if we know that new matches will be produced?
+  //the issue is that instantiations are filtered in quantifiers engine, and so there is no guarentee that
+  // we can safely skip the following lines, even when we have already produced this match.
+  Debug("smart-multi-trigger") << "Child " << fromChildIndex << " produced match " << m << std::endl;
+  //process new instantiations
+  int childIndex = (fromChildIndex+1)%(int)d_children.size();
+  std::vector< IndexedTrie > unique_var_tries;
+  processNewInstantiations( qe, m, addedLemmas, d_children_trie[childIndex].getTrie(),
+                            unique_var_tries, 0, childIndex, fromChildIndex, true );
+}
+
+void InstMatchGeneratorMulti::processNewInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
+                                                        std::vector< IndexedTrie >& unique_var_tries,
+                                                        int trieIndex, int childIndex, int endChildIndex, bool modEq ){
   if( childIndex==endChildIndex ){
     //now, process unique variables
-    collectInstantiations2( qe, m, addedLemmas, unique_var_tries, 0 );
+    processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, 0 );
   }else if( trieIndex<(int)d_children_trie[childIndex].getOrdering()->d_order.size() ){
     int curr_index = d_children_trie[childIndex].getOrdering()->d_order[trieIndex];
-    Node curr_ic = qe->getInstantiationConstant( d_f, curr_index );
+    Node curr_ic = qe->getTermDatabase()->getInstantiationConstant( d_f, curr_index );
     if( m.d_map.find( curr_ic )==m.d_map.end() ){
       //if( d_var_to_node[ curr_index ].size()==1 ){    //FIXME
       //  //unique variable(s), defer calculation
       //  unique_var_tries.push_back( IndexedTrie( std::pair< int, int >( childIndex, trieIndex ), tr ) );
       //  int newChildIndex = (childIndex+1)%(int)d_children.size();
-      //  collectInstantiations( qe, m, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
-      //                         0, newChildIndex, endChildIndex, modEq );
+      //  processNewInstantiations( qe, m, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
+      //                            0, newChildIndex, endChildIndex, modEq );
       //}else{
         //shared and non-set variable, add to InstMatch
         for( std::map< Node, InstMatchTrie >::iterator it = tr->d_data.begin(); it != tr->d_data.end(); ++it ){
           InstMatch mn( &m );
           mn.d_map[ curr_ic ] = it->first;
-          collectInstantiations( qe, mn, addedLemmas, &(it->second), unique_var_tries,
-                                  trieIndex+1, childIndex, endChildIndex, modEq );
+          processNewInstantiations( qe, mn, addedLemmas, &(it->second), unique_var_tries,
+                                    trieIndex+1, childIndex, endChildIndex, modEq );
         }
       //}
     }else{
@@ -736,8 +775,8 @@ void InstMatchGeneratorMulti::collectInstantiations( QuantifiersEngine* qe, Inst
       Node n = m.d_map[ curr_ic ];
       std::map< Node, InstMatchTrie >::iterator it = tr->d_data.find( n );
       if( it!=tr->d_data.end() ){
-        collectInstantiations( qe, m, addedLemmas, &(it->second), unique_var_tries,
-                               trieIndex+1, childIndex, endChildIndex, modEq );
+        processNewInstantiations( qe, m, addedLemmas, &(it->second), unique_var_tries,
+                                  trieIndex+1, childIndex, endChildIndex, modEq );
       }
       if( modEq ){
         //check modulo equality for other possible instantiations
@@ -749,8 +788,8 @@ void InstMatchGeneratorMulti::collectInstantiations( QuantifiersEngine* qe, Inst
             if( en!=n ){
               std::map< Node, InstMatchTrie >::iterator itc = tr->d_data.find( en );
               if( itc!=tr->d_data.end() ){
-                collectInstantiations( qe, m, addedLemmas, &(itc->second), unique_var_tries,
-                                       trieIndex+1, childIndex, endChildIndex, modEq );
+                processNewInstantiations( qe, m, addedLemmas, &(itc->second), unique_var_tries,
+                                          trieIndex+1, childIndex, endChildIndex, modEq );
               }
             }
             ++eqc;
@@ -760,14 +799,14 @@ void InstMatchGeneratorMulti::collectInstantiations( QuantifiersEngine* qe, Inst
     }
   }else{
     int newChildIndex = (childIndex+1)%(int)d_children.size();
-    collectInstantiations( qe, m, addedLemmas, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
-                           0, newChildIndex, endChildIndex, modEq );
+    processNewInstantiations( qe, m, addedLemmas, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
+                              0, newChildIndex, endChildIndex, modEq );
   }
 }
 
-void InstMatchGeneratorMulti::collectInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
-                                                      std::vector< IndexedTrie >& unique_var_tries,
-                                                      int uvtIndex, InstMatchTrie* tr, int trieIndex ){
+void InstMatchGeneratorMulti::processNewInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
+                                                         std::vector< IndexedTrie >& unique_var_tries,
+                                                         int uvtIndex, InstMatchTrie* tr, int trieIndex ){
   if( uvtIndex<(int)unique_var_tries.size() ){
     int childIndex = unique_var_tries[uvtIndex].first.first;
     if( !tr ){
@@ -776,58 +815,25 @@ void InstMatchGeneratorMulti::collectInstantiations2( QuantifiersEngine* qe, Ins
     }
     if( trieIndex<(int)d_children_trie[childIndex].getOrdering()->d_order.size() ){
       int curr_index = d_children_trie[childIndex].getOrdering()->d_order[trieIndex];
-      Node curr_ic = qe->getInstantiationConstant( d_f, curr_index );
+      Node curr_ic = qe->getTermDatabase()->getInstantiationConstant( d_f, curr_index );
       //unique non-set variable, add to InstMatch
       for( std::map< Node, InstMatchTrie >::iterator it = tr->d_data.begin(); it != tr->d_data.end(); ++it ){
         InstMatch mn( &m );
         mn.d_map[ curr_ic ] = it->first;
-        collectInstantiations2( qe, mn, addedLemmas, unique_var_tries, uvtIndex, &(it->second), trieIndex+1 );
+        processNewInstantiations2( qe, mn, addedLemmas, unique_var_tries, uvtIndex, &(it->second), trieIndex+1 );
       }
     }else{
-      collectInstantiations2( qe, m, addedLemmas, unique_var_tries, uvtIndex+1 );
+      processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, uvtIndex+1 );
     }
   }else{
     //m is an instantiation
-    if( qe->addInstantiation( d_f, m, true ) ){
+    if( qe->addInstantiation( d_f, m ) ){
       addedLemmas++;
       Debug("smart-multi-trigger") << "-> Produced instantiation " << m << std::endl;
     }
   }
 }
 
-int InstMatchGeneratorMulti::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit, bool addSplits ){
-  int addedLemmas = 0;
-  Debug("smart-multi-trigger") << "Process smart multi trigger" << std::endl;
-  for( int i=0; i<(int)d_children.size(); i++ ){
-    Debug("smart-multi-trigger") << "Calculate matches " << i << std::endl;
-    std::vector< InstMatch > newMatches;
-    InstMatch m;
-    while( d_children[i]->getNextMatch( m, qe ) ){
-      m.makeRepresentative( qe );
-      newMatches.push_back( InstMatch( &m ) );
-      m.clear();
-    }
-    for( int j=0; j<(int)newMatches.size(); j++ ){
-      processNewMatch( qe, newMatches[j], i, addedLemmas );
-    }
-  }
-  return addedLemmas;
-}
-
-void InstMatchGeneratorMulti::processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas ){
-  //see if these produce new matches
-  d_children_trie[fromChildIndex].addInstMatch( qe, d_f, m, true );
-  //possibly only do the following if we know that new matches will be produced?
-  //the issue is that instantiations are filtered in quantifiers engine, and so there is no guarentee that
-  // we can safely skip the following lines, even when we have already produced this match.
-  Debug("smart-multi-trigger") << "Child " << fromChildIndex << " produced match " << m << std::endl;
-  //collect new instantiations
-  int childIndex = (fromChildIndex+1)%(int)d_children.size();
-  std::vector< IndexedTrie > unique_var_tries;
-  collectInstantiations( qe, m, addedLemmas,
-                         d_children_trie[childIndex].getTrie(), unique_var_tries, 0, childIndex, fromChildIndex, true );
-}
-
 int InstMatchGeneratorMulti::addTerm( Node f, Node t, QuantifiersEngine* qe ){
   Assert( Options::current()->eagerInstQuant );
   int addedLemmas = 0;
@@ -843,47 +849,44 @@ int InstMatchGeneratorMulti::addTerm( Node f, Node t, QuantifiersEngine* qe ){
   return addedLemmas;
 }
 
-int InstMatchGeneratorSimple::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit, bool addSplits ){
+int InstMatchGeneratorSimple::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
   InstMatch m;
   m.add( baseMatch );
   int addedLemmas = 0;
   if( d_match_pattern.getType()==NodeManager::currentNM()->booleanType() ){
     for( int i=0; i<2; i++ ){
-      addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_pred_map_trie[i][ d_match_pattern.getOperator() ]),
-                         instLimit, addSplits );
+      addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_pred_map_trie[i][ d_match_pattern.getOperator() ]) );
     }
   }else{
-    addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_func_map_trie[ d_match_pattern.getOperator() ]),
-                       instLimit, addSplits );
+    addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_func_map_trie[ d_match_pattern.getOperator() ]) );
   }
   return addedLemmas;
 }
 
-void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex,
-                                                  TermArgTrie* tat, int instLimit, bool addSplits ){
+void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex, quantifiers::TermArgTrie* tat ){
   if( argIndex==(int)d_match_pattern.getNumChildren() ){
     //m is an instantiation
-    if( qe->addInstantiation( d_f, m, addSplits ) ){
+    if( qe->addInstantiation( d_f, m ) ){
       addedLemmas++;
       Debug("simple-multi-trigger") << "-> Produced instantiation " << m << std::endl;
     }
   }else{
     if( d_match_pattern[argIndex].getKind()==INST_CONSTANT ){
       Node ic = d_match_pattern[argIndex];
-      for( std::map< Node, TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
+      for( std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
         Node t = it->first;
         if( m.d_map[ ic ].isNull() || m.d_map[ ic ]==t ){
           Node prev = m.d_map[ ic ];
           m.d_map[ ic ] = t;
-          addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second), instLimit, addSplits );
+          addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
           m.d_map[ ic ] = prev;
         }
       }
     }else{
       Node r = qe->getEqualityQuery()->getRepresentative( d_match_pattern[argIndex] );
-      std::map< Node, TermArgTrie >::iterator it = tat->d_data.find( r );
+      std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.find( r );
       if( it!=tat->d_data.end() ){
-        addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second), instLimit, addSplits );
+        addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
       }
     }
   }
index dcb9190a19c19614c4e79e06348c53a78617edb8..7cc5b2249aabc297e47a6601b66f13f2a5b24b7e 100644 (file)
@@ -281,7 +281,7 @@ public:
       given Node can't match the pattern */
   virtual bool nonunifiable( TNode t, const std::vector<Node> & vars) = 0;
   /** add instantiations directly */
-  virtual int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit = 0, bool addSplits = false ) = 0;
+  virtual int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ) = 0;
   /** add ground term t, called when t is added to term db */
   virtual int addTerm( Node f, Node t, QuantifiersEngine* qe ) = 0;
 };/* class IMGenerator */
@@ -350,26 +350,26 @@ public:
       given Node can't match the pattern */
   bool nonunifiable( TNode t, const std::vector<Node> & vars);
   /** add instantiations */
-  int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit = 0, bool addSplits = false );
+  int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
   /** add ground term t */
   int addTerm( Node f, Node t, QuantifiersEngine* qe );
 };/* class InstMatchGenerator */
 
 /** smart multi-trigger implementation */
 class InstMatchGeneratorMulti : public IMGenerator {
-private:
-  void processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas );
 private:
   /** indexed trie */
   typedef std::pair< std::pair< int, int >, InstMatchTrie* > IndexedTrie;
-  /** collect instantiations */
-  void collectInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
-                              std::vector< IndexedTrie >& unique_var_tries,
-                              int trieIndex, int childIndex, int endChildIndex, bool modEq );
-  /** collect instantiations 2 */
-  void collectInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
-                               std::vector< IndexedTrie >& unique_var_tries,
-                               int uvtIndex, InstMatchTrie* tr = NULL, int trieIndex = 0 );
+  /** process new match */
+  void processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas );
+  /** process new instantiations */
+  void processNewInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
+                                 std::vector< IndexedTrie >& unique_var_tries,
+                                 int trieIndex, int childIndex, int endChildIndex, bool modEq );
+  /** process new instantiations 2 */
+  void processNewInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
+                                  std::vector< IndexedTrie >& unique_var_tries,
+                                  int uvtIndex, InstMatchTrie* tr = NULL, int trieIndex = 0 );
 private:
   /** var contains (variable indices) for each pattern node */
   std::map< Node, std::vector< int > > d_var_contains;
@@ -400,12 +400,14 @@ public:
       given Node can't match the pattern */
   bool nonunifiable( TNode t, const std::vector<Node> & vars) { return true; }
   /** add instantiations */
-  int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit = 0, bool addSplits = false );
+  int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
   /** add ground term t */
   int addTerm( Node f, Node t, QuantifiersEngine* qe );
 };/* class InstMatchGeneratorMulti */
 
-class TermArgTrie;
+namespace quantifiers{
+  class TermArgTrie;
+}
 
 /** smart (single)-trigger implementation */
 class InstMatchGeneratorSimple : public IMGenerator {
@@ -415,8 +417,7 @@ private:
   /** match term */
   Node d_match_pattern;
   /** add instantiations */
-  void addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas,
-                          int argIndex, TermArgTrie* tat, int instLimit, bool addSplits );
+  void addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex, quantifiers::TermArgTrie* tat );
 public:
   /** constructors */
   InstMatchGeneratorSimple( Node f, Node pat ) : d_f( f ), d_match_pattern( pat ){}
@@ -432,7 +433,7 @@ public:
       given Node can't match the pattern */
   bool nonunifiable( TNode t, const std::vector<Node> & vars) { return true; }
   /** add instantiations */
-  int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit = 0, bool addSplits = false );
+  int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
   /** add ground term t, possibly add instantiations */
   int addTerm( Node f, Node t, QuantifiersEngine* qe );
 };/* class InstMatchGeneratorSimple */
index 4d6ea2fdbe70b981a8daa8eee27948b2482cd79b..a1766ce3c69fb2e31a98d14342873f5531624f41 100644 (file)
@@ -33,7 +33,8 @@ void InstantiatorDefault::assertNode( Node assertion ){
 void InstantiatorDefault::processResetInstantiationRound( Theory::Effort effort ){
 }
 
-int InstantiatorDefault::process( Node f, Theory::Effort effort, int e, int limitInst ){
+int InstantiatorDefault::process( Node f, Theory::Effort effort, int e ){
+  /*
   if( e < 4 ){
     return InstStrategy::STATUS_UNFINISHED;
   }else if( e == 4 ){
@@ -50,5 +51,6 @@ int InstantiatorDefault::process( Node f, Theory::Effort effort, int e, int limi
     }
     d_quantEngine->addInstantiation( f, m );
   }
+  */
   return InstStrategy::STATUS_UNKNOWN;
 }
index 8e0e4723197e506c9edf43ca96e68265033b79b0..967a0c1ca44c8d5f70952083048be99c5365a174 100644 (file)
@@ -32,7 +32,7 @@ protected:
   /** reset instantiation round */
   void processResetInstantiationRound(Theory::Effort effort);
   /** process quantifier */
-  int process(Node f, Theory::Effort effort, int e, int limitInst = 0);
+  int process( Node f, Theory::Effort effort, int e );
 public:
   InstantiatorDefault(context::Context* c, QuantifiersEngine* ie, Theory* th);
   ~InstantiatorDefault() { }
diff --git a/src/theory/model.cpp b/src/theory/model.cpp
new file mode 100644 (file)
index 0000000..03bba18
--- /dev/null
@@ -0,0 +1,436 @@
+/*********************                                                        */\r
+/*! \file model.cpp\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Implementation of model class\r
+ **/\r
+\r
+#include "theory/model.h"\r
+#include "theory/quantifiers_engine.h"\r
+#include "theory/theory_engine.h"\r
+\r
+using namespace std;\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::context;\r
+using namespace CVC4::theory;\r
+\r
+void RepSet::clear(){\r
+  d_type_reps.clear();\r
+  d_tmap.clear();\r
+}\r
+\r
+void RepSet::add( Node n ){\r
+  TypeNode t = n.getType();\r
+  d_tmap[ n ] = (int)d_type_reps[t].size();\r
+  d_type_reps[t].push_back( n );\r
+}\r
+\r
+void RepSet::set( TypeNode t, std::vector< Node >& reps ){\r
+  for( size_t i=0; i<reps.size(); i++ ){\r
+    d_tmap[ reps[i] ] = i;\r
+  }\r
+  d_type_reps[t].insert( d_type_reps[t].begin(), reps.begin(), reps.end() );\r
+}\r
+\r
+void RepSet::toStream(std::ostream& out){\r
+#if 0\r
+  for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){\r
+    out << it->first << " : " << std::endl;\r
+    for( int i=0; i<(int)it->second.size(); i++ ){\r
+      out << "   " << i << ": " << it->second[i] << std::endl;\r
+    }\r
+  }\r
+#else\r
+  for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){\r
+    if( !it->first.isFunction() && !it->first.isPredicate() ){\r
+      out << "(" << it->first << " " << it->second.size();\r
+      out << " (";\r
+      for( int i=0; i<(int)it->second.size(); i++ ){\r
+        if( i>0 ){ out << " "; }\r
+        out << it->second[i];\r
+      }\r
+      out << ")";\r
+      out << ")" << std::endl;\r
+    }\r
+  }\r
+#endif\r
+}\r
+\r
+TheoryModel::TheoryModel( context::Context* c, std::string name ) :\r
+d_equalityEngine( c, name ){\r
+  d_true = NodeManager::currentNM()->mkConst( true );\r
+  d_false = NodeManager::currentNM()->mkConst( false );\r
+}\r
+\r
+void TheoryModel::addDefineFunction( Node n ){\r
+  d_define_funcs.push_back( n );\r
+  d_defines.push_back( 0 );\r
+}\r
+\r
+void TheoryModel::addDefineType( TypeNode tn ){\r
+  d_define_types.push_back( tn );\r
+  d_defines.push_back( 1 );\r
+}\r
+\r
+void TheoryModel::toStreamFunction( Node n, std::ostream& out ){\r
+  out << "(" << n;\r
+  //out << " : " << n.getType();\r
+  out << " ";\r
+  Node value = getValue( n );\r
+  if( n.getType().isSort() ){\r
+    int index = d_ra.getIndexFor( value );\r
+    if( index!=-1 ){\r
+      out << value.getType() << "_" << index;\r
+    }else{\r
+      out << value;\r
+    }\r
+  }else{\r
+    out << value;\r
+  }\r
+  out << ")" << std::endl;\r
+}\r
+\r
+void TheoryModel::toStreamType( TypeNode tn, std::ostream& out ){\r
+  out << "(" << tn;\r
+  if( tn.isSort() ){\r
+    if( d_ra.d_type_reps.find( tn )!=d_ra.d_type_reps.end() ){\r
+      out << " " << d_ra.d_type_reps[tn].size();\r
+      //out << " (";\r
+      //for( size_t i=0; i<d_ra.d_type_reps[tn].size(); i++ ){\r
+      //  if( i>0 ){ out << " "; }\r
+      //  out << d_ra.d_type_reps[tn][i];\r
+      //}\r
+      //out << ")";\r
+    }\r
+  }\r
+  out << ")" << std::endl;\r
+}\r
+\r
+void TheoryModel::toStream( std::ostream& out ){\r
+  int funcIndex = 0;\r
+  int typeIndex = 0;\r
+  for( size_t i=0; i<d_defines.size(); i++ ){\r
+    if( d_defines[i]==0 ){\r
+      toStreamFunction( d_define_funcs[funcIndex], out );\r
+      funcIndex++;\r
+    }else if( d_defines[i]==1 ){\r
+      toStreamType( d_define_types[typeIndex], out );\r
+      typeIndex++;\r
+    }\r
+  }\r
+}\r
+\r
+Node TheoryModel::getValue( TNode n ){\r
+  Debug("model") << "TheoryModel::getValue " << n << std::endl;\r
+\r
+  kind::MetaKind metakind = n.getMetaKind();\r
+\r
+  //// special case: prop engine handles boolean vars\r
+  //if(metakind == kind::metakind::VARIABLE && n.getType().isBoolean()) {\r
+  //  Debug("model") << "-> Propositional variable." << std::endl;\r
+  //  return d_te->getPropEngine()->getValue( n );\r
+  //}\r
+\r
+  // special case: value of a constant == itself\r
+  if(metakind == kind::metakind::CONSTANT) {\r
+    Debug("model") << "-> Constant." << std::endl;\r
+    return n;\r
+  }\r
+\r
+  // see if the value is explicitly set in the model\r
+  if( d_equalityEngine.hasTerm( n ) ){\r
+    Debug("model") << "-> Defined term." << std::endl;\r
+    return getRepresentative( n );\r
+  }else{\r
+    Node nn;\r
+    if( n.getNumChildren()>0 ){\r
+      std::vector< Node > children;\r
+      if( metakind == kind::metakind::PARAMETERIZED ){\r
+        Debug("model-debug") << "get operator: " << n.getOperator() << std::endl;\r
+        children.push_back( n.getOperator() );\r
+      }\r
+      //evaluate the children\r
+      for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+        Node val = getValue( n[i] );\r
+        Debug("model-debug") << i << " : " << n[i] << " -> " << val << std::endl;\r
+        Assert( !val.isNull() );\r
+        children.push_back( val );\r
+      }\r
+      Debug("model-debug") << "Done eval children" << std::endl;\r
+      nn = NodeManager::currentNM()->mkNode( n.getKind(), children );\r
+    }else{\r
+      nn = n;\r
+    }\r
+    //interpretation is the rewritten form\r
+    nn = Rewriter::rewrite( nn );\r
+\r
+    // special case: value of a constant == itself\r
+    if(metakind == kind::metakind::CONSTANT) {\r
+      Debug("model") << "-> Theory-interpreted term." << std::endl;\r
+      return nn;\r
+    }else if( d_equalityEngine.hasTerm( nn ) ){\r
+      Debug("model") << "-> Theory-interpreted (defined) term." << std::endl;\r
+      return getRepresentative( nn );\r
+    }else{\r
+      Debug("model") << "-> Model-interpreted term." << std::endl;\r
+      //otherwise, get the interpreted value in the model\r
+      return getInterpretedValue( nn );\r
+    }\r
+  }\r
+\r
+  ////case for equality\r
+  //if( n.getKind()==EQUAL ){\r
+  //  Debug("model") << "-> Equality." << std::endl;\r
+  //  Node n1 = getValue( n[0] );\r
+  //  Node n2 = getValue( n[1] );\r
+  //  return NodeManager::currentNM()->mkConst( n1==n2 );\r
+  //}\r
+}\r
+\r
+Node TheoryModel::getDomainValue( TypeNode tn, std::vector< Node >& exclude ){\r
+  if( d_ra.d_type_reps.find( tn )!=d_ra.d_type_reps.end() ){\r
+    //try to find a pre-existing arbitrary element\r
+    for( size_t i=0; i<d_ra.d_type_reps[tn].size(); i++ ){\r
+      if( std::find( exclude.begin(), exclude.end(), d_ra.d_type_reps[tn][i] )==exclude.end() ){\r
+        return d_ra.d_type_reps[tn][i];\r
+      }\r
+    }\r
+  }\r
+  return Node::null();\r
+}\r
+\r
+//FIXME: use the theory enumerator to generate constants here\r
+Node TheoryModel::getNewDomainValue( TypeNode tn, bool mkConst ){\r
+  if( tn==NodeManager::currentNM()->booleanType() ){\r
+    if( d_ra.d_type_reps[tn].empty() ){\r
+      return d_false;\r
+    }else if( d_ra.d_type_reps[tn].size()==1 ){\r
+      return NodeManager::currentNM()->mkConst( areEqual( d_ra.d_type_reps[tn][0], d_false ) );\r
+    }else{\r
+      return Node::null();\r
+    }\r
+  }else if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){\r
+    int val = 0;\r
+    do{\r
+      Node r = NodeManager::currentNM()->mkConst( Rational(val) );\r
+      if( std::find( d_ra.d_type_reps[tn].begin(), d_ra.d_type_reps[tn].end(), r )==d_ra.d_type_reps[tn].end() &&\r
+          !d_equalityEngine.hasTerm( r ) ){\r
+        return r;\r
+      }\r
+      val++;\r
+    }while( true );\r
+  }else{\r
+    //otherwise must make a variable  FIXME: how to make constants for other sorts?\r
+    //return NodeManager::currentNM()->mkVar( tn );\r
+    return Node::null();\r
+  }\r
+}\r
+\r
+/** assert equality */\r
+void TheoryModel::assertEquality( Node a, Node b, bool polarity ){\r
+  d_equalityEngine.assertEquality( a.eqNode(b), polarity, Node::null() );\r
+}\r
+\r
+/** assert predicate */\r
+void TheoryModel::assertPredicate( Node a, bool polarity ){\r
+  if( a.getKind()==EQUAL ){\r
+    d_equalityEngine.assertEquality( a, polarity, Node::null() );\r
+  }else{\r
+    d_equalityEngine.assertPredicate( a, polarity, Node::null() );\r
+  }\r
+}\r
+\r
+/** assert equality engine */\r
+void TheoryModel::assertEqualityEngine( eq::EqualityEngine* ee ){\r
+  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );\r
+  while( !eqcs_i.isFinished() ){\r
+    Node eqc = (*eqcs_i);\r
+    bool predicate = false;\r
+    bool predPolarity = false;\r
+    if( eqc.getType()==NodeManager::currentNM()->booleanType() ){\r
+      predicate = true;\r
+      predPolarity = ee->areEqual( eqc, d_true );\r
+      //FIXME: do we guarentee that all boolean equivalence classes contain either d_true or d_false?\r
+    }\r
+    eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, ee );\r
+    while( !eqc_i.isFinished() ){\r
+      if( predicate ){\r
+        assertPredicate( *eqc_i, predPolarity );\r
+      }else{\r
+        assertEquality( *eqc_i, eqc, true );\r
+      }\r
+      ++eqc_i;\r
+    }\r
+    ++eqcs_i;\r
+  }\r
+}\r
+\r
+bool TheoryModel::hasTerm( Node a ){\r
+  return d_equalityEngine.hasTerm( a );\r
+}\r
+\r
+Node TheoryModel::getRepresentative( Node a ){\r
+  if( d_equalityEngine.hasTerm( a ) ){\r
+    return d_reps[ d_equalityEngine.getRepresentative( a ) ];\r
+  }else{\r
+    return a;\r
+  }\r
+}\r
+\r
+bool TheoryModel::areEqual( Node a, Node b ){\r
+  if( a==b ){\r
+    return true;\r
+  }else if( d_equalityEngine.hasTerm( a ) && d_equalityEngine.hasTerm( b ) ){\r
+    return d_equalityEngine.areEqual( a, b );\r
+  }else{\r
+    return false;\r
+  }\r
+}\r
+\r
+bool TheoryModel::areDisequal( Node a, Node b ){\r
+  if( d_equalityEngine.hasTerm( a ) && d_equalityEngine.hasTerm( b ) ){\r
+    return d_equalityEngine.areDisequal( a, b, false );\r
+  }else{\r
+    return false;\r
+  }\r
+}\r
+\r
+//for debugging\r
+void TheoryModel::printRepresentativeDebug( const char* c, Node r ){\r
+  if( r.isNull() ){\r
+    Debug( c ) << "null";\r
+  }else if( r.getType()==NodeManager::currentNM()->booleanType() ){\r
+    if( areEqual( r, d_true ) ){\r
+      Debug( c ) << "true";\r
+    }else{\r
+      Debug( c ) << "false";\r
+    }\r
+  }else{\r
+    Debug( c ) << getRepresentative( r );\r
+  }\r
+}\r
+\r
+void TheoryModel::printRepresentative( std::ostream& out, Node r ){\r
+  Assert( !r.isNull() );\r
+  if( r.isNull() ){\r
+    out << "null";\r
+  }else if( r.getType()==NodeManager::currentNM()->booleanType() ){\r
+    if( areEqual( r, d_true ) ){\r
+      out  << "true";\r
+    }else{\r
+      out  << "false";\r
+    }\r
+  }else{\r
+    out << getRepresentative( r );\r
+  }\r
+}\r
+\r
+DefaultModel::DefaultModel( context::Context* c, std::string name ) : TheoryModel( c, name ){\r
+\r
+}\r
+\r
+Node DefaultModel::getInterpretedValue( TNode n ){\r
+  Assert( !d_equalityEngine.hasTerm( n ) );\r
+  TypeNode type = n.getType();\r
+  if( type.isFunction() || type.isPredicate() ){\r
+    //DO_THIS?\r
+    return n;\r
+  }else{\r
+    //first, try to choose an existing term as value\r
+    std::vector< Node > v_emp;\r
+    Node n2 = getDomainValue( type, v_emp );\r
+    if( !n2.isNull() ){\r
+      return n2;\r
+    }else{\r
+      //otherwise, choose new valuse\r
+      n2 = getNewDomainValue( type, true );\r
+      if( !n2.isNull() ){\r
+        return n2;\r
+      }else{\r
+        return n;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+TheoryEngineModelBuilder::TheoryEngineModelBuilder( TheoryEngine* te ) : d_te( te ){\r
+\r
+}\r
+\r
+void TheoryEngineModelBuilder::buildModel( Model* m ){\r
+  TheoryModel* tm = (TheoryModel*)m;\r
+  //reset representative information\r
+  tm->d_reps.clear();\r
+  tm->d_ra.clear();\r
+  Debug( "model-builder" ) << "TheoryEngineModelBuilder: Collect model info..." << std::endl;\r
+  //collect model info from the theory engine\r
+  d_te->collectModelInfo( tm );\r
+  Debug( "model-builder" ) << "TheoryEngineModelBuilder: Build representatives..." << std::endl;\r
+  //populate term database, store representatives\r
+  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &tm->d_equalityEngine );\r
+  while( !eqcs_i.isFinished() ){\r
+    Node eqc = (*eqcs_i);\r
+    //add terms to model\r
+    eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &tm->d_equalityEngine );\r
+    while( !eqc_i.isFinished() ){\r
+      tm->addTerm( *eqc_i );\r
+      ++eqc_i;\r
+    }\r
+    //choose representative for this equivalence class\r
+    Node rep = chooseRepresentative( tm, eqc );\r
+    //store representative in representative set\r
+    if( !rep.isNull() ){\r
+      tm->d_reps[ eqc ] = rep;\r
+      tm->d_ra.add( rep );\r
+    }\r
+    ++eqcs_i;\r
+  }\r
+  //do model-builder specific initialization\r
+  // this should include choosing representatives for equivalence classes that have not yet been\r
+  // assigned representatives\r
+  processBuildModel( tm );\r
+}\r
+\r
+Node TheoryEngineModelBuilder::chooseRepresentative( TheoryModel* tm, Node eqc ){\r
+  eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &tm->d_equalityEngine );\r
+  while( !eqc_i.isFinished() ){\r
+    //if constant, use this as representative\r
+    if( (*eqc_i).getMetaKind()==kind::metakind::CONSTANT ){\r
+      return *eqc_i;\r
+    }\r
+    ++eqc_i;\r
+  }\r
+  return Node::null();\r
+}\r
+\r
+void TheoryEngineModelBuilder::processBuildModel( TheoryModel* tm ){\r
+  Debug( "model-builder" ) << "TheoryEngineModelBuilder: Complete model..." << std::endl;\r
+  //create constants for all unresolved equivalence classes\r
+  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &tm->d_equalityEngine );\r
+  while( !eqcs_i.isFinished() ){\r
+    Node n = *eqcs_i;\r
+    if( tm->d_reps.find( n )!=tm->d_reps.end() ){\r
+      TypeNode tn = n.getType();\r
+      //add new constant to equivalence class\r
+      Node rep = tm->getNewDomainValue( tn, true );\r
+      if( !rep.isNull() ){\r
+        tm->assertEquality( n, rep, true );\r
+      }else{\r
+        rep = n;\r
+      }\r
+      tm->d_reps[ n ] = rep;\r
+      tm->d_ra.add( rep );\r
+    }\r
+    ++eqcs_i;\r
+  }\r
+}\r
diff --git a/src/theory/model.h b/src/theory/model.h
new file mode 100644 (file)
index 0000000..4d6035a
--- /dev/null
@@ -0,0 +1,165 @@
+/*********************                                                        */\r
+/*! \file model.h\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Model class\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef __CVC4__THEORY_MODEL_H\r
+#define __CVC4__THEORY_MODEL_H\r
+\r
+#include "util/model.h"\r
+#include "theory/uf/equality_engine.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+\r
+class QuantifiersEngine;\r
+\r
+/** this class stores a representative set */\r
+class RepSet {\r
+public:\r
+  RepSet(){}\r
+  ~RepSet(){}\r
+  std::map< TypeNode, std::vector< Node > > d_type_reps;\r
+  std::map< Node, int > d_tmap;\r
+  /** clear the set */\r
+  void clear();\r
+  /** has type */\r
+  bool hasType( TypeNode tn ) { return d_type_reps.find( tn )!=d_type_reps.end(); }\r
+  /** add representative for type */\r
+  void add( Node n );\r
+  /** set the representatives for type */\r
+  void set( TypeNode t, std::vector< Node >& reps );\r
+  /** returns index in d_type_reps for node n */\r
+  int getIndexFor( Node n ) { return d_tmap.find( n )!=d_tmap.end() ? d_tmap[n] : -1; }\r
+  /** debug print */\r
+  void toStream(std::ostream& out);\r
+};\r
+\r
+//representative domain\r
+typedef std::vector< int > RepDomain;\r
+\r
+class TheoryEngineModelBuilder;\r
+\r
+/** Theory Model class\r
+ *    For Model m, should call m.initialize() before using\r
+ */\r
+class TheoryModel : public Model\r
+{\r
+  friend class TheoryEngineModelBuilder;\r
+protected:\r
+  /** add term */\r
+  virtual void addTerm( Node n ) {}\r
+private:\r
+  /** definitions */\r
+  std::vector< Node > d_define_funcs;\r
+  std::vector< TypeNode > d_define_types;\r
+  std::vector< int > d_defines;\r
+protected:\r
+  /** to stream functions */\r
+  virtual void toStreamFunction( Node n, std::ostream& out );\r
+  virtual void toStreamType( TypeNode tn, std::ostream& out );\r
+public:\r
+  TheoryModel( context::Context* c, std::string name );\r
+  virtual ~TheoryModel(){}\r
+  /** equality engine containing all known equalities/disequalities */\r
+  eq::EqualityEngine d_equalityEngine;\r
+  /** map of representatives of equality engine to used representatives in representative set */\r
+  std::map< Node, Node > d_reps;\r
+  /** representative alphabet */\r
+  RepSet d_ra;\r
+  //true/false nodes\r
+  Node d_true;\r
+  Node d_false;\r
+public:\r
+  /** add defined function */\r
+  void addDefineFunction( Node n );\r
+  /** add defined type */\r
+  void addDefineType( TypeNode tn );\r
+  /**\r
+   * Get value function.  This should be called only after a ModelBuilder has called buildModel(...)\r
+   * on this model.\r
+   */\r
+  Node getValue( TNode n );\r
+  /** get interpreted value, should be a representative in d_reps */\r
+  virtual Node getInterpretedValue( TNode n ) = 0;\r
+  /** get existing domain value, with possible exclusions */\r
+  Node getDomainValue( TypeNode tn, std::vector< Node >& exclude );\r
+  /** get new domain value */\r
+  Node getNewDomainValue( TypeNode tn, bool mkConst = false );\r
+public:\r
+  /** assert equality */\r
+  void assertEquality( Node a, Node b, bool polarity );\r
+  /** assert predicate */\r
+  void assertPredicate( Node a, bool polarity );\r
+  /** assert equality engine */\r
+  void assertEqualityEngine( eq::EqualityEngine* ee );\r
+public:\r
+  //queries about equality\r
+  bool hasTerm( Node a );\r
+  Node getRepresentative( Node a );\r
+  bool areEqual( Node a, Node b );\r
+  bool areDisequal( Node a, Node b );\r
+public:\r
+  /** print representative function */\r
+  void printRepresentativeDebug( const char* c, Node r );\r
+  void printRepresentative( std::ostream& out, Node r );\r
+  /** to stream function */\r
+  void toStream( std::ostream& out );\r
+};\r
+\r
+//default model class: extends model arbitrarily\r
+class DefaultModel : public TheoryModel\r
+{\r
+public:\r
+  DefaultModel( context::Context* c, std::string name );\r
+  virtual ~DefaultModel(){}\r
+public:\r
+  Node getInterpretedValue( TNode n );\r
+};\r
+\r
+//incomplete model class: does not extend model\r
+class IncompleteModel : public TheoryModel\r
+{\r
+public:\r
+  IncompleteModel( context::Context* c, std::string name ) : TheoryModel( c, name ){}\r
+  virtual ~IncompleteModel(){}\r
+public:\r
+  Node getInterpretedValue( TNode n ) { return Node::null(); }\r
+};\r
+\r
+\r
+class TheoryEngineModelBuilder : public ModelBuilder\r
+{\r
+protected:\r
+  /** pointer to theory engine */\r
+  TheoryEngine* d_te;\r
+  /** choose representative */\r
+  virtual Node chooseRepresentative( TheoryModel* tm, Node eqc );\r
+  /** representatives that are current not set */\r
+  virtual void processBuildModel( TheoryModel* tm );\r
+public:\r
+  TheoryEngineModelBuilder( TheoryEngine* te );\r
+  virtual ~TheoryEngineModelBuilder(){}\r
+  /**\r
+   *  Build model function.\r
+   */\r
+  void buildModel( Model* m );\r
+};\r
+\r
+}\r
+}\r
+\r
+#endif
\ No newline at end of file
index de74e44f87da66f191c8dd3393c5c0577808c23d..ae5b99c0683e849c2a3cb39c192701c48b460d7a 100644 (file)
@@ -16,6 +16,14 @@ libquantifiers_la_SOURCES = \
        instantiation_engine.h \
        instantiation_engine.cpp \
        model_engine.h \
-       model_engine.cpp
+       model_engine.cpp \
+       relevant_domain.h \
+       relevant_domain.cpp \
+       rep_set_iterator.h \
+       rep_set_iterator.cpp \
+       term_database.h \
+       term_database.cpp \
+       first_order_model.h \
+       first_order_model.cpp
 
 EXTRA_DIST = kinds
\ No newline at end of file
diff --git a/src/theory/quantifiers/first_order_model.cpp b/src/theory/quantifiers/first_order_model.cpp
new file mode 100644 (file)
index 0000000..71a48b3
--- /dev/null
@@ -0,0 +1,146 @@
+/*********************                                                        */\r
+/*! \file first_order_model.cpp\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Implementation of model engine model class\r
+ **/\r
+\r
+#include "theory/quantifiers/first_order_model.h"\r
+#include "theory/quantifiers/rep_set_iterator.h"\r
+#include "theory/quantifiers/model_engine.h"\r
+#include "theory/uf/theory_uf_strong_solver.h"\r
+\r
+using namespace std;\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::context;\r
+using namespace CVC4::theory;\r
+using namespace CVC4::theory::quantifiers;\r
+\r
+FirstOrderModel::FirstOrderModel( QuantifiersEngine* qe, context::Context* c, std::string name ) : DefaultModel( c, name ),\r
+d_term_db( qe->getTermDatabase() ), d_forall_asserts( c ){\r
+\r
+}\r
+\r
+void FirstOrderModel::initialize(){\r
+  //rebuild models\r
+  d_uf_model.clear();\r
+  d_array_model.clear();\r
+  //for each quantifier, collect all operators we care about\r
+  for( int i=0; i<getNumAssertedQuantifiers(); i++ ){\r
+    Node f = getAssertedQuantifier( i );\r
+    //initialize model for term\r
+    initializeModelForTerm( f[1] );\r
+  }\r
+\r
+  if( Options::current()->printModelEngine ){\r
+    for( std::map< TypeNode, std::vector< Node > >::iterator it = d_ra.d_type_reps.begin(); it != d_ra.d_type_reps.end(); ++it ){\r
+      if( uf::StrongSolverTheoryUf::isRelevantType( it->first ) ){\r
+        Message() << "Cardinality( " << it->first << " )" << " = " << it->second.size() << std::endl;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+void FirstOrderModel::initializeModelForTerm( Node n ){\r
+  if( n.getKind()==APPLY_UF ){\r
+    Node op = n.getOperator();\r
+    if( d_uf_model.find( op )==d_uf_model.end() ){\r
+      TypeNode tn = op.getType();\r
+      tn = tn[ (int)tn.getNumChildren()-1 ];\r
+      if( tn==NodeManager::currentNM()->booleanType() || uf::StrongSolverTheoryUf::isRelevantType( tn ) ){\r
+        d_uf_model[ op ] = uf::UfModel( op, this );\r
+      }\r
+    }\r
+  }\r
+  if( n.getKind()!=STORE && n.getType().isArray() ){\r
+    d_array_model[n] = Node::null();\r
+  }\r
+  for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+    initializeModelForTerm( n[i] );\r
+  }\r
+}\r
+\r
+void FirstOrderModel::toStreamFunction( Node n, std::ostream& out ){\r
+  if( d_uf_model.find( n )!=d_uf_model.end() ){\r
+    //d_uf_model[n].toStream( out );\r
+    Node value = d_uf_model[n].getFunctionValue();\r
+    out << "(" << n << " " << value << ")";\r
+  //}else if( d_array_model.find( n )!=d_array_model.end() ){\r
+    //out << "(" << n << " " << d_array_model[n] << ")" << std::endl;\r
+  //  out << "(" << n << " Array)" << std::endl;\r
+  }else{\r
+    DefaultModel::toStreamFunction( n, out );\r
+  }\r
+}\r
+\r
+void FirstOrderModel::toStreamType( TypeNode tn, std::ostream& out ){\r
+  DefaultModel::toStreamType( tn, out );\r
+}\r
+\r
+Node FirstOrderModel::getInterpretedValue( TNode n ){\r
+  Debug("fo-model") << "get interpreted value " << n << std::endl;\r
+  TypeNode type = n.getType();\r
+  if( type.isFunction() || type.isPredicate() ){\r
+    if( d_uf_model.find( n )!=d_uf_model.end() ){\r
+      return d_uf_model[n].getFunctionValue();\r
+    }else{\r
+      return n;\r
+    }\r
+  }else if( n.getKind()==APPLY_UF ){\r
+    int depIndex;\r
+    return d_uf_model[ n.getOperator() ].getValue( n, depIndex );\r
+  }\r
+  return DefaultModel::getInterpretedValue( n );\r
+}\r
+\r
+TermDb* FirstOrderModel::getTermDatabase(){\r
+  return d_term_db;\r
+}\r
+\r
+\r
+void FirstOrderModel::toStream(std::ostream& out){\r
+  DefaultModel::toStream( out );\r
+#if 0\r
+  out << "---Current Model---" << std::endl;\r
+  out << "Representatives: " << std::endl;\r
+  d_ra.toStream( out );\r
+  out << "Functions: " << std::endl;\r
+  for( std::map< Node, uf::UfModel >::iterator it = d_uf_model.begin(); it != d_uf_model.end(); ++it ){\r
+    it->second.toStream( out );\r
+    out << std::endl;\r
+  }\r
+#elif 0\r
+  d_ra.toStream( out );\r
+  //print everything not related to UF in equality engine\r
+  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &d_equalityEngine );\r
+  while( !eqcs_i.isFinished() ){\r
+    Node eqc = (*eqcs_i);\r
+    Node rep = getRepresentative( eqc );\r
+    TypeNode type = rep.getType();\r
+    eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &d_equalityEngine );\r
+    while( !eqc_i.isFinished() ){\r
+      //do not print things that have interpretations in model\r
+      if( (*eqc_i).getMetaKind()!=kind::metakind::CONSTANT && !hasInterpretedValue( *eqc_i ) ){\r
+        out << "(" << (*eqc_i) << " " << rep << ")" << std::endl;\r
+      }\r
+      ++eqc_i;\r
+    }\r
+    ++eqcs_i;\r
+  }\r
+  //print functions\r
+  for( std::map< Node, uf::UfModel >::iterator it = d_uf_model.begin(); it != d_uf_model.end(); ++it ){\r
+    it->second.toStream( out );\r
+    out << std::endl;\r
+  }\r
+#endif\r
+}
\ No newline at end of file
diff --git a/src/theory/quantifiers/first_order_model.h b/src/theory/quantifiers/first_order_model.h
new file mode 100644 (file)
index 0000000..832acbe
--- /dev/null
@@ -0,0 +1,82 @@
+/*********************                                                        */\r
+/*! \file first_order_model.h\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Model extended classes\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef __CVC4__FIRST_ORDER_MODEL_H\r
+#define __CVC4__FIRST_ORDER_MODEL_H\r
+\r
+#include "theory/model.h"\r
+#include "theory/uf/theory_uf_model.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+\r
+struct ModelBasisAttributeId {};\r
+typedef expr::Attribute<ModelBasisAttributeId, bool> ModelBasisAttribute;\r
+//for APPLY_UF terms, 1 : term has direct child with model basis attribute,\r
+//                    0 : term has no direct child with model basis attribute.\r
+struct ModelBasisArgAttributeId {};\r
+typedef expr::Attribute<ModelBasisArgAttributeId, uint64_t> ModelBasisArgAttribute;\r
+\r
+class QuantifiersEngine;\r
+\r
+namespace quantifiers{\r
+\r
+class TermDb;\r
+\r
+class FirstOrderModel : public DefaultModel\r
+{\r
+private:\r
+  //pointer to term database\r
+  TermDb* d_term_db;\r
+  //for initialize model\r
+  void initializeModelForTerm( Node n );\r
+  /** to stream functions */\r
+  void toStreamFunction( Node n, std::ostream& out );\r
+  void toStreamType( TypeNode tn, std::ostream& out );\r
+public: //for Theory UF:\r
+  //models for each UF operator\r
+  std::map< Node, uf::UfModel > d_uf_model;\r
+public: //for Theory Arrays:\r
+  //default value for each non-store array\r
+  std::map< Node, Node > d_array_model;\r
+public: //for Theory Quantifiers:\r
+  /** list of quantifiers asserted in the current context */\r
+  context::CDList<Node> d_forall_asserts;\r
+  /** get number of asserted quantifiers */\r
+  int getNumAssertedQuantifiers() { return (int)d_forall_asserts.size(); }\r
+  /** get asserted quantifier */\r
+  Node getAssertedQuantifier( int i ) { return d_forall_asserts[i]; }\r
+public:\r
+  FirstOrderModel( QuantifiersEngine* qe, context::Context* c, std::string name );\r
+  virtual ~FirstOrderModel(){}\r
+  // initialize the model\r
+  void initialize();\r
+  /** get interpreted value */\r
+  Node getInterpretedValue( TNode n );\r
+public:\r
+  /** get term database */\r
+  TermDb* getTermDatabase();\r
+  /** to stream function */\r
+  void toStream( std::ostream& out );\r
+};\r
+\r
+}\r
+}\r
+}\r
+\r
+#endif\r
index c1476acb849332a0be8e2d1d8c29ac2bde388461..fae54c151109e1f05d5d658f6df544ffc3c16fe4 100644 (file)
@@ -18,6 +18,8 @@
 
 #include "theory/theory_engine.h"
 #include "theory/uf/theory_uf_instantiator.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/first_order_model.h"
 
 using namespace std;
 using namespace CVC4;
@@ -26,15 +28,9 @@ using namespace CVC4::context;
 using namespace CVC4::theory;
 using namespace CVC4::theory::quantifiers;
 
-//#define IE_PRINT_PROCESS_TIMES
+InstantiationEngine::InstantiationEngine( QuantifiersEngine* qe, bool setIncomplete ) :
+QuantifiersModule( qe ), d_setIncomplete( setIncomplete ){
 
-InstantiationEngine::InstantiationEngine( TheoryQuantifiers* th ) :
-d_th( th ){
-
-}
-
-QuantifiersEngine* InstantiationEngine::getQuantifiersEngine(){
-  return d_th->getQuantifiersEngine();
 }
 
 bool InstantiationEngine::hasAddedCbqiLemma( Node f ) {
@@ -46,25 +42,25 @@ void InstantiationEngine::addCbqiLemma( Node f ){
   //code for counterexample-based quantifier instantiation
   Debug("cbqi") << "Do cbqi for " << f << std::endl;
   //make the counterexample body
-  //Node ceBody = f[1].substitute( getQuantifiersEngine()->d_vars[f].begin(), getQuantifiersEngine()->d_vars[f].end(),
-  //                              getQuantifiersEngine()->d_inst_constants[f].begin(),
-  //                              getQuantifiersEngine()->d_inst_constants[f].end() );
+  //Node ceBody = f[1].substitute( d_quantEngine->d_vars[f].begin(), d_quantEngine->d_vars[f].end(),
+  //                              d_quantEngine->d_inst_constants[f].begin(),
+  //                              d_quantEngine->d_inst_constants[f].end() );
   //get the counterexample literal
-  Node ceBody = getQuantifiersEngine()->getCounterexampleBody( f );
-  Node ceLit = d_th->getValuation().ensureLiteral( ceBody.notNode() );
+  Node ceBody = d_quantEngine->getTermDatabase()->getCounterexampleBody( f );
+  Node ceLit = d_quantEngine->getValuation().ensureLiteral( ceBody.notNode() );
   d_ce_lit[ f ] = ceLit;
-  getQuantifiersEngine()->setInstantiationConstantAttr( ceLit, f );
+  d_quantEngine->getTermDatabase()->setInstantiationConstantAttr( ceLit, f );
   // set attributes, mark all literals in the body of n as dependent on cel
   //registerLiterals( ceLit, f );
   //require any decision on cel to be phase=true
-  d_th->getOutputChannel().requirePhase( ceLit, true );
+  d_quantEngine->getOutputChannel().requirePhase( ceLit, true );
   Debug("cbqi-debug") << "Require phase " << ceLit << " = true." << std::endl;
   //add counterexample lemma
   NodeBuilder<> nb(kind::OR);
   nb << f << ceLit;
   Node lem = nb;
   Debug("cbqi-debug") << "Counterexample lemma : " << lem << std::endl;
-  d_th->getOutputChannel().lemma( lem );
+  d_quantEngine->getOutputChannel().lemma( lem );
 }
 
 bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
@@ -72,8 +68,8 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
   if( Options::current()->cbqi ){
     //check if any cbqi lemma has not been added yet
     bool addedLemma = false;
-    for( int i=0; i<(int)getQuantifiersEngine()->getNumAssertedQuantifiers(); i++ ){
-      Node f = getQuantifiersEngine()->getAssertedQuantifier( i );
+    for( int i=0; i<(int)d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+      Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
       if( doCbqi( f ) && !hasAddedCbqiLemma( f ) ){
         //add cbqi lemma
         addCbqiLemma( f );
@@ -87,14 +83,9 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
   //if not, proceed to instantiation round
   Debug("inst-engine") << "IE: Instantiation Round." << std::endl;
   Debug("inst-engine-ctrl") << "IE: Instantiation Round." << std::endl;
-  //reset instantiators
+  //reset the quantifiers engine
   Debug("inst-engine-ctrl") << "Reset IE" << std::endl;
-  for( int i=0; i<theory::THEORY_LAST; i++ ){
-    if( getQuantifiersEngine()->getInstantiator( i ) ){
-      getQuantifiersEngine()->getInstantiator( i )->resetInstantiationRound( effort );
-    }
-  }
-  getQuantifiersEngine()->getTermDatabase()->reset( effort );
+  d_quantEngine->resetInstantiationRound( effort );
   //iterate over an internal effort level e
   int e = 0;
   int eLimit = effort==Theory::EFFORT_LAST_CALL ? 10 : 2;
@@ -104,20 +95,19 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
     Debug("inst-engine") << "IE: Prepare instantiation (" << e << ")." << std::endl;
     d_inst_round_status = InstStrategy::STATUS_SAT;
     //instantiate each quantifier
-    for( int q=0; q<getQuantifiersEngine()->getNumAssertedQuantifiers(); q++ ){
-      Node f = getQuantifiersEngine()->getAssertedQuantifier( q );
+    for( int q=0; q<d_quantEngine->getModel()->getNumAssertedQuantifiers(); q++ ){
+      Node f = d_quantEngine->getModel()->getAssertedQuantifier( q );
       Debug("inst-engine-debug") << "IE: Instantiate " << f << "..." << std::endl;
       //if this quantifier is active
-      if( getQuantifiersEngine()->getActive( f ) ){
-        //int e_use = getQuantifiersEngine()->getRelevance( f )==-1 ? e - 1 : e;
+      if( d_quantEngine->getActive( f ) ){
+        //int e_use = d_quantEngine->getRelevance( f )==-1 ? e - 1 : e;
         int e_use = e;
         if( e_use>=0 ){
           //use each theory instantiator to instantiate f
           for( int i=0; i<theory::THEORY_LAST; i++ ){
-            if( getQuantifiersEngine()->getInstantiator( i ) ){
-              Debug("inst-engine-debug") << "Do " << getQuantifiersEngine()->getInstantiator( i )->identify() << " " << e_use << std::endl;
-              int limitInst = 0;
-              int quantStatus = getQuantifiersEngine()->getInstantiator( i )->doInstantiation( f, effort, e_use, limitInst );
+            if( d_quantEngine->getInstantiator( i ) ){
+              Debug("inst-engine-debug") << "Do " << d_quantEngine->getInstantiator( i )->identify() << " " << e_use << std::endl;
+              int quantStatus = d_quantEngine->getInstantiator( i )->doInstantiation( f, effort, e_use );
               Debug("inst-engine-debug") << " -> status is " << quantStatus << std::endl;
               InstStrategy::updateStatus( d_inst_round_status, quantStatus );
             }
@@ -126,31 +116,31 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
       }
     }
     //do not consider another level if already added lemma at this level
-    if( getQuantifiersEngine()->hasAddedLemma() ){
+    if( d_quantEngine->hasAddedLemma() ){
       d_inst_round_status = InstStrategy::STATUS_UNKNOWN;
     }
     e++;
   }
   Debug("inst-engine") << "All instantiators finished, # added lemmas = ";
-  Debug("inst-engine") << (int)getQuantifiersEngine()->d_lemmas_waiting.size() << std::endl;
+  Debug("inst-engine") << (int)d_quantEngine->d_lemmas_waiting.size() << std::endl;
   //Notice() << "All instantiators finished, # added lemmas = " << (int)d_lemmas_waiting.size() << std::endl;
-  if( !getQuantifiersEngine()->hasAddedLemma() ){
+  if( !d_quantEngine->hasAddedLemma() ){
     Debug("inst-engine-stuck") << "No instantiations produced at this state: " << std::endl;
     for( int i=0; i<theory::THEORY_LAST; i++ ){
-      if( getQuantifiersEngine()->getInstantiator( i ) ){
-        getQuantifiersEngine()->getInstantiator( i )->debugPrint("inst-engine-stuck");
+      if( d_quantEngine->getInstantiator( i ) ){
+        d_quantEngine->getInstantiator( i )->debugPrint("inst-engine-stuck");
         Debug("inst-engine-stuck") << std::endl;
       }
     }
     Debug("inst-engine-ctrl") << "---Fail." << std::endl;
     return false;
   }else{
-    Debug("inst-engine-ctrl") << "---Done. " << (int)getQuantifiersEngine()->d_lemmas_waiting.size() << std::endl;
-#ifdef IE_PRINT_PROCESS_TIMES
-    Notice() << "lemmas = " << (int)getQuantifiersEngine()->d_lemmas_waiting.size() << std::endl;
-#endif
+    Debug("inst-engine-ctrl") << "---Done. " << (int)d_quantEngine->d_lemmas_waiting.size() << std::endl;
+    if( Options::current()->printInstEngine ){
+      Message() << "Added lemmas = " << (int)d_quantEngine->d_lemmas_waiting.size() << std::endl;
+    }
     //flush lemmas to output channel
-    getQuantifiersEngine()->flushLemmas( &d_th->getOutputChannel() );
+    d_quantEngine->flushLemmas( &d_quantEngine->getOutputChannel() );
     return true;
   }
 }
@@ -174,42 +164,43 @@ void InstantiationEngine::check( Theory::Effort e ){
   }
   if( performCheck ){
     Debug("inst-engine") << "IE: Check " << e << " " << ierCounter << std::endl;
-#ifdef IE_PRINT_PROCESS_TIMES
-    double clSet = double(clock())/double(CLOCKS_PER_SEC);
-    Notice() << "Run instantiation round " << e << " " << ierCounter << std::endl;
-#endif
+    double clSet = 0;
+    if( Options::current()->printInstEngine ){
+      clSet = double(clock())/double(CLOCKS_PER_SEC);
+      Message() << "---Instantiation Engine Round, effort = " << e << "---" << std::endl;
+    }
     bool quantActive = false;
     //for each quantifier currently asserted,
     // such that the counterexample literal is not in positive in d_counterexample_asserts
    // for( BoolMap::iterator i = d_forall_asserts.begin(); i != d_forall_asserts.end(); i++ ) {
     //  if( (*i).second ) {
-    Debug("quantifiers") << "quantifiers:  check:  asserted quantifiers size" 
-                         << getQuantifiersEngine()->getNumAssertedQuantifiers() << std::endl;
-    for( int i=0; i<(int)getQuantifiersEngine()->getNumAssertedQuantifiers(); i++ ){
-      Node n = getQuantifiersEngine()->getAssertedQuantifier( i );
+    Debug("quantifiers") << "quantifiers:  check:  asserted quantifiers size"
+                         << d_quantEngine->getModel()->getNumAssertedQuantifiers() << std::endl;
+    for( int i=0; i<(int)d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+      Node n = d_quantEngine->getModel()->getAssertedQuantifier( i );
       if( Options::current()->cbqi && hasAddedCbqiLemma( n ) ){
         Node cel = d_ce_lit[ n ];
         bool active, value;
         bool ceValue = false;
-        if( d_th->getValuation().hasSatValue( cel, value ) ){
+        if( d_quantEngine->getValuation().hasSatValue( cel, value ) ){
           active = value;
           ceValue = true;
         }else{
           active = true;
         }
-        getQuantifiersEngine()->setActive( n, active );
+        d_quantEngine->setActive( n, active );
         if( active ){
           Debug("quantifiers") << "  Active : " << n;
           quantActive = true;
         }else{
           Debug("quantifiers") << "  NOT active : " << n;
-          if( d_th->getValuation().isDecision( cel ) ){
+          if( d_quantEngine->getValuation().isDecision( cel ) ){
             Debug("quant-req-phase") << "Bad decision : " << cel << std::endl;
           }
           //note that the counterexample literal must not be a decision
-          Assert( !d_th->getValuation().isDecision( cel ) );
+          Assert( !d_quantEngine->getValuation().isDecision( cel ) );
         }
-        if( d_th->getValuation().hasSatValue( n, value ) ){
+        if( d_quantEngine->getValuation().hasSatValue( n, value ) ){
           Debug("quantifiers") << ", value = " << value;
         }
         if( ceValue ){
@@ -217,18 +208,18 @@ void InstantiationEngine::check( Theory::Effort e ){
         }
         Debug("quantifiers") << std::endl;
       }else{
-        getQuantifiersEngine()->setActive( n, true );
+        d_quantEngine->setActive( n, true );
         quantActive = true;
         Debug("quantifiers") << "  Active : " << n << ", no ce assigned." << std::endl;
       }
       Debug("quantifiers-relevance")  << "Quantifier : " << n << std::endl;
-      Debug("quantifiers-relevance")  << "   Relevance : " << getQuantifiersEngine()->getRelevance( n ) << std::endl;
-      Debug("quantifiers") << "   Relevance : " << getQuantifiersEngine()->getRelevance( n ) << std::endl;
+      Debug("quantifiers-relevance")  << "   Relevance : " << d_quantEngine->getRelevance( n ) << std::endl;
+      Debug("quantifiers") << "   Relevance : " << d_quantEngine->getRelevance( n ) << std::endl;
     }
     //}
     if( quantActive ){
       bool addedLemmas = doInstantiationRound( e );
-      //Debug("quantifiers-dec") << "Do instantiation, level = " << d_th->getValuation().getDecisionLevel() << std::endl;
+      //Debug("quantifiers-dec") << "Do instantiation, level = " << d_quantEngine->getValuation().getDecisionLevel() << std::endl;
       //for( int i=1; i<=(int)d_valuation.getDecisionLevel(); i++ ){
       //  Debug("quantifiers-dec") << "   " << d_valuation.getDecision( i ) << std::endl;
       //}
@@ -237,9 +228,12 @@ void InstantiationEngine::check( Theory::Effort e ){
           if( d_inst_round_status==InstStrategy::STATUS_SAT ){
             Debug("inst-engine") << "No instantiation given, returning SAT..." << std::endl;
             debugSat( SAT_INST_STRATEGY );
-          }else{
+          }else if( d_setIncomplete ){
             Debug("inst-engine") << "No instantiation given, returning unknown..." << std::endl;
-            d_th->getOutputChannel().setIncomplete();
+            d_quantEngine->getOutputChannel().setIncomplete();
+          }else{
+            Assert( Options::current()->finiteModelFind );
+            Debug("inst-engine") << "No instantiation given, defer to another engine..." << std::endl;
           }
         }
       }
@@ -250,30 +244,30 @@ void InstantiationEngine::check( Theory::Effort e ){
         }
       }
     }
-#ifdef IE_PRINT_PROCESS_TIMES
-    double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
-    Notice() << "Done Run instantiation round " << (clSet2-clSet) << std::endl;
-#endif
+    if( Options::current()->printInstEngine ){
+      double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
+      Message() << "Finished instantiation engine, time = " << (clSet2-clSet) << std::endl;
+    }
   }
 }
 
 void InstantiationEngine::registerQuantifier( Node f ){
   //Notice() << "do cbqi " << f << " ? " << std::endl;
-  Node ceBody = getQuantifiersEngine()->getCounterexampleBody( f );
+  Node ceBody = d_quantEngine->getTermDatabase()->getCounterexampleBody( f );
   if( !doCbqi( f ) ){
-    getQuantifiersEngine()->addTermToDatabase( ceBody, true );
+    d_quantEngine->addTermToDatabase( ceBody, true );
     //need to tell which instantiators will be responsible
     //by default, just chose the UF instantiator
-    getQuantifiersEngine()->getInstantiator( theory::THEORY_UF )->setHasConstraintsFrom( f );
+    d_quantEngine->getInstantiator( theory::THEORY_UF )->setHasConstraintsFrom( f );
   }
 
   //take into account user patterns
   if( f.getNumChildren()==3 ){
-    Node subsPat = getQuantifiersEngine()->getSubstitutedNode( f[2], f );
+    Node subsPat = d_quantEngine->getTermDatabase()->getSubstitutedNode( f[2], f );
     //add patterns
     for( int i=0; i<(int)subsPat.getNumChildren(); i++ ){
       //Notice() << "Add pattern " << subsPat[i] << " for " << f << std::endl;
-      ((uf::InstantiatorTheoryUf*)getQuantifiersEngine()->getInstantiator( theory::THEORY_UF ))->addUserPattern( f, subsPat[i] );
+      ((uf::InstantiatorTheoryUf*)d_quantEngine->getInstantiator( theory::THEORY_UF ))->addUserPattern( f, subsPat[i] );
     }
   }
 }
@@ -337,11 +331,11 @@ bool InstantiationEngine::doCbqi( Node f ){
 //      registerLiterals( n[i], f );
 //    }
 //    if( !d_ce_lit[ f ].isNull() ){
-//      if( getQuantifiersEngine()->d_te->getPropEngine()->isSatLiteral( n ) && n.getKind()!=NOT ){
+//      if( d_quantEngine->d_te->getPropEngine()->isSatLiteral( n ) && n.getKind()!=NOT ){
 //        if( n!=d_ce_lit[ f ] && n.notNode()!=d_ce_lit[ f ] ){
 //          Debug("quant-dep-dec") << "Make " << n << " dependent on ";
 //          Debug("quant-dep-dec") << d_ce_lit[ f ] << std::endl;
-//          d_th->getOutputChannel().dependentDecision( d_ce_lit[ f ], n );
+//          d_quantEngine->getOutputChannel().dependentDecision( d_ce_lit[ f ], n );
 //        }
 //      }
 //    }
@@ -351,19 +345,19 @@ bool InstantiationEngine::doCbqi( Node f ){
 void InstantiationEngine::debugSat( int reason ){
   if( reason==SAT_CBQI ){
     //Debug("quantifiers-sat") << "Decisions:" << std::endl;
-    //for( int i=1; i<=(int)d_th->getValuation().getDecisionLevel(); i++ ){
-    //  Debug("quantifiers-sat") << "   " << i << ": " << d_th->getValuation().getDecision( i ) << std::endl;
+    //for( int i=1; i<=(int)d_quantEngine->getValuation().getDecisionLevel(); i++ ){
+    //  Debug("quantifiers-sat") << "   " << i << ": " << d_quantEngine->getValuation().getDecision( i ) << std::endl;
     //}
     //for( BoolMap::iterator i = d_forall_asserts.begin(); i != d_forall_asserts.end(); i++ ) {
     //  if( (*i).second ) {
-    for( int i=0; i<(int)getQuantifiersEngine()->getNumAssertedQuantifiers(); i++ ){
-      Node f = getQuantifiersEngine()->getAssertedQuantifier( i );
+    for( int i=0; i<(int)d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+      Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
       Node cel = d_ce_lit[ f ];
       Assert( !cel.isNull() );
       bool value;
-      if( d_th->getValuation().hasSatValue( cel, value ) ){
+      if( d_quantEngine->getValuation().hasSatValue( cel, value ) ){
         if( !value ){
-          AlwaysAssert(! d_th->getValuation().isDecision( cel ),
+          AlwaysAssert(! d_quantEngine->getValuation().isDecision( cel ),
                        "bad decision on counterexample literal");
         }
       }
@@ -386,9 +380,9 @@ void InstantiationEngine::propagate( Theory::Effort level ){
   //propagate as decision all counterexample literals that are not asserted
   for( std::map< Node, Node >::iterator it = d_ce_lit.begin(); it != d_ce_lit.end(); ++it ){
     bool value;
-    if( !d_th->getValuation().hasSatValue( it->second, value ) ){
+    if( !d_quantEngine->getValuation().hasSatValue( it->second, value ) ){
       //if not already set, propagate as decision
-      d_th->getOutputChannel().propagateAsDecision( it->second );
+      d_quantEngine->getOutputChannel().propagateAsDecision( it->second );
       Debug("cbqi-prop-as-dec") << "CBQI: propagate as decision " << it->second << std::endl;
     }
   }
index c6aaed18ad87213e597dd4cf0461ae11437de711..13de210aba256ac57b84354f628d8cb056ea5230 100644 (file)
@@ -28,15 +28,14 @@ namespace quantifiers {
 
 class InstantiationEngine : public QuantifiersModule
 {
-private:
-  TheoryQuantifiers* d_th;
-  QuantifiersEngine* getQuantifiersEngine();
 private:
   typedef context::CDHashMap< Node, bool, NodeHashFunction > BoolMap;
   /** status of instantiation round (one of InstStrategy::STATUS_*) */
   int d_inst_round_status;
   /** map from universal quantifiers to their counterexample literals */
   std::map< Node, Node > d_ce_lit;
+  /** whether the instantiation engine should set incomplete if it cannot answer SAT */
+  bool d_setIncomplete;
 private:
   bool hasAddedCbqiLemma( Node f );
   void addCbqiLemma( Node f );
@@ -59,7 +58,7 @@ private:
   /** debug sat */
   void debugSat( int reason );
 public:
-  InstantiationEngine( TheoryQuantifiers* th );
+  InstantiationEngine( QuantifiersEngine* qe, bool setIncomplete = true );
   ~InstantiationEngine(){}
 
   void check( Theory::Effort e );
index a72b103d1256fbcffde87988b024dc0f2f907d06..ad259f8641f2cc95724818942e154071f491bf7d 100644 (file)
  **/
 
 #include "theory/quantifiers/model_engine.h"
+#include "theory/quantifiers/rep_set_iterator.h"
 #include "theory/theory_engine.h"
 #include "theory/uf/equality_engine.h"
 #include "theory/uf/theory_uf.h"
 #include "theory/uf/theory_uf_strong_solver.h"
 #include "theory/uf/theory_uf_instantiator.h"
+#include "theory/quantifiers/first_order_model.h"
+#include "theory/quantifiers/term_database.h"
 
-//#define ME_PRINT_PROCESS_TIMES
+//#define ME_PRINT_WARNINGS
 
 //#define DISABLE_EVAL_SKIP_MULTIPLE
-#define RECONSIDER_FUNC_DEFAULT_VALUE
+
 #define RECONSIDER_FUNC_CONSTANT
-#define USE_INDEX_ORDERING
-//#define ONE_INST_PER_QUANT_PER_ROUND
+#define EVAL_FAIL_SKIP_MULTIPLE
+//#define ONE_QUANT_PER_ROUND_INST_GEN
+//#define ONE_QUANT_PER_ROUND
 
 using namespace std;
 using namespace CVC4;
@@ -36,570 +40,417 @@ using namespace CVC4::context;
 using namespace CVC4::theory;
 using namespace CVC4::theory::quantifiers;
 
-void printRepresentative( const char* c, QuantifiersEngine* qe, Node r ){
-  if( r.getType()==NodeManager::currentNM()->booleanType() ){
-    if( qe->getEqualityQuery()->areEqual( r, NodeManager::currentNM()->mkConst( true ) ) ){
-      Debug( c ) << "true";
-    }else{
-      Debug( c ) << "false";
-    }
-  }else{
-    Debug( c ) << qe->getEqualityQuery()->getRepresentative( r );
-  }
-}
-
-RepAlphabet::RepAlphabet( RepAlphabet& ra, QuantifiersEngine* qe ){
-  //translate to current representatives
-  for( std::map< TypeNode, std::vector< Node > >::iterator it = ra.d_type_reps.begin(); it != ra.d_type_reps.end(); ++it ){
-    std::vector< Node > reps;
-    for( int i=0; i<(int)it->second.size(); i++ ){
-      //reps.push_back( ie->getEqualityQuery()->getRepresentative( it->second[i] ) );
-      reps.push_back( it->second[i] );
-    }
-    set( it->first, reps );
-  }
-}
-
-void RepAlphabet::set( TypeNode t, std::vector< Node >& reps ){
-  d_type_reps[t].insert( d_type_reps[t].begin(), reps.begin(), reps.end() );
-  for( int i=0; i<(int)reps.size(); i++ ){
-    d_tmap[ reps[i] ] = i;
-  }
-}
-
-void RepAlphabet::debugPrint( const char* c, QuantifiersEngine* qe ){
-  for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){
-    Debug( c ) << it->first << " : " << std::endl;
-    for( int i=0; i<(int)it->second.size(); i++ ){
-      Debug( c ) << "   " << i << ": " << it->second[i] << std::endl;
-      Debug( c ) << "         eq_class( " << it->second[i] << " ) : ";
-      ((uf::InstantiatorTheoryUf*)qe->getInstantiator( THEORY_UF ))->outputEqClass( c, it->second[i] );
-      Debug( c ) << std::endl;
-    }
-  }
-}
-
-RepAlphabetIterator::RepAlphabetIterator( QuantifiersEngine* qe, Node f, ModelEngine* model ){
-  for( size_t i=0; i<f[0].getNumChildren(); i++ ){
-    d_index_order.push_back( i );
-  }
-  initialize( qe, f, model );
-}
-
-RepAlphabetIterator::RepAlphabetIterator( QuantifiersEngine* qe, Node f, ModelEngine* model, std::vector< int >& indexOrder ){
-  d_index_order.insert( d_index_order.begin(), indexOrder.begin(), indexOrder.end() );
-  initialize( qe, f, model );
-}
-
-void RepAlphabetIterator::initialize( QuantifiersEngine* qe, Node f, ModelEngine* model ){
-  d_f = f;
-  d_model = model;
-  //store instantiation constants
-  for( size_t i=0; i<f[0].getNumChildren(); i++ ){
-    d_ic.push_back( qe->getInstantiationConstant( d_f, i ) );
-    d_index.push_back( 0 );
-  }
-  //make the d_var_order mapping
-  for( size_t i=0; i<d_index_order.size(); i++ ){
-    d_var_order[d_index_order[i]] = i;
-  }
-  //for testing
-  d_inst_tried = 0;
-  d_inst_tests = 0;
-}
-
-void RepAlphabetIterator::increment2( QuantifiersEngine* qe, int counter ){
-  Assert( !isFinished() );
-  //increment d_index
-  while( counter>=0 && d_index[counter]==(int)(d_model->getReps()->d_type_reps[d_f[0][d_index_order[counter]].getType()].size()-1) ){
-    counter--;
-  }
-  if( counter==-1 ){
-    d_index.clear();
-  }else{
-    for( int i=(int)d_index.size()-1; i>counter; i-- ){
-      d_index[i] = 0;
-      d_model->clearEvalFailed( i );
-    }
-    d_index[counter]++;
-    d_model->clearEvalFailed( counter );
-  }
-}
-
-void RepAlphabetIterator::increment( QuantifiersEngine* qe ){
-  if( !isFinished() ){
-    increment2( qe, (int)d_index.size()-1 );
-  }
-}
+ModelEngineBuilder::ModelEngineBuilder( QuantifiersEngine* qe ) :
+TheoryEngineModelBuilder( qe->getTheoryEngine() ),
+d_qe( qe ){
 
-bool RepAlphabetIterator::isFinished(){
-  return d_index.empty();
 }
 
-void RepAlphabetIterator::getMatch( QuantifiersEngine* ie, InstMatch& m ){
-  for( int i=0; i<(int)d_index.size(); i++ ){
-    m.d_map[ ie->getInstantiationConstant( d_f, i ) ] = getTerm( i );
-  }
+Node ModelEngineBuilder::chooseRepresentative( TheoryModel* tm, Node eqc ){
+  return eqc;
 }
 
-Node RepAlphabetIterator::getTerm( int i ){
-  TypeNode tn = d_f[0][d_index_order[i]].getType();
-  Assert( d_model->getReps()->d_type_reps.find( tn )!=d_model->getReps()->d_type_reps.end() );
-  return d_model->getReps()->d_type_reps[tn][d_index[d_index_order[i]]];
-}
-
-void RepAlphabetIterator::calculateTerms( QuantifiersEngine* qe ){
-  d_terms.clear();
-  for( int i=0; i<qe->getNumInstantiationConstants( d_f ); i++ ){
-    d_terms.push_back( getTerm( i ) );
-  }
-}
-
-void RepAlphabetIterator::debugPrint( const char* c ){
-  for( int i=0; i<(int)d_index.size(); i++ ){
-    Debug( c ) << i << ": " << d_index[i] << ", (" << getTerm( i ) << " / " << d_ic[ i ] << std::endl;
-  }
-}
-
-void RepAlphabetIterator::debugPrintSmall( const char* c ){
-  Debug( c ) << "RI: ";
-  for( int i=0; i<(int)d_index.size(); i++ ){
-    Debug( c ) << d_index[i] << ": " << getTerm( i ) << " ";
-  }
-  Debug( c ) << std::endl;
-}
-
-//set value function
-void UfModelTree::setValue( QuantifiersEngine* qe, Node n, Node v, std::vector< int >& indexOrder, bool ground, int argIndex ){
-  if( d_data.empty() ){
-    d_value = v;
-  }else if( !d_value.isNull() && d_value!=v ){
-    d_value = Node::null();
-  }
-  if( argIndex<(int)n.getNumChildren() ){
-    //take r = null when argument is the model basis
-    Node r;
-    if( ground || !n[ indexOrder[argIndex] ].getAttribute(ModelBasisAttribute()) ){
-      r = qe->getEqualityQuery()->getRepresentative( n[ indexOrder[argIndex] ] );
-    }
-    d_data[ r ].setValue( qe, n, v, indexOrder, ground, argIndex+1 );
-  }
-}
-
-//get value function
-Node UfModelTree::getValue( QuantifiersEngine* qe, Node n, std::vector< int >& indexOrder, int& depIndex, int argIndex ){
-  if( !d_value.isNull() && isTotal( n.getOperator(), argIndex ) ){
-    //Notice() << "Constant, return " << d_value << ", depIndex = " << argIndex << std::endl;
-    depIndex = argIndex;
-    return d_value;
-  }else{
-    Node val;
-    int childDepIndex[2] = { argIndex, argIndex };
-    for( int i=0; i<2; i++ ){
-      //first check the argument, then check default
-      Node r;
-      if( i==0 ){
-        r = qe->getEqualityQuery()->getRepresentative( n[ indexOrder[argIndex] ] );
+void ModelEngineBuilder::processBuildModel( TheoryModel* m ) {
+  d_addedLemmas = 0;
+  //only construct first order model if optUseModel() is true
+  if( optUseModel() ){
+    FirstOrderModel* fm = (FirstOrderModel*)m;
+    //initialize model
+    fm->initialize();
+    //analyze the quantifiers
+    Debug("fmf-model-debug") << "Analyzing quantifiers..." << std::endl;
+    analyzeQuantifiers( fm );
+    //if applicable, find exceptions
+    if( optInstGen() ){
+      //now, see if we know that any exceptions via InstGen exist
+      Debug("fmf-model-debug") << "Perform InstGen techniques for quantifiers..." << std::endl;
+      for( int i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
+        Node f = fm->getAssertedQuantifier( i );
+        if( d_quant_sat.find( f )==d_quant_sat.end() ){
+          d_addedLemmas += doInstGen( fm, f );
+          if( optOneQuantPerRoundInstGen() && d_addedLemmas>0 ){
+            break;
+          }
+        }
       }
-      std::map< Node, UfModelTree >::iterator it = d_data.find( r );
-      if( it!=d_data.end() ){
-        val = it->second.getValue( qe, n, indexOrder, childDepIndex[i], argIndex+1 );
-        if( !val.isNull() ){
-          break;
+      if( Options::current()->printModelEngine ){
+        if( d_addedLemmas>0 ){
+          Message() << "InstGen, added lemmas = " << d_addedLemmas << std::endl;
+        }else{
+          Message() << "No InstGen lemmas..." << std::endl;
         }
-      }else{
-        //argument is not a defined argument: thus, it depends on this argument
-        childDepIndex[i] = argIndex+1;
       }
+      Debug("fmf-model-debug") << "---> Added lemmas = " << d_addedLemmas << std::endl;
+    }
+    if( d_addedLemmas==0 ){
+      //if no immediate exceptions, build the model
+      //  this model will be an approximation that will need to be tested via exhaustive instantiation
+      Debug("fmf-model-debug") << "Building model..." << std::endl;
+      finishBuildModel( fm );
     }
-    //update depIndex
-    depIndex = childDepIndex[0]>childDepIndex[1] ? childDepIndex[0] : childDepIndex[1];
-    //Notice() << "Return " << val << ", depIndex = " << depIndex;
-    //Notice() << " ( " << childDepIndex[0] << ", " << childDepIndex[1] << " )" << std::endl;
-    return val;
   }
 }
 
-//simplify function
-void UfModelTree::simplify( Node op, Node defaultVal, int argIndex ){
-  if( argIndex<(int)op.getType().getNumChildren()-1 ){
-    std::vector< Node > eraseData;
-    //first process the default argument
-    Node r;
-    std::map< Node, UfModelTree >::iterator it = d_data.find( r );
-    if( it!=d_data.end() ){
-      if( !defaultVal.isNull() && it->second.d_value==defaultVal ){
-        eraseData.push_back( r );
-      }else{
-        it->second.simplify( op, defaultVal, argIndex+1 );
-        if( !it->second.d_value.isNull() && it->second.isTotal( op, argIndex+1 ) ){
-          defaultVal = it->second.d_value;
+void ModelEngineBuilder::analyzeQuantifiers( FirstOrderModel* fm ){
+  d_quant_selection_lits.clear();
+  d_quant_sat.clear();
+  d_uf_prefs.clear();
+  int quantSatInit = 0;
+  int nquantSatInit = 0;
+  //analyze the preferences of each quantifier
+  for( int i=0; i<(int)fm->getNumAssertedQuantifiers(); i++ ){
+    Node f = fm->getAssertedQuantifier( i );
+    Debug("fmf-model-prefs") << "Analyze quantifier " << f << std::endl;
+    std::vector< Node > pro_con[2];
+    std::vector< Node > constantSatOps;
+    bool constantSatReconsider;
+    //for each asserted quantifier f,
+    // - determine which literals form model basis for each quantifier
+    // - check which function/predicates have good and bad definitions according to f
+    for( std::map< Node, bool >::iterator it = d_qe->d_phase_reqs[f].begin();
+         it != d_qe->d_phase_reqs[f].end(); ++it ){
+      Node n = it->first;
+      Node gn = d_qe->getTermDatabase()->getModelBasis( n );
+      Debug("fmf-model-req") << "   Req: " << n << " -> " << it->second << std::endl;
+      //calculate preference
+      int pref = 0;
+      bool value;
+      if( d_qe->getValuation().hasSatValue( gn, value ) ){
+        if( value!=it->second ){
+          //store this literal as a model basis literal
+          //  this literal will force a default values in model that (modulo exceptions) shows
+          //  that f is satisfied by the model
+          d_quant_selection_lits[f].push_back( value ? n : n.notNode() );
+          pref = 1;
         }else{
-          defaultVal = Node::null();
+          pref = -1;
         }
       }
-    }
-    //now see if any children can be removed, and simplify the ones that cannot
-    for( std::map< Node, UfModelTree >::iterator it = d_data.begin(); it != d_data.end(); ++it ){
-      if( !it->first.isNull() ){
-        if( !defaultVal.isNull() && it->second.d_value==defaultVal ){
-          eraseData.push_back( it->first );
+      if( pref!=0 ){
+        //Store preferences for UF
+        bool isConst = !n.hasAttribute(InstConstantAttribute());
+        std::vector< Node > uf_terms;
+        if( gn.getKind()==APPLY_UF ){
+          uf_terms.push_back( gn );
+          isConst = fm->d_uf_model[gn.getOperator()].isConstant();
+        }else if( gn.getKind()==EQUAL ){
+          isConst = true;
+          for( int j=0; j<2; j++ ){
+            if( n[j].hasAttribute(InstConstantAttribute()) ){
+              if( n[j].getKind()==APPLY_UF ){
+                Node op = gn[j].getOperator();
+                if( fm->d_uf_model.find( op )!=fm->d_uf_model.end() ){
+                  uf_terms.push_back( gn[j] );
+                  isConst = isConst && fm->d_uf_model[op].isConstant();
+                }else{
+                  isConst = false;
+                }
+              }else{
+                isConst = false;
+              }
+            }
+          }
+        }
+        Debug("fmf-model-prefs") << "  It is " << ( pref==1 ? "pro" : "con" );
+        Debug("fmf-model-prefs") << " the definition of " << n << std::endl;
+        if( pref==1 && isConst ){
+          d_quant_sat[f] = true;
+          //instead, just note to the model for each uf term that f is pro its definition
+          constantSatReconsider = false;
+          constantSatOps.clear();
+          for( int j=0; j<(int)uf_terms.size(); j++ ){
+            Node op = uf_terms[j].getOperator();
+            constantSatOps.push_back( op );
+            if( d_uf_prefs[op].d_reconsiderModel ){
+              constantSatReconsider = true;
+            }
+          }
+          if( !constantSatReconsider ){
+            break;
+          }
         }else{
-          it->second.simplify( op, defaultVal, argIndex+1 );
+          int pcIndex = pref==1 ? 0 : 1;
+          for( int j=0; j<(int)uf_terms.size(); j++ ){
+            pro_con[pcIndex].push_back( uf_terms[j] );
+          }
         }
       }
     }
-    for( int i=0; i<(int)eraseData.size(); i++ ){
-      d_data.erase( eraseData[i] );
-    }
-  }
-}
-
-//is total function
-bool UfModelTree::isTotal( Node op, int argIndex ){
-  if( argIndex==(int)(op.getType().getNumChildren()-1) ){
-    return !d_value.isNull();
-  }else{
-    Node r;
-    std::map< Node, UfModelTree >::iterator it = d_data.find( r );
-    if( it!=d_data.end() ){
-      return it->second.isTotal( op, argIndex+1 );
+    if( d_quant_sat.find( f )!=d_quant_sat.end() ){
+      Debug("fmf-model-prefs") << "  * Constant SAT due to definition of ops: ";
+      for( int i=0; i<(int)constantSatOps.size(); i++ ){
+        Debug("fmf-model-prefs") << constantSatOps[i] << " ";
+        d_uf_prefs[constantSatOps[i]].d_reconsiderModel = false;
+      }
+      Debug("fmf-model-prefs") << std::endl;
+      quantSatInit++;
+      d_statistics.d_pre_sat_quant += quantSatInit;
     }else{
-      return false;
-    }
-  }
-}
-
-Node UfModelTree::getConstantValue( QuantifiersEngine* qe, Node n, std::vector< int >& indexOrder, int argIndex ){
-  return d_value;
-}
-
-void indent( const char* c, int ind ){
-  for( int i=0; i<ind; i++ ){
-    Debug( c ) << " ";
-  }
-}
-
-void UfModelTree::debugPrint( const char* c, QuantifiersEngine* qe, std::vector< int >& indexOrder, int ind, int arg ){
-  if( !d_data.empty() ){
-    for( std::map< Node, UfModelTree >::iterator it = d_data.begin(); it != d_data.end(); ++it ){
-      if( !it->first.isNull() ){
-        indent( c, ind );
-        Debug( c ) << "if x_" << indexOrder[arg] << " == " << it->first << std::endl;
-        it->second.debugPrint( c, qe, indexOrder, ind+2, arg+1 );
+      nquantSatInit++;
+      d_statistics.d_pre_nsat_quant += quantSatInit;
+      //note quantifier's value preferences to models
+      for( int k=0; k<2; k++ ){
+        for( int j=0; j<(int)pro_con[k].size(); j++ ){
+          Node op = pro_con[k][j].getOperator();
+          Node r = fm->getRepresentative( pro_con[k][j] );
+          d_uf_prefs[op].setValuePreference( f, pro_con[k][j], r, k==0 );
+        }
       }
     }
-    if( d_data.find( Node::null() )!=d_data.end() ){
-      d_data[ Node::null() ].debugPrint( c, qe, indexOrder, ind, arg+1 );
-    }
-  }else{
-    indent( c, ind );
-    Debug( c ) << "return ";
-    printRepresentative( c, qe, d_value );
-    //Debug( c ) << " { ";
-    //for( int i=0; i<(int)d_explicit.size(); i++ ){
-    //  Debug( c ) << d_explicit[i] << " ";
-    //}
-    //Debug( c ) << "}";
-    Debug( c ) << std::endl;
   }
+  Debug("fmf-model-prefs") << "Pre-Model Completion: Quantifiers SAT: " << quantSatInit << " / " << (quantSatInit+nquantSatInit) << std::endl;
 }
 
-UfModel::UfModel( Node op, ModelEngine* me ) : d_op( op ), d_me( me ), 
-  d_model_constructed( false ), d_reconsider_model( false ){
-
-  d_tree = UfModelTreeOrdered( op );  TypeNode tn = d_op.getType();  tn = tn[(int)tn.getNumChildren()-1];  Assert( tn==NodeManager::currentNM()->booleanType() || uf::StrongSolverTheoryUf::isRelevantType( tn ) );  //look at ground assertions
-  for( int i=0; i<(int)d_me->getQuantifiersEngine()->getTermDatabase()->d_op_map[ d_op ].size(); i++ ){
-    Node n = d_me->getQuantifiersEngine()->getTermDatabase()->d_op_map[ d_op ][i];
-    bool add = true;
-    if( n.getAttribute(NoMatchAttribute()) ){
-      add = false;
-      //determine if it has model basis attribute
-      for( int j=0; j<(int)n.getNumChildren(); j++ ){
-        if( n[j].getAttribute(ModelBasisAttribute()) ){
-          add = true;
-          break;
+int ModelEngineBuilder::doInstGen( FirstOrderModel* fm, Node f ){
+  //we wish to add all known exceptions to our model basis literal(s)
+  //  this will help to refine our current model.
+  //This step is advantageous over exhaustive instantiation, since we are adding instantiations that involve model basis terms,
+  //  effectively acting as partial instantiations instead of pointwise instantiations.
+  int addedLemmas = 0;
+  for( int i=0; i<(int)d_quant_selection_lits[f].size(); i++ ){
+    bool phase = d_quant_selection_lits[f][i].getKind()!=NOT;
+    Node lit = d_quant_selection_lits[f][i].getKind()==NOT ? d_quant_selection_lits[f][i][0] : d_quant_selection_lits[f][i];
+    Assert( lit.hasAttribute(InstConstantAttribute()) );
+    std::vector< Node > tr_terms;
+    if( lit.getKind()==APPLY_UF ){
+      //only match predicates that are contrary to this one, use literal matching
+      Node eq = NodeManager::currentNM()->mkNode( IFF, lit, !phase ? fm->d_true : fm->d_false );
+      fm->getTermDatabase()->setInstantiationConstantAttr( eq, f );
+      tr_terms.push_back( eq );
+    }else if( lit.getKind()==EQUAL ){
+      //collect trigger terms
+      for( int j=0; j<2; j++ ){
+        if( lit[j].hasAttribute(InstConstantAttribute()) ){
+          if( lit[j].getKind()==APPLY_UF ){
+            tr_terms.push_back( lit[j] );
+          }else{
+            tr_terms.clear();
+            break;
+          }
         }
       }
-    }
-    if( add ){
-      d_ground_asserts.push_back( n );
-      Node r = d_me->getQuantifiersEngine()->getEqualityQuery()->getRepresentative( n );
-      d_ground_asserts_reps.push_back( r );
-    }
-  }
-  //determine if it is constant
-  if( !d_ground_asserts.empty() ){
-    bool isConstant = true;
-    for( int i=1; i<(int)d_ground_asserts.size(); i++ ){
-      if( d_ground_asserts_reps[0]!=d_ground_asserts_reps[i] ){
-        isConstant = false;
-        break;
+      if( tr_terms.size()==1 && !phase ){
+        //equality between a function and a ground term, use literal matching
+        tr_terms.clear();
+        tr_terms.push_back( lit );
       }
     }
-    if( isConstant ){
-      //set constant value
-      Node t = d_me->getModelBasisApplyUfTerm( d_op );
-      Node r = d_ground_asserts_reps[0];
-      setValue( t, r, false );
-      setModel();
-      d_reconsider_model = true;
-      Debug("fmf-model-cons") << "Function " << d_op << " is the constant function ";
-      printRepresentative( "fmf-model-cons", d_me->getQuantifiersEngine(), r );
-      Debug("fmf-model-cons") << std::endl;
+    //if applicable, try to add exceptions here
+    if( !tr_terms.empty() ){
+      //make a trigger for these terms, add instantiations
+      Trigger* tr = Trigger::mkTrigger( d_qe, f, tr_terms );
+      //Notice() << "Trigger = " << (*tr) << std::endl;
+      tr->resetInstantiationRound();
+      tr->reset( Node::null() );
+      //d_qe->d_optInstMakeRepresentative = false;
+      //d_qe->d_optMatchIgnoreModelBasis = true;
+      addedLemmas += tr->addInstantiations( d_quant_basis_match[f] );
     }
   }
+  return addedLemmas;
 }
 
-void UfModel::setValue( Node n, Node v, bool ground ){
-  d_set_values[ ground ? 1 : 0 ][n] = v;
-}
-
-void UfModel::setModel(){
-  makeModel( d_me->getQuantifiersEngine(), d_tree );
-  d_model_constructed = true;
-}
-
-void UfModel::clearModel(){
-  for( int k=0; k<2; k++ ){
-    d_set_values[k].clear();
+void ModelEngineBuilder::finishBuildModel( FirstOrderModel* fm ){
+  //build model for UF
+  for( std::map< Node, uf::UfModel >::iterator it = fm->d_uf_model.begin(); it != fm->d_uf_model.end(); ++it ){
+    finishBuildModelUf( fm, it->second );
   }
-  d_tree.clear();
-  d_model_constructed = false;
-}
-
-Node UfModel::getConstantValue( QuantifiersEngine* qe, Node n ){
-  if( d_model_constructed ){
-    return d_tree.getConstantValue( qe, n );
-  }else{
-    return Node::null();
+  //build model for arrays
+  for( std::map< Node, Node >::iterator it = fm->d_array_model.begin(); it != fm->d_array_model.end(); ++it ){
+    //consult the model basis select term
+    // i.e. the default value for array A is the value of select( A, e ), where e is the model basis term
+    TypeNode tn = it->first.getType();
+    Node selModelBasis = NodeManager::currentNM()->mkNode( SELECT, it->first, fm->getTermDatabase()->getModelBasisTerm( tn[0] ) );
+    it->second = fm->getRepresentative( selModelBasis );
   }
+  Debug("fmf-model-debug") << "Done building models." << std::endl;
 }
 
-bool UfModel::isConstant(){
-  Node gn = d_me->getModelBasisApplyUfTerm( d_op );
-  Node n = getConstantValue( d_me->getQuantifiersEngine(), gn );
-  return !n.isNull();
-}
-
-void UfModel::buildModel(){
+void ModelEngineBuilder::finishBuildModelUf( FirstOrderModel* fm, uf::UfModel& model ){
+  Node op = model.getOperator();
 #ifdef RECONSIDER_FUNC_CONSTANT
-  if( d_model_constructed ){
-    if( d_reconsider_model ){
+  if( model.isModelConstructed() && model.isConstant() ){
+    if( d_uf_prefs[op].d_reconsiderModel ){
       //if we are allowed to reconsider default value, then see if the default value can be improved
-      Node t = d_me->getModelBasisApplyUfTerm( d_op );
-      Node v = d_set_values[0][t];
-      if( d_value_pro_con[1][v].size()>d_value_pro_con[0][v].size() ){
-        Debug("fmf-model-cons-debug") << "Consider changing the default value for " << d_op << std::endl;
-        clearModel();
+      Node t = d_qe->getTermDatabase()->getModelBasisOpTerm( op );
+      Node v = model.getConstantValue( t );
+      if( d_uf_prefs[op].d_value_pro_con[0][v].empty() ){
+        Debug("fmf-model-cons-debug") << "Consider changing the default value for " << op << std::endl;
+        model.clearModel();
       }
     }
   }
 #endif
-  //now, construct models for each uninterpretted function/predicate
-  if( !d_model_constructed ){
-    Debug("fmf-model-cons") << "Construct model for " << d_op << "..." << std::endl;
-    //now, set the values in the model
-    for( int i=0; i<(int)d_ground_asserts.size(); i++ ){
-      Node n = d_ground_asserts[i];
-      Node v = d_ground_asserts_reps[i];
+  if( !model.isModelConstructed() ){
+    //construct the model for the uninterpretted function/predicate
+    bool setDefaultVal = true;
+    Node defaultTerm = d_qe->getTermDatabase()->getModelBasisOpTerm( op );
+    Debug("fmf-model-cons") << "Construct model for " << op << "..." << std::endl;
+    //set the values in the model
+    for( size_t i=0; i<model.d_ground_asserts.size(); i++ ){
+      Node n = model.d_ground_asserts[i];
+      Node v = model.d_ground_asserts_reps[i];
       //if this assertion did not help the model, just consider it ground
       //set n = v in the model tree
       Debug("fmf-model-cons") << "  Set " << n << " = ";
-      printRepresentative( "fmf-model-cons", d_me->getQuantifiersEngine(), v );
+      fm->printRepresentativeDebug( "fmf-model-cons", v );
       Debug("fmf-model-cons") << std::endl;
       //set it as ground value
-      setValue( n, v );
-    }
-    //set the default value
-    //chose defaultVal based on heuristic (the best proportion of "pro" responses)
-    Node defaultVal;
-    double maxScore = -1;
-    for( int i=0; i<(int)d_values.size(); i++ ){
-      Node v = d_values[i];
-      double score = ( 1.0 + (double)d_value_pro_con[0][v].size() )/( 1.0 + (double)d_value_pro_con[1][v].size() );
-      Debug("fmf-model-cons") << "  - score( ";
-      printRepresentative( "fmf-model-cons", d_me->getQuantifiersEngine(), v );
-      Debug("fmf-model-cons") << " ) = " << score << std::endl;
-      if( score>maxScore ){
-        defaultVal = v;
-        maxScore = score;
-      }
-    }
-#ifdef RECONSIDER_FUNC_DEFAULT_VALUE
-    if( maxScore<1.0 ){
-      //consider finding another value, if possible
-      Debug("fmf-model-cons-debug") << "Poor choice for default value, score = " << maxScore << std::endl;
-      TypeNode tn = d_op.getType();
-      Node newDefaultVal = d_me->getArbitraryElement( tn[(int)tn.getNumChildren()-1], d_values );
-      if( !newDefaultVal.isNull() ){
-        defaultVal = newDefaultVal;
-        Debug("fmf-model-cons-debug") << "-> Change default value to ";
-        printRepresentative( "fmf-model-cons-debug", d_me->getQuantifiersEngine(), defaultVal );
-        Debug("fmf-model-cons-debug") << std::endl;
+      model.setValue( n, v );
+      if( model.optUsePartialDefaults() ){
+        //also set as default value if necessary
+        //if( n.getAttribute(ModelBasisArgAttribute())==1 && !d_term_pro_con[0][n].empty() ){
+        if( n.hasAttribute(ModelBasisArgAttribute()) && n.getAttribute(ModelBasisArgAttribute())==1 ){
+          model.setValue( n, v, false );
+          if( n==defaultTerm ){
+            //incidentally already set, we will not need to find a default value
+            setDefaultVal = false;
+          }
+        }
       }else{
-        Debug("fmf-model-cons-debug") << "-> Could not find arbitrary element of type " << tn[(int)tn.getNumChildren()-1] << std::endl;
-        Debug("fmf-model-cons-debug") << "      Excluding: ";
-        for( int i=0; i<(int)d_values.size(); i++ ){
-          Debug("fmf-model-cons-debug") << d_values[i] << " ";
+        if( n==defaultTerm ){
+          model.setValue( n, v, false );
+          //incidentally already set, we will not need to find a default value
+          setDefaultVal = false;
         }
-        Debug("fmf-model-cons-debug") << std::endl;
       }
     }
-#endif
-    Assert( !defaultVal.isNull() );
-    //get the default term (this term must be defined non-ground in model)
-    Node defaultTerm = d_me->getModelBasisApplyUfTerm( d_op );
-    Debug("fmf-model-cons") << "  Choose ";
-    printRepresentative("fmf-model-cons", d_me->getQuantifiersEngine(), defaultVal );
-    Debug("fmf-model-cons") << " as default value (" << defaultTerm << ")" << std::endl;
-    Debug("fmf-model-cons") << "     # quantifiers pro = " << d_value_pro_con[0][defaultVal].size() << std::endl;
-    Debug("fmf-model-cons") << "     # quantifiers con = " << d_value_pro_con[1][defaultVal].size() << std::endl;
-    setValue( defaultTerm, defaultVal, false );
+    //set the overall default value if not set already  (is this necessary??)
+    if( setDefaultVal ){
+      Debug("fmf-model-cons") << "  Choose default value..." << std::endl;
+      //chose defaultVal based on heuristic, currently the best ratio of "pro" responses
+      Node defaultVal = d_uf_prefs[op].getBestDefaultValue( defaultTerm, fm );
+      Assert( !defaultVal.isNull() );
+      model.setValue( defaultTerm, defaultVal, false );
+    }
     Debug("fmf-model-cons") << "  Making model...";
-    setModel();
-    Debug("fmf-model-cons") << "  Finished constructing model for " << d_op << "." << std::endl;
+    model.setModel();
+    Debug("fmf-model-cons") << "  Finished constructing model for " << op << "." << std::endl;
   }
 }
 
-void UfModel::setValuePreference( Node f, Node n, bool isPro ){
-  Node v = d_me->getQuantifiersEngine()->getEqualityQuery()->getRepresentative( n );
-  //Notice() << "Set value preference " << n << " = " << v << " " << isPro << std::endl;
-  if( std::find( d_values.begin(), d_values.end(), v )==d_values.end() ){
-    d_values.push_back( v );
-  }
-  int index = isPro ? 0 : 1;
-  if( std::find( d_value_pro_con[index][v].begin(), d_value_pro_con[index][v].end(), f )==d_value_pro_con[index][v].end() ){
-    d_value_pro_con[index][v].push_back( f );
-  }
+bool ModelEngineBuilder::optUseModel() {
+  return Options::current()->fmfModelBasedInst;
 }
 
-void UfModel::makeModel( QuantifiersEngine* qe, UfModelTreeOrdered& tree ){
-  for( int k=0; k<2; k++ ){
-    for( std::map< Node, Node >::iterator it = d_set_values[k].begin(); it != d_set_values[k].end(); ++it ){
-      tree.setValue( qe, it->first, it->second, k==1 );
-    }
-  }
-  tree.simplify();
+bool ModelEngineBuilder::optInstGen(){
+  return Options::current()->fmfInstGen;
+}
+
+bool ModelEngineBuilder::optOneQuantPerRoundInstGen(){
+#ifdef ONE_QUANT_PER_ROUND_INST_GEN
+  return true;
+#else
+  return false;
+#endif
 }
 
-void UfModel::debugPrint( const char* c ){
-  //Debug( c ) << "Function " << d_op << std::endl;
-  //Debug( c ) << "   Type: " << d_op.getType() << std::endl;
-  //Debug( c ) << "   Ground asserts:" << std::endl;
-  //for( int i=0; i<(int)d_ground_asserts.size(); i++ ){
-  //  Debug( c ) << "      " << d_ground_asserts[i] << " = ";
-  //  printRepresentative( c, d_me->getQuantifiersEngine(), d_ground_asserts[i] );
-  //  Debug( c ) << std::endl;
-  //}
-  //Debug( c ) << "   Model:" << std::endl;
+ModelEngineBuilder::Statistics::Statistics():
+  d_pre_sat_quant("ModelEngineBuilder::Status_quant_pre_sat", 0),
+  d_pre_nsat_quant("ModelEngineBuilder::Status_quant_pre_non_sat", 0)
+{
+  StatisticsRegistry::registerStat(&d_pre_sat_quant);
+  StatisticsRegistry::registerStat(&d_pre_nsat_quant);
+}
 
-  TypeNode t = d_op.getType();
-  Debug( c ) << d_op << "( ";
-  for( int i=0; i<(int)(t.getNumChildren()-1); i++ ){
-    Debug( c ) << "x_" << i << " : " << t[i];
-    if( i<(int)(t.getNumChildren()-2) ){
-      Debug( c ) << ", ";
-    }
-  }
-  Debug( c ) << " ) : " << t[(int)t.getNumChildren()-1] << std::endl;
-  if( d_tree.isEmpty() ){
-    Debug( c ) << "   [undefined]" << std::endl;
-  }else{
-    d_tree.debugPrint( c, d_me->getQuantifiersEngine(), 3 );
-    Debug( c ) << std::endl;
-  }
-  //Debug( c ) << "   Phase reqs:" << std::endl;  //for( int i=0; i<2; i++ ){
-  //  for( std::map< Node, std::vector< Node > >::iterator it = d_reqs[i].begin(); it != d_reqs[i].end(); ++it ){
-  //    Debug( c ) << "      " << it->first << std::endl;
-  //    for( int j=0; j<(int)it->second.size(); j++ ){
-  //      Debug( c ) << "         " << it->second[j] << " -> " << (i==1) << std::endl;
-  //    }
-  //  }
-  //}
-  //Debug( c ) << std::endl;
-  //for( int i=0; i<2; i++ ){
-  //  for( std::map< Node, std::map< Node, std::vector< Node > > >::iterator it = d_eq_reqs[i].begin(); it != d_eq_reqs[i].end(); ++it ){
-  //    Debug( c ) << "      " << "For " << it->first << ":" << std::endl;
-  //    for( std::map< Node, std::vector< Node > >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
-  //      for( int j=0; j<(int)it2->second.size(); j++ ){
-  //        Debug( c ) << "         " << it2->first << ( i==1 ? "==" : "!=" ) << it2->second[j] << std::endl;
-  //      }
-  //    }
-  //  }
-  //}
+ModelEngineBuilder::Statistics::~Statistics(){
+  StatisticsRegistry::unregisterStat(&d_pre_sat_quant);
+  StatisticsRegistry::unregisterStat(&d_pre_nsat_quant);
 }
 
 //Model Engine constructor
-ModelEngine::ModelEngine( TheoryQuantifiers* th ){
-  d_th = th;
-  d_quantEngine = th->getQuantifiersEngine();
-  d_ss = ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->getTheory( THEORY_UF ))->getStrongSolver();
+ModelEngine::ModelEngine( QuantifiersEngine* qe ) :
+QuantifiersModule( qe ),
+d_builder( qe ),
+d_rel_domain( qe->getModel() ){
+
 }
 
 void ModelEngine::check( Theory::Effort e ){
-  if( e==Theory::EFFORT_LAST_CALL ){
-    bool quantsInit = true;
+  if( e==Theory::EFFORT_LAST_CALL && !d_quantEngine->hasAddedLemma() ){
     //first, check if we can minimize the model further
-    if( !d_ss->minimize() ){
+    if( !((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->getTheory( THEORY_UF ))->getStrongSolver()->minimize() ){
       return;
     }
-    if( useModel() ){
-      //now, check if any quantifiers are un-initialized
-      for( int i=0; i<d_quantEngine->getNumAssertedQuantifiers(); i++ ){
-        Node f = d_quantEngine->getAssertedQuantifier( i );
-        if( !initializeQuantifier( f ) ){
-          quantsInit = false;
-        }
+    //the following will attempt to build a model and test that it satisfies all asserted universal quantifiers
+    int addedLemmas = 0;
+    if( d_builder.optUseModel() ){
+      //check if any quantifiers are un-initialized
+      for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+        Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
+        addedLemmas += initializeQuantifier( f );
       }
     }
-    if( quantsInit ){
-#ifdef ME_PRINT_PROCESS_TIMES
-      Notice() << "---Instantiation Round---" << std::endl;
-#endif
+    if( addedLemmas==0 ){
+      //quantifiers are initialized, we begin an instantiation round
+      double clSet = 0;
+      if( Options::current()->printModelEngine ){
+        clSet = double(clock())/double(CLOCKS_PER_SEC);
+        Message() << "---Model Engine Round---" << std::endl;
+      }
       Debug("fmf-model-debug") << "---Begin Instantiation Round---" << std::endl;
       ++(d_statistics.d_inst_rounds);
-      d_quantEngine->getTermDatabase()->reset( e );
-      //build the representatives
-      Debug("fmf-model-debug") << "Building representatives..." << std::endl;
-      buildRepresentatives();
-      if( useModel() ){
-        //initialize the model
-        Debug("fmf-model-debug") << "Initializing model..." << std::endl;
-        initializeModel();
-        //analyze the quantifiers
-        Debug("fmf-model-debug") << "Analyzing quantifiers..." << std::endl;
-        analyzeQuantifiers();
-        //build the model
-        Debug("fmf-model-debug") << "Building model..." << std::endl;
-        for( std::map< Node, UfModel >::iterator it = d_uf_model.begin(); it != d_uf_model.end(); ++it ){
-          it->second.buildModel();
+      //reset the quantifiers engine
+      d_quantEngine->resetInstantiationRound( e );
+      //initialize the model
+      Debug("fmf-model-debug") << "Build model..." << std::endl;
+      d_builder.buildModel( d_quantEngine->getModel() );
+      d_quantEngine->d_model_set = true;
+      //if builder has lemmas, add and return
+      if( d_builder.d_addedLemmas>0 ){
+        addedLemmas += (int)d_builder.d_addedLemmas;
+      }else{
+        //print debug
+        Debug("fmf-model-complete") << std::endl;
+        debugPrint("fmf-model-complete");
+        //verify we are SAT by trying exhaustive instantiation
+        if( optUseRelevantDomain() ){
+          d_rel_domain.compute();
         }
-      }
-      //print debug
-      debugPrint("fmf-model-complete");
-      //try exhaustive instantiation
-      Debug("fmf-model-debug") << "Do exhaustive instantiation..." << std::endl;
-      int addedLemmas = 0;
-      for( int i=0; i<d_quantEngine->getNumAssertedQuantifiers(); i++ ){
-        Node f = d_quantEngine->getAssertedQuantifier( i );
-        if( d_quant_sat.find( f )==d_quant_sat.end() ){
-          addedLemmas += instantiateQuantifier( f );
+        d_triedLemmas = 0;
+        d_testLemmas = 0;
+        d_relevantLemmas = 0;
+        d_totalLemmas = 0;
+        Debug("fmf-model-debug") << "Do exhaustive instantiation..." << std::endl;
+        for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+          Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
+          if( d_builder.d_quant_sat.find( f )==d_builder.d_quant_sat.end() ){
+            addedLemmas += exhaustiveInstantiate( f, optUseRelevantDomain() );
+            if( optOneQuantPerRound() && addedLemmas>0 ){
+              break;
+            }
+          }
+#ifdef ME_PRINT_WARNINGS
+          if( addedLemmas>10000 ){
+            break;
+          }
+#endif
+        }
+        Debug("fmf-model-debug") << "---> Added lemmas = " << addedLemmas << " / " << d_triedLemmas << " / ";
+        Debug("fmf-model-debug") << d_testLemmas << " / " << d_relevantLemmas << " / " << d_totalLemmas << std::endl;
+        if( Options::current()->printModelEngine ){
+          Message() << "Added Lemmas = " << addedLemmas << " / " << d_triedLemmas << " / ";
+          Message() << d_testLemmas << " / " << d_relevantLemmas << " / " << d_totalLemmas << std::endl;
+          double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
+          Message() << "Finished model engine, time = " << (clSet2-clSet) << std::endl;
+        }
+#ifdef ME_PRINT_WARNINGS
+        if( addedLemmas>10000 ){
+          Debug("fmf-exit") << std::endl;
+          debugPrint("fmf-exit");
+          exit( 0 );
         }
-      }
-#ifdef ME_PRINT_PROCESS_TIMES
-      Notice() << "Added Lemmas = " << addedLemmas << std::endl;
 #endif
-      if( addedLemmas==0 ){
-        //debugPrint("fmf-consistent");
-        //for( std::map< Node, UfModel >::iterator it = d_uf_model.begin(); it != d_uf_model.end(); ++it ){
-        //  it->second.simplify();
-        //}
-        Debug("fmf-consistent") << std::endl;
-        debugPrint("fmf-consistent");
       }
     }
-    d_quantEngine->flushLemmas( &d_th->getOutputChannel() );
+    if( addedLemmas==0 ){
+      //CVC4 will answer SAT
+      Debug("fmf-consistent") << std::endl;
+      debugPrint("fmf-consistent");
+    }else{
+      //otherwise, the search will continue
+      d_quantEngine->flushLemmas( &d_quantEngine->getOutputChannel() );
+    }
   }
 }
 
@@ -611,19 +462,31 @@ void ModelEngine::assertNode( Node f ){
 
 }
 
-bool ModelEngine::useModel() {
-  return Options::current()->fmfModelBasedInst;
+bool ModelEngine::optOneInstPerQuantRound(){
+  return Options::current()->fmfOneInstPerRound;
+}
+
+bool ModelEngine::optUseRelevantDomain(){
+  return Options::current()->fmfRelevantDomain;
+}
+
+bool ModelEngine::optOneQuantPerRound(){
+#ifdef ONE_QUANT_PER_ROUND
+  return true;
+#else
+  return false;
+#endif
 }
 
-bool ModelEngine::initializeQuantifier( Node f ){
+int ModelEngine::initializeQuantifier( Node f ){
   if( d_quant_init.find( f )==d_quant_init.end() ){
     d_quant_init[f] = true;
     Debug("inst-fmf-init") << "Initialize " << f << std::endl;
     //add the model basis instantiation
     // This will help produce the necessary information for model completion.
-    // We do this by extending distinguish ground assertions (those 
+    // We do this by extending distinguish ground assertions (those
     //   containing terms with "model basis" attribute) to hold for all cases.
-    
+
     ////first, check if any variables are required to be equal
     //for( std::map< Node, bool >::iterator it = d_quantEngine->d_phase_reqs[f].begin();
     //    it != d_quantEngine->d_phase_reqs[f].end(); ++it ){
@@ -632,747 +495,167 @@ bool ModelEngine::initializeQuantifier( Node f ){
     //    Notice() << "Unhandled phase req: " << n << std::endl;
     //  }
     //}
-
+    std::vector< Node > ics;
     std::vector< Node > terms;
     for( int j=0; j<(int)f[0].getNumChildren(); j++ ){
-      terms.push_back( getModelBasisTerm( f[0][j].getType() ) );
+      Node ic = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );
+      Node t = d_quantEngine->getTermDatabase()->getModelBasisTerm( ic.getType() );
+      ics.push_back( ic );
+      terms.push_back( t );
+      //calculate the basis match for f
+      d_builder.d_quant_basis_match[f].d_map[ ic ] = t;
     }
     ++(d_statistics.d_num_quants_init);
+    //register model basis body
+    Node n = d_quantEngine->getTermDatabase()->getCounterexampleBody( f );
+    Node gn = n.substitute( ics.begin(), ics.end(), terms.begin(), terms.end() );
+    d_quantEngine->getTermDatabase()->registerModelBasis( n, gn );
+    //add model basis instantiation
     if( d_quantEngine->addInstantiation( f, terms ) ){
-      return false;
+      return 1;
     }else{
-      //usually shouldn't happen
+      //shouldn't happen usually, but will occur if x != y is a required literal for f.
       //Notice() << "No model basis for " << f << std::endl;
       ++(d_statistics.d_num_quants_init_fail);
     }
   }
-  return true;
-}
-
-void ModelEngine::buildRepresentatives(){
-  d_ra.clear();
-  //collect all representatives for all types and store as representative alphabet
-  for( int i=0; i<d_ss->getNumCardinalityTypes(); i++ ){
-    TypeNode tn = d_ss->getCardinalityType( i );
-    std::vector< Node > reps;
-    d_ss->getRepresentatives( tn, reps );
-    Assert( !reps.empty() );
-    //if( (int)reps.size()!=d_ss->getCardinality( tn ) ){
-    //  Notice() << "InstStrategyFinteModelFind::processResetInstantiationRound: Bad representatives for type." << std::endl;
-    //  Notice() << "   " << tn << " has cardinality " << d_ss->getCardinality( tn );
-    //  Notice() << " but only " << (int)reps.size() << " were given." << std::endl;
-    //  Unimplemented( 27 );
-    //}
-    Debug("fmf-model-debug") << "   " << tn << " -> " << reps.size() << std::endl;
-    Debug("fmf-model-debug") << "      ";
-    for( int i=0; i<(int)reps.size(); i++ ){
-      Debug("fmf-model-debug") << reps[i] << " ";
-    }
-    Debug("fmf-model-debug") << std::endl;
-    //set them in the alphabet
-    d_ra.set( tn, reps );
-#ifdef ME_PRINT_PROCESS_TIMES
-    Notice() << tn << " has " << reps.size() << " representatives. " << std::endl;
-#endif
-  }
+  return 0;
 }
 
-void ModelEngine::initializeModel(){
-  d_uf_model.clear();
-  d_quant_sat.clear();
-  for( int k=0; k<2; k++ ){
-    d_pro_con_quant[k].clear();
-  }
-
-  ////now analyze quantifiers (temporary)
-  //for( int i=0; i<(int)d_quantEngine->getNumAssertedQuantifiers(); i++ ){
-  //  Node f = d_quantEngine->getAssertedQuantifier( i );
-  //  Debug("fmf-model-req") << "Phase requirements for " << f << ": " << std::endl;
-  //  for( std::map< Node, bool >::iterator it = d_quantEngine->d_phase_reqs[f].begin();
-  //       it != d_quantEngine->d_phase_reqs[f].end(); ++it ){
-  //    Node n = it->first;
-  //    Debug("fmf-model-req") << "   " << n << " -> " << it->second << std::endl;
-  //    if( n.getKind()==APPLY_UF ){
-  //      processPredicate( f, n, it->second );
-  //    }else if( n.getKind()==EQUAL ){
-  //      processEquality( f, n, it->second );
-  //    }
-  //  }
-  //}
-  for( int i=0; i<(int)d_quantEngine->getNumAssertedQuantifiers(); i++ ){
-    Node f = d_quantEngine->getAssertedQuantifier( i );
-    initializeUf( f[1] );
-    //register model basis terms
-    std::vector< Node > vars;
-    std::vector< Node > subs;
-    for( int j=0; j<(int)f[0].getNumChildren(); j++ ){
-      vars.push_back( d_quantEngine->getInstantiationConstant( f, j ) );
-      subs.push_back( getModelBasisTerm( f[0][j].getType() ) );
-    }
-    Node n = d_quantEngine->getCounterexampleBody( f );
-    Node gn = n.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
-    registerModelBasis( n, gn );
-  }
-}
-
-void ModelEngine::analyzeQuantifiers(){
-  int quantSatInit = 0;
-  int nquantSatInit = 0;
-  //analyze the preferences of each quantifier
-  for( int i=0; i<(int)d_quantEngine->getNumAssertedQuantifiers(); i++ ){
-    Node f = d_quantEngine->getAssertedQuantifier( i );
-    Debug("fmf-model-prefs") << "Analyze quantifier " << f << std::endl;
-    std::vector< Node > pro_con[2];
-    std::vector< Node > pro_con_patterns[2];
-    //check which model basis terms have good and bad definitions according to f
-    for( std::map< Node, bool >::iterator it = d_quantEngine->d_phase_reqs[f].begin();
-         it != d_quantEngine->d_phase_reqs[f].end(); ++it ){
-      Node n = it->first;
-      Node gn = d_model_basis[n];
-      Debug("fmf-model-req") << "   Req: " << n << " -> " << it->second << std::endl;
-      int pref = 0;
-      bool isConst = true;
-      std::vector< Node > uf_terms;
-      std::vector< Node > uf_term_patterns;
-      if( gn.getKind()==APPLY_UF ){
-        if( d_quantEngine->getEqualityQuery()->hasTerm( gn ) ){
-          uf_terms.push_back( gn );
-          uf_term_patterns.push_back( n );
-          bool phase = areEqual( gn, NodeManager::currentNM()->mkConst( true ) );
-          pref = phase!=it->second ? 1 : -1;
-        }
-      }else if( gn.getKind()==EQUAL ){
-        bool success = true;
-        for( int j=0; j<2; j++ ){
-          if( n[j].getKind()==APPLY_UF ){
-            Node op = gn[j].getOperator();
-            if( d_uf_model.find( op )!=d_uf_model.end() ){
-              Assert( gn[j].getKind()==APPLY_UF );
-              uf_terms.push_back( gn[j] );
-              uf_term_patterns.push_back( n[j] );
-            }else{
-              //found undefined uf operator
-              success = false;
-            }
-          }else if( n[j].hasAttribute(InstConstantAttribute()) ){
-            isConst = false;
-          }
-        }
-        if( success && !uf_terms.empty() ){
-          if( (!it->second && areEqual( gn[0], gn[1] )) || (it->second && areDisequal( gn[0], gn[1] )) ){
-            pref = 1;
-          }else if( (it->second && areEqual( gn[0], gn[1] )) || (!it->second && areDisequal( gn[0], gn[1] )) ){
-            pref = -1;
-          }
-        }
-      }
-      if( pref!=0 ){
-        Debug("fmf-model-prefs") << "  It is " << ( pref==1 ? "pro" : "con" );
-        Debug("fmf-model-prefs") << " the definition of " << n << std::endl;
-        if( pref==1 ){
-          if( isConst ){
-            for( int j=0; j<(int)uf_terms.size(); j++ ){
-              //the only uf that is initialized are those that are constant
-              Node op = uf_terms[j].getOperator();
-              Assert( d_uf_model.find( op )!=d_uf_model.end() );
-              if( !d_uf_model[op].isConstant() ){
-                isConst = false;
-                break;
-              }
-            }
-            if( isConst ){
-              d_quant_sat[f] = true;
-              //we only need to consider current term definition(s) for this quantifier to be satisified, ignore the others
-              for( int k=0; k<2; k++ ){
-                pro_con[k].clear();
-                pro_con_patterns[k].clear();
-              } 
-              //instead, just note to the model for each uf term that f is pro its definition
-              for( int j=0; j<(int)uf_terms.size(); j++ ){
-                Node op = uf_terms[j].getOperator();
-                d_uf_model[op].d_reconsider_model = false;
-              }
-            }
-          }
-        }
-        if( d_quant_sat.find( f )!=d_quant_sat.end() ){
-          Debug("fmf-model-prefs") << "  * Constant SAT due to definition of " << n << std::endl;
-          break;
-        }else{
-          int pcIndex = pref==1 ? 0 : 1;
-          for( int j=0; j<(int)uf_terms.size(); j++ ){
-            pro_con[pcIndex].push_back( uf_terms[j] );
-            pro_con_patterns[pcIndex].push_back( uf_term_patterns[j] );
-          }
-        }
-      }
-    }
-    if( d_quant_sat.find( f )!=d_quant_sat.end() ){
-      quantSatInit++;
-      d_statistics.d_pre_sat_quant += quantSatInit;
-    }else{
-      nquantSatInit++;
-      d_statistics.d_pre_nsat_quant += quantSatInit;
-    }
-    //add quantifier's preferences to vector
-    for( int k=0; k<2; k++ ){
-      for( int j=0; j<(int)pro_con[k].size(); j++ ){
-        Node op = pro_con[k][j].getOperator();
-        d_uf_model[op].setValuePreference( f, pro_con[k][j], k==0 );
-        d_pro_con_quant[k][ f ].push_back( pro_con_patterns[k][j] );
-      }
-    }
-  }
-  Debug("fmf-model-prefs") << "Pre-Model Completion: Quantifiers SAT: " << quantSatInit << " / " << (quantSatInit+nquantSatInit) << std::endl;
-}
-
-int ModelEngine::instantiateQuantifier( Node f ){
+int ModelEngine::exhaustiveInstantiate( Node f, bool useRelInstDomain ){
+  int tests = 0;
   int addedLemmas = 0;
+  int triedLemmas = 0;
   Debug("inst-fmf-ei") << "Add matches for " << f << "..." << std::endl;
   Debug("inst-fmf-ei") << "   Instantiation Constants: ";
   for( size_t i=0; i<f[0].getNumChildren(); i++ ){
-    Debug("inst-fmf-ei") << d_quantEngine->getInstantiationConstant( f, i ) << " ";
+    Debug("inst-fmf-ei") << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i ) << " ";
   }
   Debug("inst-fmf-ei") << std::endl;
-  for( int k=0; k<2; k++ ){
-    Debug("inst-fmf-ei") << "  " << ( k==0 ? "Pro" : "Con" ) << " definitions:" << std::endl;
-    for( int i=0; i<(int)d_pro_con_quant[k][f].size(); i++ ){
-      Debug("inst-fmf-ei") << "    " << d_pro_con_quant[k][f][i] << std::endl;
-    }
-  }
-  if( d_pro_con_quant[0][f].empty() ){
-    Debug("inst-fmf-ei") << "WARNING: " << f << " has no pros for default literal definitions" << std::endl;
-  }
-  d_eval_failed_lits.clear();
-  d_eval_failed.clear();
-  d_eval_term_model.clear();
-  //d_eval_term_vals.clear();
-  //d_eval_term_fv_deps.clear();
-  RepAlphabetIterator riter( d_quantEngine, f, this );
-  increment( &riter );
-#ifdef ONE_INST_PER_QUANT_PER_ROUND
-  while( !riter.isFinished() && addedLemmas==0 ){
-#else
-  while( !riter.isFinished() ){
+  if( d_builder.d_quant_selection_lits[f].empty() ){
+    Debug("inst-fmf-ei") << "WARNING: " << f << " has no model literal definitions (is f clausified?)" << std::endl;
+#ifdef ME_PRINT_WARNINGS
+    Message() << "WARNING: " << f << " has no model literal definitions (is f clausified?)" << std::endl;
 #endif
-    InstMatch m;
-    riter.getMatch( d_quantEngine, m );
-    Debug("fmf-model-eval") << "* Add instantiation " << std::endl;
-    riter.d_inst_tried++;
-    if( d_quantEngine->addInstantiation( f, m ) ){
-      addedLemmas++;
-    }
-    riter.increment( d_quantEngine );
-    increment( &riter );
-  }
-  if( Debug.isOn("inst-fmf-ei") ){
-    int totalInst = 1;
-    for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
-      totalInst = totalInst * (int)getReps()->d_type_reps[ f[0][i].getType() ].size();
-    }
-    Debug("inst-fmf-ei") << "Finished: " << std::endl;
-    Debug("inst-fmf-ei") << "   Inst Skipped: " << (totalInst-riter.d_inst_tried) << std::endl;
-    Debug("inst-fmf-ei") << "   Inst Tried: " << riter.d_inst_tried << std::endl;
-    Debug("inst-fmf-ei") << "   Inst Added: " << addedLemmas << std::endl;
-    Debug("inst-fmf-ei") << "   # Tests: " << riter.d_inst_tests << std::endl;
-  }
-  return addedLemmas;
-}
-
-void ModelEngine::registerModelBasis( Node n, Node gn ){
-  if( d_model_basis.find( n )==d_model_basis.end() ){
-    d_model_basis[n] = gn;
-    for( int i=0; i<(int)n.getNumChildren(); i++ ){
-      registerModelBasis( n[i], gn[i] );
-    }
-  }
-}
-
-Node ModelEngine::getArbitraryElement( TypeNode tn, std::vector< Node >& exclude ){
-  Node retVal;
-  if( tn==NodeManager::currentNM()->booleanType() ){
-    if( exclude.empty() ){
-      retVal = NodeManager::currentNM()->mkConst( false );
-    }else if( exclude.size()==1 ){
-      retVal = NodeManager::currentNM()->mkConst( areEqual( exclude[0], NodeManager::currentNM()->mkConst( false ) ) );
-    }
-  }else if( d_ra.d_type_reps.find( tn )!=d_ra.d_type_reps.end() ){
-    for( int i=0; i<(int)d_ra.d_type_reps[tn].size(); i++ ){
-      if( std::find( exclude.begin(), exclude.end(), d_ra.d_type_reps[tn][i] )==exclude.end() ){
-        retVal = d_ra.d_type_reps[tn][i];
-        break;
-      }
-    }
-  }
-  if( !retVal.isNull() ){
-    return d_quantEngine->getEqualityQuery()->getRepresentative( retVal );
   }else{
-    return Node::null();
-  }
-}
-
-Node ModelEngine::getModelBasisTerm( TypeNode tn, int i ){
-  return d_ss->getCardinalityTerm( tn );
-}
-
-Node ModelEngine::getModelBasisApplyUfTerm( Node op ){
-  if( d_model_basis_term.find( op )==d_model_basis_term.end() ){
-    TypeNode t = op.getType();
-    std::vector< Node > children;
-    children.push_back( op );
-    for( int i=0; i<(int)t.getNumChildren()-1; i++ ){
-      children.push_back( getModelBasisTerm( t[i] ) );
-    }
-    d_model_basis_term[op] = NodeManager::currentNM()->mkNode( APPLY_UF, children );
-  }
-  return d_model_basis_term[op];
-}
-
-bool ModelEngine::isModelBasisTerm( Node op, Node n ){
-  if( n.getOperator()==op ){
-    for( int i=0; i<(int)n.getNumChildren(); i++ ){
-      if( !n[i].getAttribute(ModelBasisAttribute()) ){
-        return false;
-      }
-    }
-    return true;
-  }else{
-    return false;
-  }
-}
-
-void ModelEngine::initializeUf( Node n ){
-  std::vector< Node > terms;
-  collectUfTerms( n, terms );
-  for( int i=0; i<(int)terms.size(); i++ ){
-    initializeUfModel( terms[i].getOperator() );
-  }
-}
-
-void ModelEngine::collectUfTerms( Node n, std::vector< Node >& terms ){
-  if( n.getKind()==APPLY_UF ){
-    terms.push_back( n );
-  }
-  for( int i=0; i<(int)n.getNumChildren(); i++ ){
-    collectUfTerms( n[i], terms );
-  }
-}
-
-void ModelEngine::initializeUfModel( Node op ){
-  if( d_uf_model.find( op )==d_uf_model.end() ){
-    TypeNode tn = op.getType();
-    tn = tn[ (int)tn.getNumChildren()-1 ];
-    if( tn==NodeManager::currentNM()->booleanType() || uf::StrongSolverTheoryUf::isRelevantType( tn ) ){
-      d_uf_model[ op ] = UfModel( op, this );
-    }
-  }
-}
-
-void ModelEngine::makeEvalTermModel( Node n ){
-  if( d_eval_term_model.find( n )==d_eval_term_model.end() ){
-    makeEvalTermIndexOrder( n );
-    if( !d_eval_term_use_default_model[n] ){
-      Node op = n.getOperator();
-      d_eval_term_model[n] = UfModelTreeOrdered( op, d_eval_term_index_order[n] );
-      d_uf_model[op].makeModel( d_quantEngine, d_eval_term_model[n] );
-      Debug("fmf-model-index-order") << "Make model for " << n << " : " << std::endl;
-      d_eval_term_model[n].debugPrint( "fmf-model-index-order", d_quantEngine, 2 );
-    }
-  }
-}
-
-struct sortGetMaxVariableNum {
-  std::map< Node, int > d_max_var_num;
-  int computeMaxVariableNum( Node n ){
-    if( n.getKind()==INST_CONSTANT ){
-      return n.getAttribute(InstVarNumAttribute());
-    }else if( n.hasAttribute(InstConstantAttribute()) ){
-      int maxVal = -1;
-      for( int i=0; i<(int)n.getNumChildren(); i++ ){
-        int val = getMaxVariableNum( n[i] );
-        if( val>maxVal ){
-          maxVal = val;
-        }
-      }
-      return maxVal;
-    }else{
-      return -1;
-    }
-  }
-  int getMaxVariableNum( Node n ){
-    std::map< Node, int >::iterator it = d_max_var_num.find( n );
-    if( it==d_max_var_num.end() ){
-      int num = computeMaxVariableNum( n );
-      d_max_var_num[n] = num;
-      return num;
-    }else{
-      return it->second;
-    }
-  }
-  bool operator() (Node i,Node j) { return (getMaxVariableNum(i)<getMaxVariableNum(j));}
-};
-
-void ModelEngine::makeEvalTermIndexOrder( Node n ){
-  if( d_eval_term_index_order.find( n )==d_eval_term_index_order.end() ){
-    //sort arguments in order of least significant vs. most significant variable in default ordering
-    std::map< Node, std::vector< int > > argIndex;
-    std::vector< Node > args;
-    for( int i=0; i<(int)n.getNumChildren(); i++ ){
-      if( argIndex.find( n[i] )==argIndex.end() ){
-        args.push_back( n[i] );
-      }
-      argIndex[n[i]].push_back( i );
-    }
-    sortGetMaxVariableNum sgmvn;
-    std::sort( args.begin(), args.end(), sgmvn );
-    for( int i=0; i<(int)args.size(); i++ ){
-      for( int j=0; j<(int)argIndex[ args[i] ].size(); j++ ){
-        d_eval_term_index_order[n].push_back( argIndex[ args[i] ][j] );
-      }
-    }
-    bool useDefault = true;
-    for( int i=0; i<(int)d_eval_term_index_order[n].size(); i++ ){
-      if( i!=d_eval_term_index_order[n][i] ){
-        useDefault = false;
-        break;
-      }
-    }
-    d_eval_term_use_default_model[n] = useDefault;
-    Debug("fmf-model-index-order") << "Will consider the following index ordering for " << n << " : ";
-    for( int i=0; i<(int)d_eval_term_index_order[n].size(); i++ ){
-      Debug("fmf-model-index-order") << d_eval_term_index_order[n][i] << " ";
-    }
-    Debug("fmf-model-index-order") << std::endl;
-  }
-}
-
-//void ModelEngine::processPredicate( Node f, Node p, bool phase ){
-//  Node op = p.getOperator();
-//  initializeUfModel( op );
-//  d_uf_model[ op ].addRequirement( f, p, phase );
-//}
-//
-//void ModelEngine::processEquality( Node f, Node eq, bool phase ){
-//  for( int i=0; i<2; i++ ){
-//    int j = i==0 ? 1 : 0;
-//    if( eq[i].getKind()==APPLY_UF && eq[i].hasAttribute(InstConstantAttribute()) ){
-//      Node op = eq[i].getOperator();
-//      initializeUfModel( op );
-//      d_uf_model[ op ].addEqRequirement( f, eq[i], eq[j], phase );
-//    }
-//  }
-//}
-
-void ModelEngine::increment( RepAlphabetIterator* rai ){
-  if( useModel() ){
-    bool success;
-    do{
-      success = true;
-      if( !rai->isFinished() ){
-        //see if instantiation is already true in current model
-        Debug("fmf-model-eval") << "Evaulating ";
-        rai->debugPrintSmall("fmf-model-eval");
-        //calculate represenative terms we are currently considering
-        rai->calculateTerms( d_quantEngine );
-        rai->d_inst_tests++;
-        //if eVal is not (int)rai->d_index.size(), then the instantiation is already true in the model,
-        // and eVal is the highest index in rai which we can safely iterate
-        int depIndex;
-        if( evaluate( rai, d_quantEngine->getCounterexampleBody( rai->d_f ), depIndex )==1 ){
-          Debug("fmf-model-eval") << "  Returned success with depIndex = " << depIndex << std::endl;
-          //Notice() << "Returned eVal = " << eVal << "/" << rai->d_index.size() << std::endl;
-          if( depIndex<(int)rai->d_index.size() ){
-#ifdef DISABLE_EVAL_SKIP_MULTIPLE
-            depIndex = (int)rai->d_index.size()-1;
-#endif
-            rai->increment2( d_quantEngine, depIndex );
-            success = false;
+    Debug("inst-fmf-ei") << "  Model literal definitions:" << std::endl;
+    for( size_t i=0; i<d_builder.d_quant_selection_lits[f].size(); i++ ){
+      Debug("inst-fmf-ei") << "    " << d_builder.d_quant_selection_lits[f][i] << std::endl;
+    }
+  }
+  RepSetIterator riter( f, d_quantEngine->getModel() );
+  //set the domain for the iterator (the sufficient set of instantiations to try)
+  if( useRelInstDomain ){
+    riter.setDomain( d_rel_domain.d_quant_inst_domain[f] );
+  }
+  RepSetEvaluator reval( d_quantEngine->getModel(), &riter );
+  while( !riter.isFinished() && ( addedLemmas==0 || !optOneInstPerQuantRound() ) ){
+    d_testLemmas++;
+    if( d_builder.optUseModel() ){
+      //see if instantiation is already true in current model
+      Debug("fmf-model-eval") << "Evaluating ";
+      riter.debugPrintSmall("fmf-model-eval");
+      Debug("fmf-model-eval") << "Done calculating terms." << std::endl;
+      tests++;
+      //if evaluate(...)==1, then the instantiation is already true in the model
+      //  depIndex is the index of the least significant variable that this evaluation relies upon
+      int depIndex = riter.getNumTerms()-1;
+      int eval = reval.evaluate( d_quantEngine->getTermDatabase()->getCounterexampleBody( f ), depIndex );
+      if( eval==1 ){
+        Debug("fmf-model-eval") << "  Returned success with depIndex = " << depIndex << std::endl;
+        riter.increment2( depIndex );
+      }else{
+        Debug("fmf-model-eval") << "  Returned " << (eval==-1 ? "failure" : "unknown") << ", depIndex = " << depIndex << std::endl;
+        InstMatch m;
+        riter.getMatch( d_quantEngine, m );
+        Debug("fmf-model-eval") << "* Add instantiation " << m << std::endl;
+        triedLemmas++;
+        d_triedLemmas++;
+        if( d_quantEngine->addInstantiation( f, m ) ){
+          addedLemmas++;
+#ifdef EVAL_FAIL_SKIP_MULTIPLE
+          if( eval==-1 ){
+            riter.increment2( depIndex );
+          }else{
+            riter.increment();
           }
+#else
+          riter.increment();
+#endif
         }else{
-          Debug("fmf-model-eval") << "  Returned failure." << std::endl;
-        }
-      }
-    }while( !success );
-  }
-}
-
-//if evaluate( rai, n, phaseReq ) = eVal,
-// if eVal = rai->d_index.size()
-//   then the formula n instantiated with rai cannot be proven to be equal to phaseReq
-// otherwise,
-//   each n{rai->d_index[0]/x_0...rai->d_index[eVal]/x_eVal, */x_(eVal+1) ... */x_n } is equal to phaseReq in the current model
-int ModelEngine::evaluate( RepAlphabetIterator* rai, Node n, int& depIndex ){
-  ++(d_statistics.d_eval_formulas);
-  //Debug("fmf-model-eval-debug") << "Evaluate " << n << " " << phaseReq << std::endl;
-  if( n.getKind()==NOT ){
-    int val = evaluate( rai, n[0], depIndex );
-    return val==1 ? -1 : ( val==-1 ? 1 : 0 );
-  }else if( n.getKind()==OR || n.getKind()==AND || n.getKind()==IMPLIES ){
-    int baseVal = n.getKind()==AND ? 1 : -1;
-    int eVal = baseVal;
-    int posDepIndex = (int)rai->d_index.size();
-    int negDepIndex = -1;
-    for( int i=0; i<(int)n.getNumChildren(); i++ ){
-      //evaluate subterm
-      int childDepIndex;
-      Node nn = ( i==0 && n.getKind()==IMPLIES ) ? n[i].notNode() : n[i];
-      int eValT = evaluate( rai, nn, childDepIndex );
-      if( eValT==baseVal ){
-        if( eVal==baseVal ){
-          if( childDepIndex>negDepIndex ){
-            negDepIndex = childDepIndex;
-          }
-        }
-      }else if( eValT==-baseVal ){
-        eVal = -baseVal;
-        if( childDepIndex<posDepIndex ){
-          posDepIndex = childDepIndex;
-          if( posDepIndex==-1 ){
-            break;
-          }
-        }
-      }else if( eValT==0 ){
-        if( eVal==baseVal ){
-          eVal = 0;
+          Debug("ajr-temp") << "* Failed Add instantiation " << m << std::endl;
+          riter.increment();
         }
       }
-    }
-    if( eVal!=0 ){
-      depIndex = eVal==-baseVal ? posDepIndex : negDepIndex;
-      return eVal;
-    }else{
-      return 0;
-    }
-  }else if( n.getKind()==IFF || n.getKind()==XOR ){
-    int depIndex1;
-    int eVal = evaluate( rai, n[0], depIndex1 );
-    if( eVal!=0 ){
-      int depIndex2;
-      int eVal2 = evaluate( rai, n.getKind()==XOR ? n[1].notNode() : n[1], depIndex2 );
-      if( eVal2!=0 ){
-        depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
-        return eVal==eVal2 ? 1 : -1;
-      }
-    }
-    return 0;
-  }else if( n.getKind()==ITE ){
-    int depIndex1;
-    int eVal = evaluate( rai, n[0], depIndex1 );
-    if( eVal==0 ){
-      //DO_THIS: evaluate children to see if they are the same value?
-      return 0;
     }else{
-      int depIndex2;
-      int eValT = evaluate( rai, n[eVal==1 ? 1 : 2], depIndex2 );
-      depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
-      return eValT;
-    }
-  }else if( n.getKind()==FORALL ){
-    return 0;
-  }else{
-    ////if we know we will fail again, immediately return
-    //if( d_eval_failed.find( n )!=d_eval_failed.end() ){
-    //  if( d_eval_failed[n] ){
-    //    return -1;
-    //  }
-    //}
-    //Debug("fmf-model-eval-debug") << "Evaluate literal " << n << std::endl;
-    //this should be a literal
-    Node gn = n.substitute( rai->d_ic.begin(), rai->d_ic.end(), rai->d_terms.begin(), rai->d_terms.end() );
-    //Debug("fmf-model-eval-debug") << "  Ground version = " << gn << std::endl;
-    int retVal = 0;
-    std::vector< Node > fv_deps;
-    if( n.getKind()==APPLY_UF ){
-      //case for boolean predicates
-      Node val = evaluateTerm( n, gn, fv_deps );
-      if( d_quantEngine->getEqualityQuery()->hasTerm( val ) ){
-        if( areEqual( val, NodeManager::currentNM()->mkConst( true ) ) ){
-          retVal = 1;
-        }else{
-          retVal = -1;
-        }
-      }
-    }else if( n.getKind()==EQUAL ){
-      //case for equality
-      retVal = evaluateEquality( n[0], n[1], gn[0], gn[1], fv_deps );
-    }
-    if( retVal!=0 ){
-      int maxIndex = -1;
-      for( int i=0; i<(int)fv_deps.size(); i++ ){
-        int index = rai->d_var_order[ fv_deps[i].getAttribute(InstVarNumAttribute()) ];
-        if( index>maxIndex ){
-          maxIndex = index;
-          if( index==(int)rai->d_index.size()-1 ){
-            break;
-          }
-        }
+      InstMatch m;
+      riter.getMatch( d_quantEngine, m );
+      Debug("fmf-model-eval") << "* Add instantiation " << std::endl;
+      triedLemmas++;
+      d_triedLemmas++;
+      if( d_quantEngine->addInstantiation( f, m ) ){
+        addedLemmas++;
       }
-      Debug("fmf-model-eval-debug") << "Evaluate literal: return " << retVal << ", depends = " << maxIndex << std::endl;
-      depIndex = maxIndex;
+      riter.increment();
     }
-    return retVal;
-  }
-}
-
-int ModelEngine::evaluateEquality( Node n1, Node n2, Node gn1, Node gn2, std::vector< Node >& fv_deps ){
-  ++(d_statistics.d_eval_eqs);
-  Debug("fmf-model-eval-debug") << "Evaluate equality: " << std::endl;
-  Debug("fmf-model-eval-debug") << "   " << n1 << " = " << n2 << std::endl;
-  Debug("fmf-model-eval-debug") << "   " << gn1 << " = " << gn2 << std::endl;
-  Node val1 = evaluateTerm( n1, gn1, fv_deps );
-  Node val2 = evaluateTerm( n2, gn2, fv_deps );
-  Debug("fmf-model-eval-debug") << "   Values :  ";
-  printRepresentative( "fmf-model-eval-debug", d_quantEngine, val1 );
-  Debug("fmf-model-eval-debug") <<  " = ";
-  printRepresentative( "fmf-model-eval-debug", d_quantEngine, val2 );
-  Debug("fmf-model-eval-debug") << std::endl;
-  int retVal = 0;
-  if( areEqual( val1, val2 ) ){
-    retVal = 1;
-  }else if( areDisequal( val1, val2 ) ){
-    retVal = -1;
-  }
-  if( retVal!=0 ){
-    Debug("fmf-model-eval-debug") << "   ---> Success, value = " << (retVal==1) << std::endl;
-  }else{
-    Debug("fmf-model-eval-debug") << "   ---> Failed" << std::endl;
-  }
-  Debug("fmf-model-eval-debug") << "       Value depends on variables: ";
-  for( int i=0; i<(int)fv_deps.size(); i++ ){
-    Debug("fmf-model-eval-debug") << fv_deps[i] << " ";
   }
-  Debug("fmf-model-eval-debug") << std::endl;
-  return retVal;
-}
-
-Node ModelEngine::evaluateTerm( Node n, Node gn, std::vector< Node >& fv_deps ){
-  if( n.hasAttribute(InstConstantAttribute()) ){
-    if( n.getKind()==INST_CONSTANT ){
-      fv_deps.push_back( n );
-      return gn;
-    //}else if( d_eval_term_fv_deps.find( n )!=d_eval_term_fv_deps.end() && 
-    //          d_eval_term_fv_deps[n].find( gn )!=d_eval_term_fv_deps[n].end() ){
-    //  fv_deps.insert( fv_deps.end(), d_eval_term_fv_deps[n][gn].begin(), d_eval_term_fv_deps[n][gn].end() );
-    //  return d_eval_term_vals[gn];
-    }else{
-      //Debug("fmf-model-eval-debug") << "Evaluate term " << n << " (" << gn << ")" << std::endl;
-      //first we must evaluate the arguments
-      Node val = gn;
-      if( n.getKind()==APPLY_UF ){
-        Node op = gn.getOperator();
-        //if it is a defined UF, then consult the interpretation
-        Node gnn = gn;
-        ++(d_statistics.d_eval_uf_terms);
-        int depIndex = 0;
-        //first we must evaluate the arguments
-        bool childrenChanged = false;
-        std::vector< Node > children;
-        children.push_back( op );
-        std::map< int, std::vector< Node > > children_var_deps;
-        //for each argument, calculate its value, and the variables its value depends upon
-        for( int i=0; i<(int)n.getNumChildren(); i++ ){
-          Node nn = evaluateTerm( n[i], gn[i], children_var_deps[i] );
-          children.push_back( nn );
-          childrenChanged = childrenChanged || nn!=gn[i];
-        }
-        //remake gn if changed
-        if( childrenChanged ){
-          gnn = NodeManager::currentNM()->mkNode( APPLY_UF, children );
-        }
-        if( d_uf_model.find( op )!=d_uf_model.end() ){
-#ifdef USE_INDEX_ORDERING
-          //make the term model specifically for n
-          makeEvalTermModel( n );
-          //now, consult the model
-          if( d_eval_term_use_default_model[n] ){
-            val = d_uf_model[op].d_tree.getValue( d_quantEngine, gnn, depIndex );
-          }else{
-            val = d_eval_term_model[ n ].getValue( d_quantEngine, gnn, depIndex );
-          }
-          //Debug("fmf-model-eval-debug") << "Evaluate term " << n << " (" << gn << ", " << gnn << ")" << std::endl;
-          //d_eval_term_model[ n ].debugPrint("fmf-model-eval-debug", d_quantEngine );
-          Assert( !val.isNull() );
-#else
-          //now, consult the model
-          val = d_uf_model[op].d_tree.getValue( d_quantEngine, gnn, depIndex );
-#endif
-        }else{
-          d_eval_term_use_default_model[n] = true;
-          val = gnn;
-          depIndex = (int)n.getNumChildren();
-        }
-        Debug("fmf-model-eval-debug") << "Evaluate term " << n << " = " << gn << " = " << gnn << " = ";
-        printRepresentative( "fmf-model-eval-debug", d_quantEngine, val );
-        Debug("fmf-model-eval-debug") << ", depIndex = " << depIndex << std::endl;
-        if( !val.isNull() ){
-#ifdef USE_INDEX_ORDERING
-          for( int i=0; i<depIndex; i++ ){
-            int index = d_eval_term_use_default_model[n] ? i : d_eval_term_index_order[n][i];
-            Debug("fmf-model-eval-debug") << "Add variables from " << index << "..." << std::endl;
-            fv_deps.insert( fv_deps.end(), children_var_deps[index].begin(),
-                            children_var_deps[index].end() );
-          }
-#else
-          //calculate the free variables that the value depends on : take those in children_var_deps[0...depIndex-1]
-          for( std::map< int, std::vector< Node > >::iterator it = children_var_deps.begin(); it != children_var_deps.end(); ++it ){
-            if( it->first<depIndex ){
-              fv_deps.insert( fv_deps.end(), it->second.begin(), it->second.end() );
-            }
-          }
-#endif
-        }
-        ////cache the result
-        //d_eval_term_vals[gn] = val;
-        //d_eval_term_fv_deps[n][gn].insert( d_eval_term_fv_deps[n][gn].end(), fv_deps.begin(), fv_deps.end() );
+  d_statistics.d_eval_formulas += reval.d_eval_formulas;
+  d_statistics.d_eval_eqs += reval.d_eval_eqs;
+  d_statistics.d_eval_uf_terms += reval.d_eval_uf_terms;
+  int totalInst = 1;
+  int relevantInst = 1;
+  for( size_t i=0; i<f[0].getNumChildren(); i++ ){
+    totalInst = totalInst * (int)d_quantEngine->getModel()->d_ra.d_type_reps[ f[0][i].getType() ].size();
+    relevantInst = relevantInst * (int)riter.d_domain[i].size();
+  }
+  d_totalLemmas += totalInst;
+  d_relevantLemmas += relevantInst;
+  Debug("inst-fmf-ei") << "Finished: " << std::endl;
+  Debug("inst-fmf-ei") << "   Inst Total: " << totalInst << std::endl;
+  Debug("inst-fmf-ei") << "   Inst Relevant: " << relevantInst << std::endl;
+  Debug("inst-fmf-ei") << "   Inst Tried: " << triedLemmas << std::endl;
+  Debug("inst-fmf-ei") << "   Inst Added: " << addedLemmas << std::endl;
+  Debug("inst-fmf-ei") << "   # Tests: " << tests << std::endl;
+///-----------
+#ifdef ME_PRINT_WARNINGS
+  if( addedLemmas>1000 ){
+    Notice() << "WARNING: many instantiations produced for " << f << ": " << std::endl;
+    Notice() << "   Inst Total: " << totalInst << std::endl;
+    Notice() << "   Inst Relevant: " << totalRelevant << std::endl;
+    Notice() << "   Inst Tried: " << triedLemmas << std::endl;
+    Notice() << "   Inst Added: " << addedLemmas << std::endl;
+    Notice() << "   # Tests: " << tests << std::endl;
+    Notice() << std::endl;
+    if( !d_builder.d_quant_selection_lits[f].empty() ){
+      Notice() << "  Model literal definitions:" << std::endl;
+      for( size_t i=0; i<d_builder.d_quant_selection_lits[f].size(); i++ ){
+        Notice() << "    " << d_builder.d_quant_selection_lits[f][i] << std::endl;
       }
-      return val;
+      Notice() << std::endl;
     }
-  }else{
-    return n;
-  }
-}
-
-void ModelEngine::clearEvalFailed( int index ){
-  for( int i=0; i<(int)d_eval_failed_lits[index].size(); i++ ){
-    d_eval_failed[ d_eval_failed_lits[index][i] ] = false;
   }
-  d_eval_failed_lits[index].clear();
-}
-
-bool ModelEngine::areEqual( Node a, Node b ){
-  return d_quantEngine->getEqualityQuery()->areEqual( a, b );
-}
-
-bool ModelEngine::areDisequal( Node a, Node b ){
-  return d_quantEngine->getEqualityQuery()->areDisequal( a, b );
+#endif
+///-----------
+  return addedLemmas;
 }
 
 void ModelEngine::debugPrint( const char* c ){
-  Debug( c ) << "---Current Model---" << std::endl;
-  Debug( c ) << "Representatives: " << std::endl;
-  d_ra.debugPrint( c, d_quantEngine );
   Debug( c ) << "Quantifiers: " << std::endl;
-  for( int i=0; i<(int)d_quantEngine->getNumAssertedQuantifiers(); i++ ){
-    Node f = d_quantEngine->getAssertedQuantifier( i );
+  for( int i=0; i<(int)d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+    Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
     Debug( c ) << "   ";
-    if( d_quant_sat.find( f )!=d_quant_sat.end() ){
+    if( d_builder.d_quant_sat.find( f )!=d_builder.d_quant_sat.end() ){
       Debug( c ) << "*SAT* ";
     }else{
       Debug( c ) << "      ";
     }
     Debug( c ) << f << std::endl;
   }
-  Debug( c ) << "Functions: " << std::endl;
-  for( std::map< Node, UfModel >::iterator it = d_uf_model.begin(); it != d_uf_model.end(); ++it ){
-    it->second.debugPrint( c );
-    Debug( c ) << std::endl;
-  }
+  //d_quantEngine->getModel()->debugPrint( c );
 }
 
 ModelEngine::Statistics::Statistics():
   d_inst_rounds("ModelEngine::Inst_Rounds", 0),
-  d_pre_sat_quant("ModelEngine::Status_quant_pre_sat", 0),
-  d_pre_nsat_quant("ModelEngine::Status_quant_pre_non_sat", 0),
   d_eval_formulas("ModelEngine::Eval_Formulas", 0 ),
   d_eval_eqs("ModelEngine::Eval_Equalities", 0 ),
   d_eval_uf_terms("ModelEngine::Eval_Uf_Terms", 0 ),
@@ -1380,8 +663,6 @@ ModelEngine::Statistics::Statistics():
   d_num_quants_init_fail("ModelEngine::Num_Quants_No_Basis", 0 )
 {
   StatisticsRegistry::registerStat(&d_inst_rounds);
-  StatisticsRegistry::registerStat(&d_pre_sat_quant);
-  StatisticsRegistry::registerStat(&d_pre_nsat_quant);
   StatisticsRegistry::registerStat(&d_eval_formulas);
   StatisticsRegistry::registerStat(&d_eval_eqs);
   StatisticsRegistry::registerStat(&d_eval_uf_terms);
@@ -1391,11 +672,11 @@ ModelEngine::Statistics::Statistics():
 
 ModelEngine::Statistics::~Statistics(){
   StatisticsRegistry::unregisterStat(&d_inst_rounds);
-  StatisticsRegistry::unregisterStat(&d_pre_sat_quant);
-  StatisticsRegistry::unregisterStat(&d_pre_nsat_quant);
   StatisticsRegistry::unregisterStat(&d_eval_formulas);
   StatisticsRegistry::unregisterStat(&d_eval_eqs);
   StatisticsRegistry::unregisterStat(&d_eval_uf_terms);
   StatisticsRegistry::unregisterStat(&d_num_quants_init);
   StatisticsRegistry::unregisterStat(&d_num_quants_init_fail);
 }
+
+
index cf6691918044305bd6b12e0f7c1a6595c5eaeaf8..b0113982664c37042f762c68bc82deb6caeb35bb 100644 (file)
@@ -11,7 +11,7 @@
  ** See the file COPYING in the top-level source directory for licensing
  ** information.\endverbatim
  **
- ** \brief Instantiation Engine classes
+ ** \brief Model Engine classes
  **/
 
 #include "cvc4_private.h"
@@ -21,6 +21,9 @@
 
 #include "theory/quantifiers_engine.h"
 #include "theory/quantifiers/theory_quantifiers.h"
+#include "theory/model.h"
+#include "theory/uf/theory_uf_model.h"
+#include "theory/quantifiers/relevant_domain.h"
 
 namespace CVC4 {
 namespace theory {
@@ -31,312 +34,87 @@ namespace uf{
 
 namespace quantifiers {
 
-/** this class stores a representative alphabet */
-class RepAlphabet {
-public:
-  RepAlphabet(){}
-  RepAlphabet( RepAlphabet& ra, QuantifiersEngine* qe );
-  ~RepAlphabet(){}
-  std::map< TypeNode, std::vector< Node > > d_type_reps;
-  std::map< Node, int > d_tmap;
-  /** clear the alphabet */
-  void clear(){
-    d_type_reps.clear();
-    d_tmap.clear();
-  }
-  /** set the representatives for type */
-  void set( TypeNode t, std::vector< Node >& reps );
-  /** returns index in d_type_reps for node n */
-  int getIndexFor( Node n ) { return d_tmap.find( n )!=d_tmap.end() ? d_tmap[n] : -1; }
-  /** debug print */
-  void debugPrint( const char* c, QuantifiersEngine* qe );
-};
-
-class ModelEngine;
-
-/** this class iterates over a RepAlphabet */
-class RepAlphabetIterator {
-private:
-  void initialize( QuantifiersEngine* qe, Node f, ModelEngine* model );
-public:
-  RepAlphabetIterator( QuantifiersEngine* qe, Node f, ModelEngine* model );
-  RepAlphabetIterator( QuantifiersEngine* qe, Node f, ModelEngine* model, std::vector< int >& indexOrder );
-  ~RepAlphabetIterator(){}
-  //pointer to quantifier
-  Node d_f;
-  //pointer to model
-  ModelEngine* d_model;
-  //index we are considering
-  std::vector< int > d_index;
-  //ordering for variables we are indexing over
-  //  for example, given reps = { a, b } and quantifier forall( x, y, z ) P( x, y, z ) with d_index_order = { 2, 0, 1 },
-  //    then we consider instantiations in this order:
-  //      a/x a/y a/z
-  //      a/x b/y a/z
-  //      b/x a/y a/z
-  //      b/x b/y a/z
-  //      ...
-  std::vector< int > d_index_order;
-  //variables to index they are considered at
-  //  for example, if d_index_order = { 2, 0, 1 }
-  //    then d_var_order = { 0 -> 1, 1 -> 2, 2 -> 0 }
-  std::map< int, int > d_var_order;
-  //the instantiation constants of d_f
-  std::vector< Node > d_ic;
-  //the current terms we are considering
-  std::vector< Node > d_terms;
-public:
-  /** increment the iterator */
-  void increment2( QuantifiersEngine* qe, int counter ); 
-  void increment( QuantifiersEngine* qe );
-  /** is the iterator finished? */
-  bool isFinished();
-  /** produce the match that this iterator represents */
-  void getMatch( QuantifiersEngine* qe, InstMatch& m );
-  /** get the i_th term we are considering */
-  Node getTerm( int i );
-  /** get the number of terms we are considering */
-  int getNumTerms() { return d_f[0].getNumChildren(); }
-  /** refresh d_term to be current with d_index */
-  void calculateTerms( QuantifiersEngine* qe );
-  /** debug print */
-  void debugPrint( const char* c );
-  void debugPrintSmall( const char* c );
-  //for debugging
-  int d_inst_tried;
-  int d_inst_tests;
-};
-
-
-class UfModelTree
-{
-public:
-  UfModelTree(){}
-  /** the data */
-  std::map< Node, UfModelTree > d_data;
-  /** the value of this tree node (if all paths lead to same value) */
-  Node d_value;
-public:
-  //is this model tree empty?
-  bool isEmpty() { return d_data.empty(); }
-  //clear
-  void clear(){
-    d_data.clear();
-    d_value = Node::null();
-  }
-  /** setValue function
-    *
-    * For each argument of n with ModelBasisAttribute() set to true will be considered default arguments if ground=false
-    *
-    */
-  void setValue( QuantifiersEngine* qe, Node n, Node v, std::vector< int >& indexOrder, bool ground, int argIndex );
-  /**  getValue function
-    *
-    *  returns $val, the value of ground term n
-    *  Say n is f( t_0...t_n )
-    *    depIndex is the index for which every term of the form f( t_0 ... t_depIndex, *,... * ) is equal to $val
-    *    for example, if g( x_0, x_1, x_2 ) := lambda x_0 x_1 x_2. if( x_1==a ) b else c,
-    *      then g( a, a, a ) would return b with depIndex = 1
-    *  If ground = true, we are asking whether the term n is constant (assumes that all non-model basis arguments are ground)
-    *
-    */
-  Node getValue( QuantifiersEngine* qe, Node n, std::vector< int >& indexOrder, int& depIndex, int argIndex );
-  ///** getConstant Value function
-  //  *
-  //  * given term n, where n may contain model basis arguments
-  //  * if n is constant for its entire domain, then this function returns the value of its domain
-  //  * otherwise, it returns null
-  //  * for example, if f( x_0, x_1 ) := if( x_0 = a ) b else if( x_1 = a ) a else b,
-  //  *   then f( a, e ) would return b, while f( e, a ) would return null
-  //  *
-  //  */
-  Node getConstantValue( QuantifiersEngine* qe, Node n, std::vector< int >& indexOrder, int argIndex );
-  /** simplify function */
-  void simplify( Node op, Node defaultVal, int argIndex );
-  // is total ?
-  bool isTotal( Node op, int argIndex );
-public:
-  void debugPrint( const char* c, QuantifiersEngine* qe, std::vector< int >& indexOrder, int ind = 0, int arg = 0 );
-};
 
-class UfModelTreeOrdered
+//the model builder
+class ModelEngineBuilder : public TheoryEngineModelBuilder
 {
-private:
-  Node d_op;
-  std::vector< int > d_index_order;
-  UfModelTree d_tree;
-public:
-  UfModelTreeOrdered(){}
-  UfModelTreeOrdered( Node op ) : d_op( op ){
-    TypeNode tn = d_op.getType();
-    for( int i=0; i<(int)(tn.getNumChildren()-1); i++ ){
-      d_index_order.push_back( i );
-    }
-  }
-  UfModelTreeOrdered( Node op, std::vector< int >& indexOrder ) : d_op( op ){
-    d_index_order.insert( d_index_order.end(), indexOrder.begin(), indexOrder.end() );
-  }
-  bool isEmpty() { return d_tree.isEmpty(); }
-  void clear() { d_tree.clear(); }
-  void setValue( QuantifiersEngine* qe, Node n, Node v, bool ground = true ){
-    d_tree.setValue( qe, n, v, d_index_order, ground, 0 );
-  }
-  Node getValue( QuantifiersEngine* qe, Node n, int& depIndex ){
-    return d_tree.getValue( qe, n, d_index_order, depIndex, 0 );
-  }
-  Node getConstantValue( QuantifiersEngine* qe, Node n ) { 
-    return d_tree.getConstantValue( qe, n, d_index_order, 0 ); 
-  }
-  void simplify() { d_tree.simplify( d_op, Node::null(), 0 ); }
-  bool isTotal() { return d_tree.isTotal( d_op, 0 ); }
-public:
-  void debugPrint( const char* c, QuantifiersEngine* qe, int ind = 0 ){
-    d_tree.debugPrint( c, qe, d_index_order, ind );
-  }
-};
-
-class UfModel
-{
-//public:
-  //std::map< Node, std::vector< Node > > d_reqs[2];
-  //std::map< Node, std::map< Node, std::vector< Node > > > d_eq_reqs[2];
-  ///** add requirement */
-  //void addRequirement( Node f, Node p, bool phase ) { d_reqs[ phase ? 1 : 0 ][ f ].push_back( p ); }
-  ///** add equality requirement */
-  //void addEqRequirement( Node f, Node t, Node te, bool phase ) { d_eq_reqs[ phase ? 1 : 0 ][ f ][ t ].push_back( te ); }
-private:
-  Node d_op;
-  ModelEngine* d_me;
-  std::vector< Node > d_ground_asserts;
-  std::vector< Node > d_ground_asserts_reps;
-  bool d_model_constructed;
-  //store for set values
-  std::map< Node, Node > d_set_values[2];
-  // preferences for default values
-  std::vector< Node > d_values;
-  std::map< Node, std::vector< Node > > d_value_pro_con[2];
-  /** set value */
-  void setValue( Node n, Node v, bool ground = true );
-  /** set model */
-  void setModel();
-  /** clear model */
-  void clearModel();
-public:
-  UfModel(){}
-  UfModel( Node op, ModelEngine* qe );
-  ~UfModel(){}
-  //data structure that stores the model
-  UfModelTreeOrdered d_tree;
-  //quantifiers that are satisfied because of the constant definition of d_op
-  bool d_reconsider_model;
-public:
-  /** debug print */
-  void debugPrint( const char* c );
-  /** get constant value */
-  Node getConstantValue( QuantifiersEngine* qe, Node n );
-  /** is empty */
-  bool isEmpty() { return d_ground_asserts.empty(); }
-  /** is constant */
-  bool isConstant();
-public:
-  /** build model */
-  void buildModel();
-  /** make model */
-  void makeModel( QuantifiersEngine* qe, UfModelTreeOrdered& tree );
-public:
-  /** set value preference */
-  void setValuePreference( Node f, Node n, bool isPro );
+protected:
+  //quantifiers engine
+  QuantifiersEngine* d_qe;
+  //map from operators to model preference data
+  std::map< Node, uf::UfModelPreferenceData > d_uf_prefs;
+  /** choose representative */
+  Node chooseRepresentative( TheoryModel* tm, Node eqc );
+  /** use constants for representatives */
+  void processBuildModel( TheoryModel* m );
+  //analyze quantifiers
+  void analyzeQuantifiers( FirstOrderModel* fm );
+  //build model
+  void finishBuildModel( FirstOrderModel* fm );
+  //theory-specific build models
+  void finishBuildModelUf( FirstOrderModel* fm, uf::UfModel& model );
+  //do InstGen techniques for quantifier, return number of lemmas produced
+  int doInstGen( FirstOrderModel* fm, Node f );
+public:
+  ModelEngineBuilder( QuantifiersEngine* qe );
+  virtual ~ModelEngineBuilder(){}
+public:
+  /** number of lemmas generated while building model */
+  int d_addedLemmas;
+  //map from quantifiers to if are constant SAT
+  std::map< Node, bool > d_quant_sat;
+  //map from quantifiers to the instantiation literals that their model is dependent upon
+  std::map< Node, std::vector< Node > > d_quant_selection_lits;
+public:
+  //map from quantifiers to model basis match
+  std::map< Node, InstMatch > d_quant_basis_match;
+  //options
+  bool optUseModel();
+  bool optInstGen();
+  bool optOneQuantPerRoundInstGen();
+  /** statistics class */
+  class Statistics {
+  public:
+    IntStat d_pre_sat_quant;
+    IntStat d_pre_nsat_quant;
+    Statistics();
+    ~Statistics();
+  };
+  Statistics d_statistics;
 };
 
-
-
-
 class ModelEngine : public QuantifiersModule
 {
-  friend class UfModel;
-  friend class RepAlphabetIterator;
+  friend class uf::UfModel;
+  friend class RepSetIterator;
 private:
-  TheoryQuantifiers* d_th;
-  QuantifiersEngine* d_quantEngine;
-  uf::StrongSolverTheoryUf* d_ss;
+  /** builder class */
+  ModelEngineBuilder d_builder;
+private:    //data maintained globally:
   //which quantifiers have been initialized
   std::map< Node, bool > d_quant_init;
-  //map from ops to model basis terms
-  std::map< Node, Node > d_model_basis_term;
-  //map from instantiation terms to their model basis equivalent
-  std::map< Node, Node > d_model_basis;
-  //the model we are working with
-  RepAlphabet d_ra;
-  std::map< Node, UfModel > d_uf_model;
-  ////map from model basis terms to quantifiers that are pro/con their definition
-  //std::map< Node, std::vector< Node > > d_quant_pro_con[2];
-  //map from quantifiers to model basis terms that are pro the definition of
-  std::map< Node, std::vector< Node > > d_pro_con_quant[2];
-  //map from quantifiers to if are constant SAT
-  std::map< Node, bool > d_quant_sat;
+private:    //analysis of current model:
+  //relevant domain
+  RelevantDomain d_rel_domain;
 private:
-  int evaluate( RepAlphabetIterator* rai, Node n, int& depIndex );
-  int evaluateEquality( Node n1, Node n2, Node gn1, Node gn2, std::vector< Node >& fv_deps );
-  Node evaluateTerm( Node n, Node gn, std::vector< Node >& fv_deps );
-  //temporary storing which literals have failed
-  void clearEvalFailed( int index );
-  std::map< Node, bool > d_eval_failed;
-  std::map< int, std::vector< Node > > d_eval_failed_lits;
-  ////temporary storing for values/free variable dependencies
-  //std::map< Node, Node > d_eval_term_vals;
-  //std::map< Node, std::map< Node, std::vector< Node > > > d_eval_term_fv_deps;
+  //options
+  bool optOneInstPerQuantRound();
+  bool optUseRelevantDomain();
+  bool optOneQuantPerRound();
 private:
-  //map from terms to the models used to calculate their value
-  std::map< Node, UfModelTreeOrdered > d_eval_term_model;
-  std::map< Node, bool > d_eval_term_use_default_model;
-  void makeEvalTermModel( Node n );
-  //index ordering to use for each term
-  std::map< Node, std::vector< int > > d_eval_term_index_order;
-  int getMaxVariableNum( int n );
-  void makeEvalTermIndexOrder( Node n );
-public:
-  void increment( RepAlphabetIterator* rai );
+  //initialize quantifiers, return number of lemmas produced
+  int initializeQuantifier( Node f );
+  //exhaustively instantiate quantifier (possibly using mbqi), return number of lemmas produced
+  int exhaustiveInstantiate( Node f, bool useRelInstDomain = false );
 private:
-  //queries about equality
-  bool areEqual( Node a, Node b );
-  bool areDisequal( Node a, Node b );
-private:
-  bool useModel();
-private:
-  //initialize quantifiers, return false if lemma needed to be added
-  bool initializeQuantifier( Node f );
-  //build representatives
-  void buildRepresentatives();
-  //initialize model
-  void initializeModel();
-  //analyze quantifiers
-  void analyzeQuantifiers();
-  //instantiate quantifier, return number of lemmas produced
-  int instantiateQuantifier( Node f );
-private:
-  //register instantiation terms with their corresponding model basis terms
-  void registerModelBasis( Node n, Node gn );
-  //for building UF model
-  void initializeUf( Node n );
-  void collectUfTerms( Node n, std::vector< Node >& terms );
-  void initializeUfModel( Node op );
-  //void processPredicate( Node f, Node p, bool phase );
-  //void processEquality( Node f, Node eq, bool phase );
+  //temporary statistics
+  int d_triedLemmas;
+  int d_testLemmas;
+  int d_totalLemmas;
+  int d_relevantLemmas;
 public:
-  ModelEngine( TheoryQuantifiers* th );
+  ModelEngine( QuantifiersEngine* qe );
   ~ModelEngine(){}
-  //get quantifiers engine
-  QuantifiersEngine* getQuantifiersEngine() { return d_quantEngine; }
-  //get representatives
-  RepAlphabet* getReps() { return &d_ra; }
-  //get arbitrary element
-  Node getArbitraryElement( TypeNode tn, std::vector< Node >& exclude );
-  //get model basis term
-  Node getModelBasisTerm( TypeNode tn, int i = 0 );
-  //get model basis term for op
-  Node getModelBasisApplyUfTerm( Node op );
-  //is model basis term for op
-  bool isModelBasisTerm( Node op, Node n );
 public:
   void check( Theory::Effort e );
   void registerQuantifier( Node f );
@@ -349,8 +127,6 @@ public:
   class Statistics {
   public:
     IntStat d_inst_rounds;
-    IntStat d_pre_sat_quant;
-    IntStat d_pre_nsat_quant;
     IntStat d_eval_formulas;
     IntStat d_eval_eqs;
     IntStat d_eval_uf_terms;
diff --git a/src/theory/quantifiers/relevant_domain.cpp b/src/theory/quantifiers/relevant_domain.cpp
new file mode 100644 (file)
index 0000000..e7ae1d1
--- /dev/null
@@ -0,0 +1,173 @@
+/*********************                                                        */\r
+/*! \file relevant_domain.cpp\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Implementation of relevant domain class\r
+ **/\r
+\r
+#include "theory/quantifiers_engine.h"\r
+#include "theory/quantifiers/relevant_domain.h"\r
+#include "theory/quantifiers/term_database.h"\r
+#include "theory/quantifiers/first_order_model.h"\r
+\r
+using namespace std;\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::context;\r
+using namespace CVC4::theory;\r
+using namespace CVC4::theory::quantifiers;\r
+\r
+RelevantDomain::RelevantDomain( FirstOrderModel* m ) : d_model( m ){\r
+\r
+}\r
+\r
+void RelevantDomain::compute(){\r
+  d_quant_inst_domain.clear();\r
+  for( int i=0; i<(int)d_model->getNumAssertedQuantifiers(); i++ ){\r
+    Node f = d_model->getAssertedQuantifier( i );\r
+    d_quant_inst_domain[f].resize( f[0].getNumChildren() );\r
+  }\r
+  //add ground terms to domain (rule 1 of complete instantiation essentially uf fragment)\r
+  for( std::map< Node, uf::UfModel >::iterator it = d_model->d_uf_model.begin();\r
+       it != d_model->d_uf_model.end(); ++it ){\r
+    Node op = it->first;\r
+    for( int i=0; i<(int)it->second.d_ground_asserts.size(); i++ ){\r
+      Node n = it->second.d_ground_asserts[i];\r
+      //add arguments to domain\r
+      for( int j=0; j<(int)n.getNumChildren(); j++ ){\r
+        if( d_model->d_ra.hasType( n[j].getType() ) ){\r
+          Node ra = d_model->getRepresentative( n[j] );\r
+          int raIndex = d_model->d_ra.getIndexFor( ra );\r
+          Assert( raIndex!=-1 );\r
+          if( std::find( d_active_domain[op][j].begin(), d_active_domain[op][j].end(), raIndex )==d_active_domain[op][j].end() ){\r
+            d_active_domain[op][j].push_back( raIndex );\r
+          }\r
+        }\r
+      }\r
+      //add to range\r
+      Node r = it->second.d_ground_asserts_reps[i];\r
+      int raIndex = d_model->d_ra.getIndexFor( r );\r
+      Assert( raIndex!=-1 );\r
+      if( std::find( d_active_range[op].begin(), d_active_range[op].end(), raIndex )==d_active_range[op].end() ){\r
+        d_active_range[op].push_back( raIndex );\r
+      }\r
+    }\r
+  }\r
+  //find fixed point for relevant domain computation\r
+  bool success;\r
+  do{\r
+    success = true;\r
+    for( int i=0; i<(int)d_model->getNumAssertedQuantifiers(); i++ ){\r
+      Node f = d_model->getAssertedQuantifier( i );\r
+      //compute the domain of relevant instantiations (rule 3 of complete instantiation, essentially uf fragment)\r
+      if( computeRelevantInstantiationDomain( d_model->getTermDatabase()->getCounterexampleBody( f ), Node::null(), -1, d_quant_inst_domain[f] ) ){\r
+        success = false;\r
+      }\r
+      //extend the possible domain for functions (rule 2 of complete instantiation, essentially uf fragment)\r
+      RepDomain range;\r
+      if( extendFunctionDomains( d_model->getTermDatabase()->getCounterexampleBody( f ), range ) ){\r
+        success = false;\r
+      }\r
+    }\r
+  }while( !success );\r
+}\r
+\r
+bool RelevantDomain::computeRelevantInstantiationDomain( Node n, Node parent, int arg, std::vector< RepDomain >& rd ){\r
+  bool domainChanged = false;\r
+  if( n.getKind()==INST_CONSTANT ){\r
+    bool domainSet = false;\r
+    int vi = n.getAttribute(InstVarNumAttribute());\r
+    Assert( !parent.isNull() );\r
+    if( parent.getKind()==APPLY_UF ){\r
+      //if the child of APPLY_UF term f( ... ), only consider the active domain of f at given argument\r
+      Node op = parent.getOperator();\r
+      if( d_active_domain.find( op )!=d_active_domain.end() ){\r
+        for( size_t i=0; i<d_active_domain[op][arg].size(); i++ ){\r
+          int d = d_active_domain[op][arg][i];\r
+          if( std::find( rd[vi].begin(), rd[vi].end(), d )==rd[vi].end() ){\r
+            rd[vi].push_back( d );\r
+            domainChanged = true;\r
+          }\r
+        }\r
+        domainSet = true;\r
+      }\r
+    }\r
+    if( !domainSet ){\r
+      //otherwise, we must consider the entire domain\r
+      TypeNode tn = n.getType();\r
+      if( d_model->d_ra.hasType( tn ) ){\r
+        if( rd[vi].size()!=d_model->d_ra.d_type_reps[tn].size() ){\r
+          rd[vi].clear();\r
+          for( size_t i=0; i<d_model->d_ra.d_type_reps[tn].size(); i++ ){\r
+            rd[vi].push_back( i );\r
+            domainChanged = true;\r
+          }\r
+        }\r
+      }else{\r
+        //infinite domain?\r
+      }\r
+    }\r
+  }else{\r
+    for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+      if( computeRelevantInstantiationDomain( n[i], n, i, rd ) ){\r
+        domainChanged = true;\r
+      }\r
+    }\r
+  }\r
+  return domainChanged;\r
+}\r
+\r
+bool RelevantDomain::extendFunctionDomains( Node n, RepDomain& range ){\r
+  if( n.getKind()==INST_CONSTANT ){\r
+    Node f = n.getAttribute(InstConstantAttribute());\r
+    int var = n.getAttribute(InstVarNumAttribute());\r
+    range.insert( range.begin(), d_quant_inst_domain[f][var].begin(), d_quant_inst_domain[f][var].end() );\r
+    return false;\r
+  }else{\r
+    Node op;\r
+    if( n.getKind()==APPLY_UF ){\r
+      op = n.getOperator();\r
+    }\r
+    bool domainChanged = false;\r
+    for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+      RepDomain childRange;\r
+      if( extendFunctionDomains( n[i], childRange ) ){\r
+        domainChanged = true;\r
+      }\r
+      if( n.getKind()==APPLY_UF ){\r
+        if( d_active_domain.find( op )!=d_active_domain.end() ){\r
+          for( int j=0; j<(int)childRange.size(); j++ ){\r
+            int v = childRange[j];\r
+            if( std::find( d_active_domain[op][i].begin(), d_active_domain[op][i].end(), v )==d_active_domain[op][i].end() ){\r
+              d_active_domain[op][i].push_back( v );\r
+              domainChanged = true;\r
+            }\r
+          }\r
+        }else{\r
+          //do this?\r
+        }\r
+      }\r
+    }\r
+    //get the range\r
+    if( n.hasAttribute(InstConstantAttribute()) ){\r
+      if( n.getKind()==APPLY_UF && d_active_range.find( op )!=d_active_range.end() ){\r
+        range.insert( range.end(), d_active_range[op].begin(), d_active_range[op].end() );\r
+      }else{\r
+        //infinite range?\r
+      }\r
+    }else{\r
+      Node r = d_model->getRepresentative( n );\r
+      range.push_back( d_model->d_ra.getIndexFor( r ) );\r
+    }\r
+    return domainChanged;\r
+  }\r
+}
\ No newline at end of file
diff --git a/src/theory/quantifiers/relevant_domain.h b/src/theory/quantifiers/relevant_domain.h
new file mode 100644 (file)
index 0000000..362a39d
--- /dev/null
@@ -0,0 +1,54 @@
+/*********************                                                        */\r
+/*! \file relevant_domain.h\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief relevant domain class\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef __CVC4__RELEVANT_DOMAIN_H\r
+#define __CVC4__RELEVANT_DOMAIN_H\r
+\r
+#include "theory/quantifiers/first_order_model.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+namespace quantifiers {\r
+\r
+class RelevantDomain\r
+{\r
+private:\r
+  FirstOrderModel* d_model;\r
+\r
+  //the domain of the arguments for each operator\r
+  std::map< Node, std::map< int, RepDomain > > d_active_domain;\r
+  //the range for each operator\r
+  std::map< Node, RepDomain > d_active_range;\r
+  //for computing relevant instantiation domain, return true if changed\r
+  bool computeRelevantInstantiationDomain( Node n, Node parent, int arg, std::vector< RepDomain >& rd );\r
+  //for computing extended\r
+  bool extendFunctionDomains( Node n, RepDomain& range );\r
+public:\r
+  RelevantDomain( FirstOrderModel* m );\r
+  virtual ~RelevantDomain(){}\r
+  //compute the relevant domain\r
+  void compute();\r
+  //relevant instantiation domain for each quantifier\r
+  std::map< Node, std::vector< RepDomain > > d_quant_inst_domain;\r
+};\r
+\r
+}\r
+}\r
+}\r
+\r
+#endif\r
diff --git a/src/theory/quantifiers/rep_set_iterator.cpp b/src/theory/quantifiers/rep_set_iterator.cpp
new file mode 100644 (file)
index 0000000..0204148
--- /dev/null
@@ -0,0 +1,523 @@
+/*********************                                                        */\r
+/*! \file rep_set_iterator.cpp\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Implementation of relevant domain class\r
+ **/\r
+\r
+#include "theory/quantifiers/rep_set_iterator.h"\r
+#include "theory/quantifiers/model_engine.h"\r
+#include "theory/quantifiers/term_database.h"\r
+\r
+#define USE_INDEX_ORDERING\r
+\r
+using namespace std;\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::context;\r
+using namespace CVC4::theory;\r
+using namespace CVC4::theory::quantifiers;\r
+\r
+RepSetIterator::RepSetIterator( Node f, FirstOrderModel* model ) : d_f( f ), d_model( model ){\r
+  //store instantiation constants\r
+  for( size_t i=0; i<f[0].getNumChildren(); i++ ){\r
+    d_index.push_back( 0 );\r
+  }\r
+  for( size_t i=0; i<f[0].getNumChildren(); i++ ){\r
+    //store default index order\r
+    d_index_order.push_back( i );\r
+    d_var_order[i] = i;\r
+    //store default domain\r
+    d_domain.push_back( RepDomain() );\r
+    for( int j=0; j<(int)d_model->d_ra.d_type_reps[d_f[0][i].getType()].size(); j++ ){\r
+      d_domain[i].push_back( j );\r
+    }\r
+  }\r
+}\r
+\r
+void RepSetIterator::setIndexOrder( std::vector< int >& indexOrder ){\r
+  d_index_order.clear();\r
+  d_index_order.insert( d_index_order.begin(), indexOrder.begin(), indexOrder.end() );\r
+  //make the d_var_order mapping\r
+  for( int i=0; i<(int)d_index_order.size(); i++ ){\r
+    d_var_order[d_index_order[i]] = i;\r
+  }\r
+}\r
+\r
+void RepSetIterator::setDomain( std::vector< RepDomain >& domain ){\r
+  d_domain.clear();\r
+  d_domain.insert( d_domain.begin(), domain.begin(), domain.end() );\r
+  //we are done if a domain is empty\r
+  for( int i=0; i<(int)d_domain.size(); i++ ){\r
+    if( d_domain[i].empty() ){\r
+      d_index.clear();\r
+    }\r
+  }\r
+}\r
+\r
+void RepSetIterator::increment2( int counter ){\r
+  Assert( !isFinished() );\r
+#ifdef DISABLE_EVAL_SKIP_MULTIPLE\r
+  counter = (int)d_index.size()-1;\r
+#endif\r
+  //increment d_index\r
+  while( counter>=0 && d_index[counter]==(int)(d_domain[counter].size()-1) ){\r
+    counter--;\r
+  }\r
+  if( counter==-1 ){\r
+    d_index.clear();\r
+  }else{\r
+    for( int i=(int)d_index.size()-1; i>counter; i-- ){\r
+      d_index[i] = 0;\r
+      //d_model->clearEvalFailed( i );\r
+    }\r
+    d_index[counter]++;\r
+    //d_model->clearEvalFailed( counter );\r
+  }\r
+}\r
+\r
+void RepSetIterator::increment(){\r
+  if( !isFinished() ){\r
+    increment2( (int)d_index.size()-1 );\r
+  }\r
+}\r
+\r
+bool RepSetIterator::isFinished(){\r
+  return d_index.empty();\r
+}\r
+\r
+void RepSetIterator::getMatch( QuantifiersEngine* qe, InstMatch& m ){\r
+  for( int i=0; i<(int)d_index.size(); i++ ){\r
+    m.d_map[ qe->getTermDatabase()->getInstantiationConstant( d_f, d_index_order[i] ) ] = getTerm( i );\r
+  }\r
+}\r
+\r
+Node RepSetIterator::getTerm( int i ){\r
+  TypeNode tn = d_f[0][d_index_order[i]].getType();\r
+  Assert( d_model->d_ra.d_type_reps.find( tn )!=d_model->d_ra.d_type_reps.end() );\r
+  int index = d_index_order[i];\r
+  return d_model->d_ra.d_type_reps[tn][d_domain[index][d_index[index]]];\r
+}\r
+\r
+void RepSetIterator::debugPrint( const char* c ){\r
+  for( int i=0; i<(int)d_index.size(); i++ ){\r
+    Debug( c ) << i << " : " << d_index[i] << " : " << getTerm( i ) << std::endl;\r
+  }\r
+}\r
+\r
+void RepSetIterator::debugPrintSmall( const char* c ){\r
+  Debug( c ) << "RI: ";\r
+  for( int i=0; i<(int)d_index.size(); i++ ){\r
+    Debug( c ) << d_index[i] << ": " << getTerm( i ) << " ";\r
+  }\r
+  Debug( c ) << std::endl;\r
+}\r
+\r
+RepSetEvaluator::RepSetEvaluator( FirstOrderModel* m, RepSetIterator* ri ) : d_model( m ), d_riter( ri ){\r
+\r
+}\r
+\r
+//if evaluate( n, phaseReq ) = eVal,\r
+// if eVal = d_riter->d_index.size()\r
+//   then the formula n instantiated with d_riter cannot be proven to be equal to phaseReq\r
+// otherwise,\r
+//   each n{d_riter->d_index[0]/x_0...d_riter->d_index[eVal]/x_eVal, */x_(eVal+1) ... */x_n } is equal to phaseReq in the current model\r
+int RepSetEvaluator::evaluate( Node n, int& depIndex ){\r
+  ++d_eval_formulas;\r
+  //Debug("fmf-eval-debug") << "Evaluate " << n << " " << phaseReq << std::endl;\r
+  //Notice() << "Eval " << n << std::endl;\r
+  if( n.getKind()==NOT ){\r
+    int val = evaluate( n[0], depIndex );\r
+    return val==1 ? -1 : ( val==-1 ? 1 : 0 );\r
+  }else if( n.getKind()==OR || n.getKind()==AND || n.getKind()==IMPLIES ){\r
+    int baseVal = n.getKind()==AND ? 1 : -1;\r
+    int eVal = baseVal;\r
+    int posDepIndex = d_riter->getNumTerms();\r
+    int negDepIndex = -1;\r
+    for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+      //evaluate subterm\r
+      int childDepIndex;\r
+      Node nn = ( i==0 && n.getKind()==IMPLIES ) ? n[i].notNode() : n[i];\r
+      int eValT = evaluate( nn, childDepIndex );\r
+      if( eValT==baseVal ){\r
+        if( eVal==baseVal ){\r
+          if( childDepIndex>negDepIndex ){\r
+            negDepIndex = childDepIndex;\r
+          }\r
+        }\r
+      }else if( eValT==-baseVal ){\r
+        eVal = -baseVal;\r
+        if( childDepIndex<posDepIndex ){\r
+          posDepIndex = childDepIndex;\r
+          if( posDepIndex==-1 ){\r
+            break;\r
+          }\r
+        }\r
+      }else if( eValT==0 ){\r
+        if( eVal==baseVal ){\r
+          eVal = 0;\r
+        }\r
+      }\r
+    }\r
+    if( eVal!=0 ){\r
+      depIndex = eVal==-baseVal ? posDepIndex : negDepIndex;\r
+      return eVal;\r
+    }else{\r
+      return 0;\r
+    }\r
+  }else if( n.getKind()==IFF || n.getKind()==XOR ){\r
+    int depIndex1;\r
+    int eVal = evaluate( n[0], depIndex1 );\r
+    if( eVal!=0 ){\r
+      int depIndex2;\r
+      int eVal2 = evaluate( n.getKind()==XOR ? n[1].notNode() : n[1], depIndex2 );\r
+      if( eVal2!=0 ){\r
+        depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;\r
+        return eVal==eVal2 ? 1 : -1;\r
+      }\r
+    }\r
+    return 0;\r
+  }else if( n.getKind()==ITE ){\r
+    int depIndex1, depIndex2;\r
+    int eVal = evaluate( n[0], depIndex1 );\r
+    if( eVal==0 ){\r
+      //evaluate children to see if they are the same value\r
+      int eval1 = evaluate( n[1], depIndex1 );\r
+      if( eval1!=0 ){\r
+        int eval2 = evaluate( n[1], depIndex2 );\r
+        if( eval1==eval2 ){\r
+          depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;\r
+          return eval1;\r
+        }\r
+      }\r
+    }else{\r
+      int eValT = evaluate( n[eVal==1 ? 1 : 2], depIndex2 );\r
+      depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;\r
+      return eValT;\r
+    }\r
+    return 0;\r
+  }else if( n.getKind()==FORALL ){\r
+    return 0;\r
+  }else{\r
+    ////if we know we will fail again, immediately return\r
+    //if( d_eval_failed.find( n )!=d_eval_failed.end() ){\r
+    //  if( d_eval_failed[n] ){\r
+    //    return -1;\r
+    //  }\r
+    //}\r
+    //Debug("fmf-eval-debug") << "Evaluate literal " << n << std::endl;\r
+    //this should be a literal\r
+    //Node gn = n.substitute( d_riter->d_ic.begin(), d_riter->d_ic.end(), d_riter->d_terms.begin(), d_riter->d_terms.end() );\r
+    //Debug("fmf-eval-debug") << "  Ground version = " << gn << std::endl;\r
+    int retVal = 0;\r
+    depIndex = d_riter->getNumTerms()-1;\r
+    if( n.getKind()==APPLY_UF ){\r
+      //case for boolean predicates\r
+      Node val = evaluateTerm( n, depIndex );\r
+      if( d_model->hasTerm( val ) ){\r
+        if( d_model->areEqual( val, d_model->d_true ) ){\r
+          retVal = 1;\r
+        }else{\r
+          retVal = -1;\r
+        }\r
+      }\r
+    }else if( n.getKind()==EQUAL ){\r
+      //case for equality\r
+      retVal = evaluateEquality( n[0], n[1], depIndex );\r
+    }else{\r
+      std::vector< int > cdi;\r
+      Node val = evaluateTermDefault( n, depIndex, cdi );\r
+      if( !val.isNull() ){\r
+        val = Rewriter::rewrite( val );\r
+        if( val==d_model->d_true ){\r
+          retVal = 1;\r
+        }else if( val==d_model->d_false ){\r
+          retVal = -1;\r
+        }\r
+      }\r
+    }\r
+    if( retVal!=0 ){\r
+      Debug("fmf-eval-debug") << "Evaluate literal: return " << retVal << ", depends = " << depIndex << std::endl;\r
+    }else{\r
+      Debug("fmf-eval-amb") << "Neither true nor false : " << n << std::endl;\r
+      //std::cout << "Neither true nor false : " << n << std::endl;\r
+    }\r
+    return retVal;\r
+  }\r
+}\r
+\r
+int RepSetEvaluator::evaluateEquality( Node n1, Node n2, int& depIndex ){\r
+  ++d_eval_eqs;\r
+  //Notice() << "Eval eq " << n1 << " " << n2 << std::endl;\r
+  Debug("fmf-eval-debug") << "Evaluate equality: " << std::endl;\r
+  Debug("fmf-eval-debug") << "   " << n1 << " = " << n2 << std::endl;\r
+  int depIndex1, depIndex2;\r
+  Node val1 = evaluateTerm( n1, depIndex1 );\r
+  Node val2 = evaluateTerm( n2, depIndex2 );\r
+  Debug("fmf-eval-debug") << "   Values :  ";\r
+  d_model->printRepresentativeDebug( "fmf-eval-debug", val1 );\r
+  Debug("fmf-eval-debug") <<  " = ";\r
+  d_model->printRepresentativeDebug( "fmf-eval-debug", val2 );\r
+  Debug("fmf-eval-debug") << std::endl;\r
+  int retVal = 0;\r
+  if( !val1.isNull() && !val2.isNull() ){\r
+    if( d_model->areEqual( val1, val2 ) ){\r
+      retVal = 1;\r
+    }else if( d_model->areDisequal( val1, val2 ) ){\r
+      retVal = -1;\r
+    }else{\r
+      Node eq = val1.eqNode( val2 );\r
+      eq = Rewriter::rewrite( eq );\r
+      if( eq==d_model->d_true ){\r
+        retVal = 1;\r
+      }else if( eq==d_model->d_false ){\r
+        retVal = -1;\r
+      }\r
+    }\r
+  }\r
+  if( retVal!=0 ){\r
+    depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;\r
+    Debug("fmf-eval-debug") << "   value = " << (retVal==1) << ", depIndex = " << depIndex << std::endl;\r
+  }else{\r
+    depIndex = d_riter->getNumTerms()-1;\r
+    Debug("fmf-eval-amb") << "Neither equal nor disequal : " << n1 << " , " << n2 << std::endl;\r
+    //std::cout << "Neither equal nor disequal : " << n1 << " , " << n2 << std::endl;\r
+  }\r
+  return retVal;\r
+}\r
+\r
+Node RepSetEvaluator::evaluateTerm( Node n, int& depIndex ){\r
+  //Notice() << "Eval term " << n << std::endl;\r
+  if( n.hasAttribute(InstConstantAttribute()) ){\r
+    Node val;\r
+    depIndex = d_riter->getNumTerms()-1;\r
+    //check the type of n\r
+    if( n.getKind()==INST_CONSTANT ){\r
+      int v = n.getAttribute(InstVarNumAttribute());\r
+      depIndex = d_riter->d_var_order[ v ];\r
+      val = d_riter->getTerm( v );\r
+    }else if( n.getKind()==ITE ){\r
+      int depIndex1, depIndex2;\r
+      int eval = evaluate( n[0], depIndex1 );\r
+      if( eval==0 ){\r
+        //evaluate children to see if they are the same\r
+        Node val1 = evaluateTerm( n[ 1 ], depIndex1 );\r
+        Node val2 = evaluateTerm( n[ 1 ], depIndex1 );\r
+        if( val1==val2 ){\r
+          val = val1;\r
+          depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;\r
+        }else{\r
+          return Node::null();\r
+        }\r
+      }else{\r
+        val = evaluateTerm( n[ eval==1 ? 1 : 2 ], depIndex2 );\r
+        depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;\r
+      }\r
+    }else{\r
+#if 0\r
+      //for select, pre-process read over writes\r
+      if( n.getKind()==SELECT ){\r
+        Node selIndex = evaluateTerm( n[1], depIndex );\r
+        if( selIndex.isNull() ){\r
+          depIndex = d_riter->getNumTerms()-1;\r
+          return Node::null();\r
+        }\r
+        Node arr = n[0];\r
+        int eval = 1;\r
+        while( arr.getKind()==STORE && eval!=0 ){\r
+          int tempIndex;\r
+          eval = evaluateEquality( selIndex, arr[1], tempIndex );\r
+          depIndex = tempIndex > depIndex ? tempIndex : depIndex;\r
+          if( eval==1 ){\r
+            val = evaluateTerm( arr[2], tempIndex );\r
+            depIndex = tempIndex > depIndex ? tempIndex : depIndex;\r
+            return val;\r
+          }else if( eval==-1 ){\r
+            arr = arr[0];\r
+          }\r
+        }\r
+        n = NodeManager::currentNM()->mkNode( SELECT, arr, selIndex );\r
+      }\r
+#endif\r
+      //default term evaluate : evaluate all children, recreate the value\r
+      std::vector< int > children_depIndex;\r
+      val = evaluateTermDefault( n, depIndex, children_depIndex );\r
+      //case split on the type of term\r
+      if( n.getKind()==APPLY_UF ){\r
+        Node op = n.getOperator();\r
+        //Debug("fmf-eval-debug") << "Evaluate term " << n << " (" << gn << ")" << std::endl;\r
+        //if it is a defined UF, then consult the interpretation\r
+        ++d_eval_uf_terms;\r
+        int argDepIndex = 0;\r
+        if( d_model->d_uf_model.find( op )!=d_model->d_uf_model.end() ){\r
+          //make the term model specifically for n\r
+          makeEvalUfModel( n );\r
+          //now, consult the model\r
+          if( d_eval_uf_use_default[n] ){\r
+            val = d_model->d_uf_model[op].d_tree.getValue( d_model, val, argDepIndex );\r
+          }else{\r
+            val = d_eval_uf_model[ n ].getValue( d_model, val, argDepIndex );\r
+          }\r
+          //Debug("fmf-eval-debug") << "Evaluate term " << n << " (" << gn << ")" << std::endl;\r
+          //d_eval_uf_model[ n ].debugPrint("fmf-eval-debug", d_qe );\r
+          Assert( !val.isNull() );\r
+        }else{\r
+          d_eval_uf_use_default[n] = true;\r
+          argDepIndex = (int)n.getNumChildren();\r
+        }\r
+        //recalculate the depIndex\r
+        depIndex = -1;\r
+        for( int i=0; i<argDepIndex; i++ ){\r
+          int index = d_eval_uf_use_default[n] ? i : d_eval_term_index_order[n][i];\r
+          Debug("fmf-eval-debug") << "Add variables from " << index << "..." << std::endl;\r
+          if( children_depIndex[index]>depIndex ){\r
+            depIndex = children_depIndex[index];\r
+          }\r
+        }\r
+        Debug("fmf-eval-debug") << "Evaluate term " << n << " = ";\r
+        d_model->printRepresentativeDebug( "fmf-eval-debug", val );\r
+        Debug("fmf-eval-debug") << ", depIndex = " << depIndex << std::endl;\r
+      }else if( n.getKind()==SELECT ){\r
+        if( d_model->d_array_model.find( n[0] )!=d_model->d_array_model.end() ){\r
+          //consult the default value for the array DO_THIS\r
+          //val = Rewriter::rewrite( val );\r
+          //val = d_model->d_array_model[ n[0] ];\r
+          val = Rewriter::rewrite( val );\r
+        }else{\r
+          val = Rewriter::rewrite( val );\r
+        }\r
+      }else{\r
+        val = Rewriter::rewrite( val );\r
+      }\r
+    }\r
+    return val;\r
+  }else{\r
+    depIndex = -1;\r
+    return n;\r
+  }\r
+}\r
+\r
+Node RepSetEvaluator::evaluateTermDefault( Node n, int& depIndex, std::vector< int >& childDepIndex ){\r
+  //first we must evaluate the arguments\r
+  std::vector< Node > children;\r
+  if( n.getMetaKind()==kind::metakind::PARAMETERIZED ){\r
+    children.push_back( n.getOperator() );\r
+  }\r
+  depIndex = -1;\r
+  //for each argument, calculate its value, and the variables its value depends upon\r
+  for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+    childDepIndex.push_back( -1 );\r
+    Node nn = evaluateTerm( n[i], childDepIndex[i] );\r
+    if( nn.isNull() ){\r
+      depIndex = d_riter->getNumTerms()-1;\r
+      return nn;\r
+    }else{\r
+      children.push_back( nn );\r
+      if( childDepIndex[i]>depIndex ){\r
+        depIndex = childDepIndex[i];\r
+      }\r
+    }\r
+  }\r
+  //recreate the value\r
+  return NodeManager::currentNM()->mkNode( n.getKind(), children );\r
+}\r
+\r
+void RepSetEvaluator::clearEvalFailed( int index ){\r
+  for( int i=0; i<(int)d_eval_failed_lits[index].size(); i++ ){\r
+    d_eval_failed[ d_eval_failed_lits[index][i] ] = false;\r
+  }\r
+  d_eval_failed_lits[index].clear();\r
+}\r
+\r
+void RepSetEvaluator::makeEvalUfModel( Node n ){\r
+  if( d_eval_uf_model.find( n )==d_eval_uf_model.end() ){\r
+    makeEvalUfIndexOrder( n );\r
+    if( !d_eval_uf_use_default[n] ){\r
+      Node op = n.getOperator();\r
+      d_eval_uf_model[n] = uf::UfModelTreeOrdered( op, d_eval_term_index_order[n] );\r
+      d_model->d_uf_model[op].makeModel( d_eval_uf_model[n] );\r
+      //Debug("fmf-index-order") << "Make model for " << n << " : " << std::endl;\r
+      //d_eval_uf_model[n].debugPrint( "fmf-index-order", d_qe, 2 );\r
+    }\r
+  }\r
+}\r
+\r
+struct sortGetMaxVariableNum {\r
+  std::map< Node, int > d_max_var_num;\r
+  int computeMaxVariableNum( Node n ){\r
+    if( n.getKind()==INST_CONSTANT ){\r
+      return n.getAttribute(InstVarNumAttribute());\r
+    }else if( n.hasAttribute(InstConstantAttribute()) ){\r
+      int maxVal = -1;\r
+      for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+        int val = getMaxVariableNum( n[i] );\r
+        if( val>maxVal ){\r
+          maxVal = val;\r
+        }\r
+      }\r
+      return maxVal;\r
+    }else{\r
+      return -1;\r
+    }\r
+  }\r
+  int getMaxVariableNum( Node n ){\r
+    std::map< Node, int >::iterator it = d_max_var_num.find( n );\r
+    if( it==d_max_var_num.end() ){\r
+      int num = computeMaxVariableNum( n );\r
+      d_max_var_num[n] = num;\r
+      return num;\r
+    }else{\r
+      return it->second;\r
+    }\r
+  }\r
+  bool operator() (Node i,Node j) { return (getMaxVariableNum(i)<getMaxVariableNum(j));}\r
+};\r
+\r
+void RepSetEvaluator::makeEvalUfIndexOrder( Node n ){\r
+  if( d_eval_term_index_order.find( n )==d_eval_term_index_order.end() ){\r
+#ifdef USE_INDEX_ORDERING\r
+    //sort arguments in order of least significant vs. most significant variable in default ordering\r
+    std::map< Node, std::vector< int > > argIndex;\r
+    std::vector< Node > args;\r
+    for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+      if( argIndex.find( n[i] )==argIndex.end() ){\r
+        args.push_back( n[i] );\r
+      }\r
+      argIndex[n[i]].push_back( i );\r
+    }\r
+    sortGetMaxVariableNum sgmvn;\r
+    std::sort( args.begin(), args.end(), sgmvn );\r
+    for( int i=0; i<(int)args.size(); i++ ){\r
+      for( int j=0; j<(int)argIndex[ args[i] ].size(); j++ ){\r
+        d_eval_term_index_order[n].push_back( argIndex[ args[i] ][j] );\r
+      }\r
+    }\r
+    bool useDefault = true;\r
+    for( int i=0; i<(int)d_eval_term_index_order[n].size(); i++ ){\r
+      if( i!=d_eval_term_index_order[n][i] ){\r
+        useDefault = false;\r
+        break;\r
+      }\r
+    }\r
+    d_eval_uf_use_default[n] = useDefault;\r
+    Debug("fmf-index-order") << "Will consider the following index ordering for " << n << " : ";\r
+    for( int i=0; i<(int)d_eval_term_index_order[n].size(); i++ ){\r
+      Debug("fmf-index-order") << d_eval_term_index_order[n][i] << " ";\r
+    }\r
+    Debug("fmf-index-order") << std::endl;\r
+#else\r
+    d_eval_uf_use_default[n] = true;\r
+#endif\r
+  }\r
+}\r
+\r
+\r
diff --git a/src/theory/quantifiers/rep_set_iterator.h b/src/theory/quantifiers/rep_set_iterator.h
new file mode 100644 (file)
index 0000000..308d09a
--- /dev/null
@@ -0,0 +1,120 @@
+/*********************                                                        */\r
+/*! \file rep_set_iterator.h\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief rep_set_iterator class\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef __CVC4__REP_SET_ITERATOR_H\r
+#define __CVC4__REP_SET_ITERATOR_H\r
+\r
+#include "theory/quantifiers_engine.h"\r
+#include "theory/quantifiers/first_order_model.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+namespace quantifiers {\r
+\r
+/** this class iterates over a RepSet */\r
+class RepSetIterator {\r
+public:\r
+  RepSetIterator( Node f, FirstOrderModel* model );\r
+  ~RepSetIterator(){}\r
+  //pointer to quantifier\r
+  Node d_f;\r
+  //pointer to model\r
+  FirstOrderModel* d_model;\r
+  //index we are considering\r
+  std::vector< int > d_index;\r
+  //domain we are considering\r
+  std::vector< RepDomain > d_domain;\r
+  //ordering for variables we are indexing over\r
+  //  for example, given reps = { a, b } and quantifier forall( x, y, z ) P( x, y, z ) with d_index_order = { 2, 0, 1 },\r
+  //    then we consider instantiations in this order:\r
+  //      a/x a/y a/z\r
+  //      a/x b/y a/z\r
+  //      b/x a/y a/z\r
+  //      b/x b/y a/z\r
+  //      ...\r
+  std::vector< int > d_index_order;\r
+  //variables to index they are considered at\r
+  //  for example, if d_index_order = { 2, 0, 1 }\r
+  //    then d_var_order = { 0 -> 1, 1 -> 2, 2 -> 0 }\r
+  std::map< int, int > d_var_order;\r
+  //the instantiation constants of d_f\r
+  std::vector< Node > d_ic;\r
+  //the current terms we are considering\r
+  std::vector< Node > d_terms;\r
+public:\r
+  /** set index order */\r
+  void setIndexOrder( std::vector< int >& indexOrder );\r
+  /** set domain */\r
+  void setDomain( std::vector< RepDomain >& domain );\r
+  /** increment the iterator */\r
+  void increment2( int counter );\r
+  void increment();\r
+  /** is the iterator finished? */\r
+  bool isFinished();\r
+  /** produce the match that this iterator represents */\r
+  void getMatch( QuantifiersEngine* qe, InstMatch& m );\r
+  /** get the i_th term we are considering */\r
+  Node getTerm( int i );\r
+  /** get the number of terms we are considering */\r
+  int getNumTerms() { return d_f[0].getNumChildren(); }\r
+  /** debug print */\r
+  void debugPrint( const char* c );\r
+  void debugPrintSmall( const char* c );\r
+};\r
+\r
+class RepSetEvaluator\r
+{\r
+private:\r
+  FirstOrderModel* d_model;\r
+  RepSetIterator* d_riter;\r
+private: //for Theory UF:\r
+  //map from terms to the models used to calculate their value\r
+  std::map< Node, bool > d_eval_uf_use_default;\r
+  std::map< Node, uf::UfModelTreeOrdered > d_eval_uf_model;\r
+  void makeEvalUfModel( Node n );\r
+  //index ordering to use for each term\r
+  std::map< Node, std::vector< int > > d_eval_term_index_order;\r
+  int getMaxVariableNum( int n );\r
+  void makeEvalUfIndexOrder( Node n );\r
+private:\r
+  //default evaluate term function\r
+  Node evaluateTermDefault( Node n, int& depIndex, std::vector< int >& childDepIndex );\r
+  //temporary storing which literals have failed\r
+  void clearEvalFailed( int index );\r
+  std::map< Node, bool > d_eval_failed;\r
+  std::map< int, std::vector< Node > > d_eval_failed_lits;\r
+public:\r
+  RepSetEvaluator( FirstOrderModel* m, RepSetIterator* ri );\r
+  virtual ~RepSetEvaluator(){}\r
+  /** evaluate functions */\r
+  int evaluate( Node n, int& depIndex );\r
+  int evaluateEquality( Node n1, Node n2, int& depIndex );\r
+  Node evaluateTerm( Node n, int& depIndex );\r
+public:\r
+  //statistics\r
+  int d_eval_formulas;\r
+  int d_eval_eqs;\r
+  int d_eval_uf_terms;\r
+};\r
+\r
+\r
+}\r
+}\r
+}\r
+\r
+#endif\r
diff --git a/src/theory/quantifiers/term_database.cpp b/src/theory/quantifiers/term_database.cpp
new file mode 100644 (file)
index 0000000..55ea693
--- /dev/null
@@ -0,0 +1,324 @@
+/*********************                                                        */\r
+/*! \file term_database.cpp\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Implementation of term databse class\r
+ **/\r
+\r
+ #include "theory/quantifiers/term_database.h"\r
+ #include "theory/quantifiers_engine.h"\r
+ #include "theory/uf/theory_uf_instantiator.h"\r
+ #include "theory/theory_engine.h"\r
+ #include "theory/quantifiers/first_order_model.h"\r
+\r
+using namespace std;\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::context;\r
+using namespace CVC4::theory;\r
+using namespace CVC4::theory::quantifiers;\r
+\r
+ bool TermArgTrie::addTerm2( QuantifiersEngine* qe, Node n, int argIndex ){\r
+   if( argIndex<(int)n.getNumChildren() ){\r
+     Node r = qe->getEqualityQuery()->getRepresentative( n[ argIndex ] );\r
+     std::map< Node, TermArgTrie >::iterator it = d_data.find( r );\r
+     if( it==d_data.end() ){\r
+       d_data[r].addTerm2( qe, n, argIndex+1 );\r
+       return true;\r
+     }else{\r
+       return it->second.addTerm2( qe, n, argIndex+1 );\r
+     }\r
+   }else{\r
+     //store n in d_data (this should be interpretted as the "data" and not as a reference to a child)\r
+     d_data[n].d_data.clear();\r
+     return false;\r
+   }\r
+ }\r
+\r
+ void TermDb::addTerm( Node n, std::vector< Node >& added, bool withinQuant ){\r
+   //don't add terms in quantifier bodies\r
+   if( !withinQuant || Options::current()->registerQuantBodyTerms ){\r
+     if( d_processed.find( n )==d_processed.end() ){\r
+       d_processed[n] = true;\r
+       //if this is an atomic trigger, consider adding it\r
+       if( Trigger::isAtomicTrigger( n ) ){\r
+         if( !n.hasAttribute(InstConstantAttribute()) ){\r
+           Debug("term-db") << "register trigger term " << n << std::endl;\r
+           //Notice() << "register trigger term " << n << std::endl;\r
+           Node op = n.getOperator();\r
+           d_op_map[op].push_back( n );\r
+           d_type_map[ n.getType() ].push_back( n );\r
+           added.push_back( n );\r
+\r
+           uf::InstantiatorTheoryUf* d_ith = (uf::InstantiatorTheoryUf*)d_quantEngine->getInstantiator( THEORY_UF );\r
+           for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+             addTerm( n[i], added, withinQuant );\r
+             if( Options::current()->efficientEMatching ){\r
+               if( d_parents[n[i]][op].empty() ){\r
+                 //must add parent to equivalence class info\r
+                 Node nir = d_ith->getRepresentative( n[i] );\r
+                 uf::EqClassInfo* eci_nir = d_ith->getEquivalenceClassInfo( nir );\r
+                 if( eci_nir ){\r
+                   eci_nir->d_pfuns[ op ] = true;\r
+                 }\r
+               }\r
+               //add to parent structure\r
+               if( std::find( d_parents[n[i]][op][i].begin(), d_parents[n[i]][op][i].end(), n )==d_parents[n[i]][op][i].end() ){\r
+                 d_parents[n[i]][op][i].push_back( n );\r
+               }\r
+             }\r
+           }\r
+           if( Options::current()->efficientEMatching ){\r
+             //new term, add n to candidate generators\r
+             for( int i=0; i<(int)d_ith->d_cand_gens[op].size(); i++ ){\r
+               d_ith->d_cand_gens[op][i]->addCandidate( n );\r
+             }\r
+           }\r
+           if( Options::current()->eagerInstQuant ){\r
+             if( !n.hasAttribute(InstLevelAttribute()) && n.getAttribute(InstLevelAttribute())==0 ){\r
+               int addedLemmas = 0;\r
+               for( int i=0; i<(int)d_ith->d_op_triggers[op].size(); i++ ){\r
+                 addedLemmas += d_ith->d_op_triggers[op][i]->addTerm( n );\r
+               }\r
+               //Message() << "Terms, added lemmas: " << addedLemmas << std::endl;\r
+               d_quantEngine->flushLemmas( &d_quantEngine->getTheoryEngine()->getTheory( THEORY_QUANTIFIERS )->getOutputChannel() );\r
+             }\r
+           }\r
+         }\r
+       }\r
+       for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+         addTerm( n[i], added, withinQuant );\r
+       }\r
+     }\r
+   }\r
+ }\r
+\r
+ void TermDb::reset( Theory::Effort effort ){\r
+   int nonCongruentCount = 0;\r
+   int congruentCount = 0;\r
+   int alreadyCongruentCount = 0;\r
+   //rebuild d_func/pred_map_trie for each operation, this will calculate all congruent terms\r
+   for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){\r
+     if( !it->second.empty() ){\r
+       if( it->second[0].getType()==NodeManager::currentNM()->booleanType() ){\r
+         d_pred_map_trie[ 0 ][ it->first ].d_data.clear();\r
+         d_pred_map_trie[ 1 ][ it->first ].d_data.clear();\r
+       }else{\r
+         d_func_map_trie[ it->first ].d_data.clear();\r
+         for( int i=0; i<(int)it->second.size(); i++ ){\r
+           Node n = it->second[i];\r
+           if( !n.getAttribute(NoMatchAttribute()) ){\r
+             if( !d_func_map_trie[ it->first ].addTerm( d_quantEngine, n ) ){\r
+               NoMatchAttribute nma;\r
+               n.setAttribute(nma,true);\r
+               congruentCount++;\r
+             }else{\r
+               nonCongruentCount++;\r
+             }\r
+           }else{\r
+             congruentCount++;\r
+             alreadyCongruentCount++;\r
+           }\r
+         }\r
+       }\r
+     }\r
+   }\r
+   for( int i=0; i<2; i++ ){\r
+     Node n = NodeManager::currentNM()->mkConst( i==1 );\r
+     eq::EqClassIterator eqc( d_quantEngine->getEqualityQuery()->getRepresentative( n ),\r
+                               ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine() );\r
+     while( !eqc.isFinished() ){\r
+       Node en = (*eqc);\r
+       if( en.getKind()==APPLY_UF && !en.hasAttribute(InstConstantAttribute()) ){\r
+         if( !en.getAttribute(NoMatchAttribute()) ){\r
+           Node op = en.getOperator();\r
+           if( !d_pred_map_trie[i][op].addTerm( d_quantEngine, en ) ){\r
+             NoMatchAttribute nma;\r
+             en.setAttribute(nma,true);\r
+             congruentCount++;\r
+           }else{\r
+             nonCongruentCount++;\r
+           }\r
+         }else{\r
+           alreadyCongruentCount++;\r
+         }\r
+       }\r
+       ++eqc;\r
+     }\r
+   }\r
+   Debug("term-db-cong") << "TermDb: Reset" << std::endl;\r
+   Debug("term-db-cong") << "Congruent/Non-Congruent = ";\r
+   Debug("term-db-cong") << congruentCount << "(" << alreadyCongruentCount << ") / " << nonCongruentCount << std::endl;\r
+}\r
+\r
+void TermDb::registerModelBasis( Node n, Node gn ){\r
+  if( d_model_basis.find( n )==d_model_basis.end() ){\r
+    d_model_basis[n] = gn;\r
+    for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+      registerModelBasis( n[i], gn[i] );\r
+    }\r
+  }\r
+}\r
+\r
+Node TermDb::getModelBasisTerm( TypeNode tn, int i ){\r
+  if( d_model_basis_term.find( tn )==d_model_basis_term.end() ){\r
+    std::stringstream ss;\r
+    ss << Expr::setlanguage(Options::current()->outputLanguage);\r
+    ss << "e_" << tn;\r
+    d_model_basis_term[tn] = NodeManager::currentNM()->mkVar( ss.str(), tn );\r
+    ModelBasisAttribute mba;\r
+    d_model_basis_term[tn].setAttribute(mba,true);\r
+  }\r
+  return d_model_basis_term[tn];\r
+}\r
+\r
+Node TermDb::getModelBasisOpTerm( Node op ){\r
+  if( d_model_basis_op_term.find( op )==d_model_basis_op_term.end() ){\r
+    TypeNode t = op.getType();\r
+    std::vector< Node > children;\r
+    children.push_back( op );\r
+    for( size_t i=0; i<t.getNumChildren()-1; i++ ){\r
+      children.push_back( getModelBasisTerm( t[i] ) );\r
+    }\r
+    d_model_basis_op_term[op] = NodeManager::currentNM()->mkNode( APPLY_UF, children );\r
+  }\r
+  return d_model_basis_op_term[op];\r
+}\r
+\r
+void TermDb::computeModelBasisArgAttribute( Node n ){\r
+  if( !n.hasAttribute(ModelBasisArgAttribute()) ){\r
+    uint64_t val = 0;\r
+    //determine if it has model basis attribute\r
+    for( int j=0; j<(int)n.getNumChildren(); j++ ){\r
+      if( n[j].getAttribute(ModelBasisAttribute()) ){\r
+        val = 1;\r
+        break;\r
+      }\r
+    }\r
+    ModelBasisArgAttribute mbaa;\r
+    n.setAttribute( mbaa, val );\r
+  }\r
+}\r
+\r
+void TermDb::makeInstantiationConstantsFor( Node f ){\r
+  if( d_inst_constants.find( f )==d_inst_constants.end() ){\r
+    Debug("quantifiers-engine") << "Instantiation constants for " << f << " : " << std::endl;\r
+    for( int i=0; i<(int)f[0].getNumChildren(); i++ ){\r
+      d_vars[f].push_back( f[0][i] );\r
+      //make instantiation constants\r
+      Node ic = NodeManager::currentNM()->mkInstConstant( f[0][i].getType() );\r
+      d_inst_constants_map[ic] = f;\r
+      d_inst_constants[ f ].push_back( ic );\r
+      Debug("quantifiers-engine") << "  " << ic << std::endl;\r
+      //set the var number attribute\r
+      InstVarNumAttribute ivna;\r
+      ic.setAttribute(ivna,i);\r
+    }\r
+  }\r
+}\r
+\r
+void TermDb::setInstantiationLevelAttr( Node n, uint64_t level ){\r
+  if( !n.hasAttribute(InstLevelAttribute()) ){\r
+    InstLevelAttribute ila;\r
+    n.setAttribute(ila,level);\r
+  }\r
+  for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+    setInstantiationLevelAttr( n[i], level );\r
+  }\r
+}\r
+\r
+\r
+void TermDb::setInstantiationConstantAttr( Node n, Node f ){\r
+  if( !n.hasAttribute(InstConstantAttribute()) ){\r
+    bool setAttr = false;\r
+    if( n.getKind()==INST_CONSTANT ){\r
+      setAttr = true;\r
+    }else{\r
+      for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+        setInstantiationConstantAttr( n[i], f );\r
+        if( n[i].hasAttribute(InstConstantAttribute()) ){\r
+          setAttr = true;\r
+        }\r
+      }\r
+    }\r
+    if( setAttr ){\r
+      InstConstantAttribute ica;\r
+      n.setAttribute(ica,f);\r
+      //also set the no-match attribute\r
+      NoMatchAttribute nma;\r
+      n.setAttribute(nma,true);\r
+    }\r
+  }\r
+}\r
+\r
+\r
+Node TermDb::getCounterexampleBody( Node f ){\r
+  std::map< Node, Node >::iterator it = d_counterexample_body.find( f );\r
+  if( it==d_counterexample_body.end() ){\r
+    makeInstantiationConstantsFor( f );\r
+    Node n = getSubstitutedNode( f[1], f );\r
+    d_counterexample_body[ f ] = n;\r
+    return n;\r
+  }else{\r
+    return it->second;\r
+  }\r
+}\r
+\r
+Node TermDb::getSkolemizedBody( Node f ){\r
+  Assert( f.getKind()==FORALL );\r
+  if( d_skolem_body.find( f )==d_skolem_body.end() ){\r
+    std::vector< Node > vars;\r
+    for( int i=0; i<(int)f[0].getNumChildren(); i++ ){\r
+      Node skv = NodeManager::currentNM()->mkSkolem( f[0][i].getType() );\r
+      d_skolem_constants[ f ].push_back( skv );\r
+      vars.push_back( f[0][i] );\r
+    }\r
+    d_skolem_body[ f ] = f[ 1 ].substitute( vars.begin(), vars.end(),\r
+                                            d_skolem_constants[ f ].begin(), d_skolem_constants[ f ].end() );\r
+    if( f.hasAttribute(InstLevelAttribute()) ){\r
+      setInstantiationLevelAttr( d_skolem_body[ f ], f.getAttribute(InstLevelAttribute()) );\r
+    }\r
+  }\r
+  return d_skolem_body[ f ];\r
+}\r
+\r
+\r
+Node TermDb::getSubstitutedNode( Node n, Node f ){\r
+  return convertNodeToPattern(n,f,d_vars[f],d_inst_constants[ f ]);\r
+}\r
+\r
+Node TermDb::convertNodeToPattern( Node n, Node f, const std::vector<Node> & vars,\r
+                                              const std::vector<Node> & inst_constants){\r
+  Node n2 = n.substitute( vars.begin(), vars.end(),\r
+                          inst_constants.begin(),\r
+                          inst_constants.end() );\r
+  setInstantiationConstantAttr( n2, f );\r
+  return n2;\r
+}\r
+\r
+Node TermDb::getFreeVariableForInstConstant( Node n ){\r
+  TypeNode tn = n.getType();\r
+  if( d_free_vars.find( tn )==d_free_vars.end() ){\r
+    //if integer or real, make zero\r
+    if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){\r
+      Rational z(0);\r
+      d_free_vars[tn] = NodeManager::currentNM()->mkConst( z );\r
+    }else{\r
+      if( d_type_map[ tn ].empty() ){\r
+        d_free_vars[tn] = NodeManager::currentNM()->mkVar( tn );\r
+      }else{\r
+        d_free_vars[tn] = d_type_map[ tn ][ 0 ];\r
+      }\r
+    }\r
+  }\r
+  return d_free_vars[tn];\r
+}
\ No newline at end of file
diff --git a/src/theory/quantifiers/term_database.h b/src/theory/quantifiers/term_database.h
new file mode 100644 (file)
index 0000000..5bf3d79
--- /dev/null
@@ -0,0 +1,151 @@
+/**********************/\r
+/*! \file term_database.h\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief term database class\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef __CVC4__QUANTIFIERS_TERM_DATABASE_H\r
+#define __CVC4__QUANTIFIERS_TERM_DATABASE_H\r
+\r
+#include "theory/theory.h"\r
+\r
+#include <map>\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+\r
+class QuantifiersEngine;\r
+\r
+namespace quantifiers {\r
+\r
+class TermArgTrie {\r
+private:\r
+  bool addTerm2( QuantifiersEngine* qe, Node n, int argIndex );\r
+public:\r
+  /** the data */\r
+  std::map< Node, TermArgTrie > d_data;\r
+public:\r
+  bool addTerm( QuantifiersEngine* qe, Node n ) { return addTerm2( qe, n, 0 ); }\r
+};/* class TermArgTrie */\r
+\r
+class TermDb {\r
+  friend class ::CVC4::theory::QuantifiersEngine;\r
+private:\r
+  /** reference to the quantifiers engine */\r
+  QuantifiersEngine* d_quantEngine;\r
+  /** calculated no match terms */\r
+  bool d_matching_active;\r
+  /** terms processed */\r
+  std::map< Node, bool > d_processed;\r
+public:\r
+  TermDb( QuantifiersEngine* qe ) : d_quantEngine( qe ), d_matching_active( true ){}\r
+  ~TermDb(){}\r
+  /** map from APPLY_UF operators to ground terms for that operator */\r
+  std::map< Node, std::vector< Node > > d_op_map;\r
+  /** map from APPLY_UF functions to trie */\r
+  std::map< Node, TermArgTrie > d_func_map_trie;\r
+  /** map from APPLY_UF predicates to trie */\r
+  std::map< Node, TermArgTrie > d_pred_map_trie[2];\r
+  /** map from type nodes to terms of that type */\r
+  std::map< TypeNode, std::vector< Node > > d_type_map;\r
+  /** add a term to the database */\r
+  void addTerm( Node n, std::vector< Node >& added, bool withinQuant = false );\r
+  /** reset (calculate which terms are active) */\r
+  void reset( Theory::Effort effort );\r
+  /** set active */\r
+  void setMatchingActive( bool a ) { d_matching_active = a; }\r
+  /** get active */\r
+  bool getMatchingActive() { return d_matching_active; }\r
+public:\r
+  /** parent structure (for efficient E-matching):\r
+      n -> op -> index -> L\r
+      map from node "n" to a list of nodes "L", where each node n' in L\r
+        has operator "op", and n'["index"] = n.\r
+      for example, d_parents[n][f][1] = { f( t1, n ), f( t2, n ), ... }\r
+  */\r
+  std::map< Node, std::map< Node, std::map< int, std::vector< Node > > > > d_parents;\r
+private:\r
+  //map from types to model basis terms\r
+  std::map< TypeNode, Node > d_model_basis_term;\r
+  //map from ops to model basis terms\r
+  std::map< Node, Node > d_model_basis_op_term;\r
+  //map from instantiation terms to their model basis equivalent\r
+  std::map< Node, Node > d_model_basis;\r
+public:\r
+  //get model basis term\r
+  Node getModelBasisTerm( TypeNode tn, int i = 0 );\r
+  //get model basis term for op\r
+  Node getModelBasisOpTerm( Node op );\r
+  // compute model basis arg\r
+  void computeModelBasisArgAttribute( Node n );\r
+  //register instantiation terms with their corresponding model basis terms\r
+  void registerModelBasis( Node n, Node gn );\r
+  //get model basis\r
+  Node getModelBasis( Node n ) { return d_model_basis[n]; }\r
+private:\r
+  /** map from universal quantifiers to the list of variables */\r
+  std::map< Node, std::vector< Node > > d_vars;\r
+  /** map from universal quantifiers to the list of skolem constants */\r
+  std::map< Node, std::vector< Node > > d_skolem_constants;\r
+  /** map from universal quantifiers to their skolemized body */\r
+  std::map< Node, Node > d_skolem_body;\r
+  /** instantiation constants to universal quantifiers */\r
+  std::map< Node, Node > d_inst_constants_map;\r
+  /** map from universal quantifiers to their counterexample body */\r
+  std::map< Node, Node > d_counterexample_body;\r
+  /** free variable for instantiation constant type */\r
+  std::map< TypeNode, Node > d_free_vars;\r
+private:\r
+  /** make instantiation constants for */\r
+  void makeInstantiationConstantsFor( Node f );\r
+public:\r
+  /** map from universal quantifiers to the list of instantiation constants */\r
+  std::map< Node, std::vector< Node > > d_inst_constants;\r
+  /** set instantiation level attr */\r
+  void setInstantiationLevelAttr( Node n, uint64_t level );\r
+  /** set instantiation constant attr */\r
+  void setInstantiationConstantAttr( Node n, Node f );\r
+  /** get the i^th instantiation constant of f */\r
+  Node getInstantiationConstant( Node f, int i ) { return d_inst_constants[f][i]; }\r
+  /** get number of instantiation constants for f */\r
+  int getNumInstantiationConstants( Node f ) { return (int)d_inst_constants[f].size(); }\r
+  /** get the ce body f[e/x] */\r
+  Node getCounterexampleBody( Node f );\r
+  /** get the skolemized body f[e/x] */\r
+  Node getSkolemizedBody( Node f );\r
+  /** returns node n with bound vars of f replaced by instantiation constants of f\r
+      node n : is the futur pattern\r
+      node f : is the quantifier containing which bind the variable\r
+      return a pattern where the variable are replaced by variable for\r
+      instantiation.\r
+   */\r
+  Node getSubstitutedNode( Node n, Node f );\r
+  /** same as before but node f is just linked to the new pattern by the\r
+      applied attribute\r
+      vars the bind variable\r
+      nvars the same variable but with an attribute\r
+  */\r
+  Node convertNodeToPattern( Node n, Node f,\r
+                             const std::vector<Node> & vars,\r
+                             const std::vector<Node> & nvars);\r
+  /** get free variable for instantiation constant */\r
+  Node getFreeVariableForInstConstant( Node n );\r
+};/* class TermDb */\r
+\r
+}\r
+}\r
+}\r
+\r
+#endif\r
index ead47e4b0a010c9a48846227b688a67edb6e5edb..27310e21b5929d3c54b9bc2352fe13e38bbb7263 100644 (file)
 #include <map>
 #include <time.h>
 #include "theory/quantifiers/theory_quantifiers_instantiator.h"
-
-#define USE_FLIP_DECISION
-
-//static bool clockSet = false;
-//double initClock;
+#include "theory/quantifiers/term_database.h"
 
 using namespace std;
 using namespace CVC4;
@@ -45,11 +41,6 @@ TheoryQuantifiers::TheoryQuantifiers(Context* c, context::UserContext* u, Output
   d_numRestarts(0){
   d_numInstantiations = 0;
   d_baseDecLevel = -1;
-  if( Options::current()->finiteModelFind ){
-    qe->addModule( new ModelEngine( this ) );
-  }else{
-    qe->addModule( new InstantiationEngine( this ) );
-  }
 }
 
 
@@ -65,10 +56,10 @@ void TheoryQuantifiers::addSharedTerm(TNode t) {
 void TheoryQuantifiers::notifyEq(TNode lhs, TNode rhs) {
   Debug("quantifiers-other") << "TheoryQuantifiers::notifyEq(): "
                      << lhs << " = " << rhs << endl;
-  
+
 }
 
-void TheoryQuantifiers::preRegisterTerm(TNode n) {  
+void TheoryQuantifiers::preRegisterTerm(TNode n) {
   Debug("quantifiers-prereg") << "TheoryQuantifiers::preRegisterTerm() " << n << endl;
   if( n.getKind()==FORALL && !n.hasAttribute(InstConstantAttribute()) ){
     getQuantifiersEngine()->registerQuantifier( n );
@@ -97,6 +88,10 @@ Node TheoryQuantifiers::getValue(TNode n) {
   }
 }
 
+void TheoryQuantifiers::collectModelInfo( TheoryModel* m ){
+
+}
+
 void TheoryQuantifiers::check(Effort e) {
   CodeTimer codeTimer(d_theoryTime);
 
@@ -119,7 +114,7 @@ void TheoryQuantifiers::check(Effort e) {
           break;
         }
       }
-      break;  
+      break;
     default:
       Unhandled(assertion.getKind());
       break;
@@ -147,7 +142,7 @@ void TheoryQuantifiers::assertExistential( Node n ){
   Assert( n.getKind()== NOT && n[0].getKind()==FORALL );
   if( !n[0].hasAttribute(InstConstantAttribute()) ){
     if( d_skolemized.find( n )==d_skolemized.end() ){
-      Node body = getQuantifiersEngine()->getSkolemizedBody( n[0] );
+      Node body = getQuantifiersEngine()->getTermDatabase()->getSkolemizedBody( n[0] );
       NodeBuilder<> nb(kind::OR);
       nb << n[0] << body.notNode();
       Node lem = nb;
@@ -159,9 +154,6 @@ void TheoryQuantifiers::assertExistential( Node n ){
 }
 
 bool TheoryQuantifiers::flipDecision(){
-#ifndef USE_FLIP_DECISION
-  return false;
-#else
   //Debug("quantifiers-flip") << "No instantiation given, flip decision, level = " << d_valuation.getDecisionLevel() << std::endl;
   //for( int i=1; i<=(int)d_valuation.getDecisionLevel(); i++ ){
   //  Debug("quantifiers-flip") << "   " << d_valuation.getDecision( i ) << std::endl;
@@ -179,7 +171,6 @@ bool TheoryQuantifiers::flipDecision(){
     return restart();
   }
   return true;
-#endif
 }
 
 bool TheoryQuantifiers::restart(){
index 05c3b9695d572df37b2ae4cf27a3bf456a011e7f..517786400d89b8ed557275dc062378bf7bce6683 100644 (file)
@@ -34,6 +34,8 @@ namespace theory {
 namespace quantifiers {
 
 class TheoryEngine;
+class ModelEngine;
+class InstantiationEngine;
 
 class TheoryQuantifiers : public Theory {
 private:
@@ -59,6 +61,7 @@ public:
   void check(Effort e);
   void propagate(Effort level);
   Node getValue(TNode n);
+  void collectModelInfo( TheoryModel* m );
   void shutdown() { }
   std::string identify() const { return std::string("TheoryQuantifiers"); }
   bool flipDecision();
index a5b6cc3bc49990ddb3fb5ad77f297973f1052ade..84b6c65c7c8f2454b281fd20b6f2caaa6d423629 100644 (file)
@@ -48,7 +48,7 @@ void InstantiatorTheoryQuantifiers::processResetInstantiationRound( Theory::Effo
 }
 
 
-int InstantiatorTheoryQuantifiers::process( Node f, Theory::Effort effort, int e, int limitInst ){
+int InstantiatorTheoryQuantifiers::process( Node f, Theory::Effort effort, int e ){
   Debug("quant-quant") << "Quant: Try to solve (" << e << ") for " << f << "... " << std::endl;
   if( e<5 ){
     return InstStrategy::STATUS_UNFINISHED;
index 39e34c3191a9085513588c4005d74bfb43038c95..bf17495a1c62bb7790261ac7481aded605dbf399 100644 (file)
@@ -42,7 +42,7 @@ private:
   /**  reset instantiation */
   void processResetInstantiationRound( Theory::Effort effort );
   /** process at effort */
-  int process( Node f, Theory::Effort effort, int e, int limitInst );
+  int process( Node f, Theory::Effort effort, int e );
 
   class Statistics {
   public:
index e8a17eadd2112aaecff838d0ff8ca77b96b158f2..e4e3df9beb3abea2a8a73f6ac1881669a4aef90b 100644 (file)
 #include "theory/uf/theory_uf_instantiator.h"
 #include "theory/uf/theory_uf_strong_solver.h"
 #include "theory/uf/equality_engine.h"
+#include "theory/arrays/theory_arrays.h"
+#include "theory/datatypes/theory_datatypes.h"
 #include "theory/quantifiers/quantifiers_rewriter.h"
+#include "theory/quantifiers/model_engine.h"
+#include "theory/quantifiers/instantiation_engine.h"
+#include "theory/quantifiers/first_order_model.h"
+#include "theory/quantifiers/term_database.h"
 
 using namespace std;
 using namespace CVC4;
@@ -36,11 +42,12 @@ void InstStrategy::resetInstantiationRound( Theory::Effort effort ){
   d_no_instantiate_temp.insert( d_no_instantiate_temp.begin(), d_no_instantiate.begin(), d_no_instantiate.end() );
   processResetInstantiationRound( effort );
 }
+
 /** do instantiation round method */
-int InstStrategy::doInstantiation( Node f, Theory::Effort effort, int e, int limitInst ){
+int InstStrategy::doInstantiation( Node f, Theory::Effort effort, int e ){
   if( shouldInstantiate( f ) ){
     int origLemmas = d_quantEngine->getNumLemmasWaiting();
-    int retVal = process( f, effort, e, limitInst );
+    int retVal = process( f, effort, e );
     if( d_quantEngine->getNumLemmasWaiting()!=origLemmas ){
       for( int i=0; i<(int)d_priority_over.size(); i++ ){
         d_priority_over[i]->d_no_instantiate_temp.push_back( f );
@@ -52,156 +59,61 @@ int InstStrategy::doInstantiation( Node f, Theory::Effort effort, int e, int lim
   }
 }
 
-bool TermArgTrie::addTerm2( QuantifiersEngine* qe, Node n, int argIndex ){
-  if( argIndex<(int)n.getNumChildren() ){
-    Node r = qe->getEqualityQuery()->getRepresentative( n[ argIndex ] );
-    std::map< Node, TermArgTrie >::iterator it = d_data.find( r );
-    if( it==d_data.end() ){
-      d_data[r].addTerm2( qe, n, argIndex+1 );
-      return true;
-    }else{
-      return it->second.addTerm2( qe, n, argIndex+1 );
-    }
+QuantifiersEngine::QuantifiersEngine(context::Context* c, TheoryEngine* te):
+d_te( te ),
+d_active( c ){
+  d_eq_query = new EqualityQueryQuantifiersEngine( this );
+  d_term_db = new quantifiers::TermDb( this );
+  d_hasAddedLemma = false;
+
+  //the model object
+  d_model = new quantifiers::FirstOrderModel( this, c, "FirstOrderModel" );
+
+  //add quantifiers modules
+  if( !Options::current()->finiteModelFind || Options::current()->fmfInstEngine ){
+    //the instantiation must set incomplete flag unless finite model finding is turned on
+    d_inst_engine = new quantifiers::InstantiationEngine( this, !Options::current()->finiteModelFind );
+    d_modules.push_back(  d_inst_engine );
   }else{
-    //store n in d_data (this should be interpretted as the "data" and not as a reference to a child)
-    d_data[n].d_data.clear();
-    return false;
+    d_inst_engine = NULL;
   }
-}
-
-void TermDb::addTerm( Node n, std::vector< Node >& added, bool withinQuant ){
-  //don't add terms in quantifier bodies
-  if( !withinQuant || Options::current()->registerQuantBodyTerms ){
-    if( d_processed.find( n )==d_processed.end() ){
-      d_processed[n] = true;
-      //if this is an atomic trigger, consider adding it
-      if( Trigger::isAtomicTrigger( n ) ){
-        if( !n.hasAttribute(InstConstantAttribute()) ){
-          Debug("term-db") << "register trigger term " << n << std::endl;
-          //Notice() << "register trigger term " << n << std::endl;
-          Node op = n.getOperator();
-          d_op_map[op].push_back( n );
-          d_type_map[ n.getType() ].push_back( n );
-          added.push_back( n );
-
-          uf::InstantiatorTheoryUf* d_ith = (uf::InstantiatorTheoryUf*)d_quantEngine->getInstantiator( THEORY_UF );
-          for( int i=0; i<(int)n.getNumChildren(); i++ ){
-            addTerm( n[i], added, withinQuant );
-            if( Options::current()->efficientEMatching ){
-              if( d_parents[n[i]][op].empty() ){
-                //must add parent to equivalence class info
-                Node nir = d_ith->getRepresentative( n[i] );
-                uf::EqClassInfo* eci_nir = d_ith->getEquivalenceClassInfo( nir );
-                if( eci_nir ){
-                  eci_nir->d_pfuns[ op ] = true;
-                }
-              }
-              //add to parent structure
-              if( std::find( d_parents[n[i]][op][i].begin(), d_parents[n[i]][op][i].end(), n )==d_parents[n[i]][op][i].end() ){
-                d_parents[n[i]][op][i].push_back( n );
-              }
-            }
-          }
-          if( Options::current()->efficientEMatching ){
-            //new term, add n to candidate generators
-            for( int i=0; i<(int)d_ith->d_cand_gens[op].size(); i++ ){
-              d_ith->d_cand_gens[op][i]->addCandidate( n );
-            }
-          }
-          if( Options::current()->eagerInstQuant ){
-            if( !n.hasAttribute(InstLevelAttribute()) && n.getAttribute(InstLevelAttribute())==0 ){
-              int addedLemmas = 0;
-              for( int i=0; i<(int)d_ith->d_op_triggers[op].size(); i++ ){
-                addedLemmas += d_ith->d_op_triggers[op][i]->addTerm( n );
-              }
-              //Message() << "Terms, added lemmas: " << addedLemmas << std::endl;
-              d_quantEngine->flushLemmas( &d_quantEngine->getTheoryEngine()->getTheory( THEORY_QUANTIFIERS )->getOutputChannel() );
-            }
-          }
-        }
-      }
-      for( int i=0; i<(int)n.getNumChildren(); i++ ){
-        addTerm( n[i], added, withinQuant );
-      }
-    }
+  if( Options::current()->finiteModelFind ){
+    d_model_engine = new quantifiers::ModelEngine( this );
+    d_modules.push_back( d_model_engine );
+  }else{
+    d_model_engine = NULL;
   }
-}
 
-void TermDb::reset( Theory::Effort effort ){
-  int nonCongruentCount = 0;
-  int congruentCount = 0;
-  int alreadyCongruentCount = 0;
-  //rebuild d_func/pred_map_trie for each operation, this will calculate all congruent terms
-  for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){
-    if( !it->second.empty() ){
-      if( it->second[0].getType()==NodeManager::currentNM()->booleanType() ){
-        d_pred_map_trie[ 0 ][ it->first ].d_data.clear();
-        d_pred_map_trie[ 1 ][ it->first ].d_data.clear();
-      }else{
-        d_func_map_trie[ it->first ].d_data.clear();
-        for( int i=0; i<(int)it->second.size(); i++ ){
-          Node n = it->second[i];
-          if( !n.getAttribute(NoMatchAttribute()) ){
-            if( !d_func_map_trie[ it->first ].addTerm( d_quantEngine, n ) ){
-              NoMatchAttribute nma;
-              n.setAttribute(nma,true);
-              congruentCount++;
-            }else{
-              nonCongruentCount++;
-            }
-          }else{
-            congruentCount++;
-            alreadyCongruentCount++;
-          }
-        }
-      }
-    }
-  }
-  for( int i=0; i<2; i++ ){
-    Node n = NodeManager::currentNM()->mkConst( i==1 );
-    eq::EqClassIterator eqc( d_quantEngine->getEqualityQuery()->getRepresentative( n ),
-                              ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine() );
-    while( !eqc.isFinished() ){
-      Node en = (*eqc);
-      if( en.getKind()==APPLY_UF && !en.hasAttribute(InstConstantAttribute()) ){
-        if( !en.getAttribute(NoMatchAttribute()) ){
-          Node op = en.getOperator();
-          if( !d_pred_map_trie[i][op].addTerm( d_quantEngine, en ) ){
-            NoMatchAttribute nma;
-            en.setAttribute(nma,true);
-            congruentCount++;
-          }else{
-            nonCongruentCount++;
-          }
-        }else{
-          alreadyCongruentCount++;
-        }
-      }
-      ++eqc;
-    }
-  }
-  Debug("term-db-cong") << "TermDb: Reset" << std::endl;
-  Debug("term-db-cong") << "Congruent/Non-Congruent = ";
-  Debug("term-db-cong") << congruentCount << "(" << alreadyCongruentCount << ") / " << nonCongruentCount << std::endl;
+  //options
+  d_optInstCheckDuplicate = true;
+  d_optInstMakeRepresentative = true;
+  d_optInstAddSplits = false;
+  d_optMatchIgnoreModelBasis = false;
+  d_optInstLimitActive = false;
+  d_optInstLimit = 0;
 }
 
+Instantiator* QuantifiersEngine::getInstantiator( int id ){
+  return d_te->getTheory( id )->getInstantiator();
+}
 
-
-QuantifiersEngine::QuantifiersEngine(context::Context* c, TheoryEngine* te):
-d_te( te ),
-d_forall_asserts( c ),
-d_active( c ){
-  d_eq_query = NULL;
-  d_term_db = new TermDb( this );
+context::Context* QuantifiersEngine::getSatContext(){
+  return d_te->getTheory( THEORY_QUANTIFIERS )->getSatContext();
 }
 
-Instantiator* QuantifiersEngine::getInstantiator( int id ){
-  return d_te->getTheory( id )->getInstantiator();
+OutputChannel& QuantifiersEngine::getOutputChannel(){
+  return d_te->getTheory( THEORY_QUANTIFIERS )->getOutputChannel();
+}
+/** get default valuation for the quantifiers engine */
+Valuation& QuantifiersEngine::getValuation(){
+  return d_te->getTheory( THEORY_QUANTIFIERS )->getValuation();
 }
 
 void QuantifiersEngine::check( Theory::Effort e ){
   CodeTimer codeTimer(d_time);
 
+  d_hasAddedLemma = false;
+  d_model_set = false;
   if( e==Theory::EFFORT_LAST_CALL ){
     ++(d_statistics.d_instantiation_rounds_lc);
   }else if( e==Theory::EFFORT_FULL ){
@@ -210,9 +122,11 @@ void QuantifiersEngine::check( Theory::Effort e ){
   for( int i=0; i<(int)d_modules.size(); i++ ){
     d_modules[i]->check( e );
   }
-  //if( e==Theory::EFFORT_FULL ){
-  //  Notice() << "Done instantiation Round" << std::endl;
-  //}
+  //build the model if not done so already
+  //  this happens if no quantifiers are currently asserted and no model-building module is enabled
+  if( Options::current()->produceModels && e==Theory::EFFORT_LAST_CALL && !d_hasAddedLemma && !d_model_set ){
+    d_te->getModelBuilder()->buildModel( d_model );
+  }
 }
 
 std::vector<Node> QuantifiersEngine::createInstVariable( std::vector<Node> & vars ){
@@ -227,25 +141,9 @@ std::vector<Node> QuantifiersEngine::createInstVariable( std::vector<Node> & var
   return inst_constant;
 }
 
-void QuantifiersEngine::makeInstantiationConstantsFor( Node f ){
-  if( d_inst_constants.find( f )==d_inst_constants.end() ){
-    Debug("quantifiers-engine") << "Instantiation constants for " << f << " : " << std::endl;
-    for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
-      d_vars[f].push_back( f[0][i] );
-      //make instantiation constants
-      Node ic = NodeManager::currentNM()->mkInstConstant( f[0][i].getType() );
-      d_inst_constants_map[ic] = f;
-      d_inst_constants[ f ].push_back( ic );
-      Debug("quantifiers-engine") << "  " << ic << std::endl;
-      //set the var number attribute
-      InstVarNumAttribute ivna;
-      ic.setAttribute(ivna,i);
-    }
-  }
-}
-
 void QuantifiersEngine::registerQuantifier( Node f ){
   if( std::find( d_quants.begin(), d_quants.end(), f )==d_quants.end() ){
+    d_quants.push_back( f );
     std::vector< Node > quants;
 #ifdef REWRITE_ASSERTED_QUANTIFIERS
     //do assertion-time rewriting of quantifier
@@ -277,9 +175,9 @@ void QuantifiersEngine::registerQuantifier( Node f ){
       ++(d_statistics.d_num_quant);
       Assert( quants[q].getKind()==FORALL );
       //register quantifier
-      d_quants.push_back( quants[q] );
+      d_r_quants.push_back( quants[q] );
       //make instantiation constants for quants[q]
-      makeInstantiationConstantsFor( quants[q] );
+      d_term_db->makeInstantiationConstantsFor( quants[q] );
       //compute symbols in quants[q]
       std::vector< Node > syms;
       computeSymbols( quants[q][1], syms );
@@ -302,7 +200,7 @@ void QuantifiersEngine::registerQuantifier( Node f ){
       for( int i=0; i<(int)d_modules.size(); i++ ){
         d_modules[i]->registerQuantifier( quants[q] );
       }
-      Node ceBody = getCounterexampleBody( quants[q] );
+      Node ceBody = d_term_db->getCounterexampleBody( quants[q] );
       generatePhaseReqs( quants[q], ceBody );
       //also register it with the strong solver
       if( Options::current()->finiteModelFind ){
@@ -315,14 +213,14 @@ void QuantifiersEngine::registerQuantifier( Node f ){
 void QuantifiersEngine::registerPattern( std::vector<Node> & pattern) {
   for(std::vector<Node>::iterator p = pattern.begin(); p != pattern.end(); ++p){
     std::vector< Node > added;
-    d_term_db->addTerm(*p,added);
+    getTermDatabase()->addTerm(*p,added);
   }
 }
 
 void QuantifiersEngine::assertNode( Node f ){
   Assert( f.getKind()==FORALL );
   for( int j=0; j<(int)d_quant_rewritten[f].size(); j++ ){
-    d_forall_asserts.push_back( d_quant_rewritten[f][j] );
+    d_model->d_forall_asserts.push_back( d_quant_rewritten[f][j] );
     for( int i=0; i<(int)d_modules.size(); i++ ){
       d_modules[i]->assertNode( d_quant_rewritten[f][j] );
     }
@@ -337,20 +235,26 @@ void QuantifiersEngine::propagate( Theory::Effort level ){
   }
 }
 
+void QuantifiersEngine::resetInstantiationRound( Theory::Effort level ){
+  for( int i=0; i<theory::THEORY_LAST; i++ ){
+    if( getInstantiator( i ) ){
+      getInstantiator( i )->resetInstantiationRound( level );
+    }
+  }
+  getTermDatabase()->reset( level );
+}
+
 void QuantifiersEngine::addTermToDatabase( Node n, bool withinQuant ){
-  if( d_term_db ){
-    std::vector< Node > added;
-    d_term_db->addTerm( n, added, withinQuant );
+  std::vector< Node > added;
+  getTermDatabase()->addTerm( n, added, withinQuant );
 #ifdef COMPUTE_RELEVANCE
-    for( int i=0; i<(int)added.size(); i++ ){
-      if( !withinQuant ){
-        setRelevance( added[i].getOperator(), 0 );
-      }
+  for( int i=0; i<(int)added.size(); i++ ){
+    if( !withinQuant ){
+      setRelevance( added[i].getOperator(), 0 );
     }
-#endif
-  }else{
-    Notice() << "Warning: no term database for quantifier engine." << std::endl;
   }
+#endif
+
 }
 
 bool QuantifiersEngine::addLemma( Node lem ){
@@ -377,8 +281,8 @@ bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& terms )
     //}
   Assert( f.getKind()==FORALL );
   Assert( !f.hasAttribute(InstConstantAttribute()) );
-  Assert( d_vars[f].size()==terms.size() && d_vars[f].size()==f[0].getNumChildren() );
-  Node body = f[ 1 ].substitute( d_vars[f].begin(), d_vars[f].end(),
+  Assert( d_term_db->d_vars[f].size()==terms.size() && d_term_db->d_vars[f].size()==f[0].getNumChildren() );
+  Node body = f[ 1 ].substitute( d_term_db->d_vars[f].begin(), d_term_db->d_vars[f].end(),
                                  terms.begin(), terms.end() );
   NodeBuilder<> nb(kind::OR);
   nb << d_rewritten_quant[f].notNode() << body;
@@ -411,11 +315,11 @@ bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& terms )
             maxInstLevel = terms[i].getAttribute(InstLevelAttribute());
           }
         }else{
-          setInstantiationLevelAttr( terms[i], 0 );
+          d_term_db->setInstantiationLevelAttr( terms[i], 0 );
         }
       }
     }
-    setInstantiationLevelAttr( body, maxInstLevel+1 );
+    d_term_db->setInstantiationLevelAttr( body, maxInstLevel+1 );
     ++(d_statistics.d_instantiations);
     d_statistics.d_total_inst_var += (int)terms.size();
     d_statistics.d_max_instantiation_level.maxAssign( maxInstLevel+1 );
@@ -426,7 +330,7 @@ bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& terms )
   }
 }
 
-bool QuantifiersEngine::addInstantiation( Node f, InstMatch& m, bool addSplits ){
+bool QuantifiersEngine::addInstantiation( Node f, InstMatch& m ){
   m.makeComplete( f, this );
   m.makeRepresentative( this );
   Debug("quant-duplicate") << "After make rep: " << m << std::endl;
@@ -437,7 +341,7 @@ bool QuantifiersEngine::addInstantiation( Node f, InstMatch& m, bool addSplits )
   }
   Debug("quant-duplicate") << " -> Does not exist." << std::endl;
   std::vector< Node > match;
-  m.computeTermVec( d_inst_constants[f], match );
+  m.computeTermVec( d_term_db->d_inst_constants[f], match );
 
   //old....
   //m.makeRepresentative( d_eq_query );
@@ -494,40 +398,16 @@ bool QuantifiersEngine::addSplitEquality( Node n1, Node n2, bool reqPhase, bool
 }
 
 void QuantifiersEngine::flushLemmas( OutputChannel* out ){
-  for( int i=0; i<(int)d_lemmas_waiting.size(); i++ ){
-    out->lemma( d_lemmas_waiting[i] );
-  }
-  d_lemmas_waiting.clear();
-}
-
-Node QuantifiersEngine::getCounterexampleBody( Node f ){
-  std::map< Node, Node >::iterator it = d_counterexample_body.find( f );
-  if( it==d_counterexample_body.end() ){
-    makeInstantiationConstantsFor( f );
-    Node n = getSubstitutedNode( f[1], f );
-    d_counterexample_body[ f ] = n;
-    return n;
-  }else{
-    return it->second;
-  }
-}
-
-Node QuantifiersEngine::getSkolemizedBody( Node f ){
-  Assert( f.getKind()==FORALL );
-  if( d_skolem_body.find( f )==d_skolem_body.end() ){
-    std::vector< Node > vars;
-    for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
-      Node skv = NodeManager::currentNM()->mkSkolem( f[0][i].getType() );
-      d_skolem_constants[ f ].push_back( skv );
-      vars.push_back( f[0][i] );
-    }
-    d_skolem_body[ f ] = f[ 1 ].substitute( vars.begin(), vars.end(),
-                                            d_skolem_constants[ f ].begin(), d_skolem_constants[ f ].end() );
-    if( f.hasAttribute(InstLevelAttribute()) ){
-      setInstantiationLevelAttr( d_skolem_body[ f ], f.getAttribute(InstLevelAttribute()) );
+  if( !d_lemmas_waiting.empty() ){
+    //take default output channel if none is provided
+    d_hasAddedLemma = true;
+    for( int i=0; i<(int)d_lemmas_waiting.size(); i++ ){
+      if( out ){
+        out->lemma( d_lemmas_waiting[i] );
+      }
     }
+    d_lemmas_waiting.clear();
   }
-  return d_skolem_body[ f ];
 }
 
 void QuantifiersEngine::getPhaseReqTerms( Node f, std::vector< Node >& nodes ){
@@ -553,7 +433,7 @@ void QuantifiersEngine::getPhaseReqTerms( Node f, std::vector< Node >& nodes ){
         }
         Debug("literal-matching") << "  Make " << prev << " -> " << nodes[i] << std::endl;
         Assert( prev.hasAttribute(InstConstantAttribute()) );
-        setInstantiationConstantAttr( nodes[i], prev.getAttribute(InstConstantAttribute()) );
+        d_term_db->setInstantiationConstantAttr( nodes[i], prev.getAttribute(InstConstantAttribute()) );
         ++(d_statistics.d_lit_phase_req);
       }else{
         ++(d_statistics.d_lit_phase_nreq);
@@ -634,54 +514,6 @@ void QuantifiersEngine::generatePhaseReqs( Node f, Node n ){
 
 }
 
-Node QuantifiersEngine::getSubstitutedNode( Node n, Node f ){
-  return convertNodeToPattern(n,f,d_vars[f],d_inst_constants[ f ]);
-}
-
-Node QuantifiersEngine::convertNodeToPattern( Node n, Node f, const std::vector<Node> & vars,
-                                              const std::vector<Node> & inst_constants){
-  Node n2 = n.substitute( vars.begin(), vars.end(),
-                          inst_constants.begin(),
-                          inst_constants.end() );
-  setInstantiationConstantAttr( n2, f );
-  return n2;
-}
-
-
-void QuantifiersEngine::setInstantiationLevelAttr( Node n, uint64_t level ){
-  if( !n.hasAttribute(InstLevelAttribute()) ){
-    InstLevelAttribute ila;
-    n.setAttribute(ila,level);
-  }
-  for( int i=0; i<(int)n.getNumChildren(); i++ ){
-    setInstantiationLevelAttr( n[i], level );
-  }
-}
-
-
-void QuantifiersEngine::setInstantiationConstantAttr( Node n, Node f ){
-  if( !n.hasAttribute(InstConstantAttribute()) ){
-    bool setAttr = false;
-    if( n.getKind()==INST_CONSTANT ){
-      setAttr = true;
-    }else{
-      for( int i=0; i<(int)n.getNumChildren(); i++ ){
-        setInstantiationConstantAttr( n[i], f );
-        if( n[i].hasAttribute(InstConstantAttribute()) ){
-          setAttr = true;
-        }
-      }
-    }
-    if( setAttr ){
-      InstConstantAttribute ica;
-      n.setAttribute(ica,f);
-      //also set the no-match attribute
-      NoMatchAttribute nma;
-      n.setAttribute(nma,true);
-    }
-  }
-}
-
 QuantifiersEngine::Statistics::Statistics():
   d_num_quant("QuantifiersEngine::Num_Quantifiers", 0),
   d_instantiation_rounds("QuantifiersEngine::Rounds_Instantiation_Full", 0),
@@ -737,24 +569,6 @@ QuantifiersEngine::Statistics::~Statistics(){
   StatisticsRegistry::unregisterStat(&d_multi_trigger_instantiations);
 }
 
-Node QuantifiersEngine::getFreeVariableForInstConstant( Node n ){
-  TypeNode tn = n.getType();
-  if( d_free_vars.find( tn )==d_free_vars.end() ){
-    //if integer or real, make zero
-    if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){
-      Rational z(0);
-      d_free_vars[tn] = NodeManager::currentNM()->mkConst( z );
-    }else{
-      if( d_term_db->d_type_map[ tn ].empty() ){
-        d_free_vars[tn] = NodeManager::currentNM()->mkVar( tn );
-      }else{
-        d_free_vars[tn] =d_term_db->d_type_map[ tn ][ 0 ];
-      }
-    }
-  }
-  return d_free_vars[tn];
-}
-
 /** compute symbols */
 void QuantifiersEngine::computeSymbols( Node n, std::vector< Node >& syms ){
   if( n.getKind()==APPLY_UF ){
@@ -786,3 +600,87 @@ void QuantifiersEngine::setRelevance( Node s, int r ){
     }
   }
 }
+
+
+
+bool EqualityQueryQuantifiersEngine::hasTerm( Node a ){
+  eq::EqualityEngine* ee = d_qe->getTheoryEngine()->getSharedTermsDatabase()->getEqualityEngine();
+  if( ee->hasTerm( a ) ){
+    return true;
+  }
+  for( int i=0; i<theory::THEORY_LAST; i++ ){
+    if( d_qe->getInstantiator( i ) ){
+      if( d_qe->getInstantiator( i )->hasTerm( a ) ){
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+Node EqualityQueryQuantifiersEngine::getRepresentative( Node a ){
+  eq::EqualityEngine* ee = d_qe->getTheoryEngine()->getSharedTermsDatabase()->getEqualityEngine();
+  if( ee->hasTerm( a ) ){
+    return ee->getRepresentative( a );
+  }
+  for( int i=0; i<theory::THEORY_LAST; i++ ){
+    if( d_qe->getInstantiator( i ) ){
+      if( d_qe->getInstantiator( i )->hasTerm( a ) ){
+        return d_qe->getInstantiator( i )->getRepresentative( a );
+      }
+    }
+  }
+  return a;
+}
+
+bool EqualityQueryQuantifiersEngine::areEqual( Node a, Node b ){
+  if( a==b ){
+    return true;
+  }else{
+    eq::EqualityEngine* ee = d_qe->getTheoryEngine()->getSharedTermsDatabase()->getEqualityEngine();
+    if( ee->hasTerm( a ) && ee->hasTerm( b ) ){
+      if( ee->areEqual( a, b ) ){
+        return true;
+      }
+    }
+    for( int i=0; i<theory::THEORY_LAST; i++ ){
+      if( d_qe->getInstantiator( i ) ){
+        if( d_qe->getInstantiator( i )->areEqual( a, b ) ){
+          return true;
+        }
+      }
+    }
+    //std::cout << "Equal = " << eq_sh << " " << eq_uf << " " << eq_a << " " << eq_dt << std::endl;
+    return false;
+  }
+}
+
+bool EqualityQueryQuantifiersEngine::areDisequal( Node a, Node b ){
+  eq::EqualityEngine* ee = d_qe->getTheoryEngine()->getSharedTermsDatabase()->getEqualityEngine();
+  if( ee->hasTerm( a ) && ee->hasTerm( b ) ){
+    if( ee->areDisequal( a, b, false ) ){
+      return true;
+    }
+  }
+  for( int i=0; i<theory::THEORY_LAST; i++ ){
+    if( d_qe->getInstantiator( i ) ){
+      if( d_qe->getInstantiator( i )->areDisequal( a, b ) ){
+        return true;
+      }
+    }
+  }
+  return false;
+  //std::cout << "Disequal = " << deq_sh << " " << deq_uf << " " << deq_a << " " << deq_dt << std::endl;
+}
+
+Node EqualityQueryQuantifiersEngine::getInternalRepresentative( Node a ){
+  //for( int i=0; i<theory::THEORY_LAST; i++ ){
+  //  if( d_qe->getInstantiator( i ) ){
+  //    if( d_qe->getInstantiator( i )->hasTerm( a ) ){
+  //      return d_qe->getInstantiator( i )->getInternalRepresentative( a );
+  //    }
+  //  }
+  //}
+  //return a;
+  return d_qe->getInstantiator( THEORY_UF )->getInternalRepresentative( a );
+}
index d0c5fb00b7ada44fe0b4de4c1d06229ddd0f6930..5477214b05ef348b407e6ddb07db0c4540e91f83 100644 (file)
@@ -66,7 +66,7 @@ protected:
   /** reset instantiation */
   virtual void processResetInstantiationRound( Theory::Effort effort ) = 0;
   /** process method */
-  virtual int process( Node f, Theory::Effort effort, int e, int limitInst = 0 ) = 0;
+  virtual int process( Node f, Theory::Effort effort, int e ) = 0;
 public:
   InstStrategy( QuantifiersEngine* ie ) : d_quantEngine( ie ){}
   virtual ~InstStrategy(){}
@@ -74,7 +74,7 @@ public:
   /** reset instantiation */
   void resetInstantiationRound( Theory::Effort effort );
   /** do instantiation round method */
-  int doInstantiation( Node f, Theory::Effort effort, int e, int limitInst = 0 );
+  int doInstantiation( Node f, Theory::Effort effort, int e );
   /** update status */
   static void updateStatus( int& currStatus, int addStatus ){
     if( addStatus==STATUS_UNFINISHED ){
@@ -99,9 +99,13 @@ public:
 };/* class InstStrategy */
 
 class QuantifiersModule {
+protected:
+  QuantifiersEngine* d_quantEngine;
 public:
-  QuantifiersModule(){}
+  QuantifiersModule( QuantifiersEngine* qe ) : d_quantEngine( qe ){}
   ~QuantifiersModule(){}
+  //get quantifiers engine
+  QuantifiersEngine* getQuantifiersEngine() { return d_quantEngine; }
   /* Call during check registerQuantifier has already been called */
   virtual void check( Theory::Effort e ) = 0;
   /* Called for new quantifiers */
@@ -111,59 +115,17 @@ public:
   virtual Node explain(TNode n) = 0;
 };/* class QuantifiersModule */
 
-class TermArgTrie {
-private:
-  bool addTerm2( QuantifiersEngine* qe, Node n, int argIndex );
-public:
-  /** the data */
-  std::map< Node, TermArgTrie > d_data;
-public:
-  bool addTerm( QuantifiersEngine* qe, Node n ) { return addTerm2( qe, n, 0 ); }
-};/* class TermArgTrie */
-
-class TermDb {
-private:
-  /** reference to the quantifiers engine */
-  QuantifiersEngine* d_quantEngine;
-  /** calculated no match terms */
-  bool d_matching_active;
-  /** terms processed */
-  std::map< Node, bool > d_processed;
-public:
-  TermDb( QuantifiersEngine* qe ) : d_quantEngine( qe ), d_matching_active( true ){}
-  ~TermDb(){}
-  /** map from APPLY_UF operators to ground terms for that operator */
-  std::map< Node, std::vector< Node > > d_op_map;
-  /** map from APPLY_UF functions to trie */
-  std::map< Node, TermArgTrie > d_func_map_trie;
-  /** map from APPLY_UF predicates to trie */
-  std::map< Node, TermArgTrie > d_pred_map_trie[2];
-  /** map from type nodes to terms of that type */
-  std::map< TypeNode, std::vector< Node > > d_type_map;
-  /** add a term to the database */
-  void addTerm( Node n, std::vector< Node >& added, bool withinQuant = false );
-  /** reset (calculate which terms are active) */
-  void reset( Theory::Effort effort );
-  /** set active */
-  void setMatchingActive( bool a ) { d_matching_active = a; }
-  /** get active */
-  bool getMatchingActive() { return d_matching_active; }
-public:
-  /** parent structure (for efficient E-matching):
-      n -> op -> index -> L
-      map from node "n" to a list of nodes "L", where each node n' in L
-        has operator "op", and n'["index"] = n.
-      for example, d_parents[n][f][1] = { f( t1, n ), f( t2, n ), ... }
-  */
-  std::map< Node, std::map< Node, std::map< int, std::vector< Node > > > > d_parents;
-};/* class TermDb */
-
 namespace quantifiers {
   class InstantiationEngine;
+  class ModelEngine;
+  class TermDb;
+  class FirstOrderModel;
 }/* CVC4::theory::quantifiers */
 
+
 class QuantifiersEngine {
   friend class quantifiers::InstantiationEngine;
+  friend class quantifiers::ModelEngine;
   friend class InstMatch;
 private:
   typedef context::CDHashMap< Node, bool, NodeHashFunction > BoolMap;
@@ -171,41 +133,35 @@ private:
   TheoryEngine* d_te;
   /** vector of modules for quantifiers */
   std::vector< QuantifiersModule* > d_modules;
+  /** instantiation engine */
+  quantifiers::InstantiationEngine* d_inst_engine;
+  /** model engine */
+  quantifiers::ModelEngine* d_model_engine;
   /** equality query class */
   EqualityQuery* d_eq_query;
 
-  /** list of all quantifiers */
+  /** list of all quantifiers (pre-rewrite) */
   std::vector< Node > d_quants;
-  /** list of quantifiers asserted in the current context */
-  context::CDList<Node> d_forall_asserts;
-  /** map from universal quantifiers to the list of variables */
-  std::map< Node, std::vector< Node > > d_vars;
-  /** map from universal quantifiers to the list of skolem constants */
-  std::map< Node, std::vector< Node > > d_skolem_constants;
-  /** map from universal quantifiers to their skolemized body */
-  std::map< Node, Node > d_skolem_body;
-  /** map from universal quantifiers to their bound body */
-  std::map< Node, Node > d_bound_body;
-  /** instantiation constants to universal quantifiers */
-  std::map< Node, Node > d_inst_constants_map;
-  /** map from universal quantifiers to their counterexample body */
-  std::map< Node, Node > d_counterexample_body;
-  /** map from universal quantifiers to the list of instantiation constants */
-  std::map< Node, std::vector< Node > > d_inst_constants;
+  /** list of all quantifiers (post-rewrite) */
+  std::vector< Node > d_r_quants;
   /** map from quantifiers to whether they are active */
   BoolMap d_active;
   /** lemmas produced */
   std::map< Node, bool > d_lemmas_produced;
   /** lemmas waiting */
   std::vector< Node > d_lemmas_waiting;
+  /** has added lemma this round */
+  bool d_hasAddedLemma;
   /** inst matches produced for each quantifier */
   std::map< Node, InstMatchTrie > d_inst_match_trie;
-  /** free variable for instantiation constant type */
-  std::map< TypeNode, Node > d_free_vars;
   /** owner of quantifiers */
   std::map< Node, Theory* > d_owner;
   /** term database */
-  TermDb* d_term_db;
+  quantifiers::TermDb* d_term_db;
+  /** extended model object */
+  quantifiers::FirstOrderModel* d_model;
+  /** has the model been set? */
+  bool d_model_set;
   /** universal quantifiers that have been rewritten */
   std::map< Node, std::vector< Node > > d_quant_rewritten;
   /** map from rewritten universal quantifiers to the quantifier they are the consequence of */
@@ -223,12 +179,6 @@ private:
 private:
   /** helper functions compute phase requirements */
   static void computePhaseReqs2( Node n, bool polarity, std::map< Node, int >& phaseReqs );
-  /** set instantiation level attr */
-  void setInstantiationLevelAttr( Node n, uint64_t level );
-  /** set instantiation constant attr */
-  void setInstantiationConstantAttr( Node n, Node f );
-  /** make instantiation constants for */
-  void makeInstantiationConstantsFor( Node f );
 
   KEEP_STATISTIC(TimerStat, d_time, "theory::QuantifiersEngine::time");
 
@@ -241,11 +191,17 @@ public:
   TheoryEngine* getTheoryEngine() { return d_te; }
   /** get equality query object */
   EqualityQuery* getEqualityQuery() { return d_eq_query; }
-  /** set equality query object */
-  void setEqualityQuery( EqualityQuery* eq ) { d_eq_query = eq; }
+  /** get instantiation engine */
+  quantifiers::InstantiationEngine* getInstantiationEngine() { return d_inst_engine; }
+  /** get model engine */
+  quantifiers::ModelEngine* getModelEngine() { return d_model_engine; }
+  /** get default sat context for quantifiers engine */
+  context::Context* getSatContext();
+  /** get default output channel for the quantifiers engine */
+  OutputChannel& getOutputChannel();
+  /** get default valuation for the quantifiers engine */
+  Valuation& getValuation();
 public:
-  /** add module */
-  void addModule( QuantifiersModule* qm ) { d_modules.push_back( qm ); }
   /** check at level */
   void check( Theory::Effort e );
   /** register (non-rewritten) quantifier */
@@ -256,19 +212,24 @@ public:
   void assertNode( Node f );
   /** propagate */
   void propagate( Theory::Effort level );
+  /** reset instantiation round */
+  void resetInstantiationRound( Theory::Effort level );
+
+  //create inst variable
+  std::vector<Node> createInstVariable( std::vector<Node> & vars );
 public:
   /** add lemma lem */
   bool addLemma( Node lem );
   /** instantiate f with arguments terms */
   bool addInstantiation( Node f, std::vector< Node >& terms );
   /** do instantiation specified by m */
-  bool addInstantiation( Node f, InstMatch& m, bool addSplits = false );
+  bool addInstantiation( Node f, InstMatch& m );
   /** split on node n */
   bool addSplit( Node n, bool reqPhase = false, bool reqPhasePol = true );
   /** add split equality */
   bool addSplitEquality( Node n1, Node n2, bool reqPhase = false, bool reqPhasePol = true );
   /** has added lemma */
-  bool hasAddedLemma() { return !d_lemmas_waiting.empty(); }
+  bool hasAddedLemma() { return !d_lemmas_waiting.empty() || d_hasAddedLemma; }
   /** flush lemmas */
   void flushLemmas( OutputChannel* out );
   /** get number of waiting lemmas */
@@ -278,24 +239,6 @@ public:
   int getNumQuantifiers() { return (int)d_quants.size(); }
   /** get quantifier */
   Node getQuantifier( int i ) { return d_quants[i]; }
-  /** get number of asserted quantifiers */
-  int getNumAssertedQuantifiers() { return (int)d_forall_asserts.size(); }
-  /** get asserted quantifier */
-  Node getAssertedQuantifier( int i ) { return d_forall_asserts[i]; }
-  /** get instantiation constants */
-  void getInstantiationConstantsFor( Node f, std::vector< Node >& ics ) {
-    ics.insert( ics.begin(), d_inst_constants[f].begin(), d_inst_constants[f].end() );
-  }
-  /** get the i^th instantiation constant of f */
-  Node getInstantiationConstant( Node f, int i ) { return d_inst_constants[f][i]; }
-  /** get number of instantiation constants for f */
-  int getNumInstantiationConstants( Node f ) { return (int)d_inst_constants[f].size(); }
-  std::vector<Node> createInstVariable( std::vector<Node> & vars );
-public:
-  /** get the ce body f[e/x] */
-  Node getCounterexampleBody( Node f );
-  /** get the skolemized body f[e/x] */
-  Node getSkolemizedBody( Node f );
   /** set active */
   void setActive( Node n, bool val ) { d_active[n] = val; }
   /** get active */
@@ -316,26 +259,6 @@ public:
   static void computePhaseReqs( Node n, bool polarity, std::map< Node, bool >& phaseReqs );
   /** compute phase requirements */
   void generatePhaseReqs( Node f, Node n );
-public:
-  /** returns node n with bound vars of f replaced by instantiation constants of f
-      node n : is the futur pattern
-      node f : is the quantifier containing which bind the variable
-      return a pattern where the variable are replaced by variable for
-      instantiation.
-   */
-  Node getSubstitutedNode( Node n, Node f );
-  /** same as before but node f is just linked to the new pattern by the
-      applied attribute
-      vars the bind variable
-      nvars the same variable but with an attribute
-  */
-  Node convertNodeToPattern( Node n, Node f,
-                             const std::vector<Node> & vars,
-                             const std::vector<Node> & nvars);
-  /** get free variable for instantiation constant */
-  Node getFreeVariableForInstConstant( Node n );
-  /** get bound variable for variable */
-  Node getBoundVariableForVariable( Node n );
 public:
   /** has owner */
   bool hasOwner( Node f ) { return d_owner.find( f )!=d_owner.end(); }
@@ -344,8 +267,10 @@ public:
   /** set owner */
   void setOwner( Node f, Theory* t ) { d_owner[f] = t; }
 public:
+  /** get model */
+  quantifiers::FirstOrderModel* getModel() { return d_model; }
   /** get term database */
-  TermDb* getTermDatabase() { return d_term_db; }
+  quantifiers::TermDb* getTermDatabase() { return d_term_db; }
   /** add term to database */
   void addTermToDatabase( Node n, bool withinQuant = false );
 private:
@@ -380,8 +305,35 @@ public:
     ~Statistics();
   };/* class QuantifiersEngine::Statistics */
   Statistics d_statistics;
+public:
+  /** options */
+  bool d_optInstCheckDuplicate;
+  bool d_optInstMakeRepresentative;
+  bool d_optInstAddSplits;
+  bool d_optMatchIgnoreModelBasis;
+  bool d_optInstLimitActive;
+  int d_optInstLimit;
 };/* class QuantifiersEngine */
 
+
+
+/** equality query object using theory engine */
+class EqualityQueryQuantifiersEngine : public EqualityQuery
+{
+private:
+  /** pointer to theory engine */
+  QuantifiersEngine* d_qe;
+public:
+  EqualityQueryQuantifiersEngine( QuantifiersEngine* qe ) : d_qe( qe ){}
+  ~EqualityQueryQuantifiersEngine(){}
+  /** general queries about equality */
+  bool hasTerm( Node a );
+  Node getRepresentative( Node a );
+  bool areEqual( Node a, Node b );
+  bool areDisequal( Node a, Node b );
+  Node getInternalRepresentative( Node a );
+}; /* EqualityQueryQuantifiersEngine */
+
 }/* CVC4::theory namespace */
 }/* CVC4 namespace */
 
index 0d7f5005a2d07330e3f7d27bab781cd6308be659..265026b392d2e94483100f15ffed512addc4f24e 100644 (file)
@@ -317,13 +317,14 @@ Answer TheoryRewriteRules::addWatchIfDontKnow(Node g0, const RuleInst* ri,
                                               const size_t gid){
   /** TODO: Should use the representative of g, but should I keep the
       mapping for myself? */
-  /* If it false in one model (current valuation) it's false for all */
-  if (useCurrentModel){
-    Node val = getValuation().getValue(g0);
-    Debug("rewriterules") << "getValue:" << g0 << " = "
-                          << val << " is " << (val == d_false) << std::endl;
-    if (val == d_false) return AFALSE;
-  };
+  //AJR: removed this code after talking with Francois
+  ///* If it false in one model (current valuation) it's false for all */
+  //if (useCurrentModel){
+  //  Node val = getValuation().getValue(g0);
+  //  Debug("rewriterules") << "getValue:" << g0 << " = "
+  //                        << val << " is " << (val == d_false) << std::endl;
+  //  if (val == d_false) return AFALSE;
+  //};
   /** Currently create a node with a literal */
   Node g = getValuation().ensureLiteral(g0);
   GuardedMap::iterator l_i = d_guardeds.find(g);
@@ -508,6 +509,10 @@ Node TheoryRewriteRules::explain(TNode n){
   return substGuards(&i, TCache ());
 }
 
+void TheoryRewriteRules::collectModelInfo( TheoryModel* m ){
+
+}
+
 Theory::PPAssertStatus TheoryRewriteRules::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
   addRewriteRule(in);
   return PP_ASSERT_STATUS_UNSOLVED;
index e47fd2fd4f2fa071b3de43098e32622b15667648..d1c3eecf3258c9b21bfb088e4063cee1a09705cf 100644 (file)
@@ -30,6 +30,7 @@
 #include "theory/inst_match_impl.h"
 #include "util/stats.h"
 #include "theory/rewriterules/theory_rewriterules_preprocess.h"
+#include "theory/model.h"
 
 namespace CVC4 {
 namespace theory {
@@ -182,6 +183,7 @@ private:
       inside check */
   typedef std::vector< RuleInst* > QRuleInsts;
   QRuleInsts d_ruleinsts_to_add;
+
  public:
   /** true and false for predicate */
   Node d_true;
@@ -199,6 +201,7 @@ private:
   /** Usual function for theories */
   void check(Theory::Effort e);
   Node explain(TNode n);
+  void collectModelInfo( TheoryModel* m );
   void notifyEq(TNode lhs, TNode rhs);
   std::string identify() const {
     return "THEORY_REWRITERULES";
index d66fc78cbd12689226b30f1eefbd8a89fb2e3e5a..c3116aba08afd7816b84b28f62e48b40123098da 100644 (file)
@@ -22,6 +22,8 @@
 #include "theory/rewriterules/theory_rewriterules_preprocess.h"
 #include "theory/rewriterules/theory_rewriterules.h"
 
+#include "theory/quantifiers/term_database.h"
+
 using namespace std;
 using namespace CVC4;
 using namespace CVC4::kind;
@@ -72,7 +74,7 @@ inline void addPattern(TheoryRewriteRules & re,
                        TNode r){
   if (tri.getKind() == kind::NOT && tri[0].getKind() == kind::APPLY_UF)
     tri = tri[0];
-  pattern.push_back(re.getQuantifiersEngine()->
+  pattern.push_back(re.getQuantifiersEngine()->getTermDatabase()->
                     convertNodeToPattern(tri,r,vars,inst_constants));
 }
 
index fb972b73fd073dc43c0a3dd75ec2ab40a5fee644..7b6527517495105c910a50ea9b860c42439d33d3 100644 (file)
@@ -123,14 +123,14 @@ private:
   bool propagateEquality(TNode equality, bool polarity);
 
   /** Theory engine */
-  TheoryEngine* d_theoryEngine;  
+  TheoryEngine* d_theoryEngine;
 
   /** Are we in conflict */
   context::CDO<bool> d_inConflict;
-  
+
   /** Conflicting terms, if any */
   Node d_conflictLHS, d_conflictRHS;
-  
+
   /** Polarity of the conflict */
   bool d_conflictPolarity;
 
@@ -166,7 +166,7 @@ public:
    */
   bool isKnown(TNode literal) const;
 
-  /** 
+  /**
    * Returns an explanation of the propagation that came from the database.
    */
   Node explain(TNode literal) const;
@@ -175,10 +175,10 @@ public:
    * Add an equality to propagate.
    */
   void addEqualityToPropagate(TNode equality);
-  
+
   /**
-   * Add a shared term to the database. The shared term is a subterm of the atom and 
-   * should be associated with the given theory. 
+   * Add a shared term to the database. The shared term is a subterm of the atom and
+   * should be associated with the given theory.
    */
   void addSharedTerm(TNode atom, TNode term, theory::Theory::Set theories);
 
@@ -211,7 +211,7 @@ public:
    * Get the theories that share the term and have been notified already.
    */
   theory::Theory::Set getNotifiedTheories(TNode term) const;
-   
+
   /**
    * Returns true if the term is currently registered as shared with some theory.
    */
@@ -238,6 +238,10 @@ public:
    */
   bool areDisequal(TNode a, TNode b) const;
 
+  /**
+   * get equality engine
+   */
+  theory::eq::EqualityEngine* getEqualityEngine() { return &d_equalityEngine; }
 protected:
 
   /**
index 1dd0a1209778deca674ed7fef1181abef1914879..1301da653166b9607e832ba6a24546f954188377 100644 (file)
@@ -78,21 +78,21 @@ TheoryId Theory::theoryOf(TheoryOfMode mode, TNode node) {
     break;
   case THEORY_OF_TERM_BASED:
     // Variables
-    if (node.getMetaKind() == kind::metakind::VARIABLE) {      
-      if (theoryOf(node.getType()) != theory::THEORY_BOOL) {      
+    if (node.getMetaKind() == kind::metakind::VARIABLE) {
+      if (theoryOf(node.getType()) != theory::THEORY_BOOL) {
         // We treat the varibables as uninterpreted
         return s_uninterpretedSortOwner;
       } else {
         // Except for the Boolean ones, which we just ignore anyhow
         return theory::THEORY_BOOL;
       }
-    }    
+    }
     // Constants
     if (node.getMetaKind() == kind::metakind::CONSTANT) {
-      // Constants go to the theory of the type 
+      // Constants go to the theory of the type
       return theoryOf(node.getType());
-    }    
-    // Equality 
+    }
+    // Equality
     if (node.getKind() == kind::EQUAL) {
       // If one of them is an ITE, it's irelevant, since they will get replaced out anyhow
       if (node[0].getKind() == kind::ITE) {
@@ -100,7 +100,7 @@ TheoryId Theory::theoryOf(TheoryOfMode mode, TNode node) {
       }
       if (node[1].getKind() == kind::ITE) {
         return theoryOf(node[1].getType());
-      }  
+      }
       // If both sides belong to the same theory the choice is easy
       TheoryId T1 = theoryOf(node[0]);
       TheoryId T2 = theoryOf(node[1]);
@@ -108,12 +108,12 @@ TheoryId Theory::theoryOf(TheoryOfMode mode, TNode node) {
         return T1;
       }
       TheoryId T3 = theoryOf(node[0].getType());
-      // This is a case of 
+      // This is a case of
       // * x*y = f(z) -> UF
       // * x = c      -> UF
       // * f(x) = read(a, y) -> either UF or ARRAY
       // at least one of the theories has to be parametric, i.e. theory of the type is different
-      // from the theory of the term     
+      // from the theory of the term
       if (T1 == T3) {
         return T2;
       }
@@ -122,13 +122,13 @@ TheoryId Theory::theoryOf(TheoryOfMode mode, TNode node) {
       }
       // If both are parametric, we take the smaller one (arbitraty)
       return T1 < T2 ? T1 : T2;
-    }      
+    }
     // Regular nodes are owned by the kind
-    return kindToTheoryId(node.getKind());  
-    break;    
+    return kindToTheoryId(node.getKind());
+    break;
   default:
     Unreachable();
-  }   
+  }
 }
 
 void Theory::addSharedTermInternal(TNode n) {
@@ -194,31 +194,21 @@ void Instantiator::resetInstantiationRound(Theory::Effort effort) {
   processResetInstantiationRound(effort);
 }
 
-int Instantiator::doInstantiation(Node f, Theory::Effort effort, int e, int limitInst) {
+int Instantiator::doInstantiation(Node f, Theory::Effort effort, int e ) {
   if(hasConstraintsFrom(f)) {
-    int origLemmas = d_quantEngine->getNumLemmasWaiting();
-    int status = process(f, effort, e, limitInst);
-    if(limitInst <= 0 || (d_quantEngine->getNumLemmasWaiting()-origLemmas) < limitInst) {
-      if(d_instStrategies.empty()) {
-        Debug("inst-engine-inst") << "There are no instantiation strategies allocated." << endl;
-      } else {
-        for(int i = 0; i < (int) d_instStrategies.size(); ++i) {
-          if(isActiveStrategy(d_instStrategies[i])) {
-            Debug("inst-engine-inst") << d_instStrategies[i]->identify() << " process " << effort << endl;
-            //call the instantiation strategy's process method
-            int s_limitInst = limitInst > 0 ? limitInst - (d_quantEngine->getNumLemmasWaiting() - origLemmas) : 0;
-            int s_status = d_instStrategies[i]->doInstantiation(f, effort, e, s_limitInst);
-            Debug("inst-engine-inst") << "  -> status is " << s_status << endl;
-            if(limitInst > 0 && (d_quantEngine->getNumLemmasWaiting() - origLemmas) >= limitInst) {
-              Assert( (d_quantEngine->getNumLemmasWaiting() - origLemmas) == limitInst );
-              i = (int) d_instStrategies.size();
-              status = InstStrategy::STATUS_UNKNOWN;
-            } else {
-              InstStrategy::updateStatus(status, s_status);
-            }
-          } else {
-            Debug("inst-engine-inst") << d_instStrategies[i]->identify() << " is not active." << endl;
-          }
+    int status = process(f, effort, e );
+    if(d_instStrategies.empty()) {
+      Debug("inst-engine-inst") << "There are no instantiation strategies allocated." << endl;
+    } else {
+      for(int i = 0; i < (int) d_instStrategies.size(); ++i) {
+        if(isActiveStrategy(d_instStrategies[i])) {
+          Debug("inst-engine-inst") << d_instStrategies[i]->identify() << " process " << effort << endl;
+          //call the instantiation strategy's process method
+          int s_status = d_instStrategies[i]->doInstantiation( f, effort, e );
+          Debug("inst-engine-inst") << "  -> status is " << s_status << endl;
+          InstStrategy::updateStatus(status, s_status);
+        } else {
+          Debug("inst-engine-inst") << d_instStrategies[i]->identify() << " is not active." << endl;
         }
       }
     }
index 217972dce44ba19ed706451e14f8462765ba1524..7d003bf25bf3790c419596693b04f515d95e756b 100644 (file)
@@ -50,6 +50,7 @@ namespace theory {
 class Instantiator;
 class InstStrategy;
 class QuantifiersEngine;
+class TheoryModel;
 
 /**
  * Information about an assertion for the theories.
@@ -330,12 +331,12 @@ public:
   static inline TheoryId theoryOf(TNode node) {
     return theoryOf(s_theoryOfMode, node);
   }
-  
+
   /** Set the theoryOf mode */
   static void setTheoryOfMode(TheoryOfMode mode) {
     s_theoryOfMode = mode;
   }
-  
+
   /**
    * Set the owner of the uninterpreted sort.
    */
@@ -545,40 +546,13 @@ public:
   }
 
   /**
-   * Return the value of a node (typically used after a ).  If the
-   * theory supports model generation but has no value for this node,
-   * it should return Node::null().  If the theory doesn't support
-   * model generation at all, or usually would but doesn't in its
-   * current state, it should throw an exception saying so.
-   *
-   * The TheoryEngine is passed in so that you can recursively request
-   * values for the Node's children.  This is important because the
-   * TheoryEngine takes care of simple cases (metakind CONSTANT,
-   * Boolean-valued VARIABLES, ...) and can dispatch to other theories
-   * if that's necessary.  Only call your own getValue() recursively
-   * if you *know* that you are responsible handle the Node you're
-   * asking for; other theories can use your types, so be careful
-   * here!  To be safe, it's best to delegate back to the
-   * TheoryEngine (by way of the Valuation proxy object, which avoids
-   * direct dependence on TheoryEngine).
-   *
-   * Usually, you need to handle at least the two cases of EQUAL and
-   * VARIABLE---EQUAL in case a value of yours is on the LHS of an
-   * EQUAL, and VARIABLE for variables of your types.  You also need
-   * to support any operators that can survive your rewriter.  You
-   * don't need to handle constants, as they are handled by the
-   * TheoryEngine.
-   *
-   * There are some gotchas here.  The user may be requesting the
-   * value of an expression that wasn't part of the satisfiable
-   * assertion, or has been declared since.  If you don't have a value
-   * and suspect this situation is the case, return Node::null()
-   * rather than throwing an exception.
-   */
-  virtual Node getValue(TNode n) {
-    Unimplemented("Theory %s doesn't support Theory::getValue interface",
+   * Get all relevant information in this theory regarding the current
+   * model.  This should be called after a call to check( FULL_EFFORT )
+   * for all theories with no conflicts and no lemmas added.
+   */
+  virtual void collectModelInfo( TheoryModel* m ){
+    Unimplemented("Theory %s doesn't support Theory::getModel interface",
                   identify().c_str());
-    return Node::null();
   }
 
   /**
@@ -824,7 +798,7 @@ protected:
   /** reset instantiation round */
   virtual void processResetInstantiationRound( Theory::Effort effort ) = 0;
   /** process quantifier */
-  virtual int process( Node f, Theory::Effort effort, int e, int limitInst = 0 ) = 0;
+  virtual int process( Node f, Theory::Effort effort, int e ) = 0;
 public:
   /** set has constraints from quantifier f */
   void setHasConstraintsFrom( Node f );
@@ -844,16 +818,22 @@ public:
   virtual void preRegisterTerm( Node t ) { }
   /** assertNode function, assertion was asserted to theory */
   virtual void assertNode( Node assertion ){}
-  /** reset instantiation round */
-  void resetInstantiationRound( Theory::Effort effort );
-  /** do instantiation method*/
-  int doInstantiation( Node f, Theory::Effort effort, int e, int limitInst = 0 );
   /** identify */
   virtual std::string identify() const { return std::string("Unknown"); }
   /** print debug information */
   virtual void debugPrint( const char* c ) {}
-  /** get status */
-  //int getStatus() { return d_status; }
+public:
+  /** reset instantiation round */
+  void resetInstantiationRound( Theory::Effort effort );
+  /** do instantiation method*/
+  int doInstantiation( Node f, Theory::Effort effort, int e );
+public:
+  /** general queries about equality */
+  virtual bool hasTerm( Node a ) { return false; }
+  virtual bool areEqual( Node a, Node b ) { return false; }
+  virtual bool areDisequal( Node a, Node b ) { return false; }
+  virtual Node getRepresentative( Node a ) { return a; }
+  virtual Node getInternalRepresentative( Node a ) { return getRepresentative( a ); }
 };/* class Instantiator */
 
 inline Assertion Theory::get() {
index 50682f64742f67f0f741554fc284f977e0c89230..8729243854c230a32533afe5f49132cefd4cc9c4 100644 (file)
 #include "util/node_visitor.h"
 #include "util/ite_removal.h"
 
+#include "theory/model.h"
 #include "theory/quantifiers_engine.h"
 #include "theory/quantifiers/theory_quantifiers.h"
+#include "theory/quantifiers/model_engine.h"
+#include "theory/quantifiers/first_order_model.h"
 
 using namespace std;
 
@@ -53,6 +56,8 @@ TheoryEngine::TheoryEngine(context::Context* context,
   d_logicInfo(logicInfo),
   d_sharedTerms(this, context),
   d_quantEngine(NULL),
+  d_curr_model(NULL),
+  d_curr_model_builder(NULL),
   d_ppCache(),
   d_possiblePropagations(context),
   d_hasPropagated(context),
@@ -80,6 +85,10 @@ TheoryEngine::TheoryEngine(context::Context* context,
   // initialize the quantifiers engine
   d_quantEngine = new QuantifiersEngine(context, this);
 
+  //build model information if applicable
+  d_curr_model = new theory::DefaultModel( context, "DefaultModel" );
+  d_curr_model_builder = new theory::TheoryEngineModelBuilder( this );
+
   Rewriter::init();
   StatisticsRegistry::registerStat(&d_combineTheoriesTime);
   d_true = NodeManager::currentNM()->mkConst<bool>(true);
@@ -175,7 +184,7 @@ void TheoryEngine::dumpAssertions(const char* tag) {
         Dump(tag) << CommentCommand("Completeness check");
         Dump(tag) << PushCommand();
 
-        // Dump the shared terms 
+        // Dump the shared terms
         if (d_logicInfo.isSharingEnabled()) {
           Dump(tag) << CommentCommand("Shared terms");
           context::CDList<TNode>::const_iterator it = theory->shared_terms_begin(), it_end = theory->shared_terms_end();
@@ -186,14 +195,14 @@ void TheoryEngine::dumpAssertions(const char* tag) {
           }
         }
 
-        // Dump the assertions 
+        // Dump the assertions
         Dump(tag) << CommentCommand("Assertions");
         context::CDList<Assertion>::const_iterator it = theory->facts_begin(), it_end = theory->facts_end();
         for (; it != it_end; ++ it) {
           // Get the assertion
           Node assertionNode = (*it).assertion;
           // Purify all the terms
-          
+
           BoolExpr assertionExpr(assertionNode.toExpr());
           if ((*it).isPreregistered) {
             Dump(tag) << CommentCommand("Preregistered");
@@ -223,24 +232,24 @@ void TheoryEngine::dumpAssertions(const char* tag) {
                   continue;
                 }
 
-                // Check equality 
+                // Check equality
                 Dump(tag) << PushCommand();
                 BoolExpr eqExpr(equality.toExpr());
                 Dump(tag) << AssertCommand(eqExpr);
-                Dump(tag) << CheckSatCommand();              
+                Dump(tag) << CheckSatCommand();
                 Dump(tag) << PopCommand();
 
-                // Check disequality 
+                // Check disequality
                 Dump(tag) << PushCommand();
                 BoolExpr diseqExpr(disequality.toExpr());
                 Dump(tag) << AssertCommand(diseqExpr);
-                Dump(tag) << CheckSatCommand();              
-                Dump(tag) << PopCommand();                
+                Dump(tag) << CheckSatCommand();
+                Dump(tag) << PopCommand();
               }
             }
           }
         }
-        
+
         Dump(tag) << PopCommand();
       }
     }
@@ -297,8 +306,8 @@ void TheoryEngine::check(Theory::Effort effort) {
     // If in full effort, we have a fake new assertion just to jumpstart the checking
     if (Theory::fullEffort(effort)) {
       d_factsAsserted = true;
-    } 
-    
+    }
+
     // Check until done
     while (d_factsAsserted && !d_inConflict && !d_lemmasAdded) {
 
@@ -335,17 +344,22 @@ void TheoryEngine::check(Theory::Effort effort) {
 
     // Must consult quantifiers theory for last call to ensure sat, or otherwise add a lemma
     if( effort == Theory::EFFORT_FULL &&
-        d_logicInfo.isQuantified() &&
         ! d_inConflict &&
         ! d_lemmasAdded ) {
-      ((theory::quantifiers::TheoryQuantifiers*) d_theoryTable[THEORY_QUANTIFIERS])->performCheck(Theory::EFFORT_LAST_CALL);
-      // if we have given up, then possibly flip decision
-      if(Options::current()->flipDecision) {
-        if(d_incomplete && !d_inConflict && !d_lemmasAdded) {
-          if( ((theory::quantifiers::TheoryQuantifiers*) d_theoryTable[THEORY_QUANTIFIERS])->flipDecision() ) {
-            d_incomplete = false;
+      if( d_logicInfo.isQuantified() ){
+        ((theory::quantifiers::TheoryQuantifiers*) d_theoryTable[THEORY_QUANTIFIERS])->performCheck(Theory::EFFORT_LAST_CALL);
+        // if we have given up, then possibly flip decision
+        if(Options::current()->flipDecision) {
+          if(d_incomplete && !d_inConflict && !d_lemmasAdded) {
+            if( ((theory::quantifiers::TheoryQuantifiers*) d_theoryTable[THEORY_QUANTIFIERS])->flipDecision() ) {
+              d_incomplete = false;
+            }
           }
         }
+        //if returning incomplete or SAT, we have ensured that the model in the quantifiers engine has been built
+      }else if( Options::current()->produceModels ){
+        //must build model at this point
+        d_curr_model_builder->buildModel( d_curr_model );
       }
     }
 
@@ -354,8 +368,8 @@ void TheoryEngine::check(Theory::Effort effort) {
   } catch(const theory::Interrupted&) {
     Trace("theory") << "TheoryEngine::check() => conflict" << endl;
   }
-  
-  // If fulleffort, check all theories 
+
+  // If fulleffort, check all theories
   if(Dump.isOn("theory::fullcheck") && Theory::fullEffort(effort)) {
     if (!d_inConflict && !d_lemmasAdded) {
       dumpAssertions("theory::fullcheck");
@@ -415,7 +429,7 @@ void TheoryEngine::combineTheories() {
         Node literal = value ? equality : equality.notNode();
         Node normalizedLiteral = value ? normalizedEquality : normalizedEquality.notNode();
         // We're sending the original literal back, backed by the normalized one
-        if (markPropagation(literal, normalizedLiteral, /* to */ carePair.theory, /* from */ THEORY_SAT_SOLVER)) {        
+        if (markPropagation(literal, normalizedLiteral, /* to */ carePair.theory, /* from */ THEORY_SAT_SOLVER)) {
           // We assert it, and we know it's preregistereed if it's the same theory
           bool preregistered = Theory::theoryOf(literal) == carePair.theory;
           theoryOf(carePair.theory)->assertFact(literal, preregistered);
@@ -427,7 +441,7 @@ void TheoryEngine::combineTheories() {
         }
       }
     }
-        
+
     // We need to split on it
     Debug("sharing") << "TheoryEngine::combineTheories(): requesting a split " << std::endl;
     lemma(equality.orNode(equality.notNode()), false, false);
@@ -528,23 +542,26 @@ bool TheoryEngine::properExplanation(TNode node, TNode expl) const {
   return true;
 }
 
-Node TheoryEngine::getValue(TNode node) {
-  kind::MetaKind metakind = node.getMetaKind();
-
-  // special case: prop engine handles boolean vars
-  if(metakind == kind::metakind::VARIABLE && node.getType().isBoolean()) {
-    return d_propEngine->getValue(node);
+void TheoryEngine::collectModelInfo( theory::TheoryModel* m ){
+  //consult each theory to get all relevant information concerning the model
+  for( int i=0; i<theory::THEORY_LAST; i++ ){
+    if( d_theoryTable[i] ){
+      d_theoryTable[i]->collectModelInfo( m );
+    }
   }
+}
 
-  // special case: value of a constant == itself
-  if(metakind == kind::metakind::CONSTANT) {
-    return node;
+/* get model */
+TheoryModel* TheoryEngine::getModel(){
+  Debug("model") << "TheoryEngine::getModel()" << std::endl;
+  if( d_logicInfo.isQuantified() ){
+    Debug("model") << "Get model from quantifiers engine." << std::endl;
+    return d_quantEngine->getModel();
+  }else{
+    Debug("model") << "Get default model." << std::endl;
+    return d_curr_model;
   }
-
-  // otherwise ask the theory-in-charge
-  return theoryOf(node)->getValue(node);
-
-}/* TheoryEngine::getValue(TNode node) */
+}
 
 bool TheoryEngine::presolve() {
 
@@ -777,7 +794,7 @@ bool TheoryEngine::markPropagation(TNode assertion, TNode originalAssertion, the
   // What and where it came from
   NodeTheoryPair toExplain(originalAssertion, fromTheoryId, d_propagationMapTimestamp);
 
-  // See if the theory already got this literal  
+  // See if the theory already got this literal
   PropagationMap::const_iterator find = d_propagationMap.find(toAssert);
   if (find != d_propagationMap.end()) {
     // The theory already knows this
@@ -796,11 +813,11 @@ bool TheoryEngine::markPropagation(TNode assertion, TNode originalAssertion, the
 
 
 void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId, theory::TheoryId fromTheoryId) {
+
   Trace("theory::assertToTheory") << "TheoryEngine::assertToTheory(" << assertion << ", " << toTheoryId << ", " << fromTheoryId << ")" << std::endl;
-  
+
   Assert(toTheoryId != fromTheoryId);
-  
+
   if (d_inConflict) {
     return;
   }
@@ -813,7 +830,7 @@ void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId,
       // We assert it, and we know it's preregistereed
       toTheory->assertFact(assertion, true);
       // Mark that we have more information
-      d_factsAsserted = true;      
+      d_factsAsserted = true;
     } else {
       Assert(toTheoryId == THEORY_SAT_SOLVER);
       // Check for propositional conflict
@@ -825,18 +842,18 @@ void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId,
         } else {
           return;
         }
-      } 
+      }
       d_propagatedLiterals.push_back(assertion);
     }
     return;
   }
-  
+
   // Polarity of the assertion
   bool polarity = assertion.getKind() != kind::NOT;
-  
+
   // Atom of the assertion
   TNode atom = polarity ? assertion : assertion[0];
-  
+
   // If sending to the shared terms database, it's also simple
   if (toTheoryId == THEORY_BUILTIN) {
     Assert(atom.getKind() == kind::EQUAL);
@@ -845,11 +862,11 @@ void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId,
     }
     return;
   }
-  
-  // Things from the SAT solver are already normalized, so they go 
+
+  // Things from the SAT solver are already normalized, so they go
   // directly to the apropriate theory
   if (fromTheoryId == THEORY_SAT_SOLVER) {
-    // We know that this is normalized, so just send it off to the theory 
+    // We know that this is normalized, so just send it off to the theory
     if (markPropagation(assertion, assertion, toTheoryId, fromTheoryId)) {
       // We assert it, and we know it's preregistereed coming from the SAT solver directly
       theoryOf(toTheoryId)->assertFact(assertion, true);
@@ -858,7 +875,7 @@ void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId,
     }
     return;
   }
-  
+
   // Propagations to the SAT solver are just enqueued for pickup by
   // the SAT solver later
   if (toTheoryId == THEORY_SAT_SOLVER) {
@@ -898,14 +915,14 @@ void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId,
   // Normalize to lhs < rhs if not a sat literal
   Assert(atom.getKind() == kind::EQUAL);
   Assert(atom[0] != atom[1]);
-  
+
   Node normalizedAtom = atom;
   if (!d_propEngine->isSatLiteral(normalizedAtom)) {
     Node reverse = atom[1].eqNode(atom[0]);
     if (d_propEngine->isSatLiteral(reverse) || atom[0] > atom[1]) {
       normalizedAtom = reverse;
-    }  
-  } 
+    }
+  }
   Node normalizedAssertion = polarity ? normalizedAtom : normalizedAtom.notNode();
 
   // Try and assert (note that we assert the non-normalized one)
@@ -915,7 +932,7 @@ void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId,
     // Assert away
     theoryOf(toTheoryId)->assertFact(normalizedAssertion, preregistered);
     d_factsAsserted = true;
-  } 
+  }
 
   return;
 }
@@ -923,7 +940,7 @@ void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId,
 void TheoryEngine::assertFact(TNode literal)
 {
   Trace("theory") << "TheoryEngine::assertFact(" << literal << ")" << std::endl;
-  
+
   d_propEngine->checkTime();
 
   // If we're in conflict, nothing to do
@@ -997,7 +1014,7 @@ bool TheoryEngine::propagate(TNode literal, theory::TheoryId theory) {
     }
     if (theory != THEORY_BUILTIN) {
       // Assert to the shared terms database
-      assertToTheory(literal, /* to */ THEORY_BUILTIN, /* from */ theory);      
+      assertToTheory(literal, /* to */ THEORY_BUILTIN, /* from */ theory);
     }
   } else {
     // Just send off to the SAT solver
@@ -1075,7 +1092,7 @@ Node TheoryEngine::getExplanation(TNode node) {
     return explanation;
   }
 
-  // Initial thing to explain 
+  // Initial thing to explain
   NodeTheoryPair toExplain(node, THEORY_SAT_SOLVER, d_propagationMapTimestamp);
   Assert(d_propagationMap.find(toExplain) != d_propagationMap.end());
   // Create the workplace for explanations
@@ -1084,9 +1101,9 @@ Node TheoryEngine::getExplanation(TNode node) {
   // Process the explanation
   getExplanation(explanationVector);
   Node explanation = mkExplanation(explanationVector);
-  
+
   Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << ") => " << explanation << std::endl;
+
   return explanation;
 }
 
@@ -1131,7 +1148,7 @@ theory::LemmaStatus TheoryEngine::lemma(TNode node, bool negated, bool removable
   if(!removable) {
     d_decisionEngine->addAssertions(additionalLemmas, 1, iteSkolemMap);
   }
-  
+
   // Mark that we added some lemmas
   d_lemmasAdded = true;
 
@@ -1151,7 +1168,7 @@ void TheoryEngine::conflict(TNode conflict, TheoryId theoryId) {
     Dump("t-conflicts") << CommentCommand("theory conflict: expect unsat")
                         << CheckSatCommand(conflict.toExpr());
   }
-  
+
   // In the multiple-theories case, we need to reconstruct the conflict
   if (d_logicInfo.isSharingEnabled()) {
     // Create the workplace for explanations
@@ -1184,9 +1201,9 @@ void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector
 
   unsigned i = 0; // Index of the current literal we are processing
   unsigned j = 0; // Index of the last literal we are keeping
-    
+
   while (i < explanationVector.size()) {
-  
+
     // Get the current literal to explain
     NodeTheoryPair toExplain = explanationVector[i];
 
@@ -1196,7 +1213,7 @@ void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector
     if (toExplain.node.isConst() && toExplain.node.getConst<bool>()) {
       ++ i;
       continue;
-    }    
+    }
     if (toExplain.node.getKind() == kind::NOT && toExplain.node[0].isConst() && !toExplain.node[0].getConst<bool>()) {
       ++ i;
       continue;
@@ -1219,7 +1236,7 @@ void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector
       continue;
     }
 
-    // See if it was sent to the theory by another theory 
+    // See if it was sent to the theory by another theory
     PropagationMap::const_iterator find = d_propagationMap.find(toExplain);
     if (find != d_propagationMap.end()) {
       // There is some propagation, check if its a timely one
@@ -1244,10 +1261,10 @@ void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector
     explanationVector.push_back(newExplain);
     ++ i;
   }
-    
+
   // Keep only the relevant literals
   explanationVector.resize(j);
-}  
+}
 
 
 void TheoryEngine::ppUnconstrainedSimp(vector<Node>& assertions)
index 3d70ffa6be735f97b8d659cf0ff4d9031ebf3062..f55c7c258e1f921e33e7415cdc58f907334553f3 100644 (file)
 #include "util/cache.h"
 #include "theory/ite_simplifier.h"
 #include "theory/unconstrained_simplifier.h"
+#include "theory/model.h"
 
 namespace CVC4 {
 
 /**
- * A pair of a theory and a node. This is used to mark the flow of 
+ * A pair of a theory and a node. This is used to mark the flow of
  * propagations between theories.
- */ 
+ */
 struct NodeTheoryPair {
   Node node;
   theory::TheoryId theory;
@@ -57,7 +58,7 @@ struct NodeTheoryPair {
   : node(node), theory(theory), timestamp(timestamp) {}
   NodeTheoryPair()
   : theory(theory::THEORY_LAST) {}
-  // Comparison doesn't take into account the timestamp  
+  // Comparison doesn't take into account the timestamp
   bool operator == (const NodeTheoryPair& pair) const {
     return node == pair.node && theory == pair.theory;
   }
@@ -84,7 +85,7 @@ class DecisionEngine;
  * CVC4.
  */
 class TheoryEngine {
-  
+
   /** Shared terms database can use the internals notify the theories */
   friend class SharedTermsDatabase;
 
@@ -125,6 +126,15 @@ class TheoryEngine {
    */
   theory::QuantifiersEngine* d_quantEngine;
 
+  /**
+   * Default model object
+   */
+  theory::DefaultModel* d_curr_model;
+  /**
+   * Model builder object
+   */
+  theory::TheoryEngineModelBuilder* d_curr_model_builder;
+
   typedef std::hash_map<Node, Node, NodeHashFunction> NodeMap;
   typedef std::hash_map<TNode, Node, TNodeHashFunction> TNodeMap;
 
@@ -389,7 +399,7 @@ class TheoryEngine {
    * Adds a new lemma, returning its status.
    */
   theory::LemmaStatus lemma(TNode node, bool negated, bool removable);
-  
+
   /** Time spent in theory combination */
   TimerStat d_combineTheoriesTime;
 
@@ -432,6 +442,13 @@ public:
     return d_propEngine;
   }
 
+  /**
+   * Get a pointer to the underlying sat context.
+   */
+  inline context::Context* getSatContext() const {
+    return d_context;
+  }
+
   /**
    * Get a pointer to the underlying quantifiers engine.
    */
@@ -472,12 +489,12 @@ private:
   void assertToTheory(TNode assertion, theory::TheoryId toTheoryId, theory::TheoryId fromTheoryId);
 
   /**
-   * Marks a theory propagation from a theory to a theory where a 
+   * Marks a theory propagation from a theory to a theory where a
    * theory could be the THEORY_SAT_SOLVER for literals coming from
    * or being propagated to the SAT solver. If the receiving theory
    * already recieved the literal, the method returns false, otherwise
    * it returns true.
-   * 
+   *
    * @param assertion the normalized assertion being sent
    * @param originalAssertion the actual assertion that was sent
    * @param toTheoryId the theory that is on the receiving end
@@ -488,7 +505,7 @@ private:
 
   /**
    * Computes the explanation by travarsing the propagation graph and
-   * asking relevant theories to explain the propagations. Initially 
+   * asking relevant theories to explain the propagations. Initially
    * the explanation vector should contain only the element (node, theory)
    * where the node is the one to be explained, and the theory is the
    * theory that sent the literal.
@@ -623,9 +640,19 @@ public:
   Node getExplanation(TNode node);
 
   /**
-   * Returns the value of the given node.
+   * collect model info
+   */
+  void collectModelInfo( theory::TheoryModel* m );
+
+  /**
+   * Get the current model
    */
-  Node getValue(TNode node);
+  theory::TheoryModel* getModel();
+
+  /**
+   * Get the model builder
+   */
+  theory::TheoryEngineModelBuilder* getModelBuilder() { return d_curr_model_builder; }
 
   /**
    * Get the theory associated to a given Node.
@@ -685,6 +712,8 @@ public:
   Node ppSimpITE(TNode assertion);
   void ppUnconstrainedSimp(std::vector<Node>& assertions);
 
+  SharedTermsDatabase* getSharedTermsDatabase() { return &d_sharedTerms; }
+
 };/* class TheoryEngine */
 
 }/* CVC4 namespace */
index d665fef91b5b8485a8fd09f9993fe636f0c20fc6..55ca07d77773f2c884feaa00e77e438db47dc484 100644 (file)
@@ -144,8 +144,8 @@ int Trigger::addTerm( Node t ){
   return d_mg->addTerm( d_f, t, d_quantEngine );
 }
 
-int Trigger::addInstantiations( InstMatch& baseMatch, int instLimit, bool addSplits ){
-  int addedLemmas = d_mg->addInstantiations( d_f, baseMatch, d_quantEngine, instLimit, addSplits );
+int Trigger::addInstantiations( InstMatch& baseMatch ){
+  int addedLemmas = d_mg->addInstantiations( d_f, baseMatch, d_quantEngine );
   if( addedLemmas>0 ){
     Debug("inst-trigger") << "Added " << addedLemmas << " lemmas, trigger was ";
     for( int i=0; i<(int)d_nodes.size(); i++ ){
index 457df0ab4d9a9b26dc461f0ad25bd1b7360a2824..476ef392e3ef9d76627905917235dedf334a80c6 100644 (file)
@@ -97,7 +97,7 @@ public:
 public:
   /** add all available instantiations exhaustively, in any equivalence class
       if limitInst>0, limitInst is the max # of instantiations to try */
-  int addInstantiations( InstMatch& baseMatch, int instLimit = 0, bool addSplits = false );
+  int addInstantiations( InstMatch& baseMatch );
   /** mkTrigger method
      ie     : quantifier engine;
      f      : forall something ....
index 2c9cd3b809c4f2fe554c9f8bf60b2152900035c0..b8446761c8d2c7dc9dd3ec54bbbed4fa4b9cb430 100644 (file)
@@ -22,6 +22,8 @@ libuf_la_SOURCES = \
        theory_uf_candidate_generator.h \
        theory_uf_candidate_generator.cpp \
        inst_strategy.h \
-       inst_strategy.cpp
+       inst_strategy.cpp \
+       theory_uf_model.h \
+       theory_uf_model.cpp
 
 EXTRA_DIST = kinds
index 2ca2dcb5a62693ddb7721f206042860256351356..669df055a2c9978857e12c4479cfcf8abe6db094 100644 (file)
@@ -20,6 +20,7 @@
 #include "theory/theory_engine.h"
 #include "theory/uf/theory_uf.h"
 #include "theory/uf/equality_engine.h"
+#include "theory/quantifiers/term_database.h"
 
 using namespace std;
 using namespace CVC4;
@@ -34,7 +35,7 @@ using namespace CVC4::theory::uf;
 
 struct sortQuantifiersForSymbol {
   QuantifiersEngine* d_qe;
-  bool operator() (Node i, Node j) { 
+  bool operator() (Node i, Node j) {
     int nqfsi = d_qe->getNumQuantifiersForSymbol( i.getOperator() );
     int nqfsj = d_qe->getNumQuantifiersForSymbol( j.getOperator() );
     if( nqfsi<nqfsj ){
@@ -54,7 +55,7 @@ void InstStrategyCheckCESolved::processResetInstantiationRound( Theory::Effort e
   }
 }
 
-int InstStrategyCheckCESolved::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategyCheckCESolved::process( Node f, Theory::Effort effort, int e ){
   if( e==0 ){
     //calc solved if not done so already
     if( d_solved.find( f )==d_solved.end() ){
@@ -68,7 +69,7 @@ int InstStrategyCheckCESolved::process( Node f, Theory::Effort effort, int e, in
         //d_quantEngine->d_hasInstantiated[f] = true;
       }
       d_solved[f] = false;
-    } 
+    }
     Debug("quant-uf-strategy") << "done." << std::endl;
   }
   return STATUS_UNKNOWN;
@@ -78,8 +79,8 @@ void InstStrategyCheckCESolved::calcSolved( Node f ){
   d_th->d_baseMatch[f].clear();
   d_solved[ f ]= true;
   //check if instantiation constants are solved for
-  for( int j = 0; j<(int)d_quantEngine->getNumInstantiationConstants( f ); j++ ){
-    Node i = d_quantEngine->getInstantiationConstant( f, j );
+  for( int j = 0; j<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); j++ ){
+    Node i = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );
     Node rep = d_th->getInternalRepresentative( i );
     if( !rep.hasAttribute(InstConstantAttribute()) ){
       d_th->d_baseMatch[f].d_map[ i ] = rep;
@@ -99,7 +100,7 @@ void InstStrategyUserPatterns::processResetInstantiationRound( Theory::Effort ef
   }
 }
 
-int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e ){
   if( e==0 ){
     return STATUS_UNFINISHED;
   }else if( e==1 ){
@@ -114,10 +115,10 @@ int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e, int
 //#endif
       }
       if( processTrigger ){
-        //if( d_user_gen[f][i]->isMultiTrigger() ) 
+        //if( d_user_gen[f][i]->isMultiTrigger() )
           //Notice() << "  Process (user) " << (*d_user_gen[f][i]) << " for " << f << "..." << std::endl;
-        int numInst = d_user_gen[f][i]->addInstantiations( d_th->d_baseMatch[f], instLimit );
-        //if( d_user_gen[f][i]->isMultiTrigger() ) 
+        int numInst = d_user_gen[f][i]->addInstantiations( d_th->d_baseMatch[f] );
+        //if( d_user_gen[f][i]->isMultiTrigger() )
           //Notice() << "  Done, numInst = " << numInst << "." << std::endl;
         d_th->d_statistics.d_instantiations_user_pattern += numInst;
         if( d_user_gen[f][i]->isMultiTrigger() ){
@@ -131,7 +132,7 @@ int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e, int
   }
   return STATUS_UNKNOWN;
 }
-  
+
 void InstStrategyUserPatterns::addUserPattern( Node f, Node pat ){
   //add to generators
   std::vector< Node > nodes;
@@ -143,11 +144,11 @@ void InstStrategyUserPatterns::addUserPattern( Node f, Node pat ){
     d_quantEngine->getPhaseReqTerms( f, nodes );
     //check match option
     int matchOption = Options::current()->efficientEMatching ? InstMatchGenerator::MATCH_GEN_EFFICIENT_E_MATCH : 0;
-    d_user_gen[f].push_back( Trigger::mkTrigger( d_quantEngine, f, nodes, matchOption, true, Trigger::TR_MAKE_NEW, 
+    d_user_gen[f].push_back( Trigger::mkTrigger( d_quantEngine, f, nodes, matchOption, true, Trigger::TR_MAKE_NEW,
                                                  Options::current()->smartTriggers ) );
   }
 }
+
 void InstStrategyAutoGenTriggers::processResetInstantiationRound( Theory::Effort effort ){
   //reset triggers
   for( std::map< Node, std::map< Trigger*, bool > >::iterator it = d_auto_gen_trigger.begin(); it != d_auto_gen_trigger.end(); ++it ){
@@ -158,7 +159,7 @@ void InstStrategyAutoGenTriggers::processResetInstantiationRound( Theory::Effort
   }
 }
 
-int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e ){
   int peffort = f.getNumChildren()==3 ? 2 : 1;
   //int peffort = f.getNumChildren()==3 ? 2 : 1;
   //int peffort = 1;
@@ -192,10 +193,10 @@ int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e,
 #endif
         }
         if( processTrigger ){
-          //if( tr->isMultiTrigger() ) 
+          //if( tr->isMultiTrigger() )
             Debug("quant-uf-strategy-auto-gen-triggers") << "  Process " << (*tr) << "..." << std::endl;
-          int numInst = tr->addInstantiations( d_th->d_baseMatch[f], instLimit );
-          //if( tr->isMultiTrigger() ) 
+          int numInst = tr->addInstantiations( d_th->d_baseMatch[f] );
+          //if( tr->isMultiTrigger() )
             Debug("quant-uf-strategy-auto-gen-triggers") << "  Done, numInst = " << numInst << "." << std::endl;
           if( d_tr_strategy==Trigger::TS_MIN_TRIGGER ){
             d_th->d_statistics.d_instantiations_auto_gen_min += numInst;
@@ -222,8 +223,8 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
     d_patTerms[0][f].clear();
     d_patTerms[1][f].clear();
     std::vector< Node > patTermsF;
-    Trigger::collectPatTerms( d_quantEngine, f, d_quantEngine->getCounterexampleBody( f ), patTermsF, d_tr_strategy, true );
-    Debug("auto-gen-trigger") << "Collected pat terms for " << d_quantEngine->getCounterexampleBody( f ) << std::endl;
+    Trigger::collectPatTerms( d_quantEngine, f, d_quantEngine->getTermDatabase()->getCounterexampleBody( f ), patTermsF, d_tr_strategy, true );
+    Debug("auto-gen-trigger") << "Collected pat terms for " << d_quantEngine->getTermDatabase()->getCounterexampleBody( f ) << std::endl;
     Debug("auto-gen-trigger") << "   ";
     for( int i=0; i<(int)patTermsF.size(); i++ ){
       Debug("auto-gen-trigger") << patTermsF[i] << " ";
@@ -299,7 +300,7 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
     int matchOption = Options::current()->efficientEMatching ? InstMatchGenerator::MATCH_GEN_EFFICIENT_E_MATCH : 0;
     Trigger* tr = NULL;
     if( d_is_single_trigger[ patTerms[0] ] ){
-      tr = Trigger::mkTrigger( d_quantEngine, f, patTerms[0], matchOption, false, Trigger::TR_RETURN_NULL, 
+      tr = Trigger::mkTrigger( d_quantEngine, f, patTerms[0], matchOption, false, Trigger::TR_RETURN_NULL,
                                Options::current()->smartTriggers );
       d_single_trigger_gen[ patTerms[0] ] = true;
     }else{
@@ -313,12 +314,12 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
         d_made_multi_trigger[f] = true;
       }
       //will possibly want to get an old trigger
-      tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, false, Trigger::TR_GET_OLD, 
+      tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, false, Trigger::TR_GET_OLD,
                                Options::current()->smartTriggers );
     }
     if( tr ){
       if( tr->isMultiTrigger() ){
-        //disable all other multi triggers 
+        //disable all other multi triggers
         for( std::map< Trigger*, bool >::iterator it = d_auto_gen_trigger[f].begin(); it != d_auto_gen_trigger[f].end(); ++it ){
           if( it->first->isMultiTrigger() ){
             d_auto_gen_trigger[f][ it->first ] = false;
@@ -344,7 +345,7 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
             success = false;
             if( d_quantEngine->getNumQuantifiersForSymbol( patTerms[index].getOperator() )<=nqfs_curr ){
               d_single_trigger_gen[ patTerms[index] ] = true;
-              Trigger* tr2 = Trigger::mkTrigger( d_quantEngine, f, patTerms[index], matchOption, false, Trigger::TR_RETURN_NULL, 
+              Trigger* tr2 = Trigger::mkTrigger( d_quantEngine, f, patTerms[index], matchOption, false, Trigger::TR_RETURN_NULL,
                                                  Options::current()->smartTriggers );
               if( tr2 ){
                 //Notice() << "Add additional trigger " << patTerms[index] << std::endl;
@@ -368,11 +369,11 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
 void InstStrategyAddFailSplits::processResetInstantiationRound( Theory::Effort effort ){
 }
 
-int InstStrategyAddFailSplits::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategyAddFailSplits::process( Node f, Theory::Effort effort, int e ){
   if( e<4 ){
     return STATUS_UNFINISHED;
   }else{
-    for( std::map< Node, std::map< Node, std::vector< InstMatchGenerator* > > >::iterator it = InstMatchGenerator::d_match_fails.begin(); 
+    for( std::map< Node, std::map< Node, std::vector< InstMatchGenerator* > > >::iterator it = InstMatchGenerator::d_match_fails.begin();
          it != InstMatchGenerator::d_match_fails.end(); ++it ){
       for( std::map< Node, std::vector< InstMatchGenerator* > >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
         if( !it2->second.empty() ){
@@ -394,7 +395,7 @@ int InstStrategyAddFailSplits::process( Node f, Theory::Effort effort, int e, in
 void InstStrategyFreeVariable::processResetInstantiationRound( Theory::Effort effort ){
 }
 
-int InstStrategyFreeVariable::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategyFreeVariable::process( Node f, Theory::Effort effort, int e ){
   if( e<5 ){
     return STATUS_UNFINISHED;
   }else{
index 906169811c1963c4d31ac7c9d191758a53551ace..09b8087f26d4d96a07c897b0f3c3e64b9d8aecf6 100644 (file)
@@ -45,9 +45,9 @@ private:
   void calcSolved( Node f );
   /** process functions */
   void processResetInstantiationRound( Theory::Effort effort );
-  int process( Node f, Theory::Effort effort, int e, int instLimit );
+  int process( Node f, Theory::Effort effort, int e );
 public:
-  InstStrategyCheckCESolved( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) : 
+  InstStrategyCheckCESolved( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
       InstStrategy( ie ), d_th( th ){}
   ~InstStrategyCheckCESolved(){}
   /** identify */
@@ -64,9 +64,9 @@ private:
   std::map< Node, int > d_counter;
   /** process functions */
   void processResetInstantiationRound( Theory::Effort effort );
-  int process( Node f, Theory::Effort effort, int e, int instLimit );
+  int process( Node f, Theory::Effort effort, int e );
 public:
-  InstStrategyUserPatterns( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) : 
+  InstStrategyUserPatterns( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
       InstStrategy( ie ), d_th( th ){}
   ~InstStrategyUserPatterns(){}
 public:
@@ -109,11 +109,11 @@ private:
 private:
   /** process functions */
   void processResetInstantiationRound( Theory::Effort effort );
-  int process( Node f, Theory::Effort effort, int e, int instLimit );
+  int process( Node f, Theory::Effort effort, int e );
   /** generate triggers */
   void generateTriggers( Node f );
 public:
-  InstStrategyAutoGenTriggers( InstantiatorTheoryUf* th, QuantifiersEngine* ie, int tstrt, int rstrt, int rgfr = -1 ) : 
+  InstStrategyAutoGenTriggers( InstantiatorTheoryUf* th, QuantifiersEngine* ie, int tstrt, int rstrt, int rgfr = -1 ) :
       InstStrategy( ie ), d_th( th ), d_tr_strategy( tstrt ), d_rlv_strategy( rstrt ), d_generate_additional( false ){
     setRegenerateFrequency( rgfr );
   }
@@ -144,9 +144,9 @@ private:
   InstantiatorTheoryUf* d_th;
   /** process functions */
   void processResetInstantiationRound( Theory::Effort effort );
-  int process( Node f, Theory::Effort effort, int e, int instLimit );
+  int process( Node f, Theory::Effort effort, int e );
 public:
-  InstStrategyAddFailSplits( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) : 
+  InstStrategyAddFailSplits( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
       InstStrategy( ie ), d_th( th ){}
   ~InstStrategyAddFailSplits(){}
   /** identify */
@@ -163,9 +163,9 @@ private:
   std::map< Node, bool > d_guessed;
   /** process functions */
   void processResetInstantiationRound( Theory::Effort effort );
-  int process( Node f, Theory::Effort effort, int e, int instLimit );
+  int process( Node f, Theory::Effort effort, int e );
 public:
-  InstStrategyFreeVariable( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) : 
+  InstStrategyFreeVariable( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
       InstStrategy( ie ), d_th( th ){}
   ~InstStrategyFreeVariable(){}
   /** identify */
index ec353dc599ba3f559a13a6ae1ddba2e753f317cf..ce8785f869dddd2a2e85539cd969a68ec2ba7b78 100644 (file)
@@ -17,7 +17,49 @@ parameterized APPLY_UF VARIABLE 1: "uninterpreted function application"
 typerule APPLY_UF ::CVC4::theory::uf::UfTypeRule
 
 operator CARDINALITY_CONSTRAINT 2 "cardinality constraint"
-
 typerule CARDINALITY_CONSTRAINT ::CVC4::theory::uf::CardinalityConstraintTypeRule
 
+#
+# For compact function models
+# There are three cases for FUNCTION_MODEL nodes:
+# (1) The node has two children, the first being of kind FUNCTION_CASE_SPLIT.  The second child specifies a default value.
+# (2) The node has one child of kind FUNCTION_CASE_SPLIT.
+# (3) The node has one child, it's default value.
+# 
+# Semantics of FUNCTION_MODEL kind-ed nodes.  The value of n applied to arguments args is
+#
+# getValueFM( n, args, 0 ), where:
+# 
+# Node getValueFM( n, args, argIndex )
+# if n.getKind()!=FUNCTION_MODEL
+#   return n;
+# else if (1)
+#   val = getValueFCS( n[0], args, argIndex );
+#   if !val.isNull()
+#     return val;
+#   else 
+#     return getValueFM( n[1], args, argIndex+1 );
+# else if (2)
+#   return getValueFCS( n[0], args, argIndex );
+# else if (3)
+#   return getValueFM( n[0], args, argIndex+1 );
+# 
+# Node getValueFCS( n, args, argIndex ) :
+#   //n.getKind()==FUNCTION_CASE_SPLIT
+#   //n[j].getKind()==FUNCTION_CASE for all 0<=j<n.getNumChildren()
+#   if( args[argIndex]=n[i][0] for some i)  
+#     return getValueFM( n[i][1], args, argIndex+1 );
+#   else
+#     return null;
+#
+
+operator FUNCTION_MODEL 1:2 "function model"
+typerule FUNCTION_MODEL ::CVC4::theory::uf::FunctionModelTypeRule
+
+operator FUNCTION_CASE_SPLIT 1: "function case split"
+typerule FUNCTION_CASE_SPLIT ::CVC4::theory::uf::FunctionCaseSplitTypeRule
+
+operator FUNCTION_CASE 2 "function case"
+typerule FUNCTION_CASE ::CVC4::theory::uf::FunctionCaseTypeRule
+
 endtheory
index 5d36cd082f938232d78df88ff836db2f0db38dc5..ac194d5ed929d02cbd500eed65faeca27130e91e 100644 (file)
@@ -20,6 +20,7 @@
 #include "theory/uf/theory_uf.h"
 #include "theory/uf/theory_uf_instantiator.h"
 #include "theory/uf/theory_uf_strong_solver.h"
+#include "theory/model.h"
 
 using namespace std;
 using namespace CVC4;
@@ -173,6 +174,10 @@ Node TheoryUF::explain(TNode literal) {
   return mkAnd(assumptions);
 }
 
+void TheoryUF::collectModelInfo( TheoryModel* m ){
+  m->assertEqualityEngine( &d_equalityEngine );
+}
+
 void TheoryUF::presolve() {
   // TimerStat::CodeTimer codeTimer(d_presolveTimer);
 
index db417b08c76df8ac5af39474daac4bb76549e2f9..604b1f44c8e45204bf716ff4eb0d91b1f7d81e48 100644 (file)
@@ -132,8 +132,8 @@ private:
   Node d_conflictNode;
 
   /**
-   * Should be called to propagate the literal. We use a node here 
-   * since some of the propagated literals are not kept anywhere. 
+   * Should be called to propagate the literal. We use a node here
+   * since some of the propagated literals are not kept anywhere.
    */
   bool propagate(TNode literal);
 
@@ -193,6 +193,8 @@ public:
   void preRegisterTerm(TNode term);
   Node explain(TNode n);
 
+  void collectModelInfo( TheoryModel* m );
+
   void ppStaticLearn(TNode in, NodeBuilder<>& learned);
   void presolve();
 
index e8aa98aa7a82a81aa78bff0ae8e533117dbcfbba..5342188f79ad89cb883bc68040569e356353a327 100644 (file)
@@ -17,6 +17,7 @@
 #include "theory/uf/theory_uf_candidate_generator.h"
 #include "theory/theory_engine.h"
 #include "theory/uf/theory_uf.h"
+#include "theory/quantifiers/term_database.h"
 
 using namespace std;
 using namespace CVC4;
@@ -25,7 +26,7 @@ using namespace CVC4::context;
 using namespace CVC4::theory;
 using namespace CVC4::theory::uf;
 
-CandidateGeneratorTheoryUf::CandidateGeneratorTheoryUf( InstantiatorTheoryUf* ith, Node op ) : 
+CandidateGeneratorTheoryUf::CandidateGeneratorTheoryUf( InstantiatorTheoryUf* ith, Node op ) :
   d_op( op ), d_ith( ith ), d_term_iter( -2 ){
   Assert( !d_op.isNull() );
 }
@@ -84,12 +85,12 @@ Node CandidateGeneratorTheoryUf::getNextCandidate(){
 }
 
 
-//CandidateGeneratorTheoryUfDisequal::CandidateGeneratorTheoryUfDisequal( InstantiatorTheoryUf* ith, Node eqc ) : 
+//CandidateGeneratorTheoryUfDisequal::CandidateGeneratorTheoryUfDisequal( InstantiatorTheoryUf* ith, Node eqc ) :
 //  d_ith( ith ), d_eq_class( eqc ){
 //  d_eci = NULL;
 //}
 //void CandidateGeneratorTheoryUfDisequal::resetInstantiationRound(){
-//  
+//
 //}
 ////we will iterate over all terms that are disequal from eqc
 //void CandidateGeneratorTheoryUfDisequal::reset( Node eqc ){
@@ -119,12 +120,12 @@ Node CandidateGeneratorTheoryUf::getNextCandidate(){
 //}
 
 
-CandidateGeneratorTheoryUfLitEq::CandidateGeneratorTheoryUfLitEq( InstantiatorTheoryUf* ith, Node mpat ) : 
+CandidateGeneratorTheoryUfLitEq::CandidateGeneratorTheoryUfLitEq( InstantiatorTheoryUf* ith, Node mpat ) :
   d_match_pattern( mpat ), d_ith( ith ){
-  
+
 }
 void CandidateGeneratorTheoryUfLitEq::resetInstantiationRound(){
-  
+
 }
 void CandidateGeneratorTheoryUfLitEq::reset( Node eqc ){
   d_eq = eq::EqClassesIterator( ((TheoryUF*)d_ith->getTheory())->getEqualityEngine() );
@@ -142,15 +143,15 @@ Node CandidateGeneratorTheoryUfLitEq::getNextCandidate(){
 }
 
 
-CandidateGeneratorTheoryUfLitDeq::CandidateGeneratorTheoryUfLitDeq( InstantiatorTheoryUf* ith, Node mpat ) : 
+CandidateGeneratorTheoryUfLitDeq::CandidateGeneratorTheoryUfLitDeq( InstantiatorTheoryUf* ith, Node mpat ) :
   d_match_pattern( mpat ), d_ith( ith ){
-  
+
 }
 void CandidateGeneratorTheoryUfLitDeq::resetInstantiationRound(){
-  
+
 }
 void CandidateGeneratorTheoryUfLitDeq::reset( Node eqc ){
-  Node false_term = ((TheoryUF*)d_ith->getTheory())->getEqualityEngine()->getRepresentative( 
+  Node false_term = ((TheoryUF*)d_ith->getTheory())->getEqualityEngine()->getRepresentative(
                       NodeManager::currentNM()->mkConst<bool>(false) );
   d_eqc_false = eq::EqClassIterator( false_term, ((TheoryUF*)d_ith->getTheory())->getEqualityEngine() );
 }
index 9fdcb595211e60f8195a1a2fe1081743b184be07..e3999c163d74fc6b7e7dde04e59d1358ba46add3 100644 (file)
@@ -18,7 +18,7 @@
 #include "theory/theory_engine.h"
 #include "theory/uf/theory_uf.h"
 #include "theory/uf/equality_engine.h"
-//#include "theory/uf/inst_strategy_model_find.h"
+#include "theory/quantifiers/term_database.h"
 
 using namespace std;
 using namespace CVC4;
@@ -32,7 +32,7 @@ EqClassInfo::EqClassInfo( context::Context* c ) : d_funs( c ), d_pfuns( c ), d_d
 }
 
 //set member
-void EqClassInfo::setMember( Node n, TermDb* db ){
+void EqClassInfo::setMember( Node n, quantifiers::TermDb* db ){
   if( n.getKind()==APPLY_UF ){
     d_funs[n.getOperator()] = true;
   }
@@ -65,15 +65,7 @@ void EqClassInfo::merge( EqClassInfo* eci ){
 InstantiatorTheoryUf::InstantiatorTheoryUf(context::Context* c, CVC4::theory::QuantifiersEngine* qe, Theory* th) :
 Instantiator( c, qe, th )
 {
-  qe->setEqualityQuery( new EqualityQueryInstantiatorTheoryUf( this ) );
-
-  if( Options::current()->finiteModelFind ){
-    //if( Options::current()->cbqi ){
-    //  addInstStrategy( new InstStrategyCheckCESolved( this, qe ) );
-    //}
-    //addInstStrategy( new InstStrategyFiniteModelFind( c, this, ((TheoryUF*)th)->getStrongSolver(), qe ) );
-    qe->getTermDatabase()->setMatchingActive( false );
-  }else{
+  if( !Options::current()->finiteModelFind || Options::current()->fmfInstEngine ){
     if( Options::current()->cbqi ){
       addInstStrategy( new InstStrategyCheckCESolved( this, qe ) );
     }
@@ -88,7 +80,9 @@ Instantiator( c, qe, th )
     i_ag->setGenerateAdditional( true );
     addInstStrategy( i_ag );
     //addInstStrategy( new InstStrategyAddFailSplits( this, ie ) );
-    addInstStrategy( new InstStrategyFreeVariable( this, qe ) );
+    if( !Options::current()->finiteModelFind ){
+      addInstStrategy( new InstStrategyFreeVariable( this, qe ) );
+    }
     //d_isup->setPriorityOver( i_ag );
     //d_isup->setPriorityOver( i_agm );
     //i_ag->setPriorityOver( i_agm );
@@ -125,7 +119,7 @@ void InstantiatorTheoryUf::processResetInstantiationRound( Theory::Effort effort
   d_ground_reps.clear();
 }
 
-int InstantiatorTheoryUf::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstantiatorTheoryUf::process( Node f, Theory::Effort effort, int e ){
   Debug("quant-uf") << "UF: Try to solve (" << e << ") for " << f << "... " << std::endl;
   return InstStrategy::STATUS_SAT;
 }
@@ -405,7 +399,7 @@ bool InstantiatorTheoryUf::collectParentsTermsIps( Node n, Node f, int arg, std:
       eqc_iter++;
     }
   }else{
-    TermDb* db = d_quantEngine->getTermDatabase();
+    quantifiers::TermDb* db = d_quantEngine->getTermDatabase();
     //see if parent f exists from argument arg
     if( db->d_parents.find( n )!=db->d_parents.end() ){
       if( db->d_parents[n].find( f )!=db->d_parents[n].end() ){
@@ -481,7 +475,7 @@ void InstantiatorTheoryUf::registerCandidateGenerator( CandidateGenerator* cg, N
 
   //take all terms from the uf term db and add to candidate generator
   Node op = pat.getOperator();
-  TermDb* db = d_quantEngine->getTermDatabase();
+  quantifiers::TermDb* db = d_quantEngine->getTermDatabase();
   for( int i=0; i<(int)db->d_op_map[op].size(); i++ ){
     cg->addCandidate( db->d_op_map[op][i] );
   }
index e50e3823ca93916a8aa55747ee0077189642c862..4ddc01986b9f66997d30da8510826a4662a07727 100644 (file)
@@ -31,7 +31,9 @@
 namespace CVC4 {
 namespace theory {
 
-class TermDb;
+namespace quantifiers{
+  class TermDb;
+}
 
 namespace uf {
 
@@ -56,7 +58,7 @@ public:
   EqClassInfo( context::Context* c );
   ~EqClassInfo(){}
   //set member
-  void setMember( Node n, TermDb* db );
+  void setMember( Node n, quantifiers::TermDb* db );
   //has function "funs"
   bool hasFunction( Node op );
   //has parent "pfuns"
@@ -67,7 +69,7 @@ public:
 
 class InstantiatorTheoryUf : public Instantiator{
   friend class ::CVC4::theory::InstMatchGenerator;
-  friend class ::CVC4::theory::TermDb;
+  friend class ::CVC4::theory::quantifiers::TermDb;
 protected:
   typedef context::CDHashMap<Node, bool, NodeHashFunction> BoolMap;
   typedef context::CDHashMap<Node, int, NodeHashFunction> IntMap;
@@ -95,7 +97,7 @@ private:
   /** reset instantiation */
   void processResetInstantiationRound( Theory::Effort effort );
   /** calculate matches for quantifier f at effort */
-  int process( Node f, Theory::Effort effort, int e, int instLimit );
+  int process( Node f, Theory::Effort effort, int e );
 public:
   /** statistics class */
   class Statistics {
diff --git a/src/theory/uf/theory_uf_model.cpp b/src/theory/uf/theory_uf_model.cpp
new file mode 100644 (file)
index 0000000..a85dea9
--- /dev/null
@@ -0,0 +1,554 @@
+/*********************                                                        */\r
+/*! \file theory_uf_model.cpp\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Implementation of Theory UF Model\r
+ **/\r
+\r
+#include "theory/quantifiers/model_engine.h"\r
+#include "theory/theory_engine.h"\r
+#include "theory/uf/equality_engine.h"\r
+#include "theory/uf/theory_uf.h"\r
+#include "theory/uf/theory_uf_strong_solver.h"\r
+#include "theory/uf/theory_uf_instantiator.h"\r
+#include "theory/quantifiers/first_order_model.h"\r
+#include "theory/quantifiers/term_database.h"\r
+\r
+#define RECONSIDER_FUNC_DEFAULT_VALUE\r
+#define USE_PARTIAL_DEFAULT_VALUES\r
+\r
+using namespace std;\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::context;\r
+using namespace CVC4::theory;\r
+using namespace CVC4::theory::uf;\r
+\r
+//clear\r
+void UfModelTree::clear(){\r
+  d_data.clear();\r
+  d_value = Node::null();\r
+}\r
+\r
+bool UfModelTree::hasConcreteArgumentDefinition(){\r
+  if( d_data.size()>1 ){\r
+    return true;\r
+  }else if( d_data.empty() ){\r
+    return false;\r
+  }else{\r
+    Node r;\r
+    return d_data.find( r )==d_data.end();\r
+  }\r
+}\r
+\r
+//set value function\r
+void UfModelTree::setValue( TheoryModel* m, Node n, Node v, std::vector< int >& indexOrder, bool ground, int argIndex ){\r
+  if( d_data.empty() ){\r
+    d_value = v;\r
+  }else if( !d_value.isNull() && d_value!=v ){\r
+    d_value = Node::null();\r
+  }\r
+  if( argIndex<(int)n.getNumChildren() ){\r
+    //take r = null when argument is the model basis\r
+    Node r;\r
+    if( ground || !n[ indexOrder[argIndex] ].getAttribute(ModelBasisAttribute()) ){\r
+      r = m->getRepresentative( n[ indexOrder[argIndex] ] );\r
+    }\r
+    d_data[ r ].setValue( m, n, v, indexOrder, ground, argIndex+1 );\r
+  }\r
+}\r
+\r
+//get value function\r
+Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int& depIndex, int argIndex ){\r
+  if( !d_value.isNull() && isTotal( n.getOperator(), argIndex ) ){\r
+    //Notice() << "Constant, return " << d_value << ", depIndex = " << argIndex << std::endl;\r
+    depIndex = argIndex;\r
+    return d_value;\r
+  }else{\r
+    Node val;\r
+    int childDepIndex[2] = { argIndex, argIndex };\r
+    for( int i=0; i<2; i++ ){\r
+      //first check the argument, then check default\r
+      Node r;\r
+      if( i==0 ){\r
+        r = m->getRepresentative( n[ indexOrder[argIndex] ] );\r
+      }\r
+      std::map< Node, UfModelTree >::iterator it = d_data.find( r );\r
+      if( it!=d_data.end() ){\r
+        val = it->second.getValue( m, n, indexOrder, childDepIndex[i], argIndex+1 );\r
+        if( !val.isNull() ){\r
+          break;\r
+        }\r
+      }else{\r
+        //argument is not a defined argument: thus, it depends on this argument\r
+        childDepIndex[i] = argIndex+1;\r
+      }\r
+    }\r
+    //update depIndex\r
+    depIndex = childDepIndex[0]>childDepIndex[1] ? childDepIndex[0] : childDepIndex[1];\r
+    //Notice() << "Return " << val << ", depIndex = " << depIndex;\r
+    //Notice() << " ( " << childDepIndex[0] << ", " << childDepIndex[1] << " )" << std::endl;\r
+    return val;\r
+  }\r
+}\r
+\r
+Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, std::vector< int >& depIndex, int argIndex ){\r
+  if( argIndex==(int)indexOrder.size() ){\r
+    return d_value;\r
+  }else{\r
+    Node val;\r
+    bool depArg = false;\r
+    //will try concrete value first, then default\r
+    for( int i=0; i<2; i++ ){\r
+      Node r;\r
+      if( i==0 ){\r
+        r = m->getRepresentative( n[ indexOrder[argIndex] ] );\r
+      }\r
+      std::map< Node, UfModelTree >::iterator it = d_data.find( r );\r
+      if( it!=d_data.end() ){\r
+        val = it->second.getValue( m, n, indexOrder, depIndex, argIndex+1 );\r
+        //we have found a value\r
+        if( !val.isNull() ){\r
+          if( i==0 ){\r
+            depArg = true;\r
+          }\r
+          break;\r
+        }\r
+      }\r
+    }\r
+    //it depends on this argument if we found it via concrete argument value,\r
+    // or if found by default/disequal from some concrete argument value(s).\r
+    if( depArg || hasConcreteArgumentDefinition() ){\r
+      if( std::find( depIndex.begin(), depIndex.end(), indexOrder[argIndex] )==depIndex.end() ){\r
+        depIndex.push_back( indexOrder[argIndex] );\r
+      }\r
+    }\r
+    return val;\r
+  }\r
+}\r
+\r
+Node UfModelTree::getFunctionValue(){\r
+  if( !d_data.empty() ){\r
+    Node defaultValue;\r
+    std::vector< Node > caseValues;\r
+    for( std::map< Node, UfModelTree >::iterator it = d_data.begin(); it != d_data.end(); ++it ){\r
+      if( it->first.isNull() ){\r
+        defaultValue = it->second.getFunctionValue();\r
+      }else{\r
+        caseValues.push_back( NodeManager::currentNM()->mkNode( FUNCTION_CASE, it->first, it->second.getFunctionValue() ) );\r
+      }\r
+    }\r
+    if( caseValues.empty() && defaultValue.getKind()!=FUNCTION_CASE_SPLIT && defaultValue.getKind()!=FUNCTION_MODEL ){\r
+      return defaultValue;\r
+    }else{\r
+      std::vector< Node > children;\r
+      if( !caseValues.empty() ){\r
+        children.push_back( NodeManager::currentNM()->mkNode( FUNCTION_CASE_SPLIT, caseValues ) );\r
+      }\r
+      if( !defaultValue.isNull() ){\r
+        children.push_back( defaultValue );\r
+      }\r
+      return NodeManager::currentNM()->mkNode( FUNCTION_MODEL, children );\r
+    }\r
+  }else{\r
+    Assert( !d_value.isNull() );\r
+    return d_value;\r
+  }\r
+}\r
+\r
+//simplify function\r
+void UfModelTree::simplify( Node op, Node defaultVal, int argIndex ){\r
+  if( argIndex<(int)op.getType().getNumChildren()-1 ){\r
+    std::vector< Node > eraseData;\r
+    //first process the default argument\r
+    Node r;\r
+    std::map< Node, UfModelTree >::iterator it = d_data.find( r );\r
+    if( it!=d_data.end() ){\r
+      if( !defaultVal.isNull() && it->second.d_value==defaultVal ){\r
+        eraseData.push_back( r );\r
+      }else{\r
+        it->second.simplify( op, defaultVal, argIndex+1 );\r
+        if( !it->second.d_value.isNull() && it->second.isTotal( op, argIndex+1 ) ){\r
+          defaultVal = it->second.d_value;\r
+        }else{\r
+          defaultVal = Node::null();\r
+          if( it->second.isEmpty() ){\r
+            eraseData.push_back( r );\r
+          }\r
+        }\r
+      }\r
+    }\r
+    //now see if any children can be removed, and simplify the ones that cannot\r
+    for( std::map< Node, UfModelTree >::iterator it = d_data.begin(); it != d_data.end(); ++it ){\r
+      if( !it->first.isNull() ){\r
+        if( !defaultVal.isNull() && it->second.d_value==defaultVal ){\r
+          eraseData.push_back( it->first );\r
+        }else{\r
+          it->second.simplify( op, defaultVal, argIndex+1 );\r
+          if( it->second.isEmpty() ){\r
+            eraseData.push_back( it->first );\r
+          }\r
+        }\r
+      }\r
+    }\r
+    for( int i=0; i<(int)eraseData.size(); i++ ){\r
+      d_data.erase( eraseData[i] );\r
+    }\r
+  }\r
+}\r
+\r
+//is total function\r
+bool UfModelTree::isTotal( Node op, int argIndex ){\r
+  if( argIndex==(int)(op.getType().getNumChildren()-1) ){\r
+    return !d_value.isNull();\r
+  }else{\r
+    Node r;\r
+    std::map< Node, UfModelTree >::iterator it = d_data.find( r );\r
+    if( it!=d_data.end() ){\r
+      return it->second.isTotal( op, argIndex+1 );\r
+    }else{\r
+      return false;\r
+    }\r
+  }\r
+}\r
+\r
+Node UfModelTree::getConstantValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int argIndex ){\r
+  return d_value;\r
+}\r
+\r
+void indent( std::ostream& out, int ind ){\r
+  for( int i=0; i<ind; i++ ){\r
+    out << " ";\r
+  }\r
+}\r
+\r
+void UfModelTree::debugPrint( std::ostream& out, TheoryModel* m, std::vector< int >& indexOrder, int ind, int arg ){\r
+  if( !d_data.empty() ){\r
+    for( std::map< Node, UfModelTree >::iterator it = d_data.begin(); it != d_data.end(); ++it ){\r
+      if( !it->first.isNull() ){\r
+        indent( out, ind );\r
+        out << "if x_" << indexOrder[arg] << " == " << it->first << std::endl;\r
+        it->second.debugPrint( out, m, indexOrder, ind+2, arg+1 );\r
+      }\r
+    }\r
+    if( d_data.find( Node::null() )!=d_data.end() ){\r
+      d_data[ Node::null() ].debugPrint( out, m, indexOrder, ind, arg+1 );\r
+    }\r
+  }else{\r
+    indent( out, ind );\r
+    out << "return ";\r
+    m->printRepresentative( out, d_value );\r
+    //out << " { ";\r
+    //for( int i=0; i<(int)d_explicit.size(); i++ ){\r
+    //  out << d_explicit[i] << " ";\r
+    //}\r
+    //out << "}";\r
+    out << std::endl;\r
+  }\r
+}\r
+\r
+UfModel::UfModel( Node op, quantifiers::FirstOrderModel* m ) : d_model( m ), d_op( op ),\r
+d_model_constructed( false ){\r
+  d_tree = UfModelTreeOrdered( op );\r
+  TypeNode tn = d_op.getType();\r
+  tn = tn[(int)tn.getNumChildren()-1];\r
+  Assert( tn==NodeManager::currentNM()->booleanType() || tn.isDatatype() || uf::StrongSolverTheoryUf::isRelevantType( tn ) );\r
+  //look at ground assertions\r
+  for( size_t i=0; i<d_model->getTermDatabase()->d_op_map[ d_op ].size(); i++ ){\r
+    Node n = d_model->getTermDatabase()->d_op_map[ d_op ][i];\r
+    d_model->getTermDatabase()->computeModelBasisArgAttribute( n );\r
+    if( !n.getAttribute(NoMatchAttribute()) || n.getAttribute(ModelBasisArgAttribute())==1 ){\r
+      Node r = d_model->getRepresentative( n );\r
+      d_ground_asserts_reps.push_back( r );\r
+      d_ground_asserts.push_back( n );\r
+    }\r
+  }\r
+  //determine if it is constant\r
+  if( !d_ground_asserts.empty() ){\r
+    bool isConstant = true;\r
+    for( int i=1; i<(int)d_ground_asserts.size(); i++ ){\r
+      if( d_ground_asserts_reps[0]!=d_ground_asserts_reps[i] ){\r
+        isConstant = false;\r
+        break;\r
+      }\r
+    }\r
+    if( isConstant ){\r
+      //set constant value\r
+      Node t = d_model->getTermDatabase()->getModelBasisOpTerm( d_op );\r
+      Node r = d_ground_asserts_reps[0];\r
+      setValue( t, r, false );\r
+      setModel();\r
+      Debug("fmf-model-cons") << "Function " << d_op << " is the constant function ";\r
+      d_model->printRepresentativeDebug( "fmf-model-cons", r );\r
+      Debug("fmf-model-cons") << std::endl;\r
+    }\r
+  }\r
+}\r
+\r
+Node UfModel::getIntersection( Node n1, Node n2, bool& isGround ){\r
+  //Notice() << "Get intersection " << n1 << " " << n2 << std::endl;\r
+  isGround = true;\r
+  std::vector< Node > children;\r
+  children.push_back( n1.getOperator() );\r
+  for( int i=0; i<(int)n1.getNumChildren(); i++ ){\r
+    if( n1[i]==n2[i] ){\r
+      if( n1[i].getAttribute(ModelBasisAttribute()) ){\r
+        isGround = false;\r
+      }\r
+      children.push_back( n1[i] );\r
+    }else if( n1[i].getAttribute(ModelBasisAttribute()) ){\r
+      children.push_back( n2[i] );\r
+    }else if( n2[i].getAttribute(ModelBasisAttribute()) ){\r
+      children.push_back( n1[i] );\r
+    }else if( d_model->areEqual( n1[i], n2[i] ) ){\r
+      children.push_back( n1[i] );\r
+    }else{\r
+      return Node::null();\r
+    }\r
+  }\r
+  return NodeManager::currentNM()->mkNode( APPLY_UF, children );\r
+}\r
+\r
+void UfModel::setValue( Node n, Node v, bool ground, bool isReq ){\r
+  Assert( !n.isNull() );\r
+  Assert( !v.isNull() );\r
+  d_set_values[ isReq ? 1 : 0 ][ ground ? 1 : 0 ][n] = v;\r
+  if( optUsePartialDefaults() ){\r
+    if( !ground ){\r
+      int defSize = (int)d_defaults.size();\r
+      for( int i=0; i<defSize; i++ ){\r
+        bool isGround;\r
+        //for soundness, to allow variable order-independent function interpretations,\r
+        //  we must ensure that the intersection of all default terms\r
+        //  is also defined.\r
+        //for example, if we have that f( e, a ) = ..., and f( b, e ) = ...,\r
+        //  then we must define f( b, a ).\r
+        Node ni = getIntersection( n, d_defaults[i], isGround );\r
+        if( !ni.isNull() ){\r
+          //if the intersection exists, and is not already defined\r
+          if( d_set_values[0][ isGround ? 1 : 0 ].find( ni )==d_set_values[0][ isGround ? 1 : 0 ].end() &&\r
+              d_set_values[1][ isGround ? 1 : 0 ].find( ni )==d_set_values[1][ isGround ? 1 : 0 ].end() ){\r
+            //use the current value\r
+            setValue( ni, v, isGround, false );\r
+          }\r
+        }\r
+      }\r
+      d_defaults.push_back( n );\r
+    }\r
+    if( isReq && d_set_values[0][ ground ? 1 : 0 ].find( n )!=d_set_values[0][ ground ? 1 : 0 ].end()){\r
+      d_set_values[0][ ground ? 1 : 0 ].erase( n );\r
+    }\r
+  }\r
+}\r
+\r
+Node UfModel::getValue( Node n, int& depIndex ){\r
+  return d_tree.getValue( d_model, n, depIndex );\r
+}\r
+\r
+Node UfModel::getValue( Node n, std::vector< int >& depIndex ){\r
+  return d_tree.getValue( d_model, n, depIndex );\r
+}\r
+\r
+Node UfModel::getConstantValue( Node n ){\r
+  if( d_model_constructed ){\r
+    return d_tree.getConstantValue( d_model, n );\r
+  }else{\r
+    return Node::null();\r
+  }\r
+}\r
+\r
+Node UfModel::getFunctionValue(){\r
+  if( d_func_value.isNull() && d_model_constructed ){\r
+    d_func_value = d_tree.getFunctionValue();\r
+  }\r
+  return d_func_value;\r
+}\r
+\r
+bool UfModel::isConstant(){\r
+  Node gn = d_model->getTermDatabase()->getModelBasisOpTerm( d_op );\r
+  Node n = getConstantValue( gn );\r
+  return !n.isNull();\r
+}\r
+\r
+bool UfModel::optUsePartialDefaults(){\r
+#ifdef USE_PARTIAL_DEFAULT_VALUES\r
+  return true;\r
+#else\r
+  return false;\r
+#endif\r
+}\r
+\r
+void UfModel::setModel(){\r
+  makeModel( d_tree );\r
+  d_model_constructed = true;\r
+  d_func_value = Node::null();\r
+\r
+  //for debugging, make sure model satisfies all ground assertions\r
+  for( size_t i=0; i<d_ground_asserts.size(); i++ ){\r
+    int depIndex;\r
+    Node n = d_tree.getValue( d_model, d_ground_asserts[i], depIndex );\r
+    if( n!=d_ground_asserts_reps[i] ){\r
+      Debug("fmf-bad") << "Bad model : " << d_ground_asserts[i] << " := ";\r
+      d_model->printRepresentativeDebug("fmf-bad", n );\r
+      Debug("fmf-bad") << " != ";\r
+      d_model->printRepresentativeDebug("fmf-bad", d_ground_asserts_reps[i] );\r
+      Debug("fmf-bad") << std::endl;\r
+    }\r
+  }\r
+}\r
+\r
+void UfModel::clearModel(){\r
+  for( int j=0; j<2; j++ ){\r
+    for( int k=0; k<2; k++ ){\r
+      d_set_values[j][k].clear();\r
+    }\r
+  }\r
+  d_tree.clear();\r
+  d_model_constructed = false;\r
+}\r
+\r
+void UfModel::makeModel( UfModelTreeOrdered& tree ){\r
+  for( int j=0; j<2; j++ ){\r
+    for( int k=0; k<2; k++ ){\r
+      for( std::map< Node, Node >::iterator it = d_set_values[j][k].begin(); it != d_set_values[j][k].end(); ++it ){\r
+        tree.setValue( d_model, it->first, it->second, k==1 );\r
+      }\r
+    }\r
+  }\r
+  tree.simplify();\r
+}\r
+\r
+void UfModel::toStream(std::ostream& out){\r
+  //out << "Function " << d_op << std::endl;\r
+  //out << "   Type: " << d_op.getType() << std::endl;\r
+  //out << "   Ground asserts:" << std::endl;\r
+  //for( int i=0; i<(int)d_ground_asserts.size(); i++ ){\r
+  //  out << "      " << d_ground_asserts[i] << " = ";\r
+  //  d_model->printRepresentative( out, d_ground_asserts[i] );\r
+  //  out << std::endl;\r
+  //}\r
+  //out << "   Model:" << std::endl;\r
+\r
+  TypeNode t = d_op.getType();\r
+  out << d_op << "( ";\r
+  for( int i=0; i<(int)(t.getNumChildren()-1); i++ ){\r
+    out << "x_" << i << " : " << t[i];\r
+    if( i<(int)(t.getNumChildren()-2) ){\r
+      out << ", ";\r
+    }\r
+  }\r
+  out << " ) : " << t[(int)t.getNumChildren()-1] << std::endl;\r
+  if( d_tree.isEmpty() ){\r
+    out << "   [undefined]" << std::endl;\r
+  }else{\r
+    d_tree.debugPrint( out, d_model, 3 );\r
+    out << std::endl;\r
+  }\r
+  //out << "   Phase reqs:" << std::endl;  //for( int i=0; i<2; i++ ){\r
+  //  for( std::map< Node, std::vector< Node > >::iterator it = d_reqs[i].begin(); it != d_reqs[i].end(); ++it ){\r
+  //    out << "      " << it->first << std::endl;\r
+  //    for( int j=0; j<(int)it->second.size(); j++ ){\r
+  //      out << "         " << it->second[j] << " -> " << (i==1) << std::endl;\r
+  //    }\r
+  //  }\r
+  //}\r
+  //out << std::endl;\r
+  //for( int i=0; i<2; i++ ){\r
+  //  for( std::map< Node, std::map< Node, std::vector< Node > > >::iterator it = d_eq_reqs[i].begin(); it != d_eq_reqs[i].end(); ++it ){\r
+  //    out << "      " << "For " << it->first << ":" << std::endl;\r
+  //    for( std::map< Node, std::vector< Node > >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){\r
+  //      for( int j=0; j<(int)it2->second.size(); j++ ){\r
+  //        out << "         " << it2->first << ( i==1 ? "==" : "!=" ) << it2->second[j] << std::endl;\r
+  //      }\r
+  //    }\r
+  //  }\r
+  //}\r
+}\r
+\r
+Node UfModel::toIte2( Node fm_node, std::vector< Node >& args, int index, Node defaultNode ){\r
+  if( fm_node.getKind()==FUNCTION_MODEL ){\r
+    if( fm_node[0].getKind()==FUNCTION_CASE_SPLIT ){\r
+      Node retNode;\r
+      Node childDefaultNode = defaultNode;\r
+      //get new default\r
+      if( fm_node.getNumChildren()==2 ){\r
+        childDefaultNode = toIte2( fm_node[1], args, index+1, defaultNode );\r
+      }\r
+      retNode = childDefaultNode;\r
+      for( int i=(int)fm_node[0].getNumChildren()-1; i>=0; i-- ){\r
+        Node childNode = toIte2( fm_node[0][1], args, index+1, childDefaultNode );\r
+        retNode = NodeManager::currentNM()->mkNode( ITE, args[index].eqNode( fm_node[0][0] ), childNode, retNode );\r
+      }\r
+      return retNode;\r
+    }else{\r
+      return toIte2( fm_node[0], args, index+1, defaultNode );\r
+    }\r
+  }else{\r
+    return fm_node;\r
+  }\r
+}\r
+\r
+\r
+void UfModelPreferenceData::setValuePreference( Node f, Node n, Node r, bool isPro ){\r
+  if( std::find( d_values.begin(), d_values.end(), r )==d_values.end() ){\r
+    d_values.push_back( r );\r
+  }\r
+  int index = isPro ? 0 : 1;\r
+  if( std::find( d_value_pro_con[index][r].begin(), d_value_pro_con[index][r].end(), f )==d_value_pro_con[index][r].end() ){\r
+    d_value_pro_con[index][r].push_back( f );\r
+  }\r
+  d_term_pro_con[index][n].push_back( f );\r
+}\r
+\r
+Node UfModelPreferenceData::getBestDefaultValue( Node defaultTerm, TheoryModel* m ){\r
+  Node defaultVal;\r
+  double maxScore = -1;\r
+  for( size_t i=0; i<d_values.size(); i++ ){\r
+    Node v = d_values[i];\r
+    double score = ( 1.0 + (double)d_value_pro_con[0][v].size() )/( 1.0 + (double)d_value_pro_con[1][v].size() );\r
+    Debug("fmf-model-cons") << "  - score( ";\r
+    m->printRepresentativeDebug( "fmf-model-cons", v );\r
+    Debug("fmf-model-cons") << " ) = " << score << std::endl;\r
+    if( score>maxScore ){\r
+      defaultVal = v;\r
+      maxScore = score;\r
+    }\r
+  }\r
+#ifdef RECONSIDER_FUNC_DEFAULT_VALUE\r
+  if( maxScore<1.0 ){\r
+    //consider finding another value, if possible\r
+    Debug("fmf-model-cons-debug") << "Poor choice for default value, score = " << maxScore << std::endl;\r
+    TypeNode tn = defaultTerm.getType();\r
+    Node newDefaultVal = m->getDomainValue( tn, d_values );\r
+    if( !newDefaultVal.isNull() ){\r
+      defaultVal = newDefaultVal;\r
+      Debug("fmf-model-cons-debug") << "-> Change default value to ";\r
+      m->printRepresentativeDebug( "fmf-model-cons-debug", defaultVal );\r
+      Debug("fmf-model-cons-debug") << std::endl;\r
+    }else{\r
+      Debug("fmf-model-cons-debug") << "-> Could not find arbitrary element of type " << tn[(int)tn.getNumChildren()-1] << std::endl;\r
+      Debug("fmf-model-cons-debug") << "      Excluding: ";\r
+      for( int i=0; i<(int)d_values.size(); i++ ){\r
+        Debug("fmf-model-cons-debug") << d_values[i] << " ";\r
+      }\r
+      Debug("fmf-model-cons-debug") << std::endl;\r
+    }\r
+  }\r
+#endif\r
+  //get the default term (this term must be defined non-ground in model)\r
+  Debug("fmf-model-cons") << "  Choose ";\r
+  m->printRepresentativeDebug("fmf-model-cons", defaultVal );\r
+  Debug("fmf-model-cons") << " as default value (" << defaultTerm << ")" << std::endl;\r
+  Debug("fmf-model-cons") << "     # quantifiers pro = " << d_value_pro_con[0][defaultVal].size() << std::endl;\r
+  Debug("fmf-model-cons") << "     # quantifiers con = " << d_value_pro_con[1][defaultVal].size() << std::endl;\r
+  return defaultVal;\r
+}
\ No newline at end of file
diff --git a/src/theory/uf/theory_uf_model.h b/src/theory/uf/theory_uf_model.h
new file mode 100644 (file)
index 0000000..406c7ff
--- /dev/null
@@ -0,0 +1,216 @@
+/*********************                                                        */\r
+/*! \file theory_uf_model.h\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Model for Theory UF\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef __CVC4__THEORY_UF_MODEL_H\r
+#define __CVC4__THEORY_UF_MODEL_H\r
+\r
+#include "theory/model.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+\r
+namespace quantifiers{\r
+  class FirstOrderModel;\r
+}\r
+\r
+namespace uf {\r
+\r
+class UfModelTree\r
+{\r
+public:\r
+  UfModelTree(){}\r
+  /** the data */\r
+  std::map< Node, UfModelTree > d_data;\r
+  /** the value of this tree node (if all paths lead to same value) */\r
+  Node d_value;\r
+  /** has concrete argument defintion */\r
+  bool hasConcreteArgumentDefinition();\r
+public:\r
+  //is this model tree empty?\r
+  bool isEmpty() { return d_data.empty() && d_value.isNull(); }\r
+  //clear\r
+  void clear();\r
+  /** setValue function\r
+    *\r
+    * For each argument of n with ModelBasisAttribute() set to true will be considered default arguments if ground=false\r
+    *\r
+    */\r
+  void setValue( TheoryModel* m, Node n, Node v, std::vector< int >& indexOrder, bool ground, int argIndex );\r
+  /**  getValue function\r
+    *\r
+    *  returns $val, the value of ground term n\r
+    *  Say n is f( t_0...t_n )\r
+    *    depIndex is the index for which every term of the form f( t_0 ... t_depIndex, *,... * ) is equal to $val\r
+    *    for example, if g( x_0, x_1, x_2 ) := lambda x_0 x_1 x_2. if( x_1==a ) b else c,\r
+    *      then g( a, a, a ) would return b with depIndex = 1\r
+    *  If ground = true, we are asking whether the term n is constant (assumes that all non-model basis arguments are ground)\r
+    *\r
+    */\r
+  Node getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int& depIndex, int argIndex );\r
+  Node getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, std::vector< int >& depIndex, int argIndex );\r
+  ///** getConstant Value function\r
+  //  *\r
+  //  * given term n, where n may contain model basis arguments\r
+  //  * if n is constant for its entire domain, then this function returns the value of its domain\r
+  //  * otherwise, it returns null\r
+  //  * for example, if f( x_0, x_1 ) := if( x_0 = a ) b else if( x_1 = a ) a else b,\r
+  //  *   then f( a, e ) would return b, while f( e, a ) would return null\r
+  //  *\r
+  //  */\r
+  Node getConstantValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int argIndex );\r
+  /** getFunctionValue */\r
+  Node getFunctionValue();\r
+  /** simplify function */\r
+  void simplify( Node op, Node defaultVal, int argIndex );\r
+  // is total ?\r
+  bool isTotal( Node op, int argIndex );\r
+public:\r
+  void debugPrint( std::ostream& out, TheoryModel* m, std::vector< int >& indexOrder, int ind = 0, int arg = 0 );\r
+};\r
+\r
+class UfModelTreeOrdered\r
+{\r
+private:\r
+  Node d_op;\r
+  std::vector< int > d_index_order;\r
+  UfModelTree d_tree;\r
+public:\r
+  UfModelTreeOrdered(){}\r
+  UfModelTreeOrdered( Node op ) : d_op( op ){\r
+    TypeNode tn = d_op.getType();\r
+    for( int i=0; i<(int)(tn.getNumChildren()-1); i++ ){\r
+      d_index_order.push_back( i );\r
+    }\r
+  }\r
+  UfModelTreeOrdered( Node op, std::vector< int >& indexOrder ) : d_op( op ){\r
+    d_index_order.insert( d_index_order.end(), indexOrder.begin(), indexOrder.end() );\r
+  }\r
+  bool isEmpty() { return d_tree.isEmpty(); }\r
+  void clear() { d_tree.clear(); }\r
+  void setValue( TheoryModel* m, Node n, Node v, bool ground = true ){\r
+    d_tree.setValue( m, n, v, d_index_order, ground, 0 );\r
+  }\r
+  Node getValue( TheoryModel* m, Node n, int& depIndex ){\r
+    return d_tree.getValue( m, n, d_index_order, depIndex, 0 );\r
+  }\r
+  Node getValue( TheoryModel* m, Node n, std::vector< int >& depIndex ){\r
+    return d_tree.getValue( m, n, d_index_order, depIndex, 0 );\r
+  }\r
+  Node getConstantValue( TheoryModel* m, Node n ) {\r
+    return d_tree.getConstantValue( m, n, d_index_order, 0 );\r
+  }\r
+  Node getFunctionValue(){\r
+    return d_tree.getFunctionValue();\r
+  }\r
+  void simplify() { d_tree.simplify( d_op, Node::null(), 0 ); }\r
+  bool isTotal() { return d_tree.isTotal( d_op, 0 ); }\r
+public:\r
+  void debugPrint( std::ostream& out, TheoryModel* m, int ind = 0 ){\r
+    d_tree.debugPrint( out, m, d_index_order, ind );\r
+  }\r
+};\r
+\r
+class UfModel\r
+{\r
+private:\r
+  quantifiers::FirstOrderModel* d_model;\r
+  //the operator this model is for\r
+  Node d_op;\r
+  //is model constructed\r
+  bool d_model_constructed;\r
+  //store for set values\r
+  std::map< Node, Node > d_set_values[2][2];\r
+private:\r
+  // defaults\r
+  std::vector< Node > d_defaults;\r
+  Node getIntersection( Node n1, Node n2, bool& isGround );\r
+public:\r
+  UfModel(){}\r
+  UfModel( Node op, quantifiers::FirstOrderModel* m );\r
+  ~UfModel(){}\r
+  //ground terms for this operator\r
+  std::vector< Node > d_ground_asserts;\r
+  //the representatives they are equal to\r
+  std::vector< Node > d_ground_asserts_reps;\r
+  //data structure that stores the model\r
+  UfModelTreeOrdered d_tree;\r
+  //node equivalent of this model\r
+  Node d_func_value;\r
+public:\r
+  /** get operator */\r
+  Node getOperator() { return d_op; }\r
+  /** debug print */\r
+  void toStream( std::ostream& out );\r
+  /** set value */\r
+  void setValue( Node n, Node v, bool ground = true, bool isReq = true );\r
+  /** get value, return arguments that the value depends on */\r
+  Node getValue( Node n, int& depIndex );\r
+  Node getValue( Node n, std::vector< int >& depIndex );\r
+  /** get constant value */\r
+  Node getConstantValue( Node n );\r
+  /** get function value for this function */\r
+  Node getFunctionValue();\r
+  /** is model constructed */\r
+  bool isModelConstructed() { return d_model_constructed; }\r
+  /** is empty */\r
+  bool isEmpty() { return d_ground_asserts.empty(); }\r
+  /** is constant */\r
+  bool isConstant();\r
+  /** uses partial default values */\r
+  bool optUsePartialDefaults();\r
+public:\r
+  /** set model */\r
+  void setModel();\r
+  /** clear model */\r
+  void clearModel();\r
+  /** make model */\r
+  void makeModel( UfModelTreeOrdered& tree );\r
+public:\r
+  /** set value preference */\r
+  void setValuePreference( Node f, Node n, bool isPro );\r
+private:\r
+  //helper for to ITE function.\r
+  static Node toIte2( Node fm_node, std::vector< Node >& args, int index, Node defaultNode );\r
+public:\r
+  /** to ITE function for function model nodes */\r
+  static Node toIte( Node fm_node, std::vector< Node >& args ) { return toIte2( fm_node, args, 0, Node::null() ); }\r
+};\r
+\r
+//this class stores temporary information useful to model engine for constructing model\r
+class UfModelPreferenceData\r
+{\r
+public:\r
+  UfModelPreferenceData() : d_reconsiderModel( false ){}\r
+  virtual ~UfModelPreferenceData(){}\r
+  // preferences for default values\r
+  std::vector< Node > d_values;\r
+  std::map< Node, std::vector< Node > > d_value_pro_con[2];\r
+  std::map< Node, std::vector< Node > > d_term_pro_con[2];\r
+  bool d_reconsiderModel;\r
+  /** set value preference */\r
+  void setValuePreference( Node f, Node n, Node r, bool isPro );\r
+  /** get best default value */\r
+  Node getBestDefaultValue( Node defaultTerm, TheoryModel* m );\r
+};\r
+\r
+\r
+}\r
+}\r
+}\r
+\r
+#endif\r
index ebbbb139d72a33ea482dda5c8968d1d01eb6728b..e2dd551745d8247c337a49fb38ebeacc4b844208 100644 (file)
 #include "theory/uf/equality_engine.h"
 #include "theory/uf/theory_uf_instantiator.h"
 #include "theory/theory_engine.h"
+#include "theory/quantifiers/term_database.h"
 
-//#define USE_REGION_SAT
+//#define USE_SMART_SPLITS
+//#define ONE_SPLIT_REGION
+//#define DISABLE_QUICK_CLIQUE_CHECKS
+//#define COMBINE_REGIONS_SMALL_INTO_LARGE
 
 using namespace std;
 using namespace CVC4;
@@ -29,6 +33,10 @@ using namespace CVC4::context;
 using namespace CVC4::theory;
 using namespace CVC4::theory::uf;
 
+void StrongSolverTheoryUf::ConflictFind::Region::addRep( Node n ) {
+  setRep( n, true );
+}
+
 void StrongSolverTheoryUf::ConflictFind::Region::takeNode( StrongSolverTheoryUf::ConflictFind::Region* r, Node n ){
   //Debug("uf-ss") << "takeNode " << r << " " << n << std::endl;
   //Debug("uf-ss") << "r : " << std::endl;
@@ -64,7 +72,6 @@ void StrongSolverTheoryUf::ConflictFind::Region::takeNode( StrongSolverTheoryUf:
   }
   //remove representative
   r->setRep( n, false );
-  //Debug("uf-ss") << "done takeNode " << r << " " << n << std::endl;
 }
 
 void StrongSolverTheoryUf::ConflictFind::Region::combine( StrongSolverTheoryUf::ConflictFind::Region* r ){
@@ -98,29 +105,6 @@ void StrongSolverTheoryUf::ConflictFind::Region::combine( StrongSolverTheoryUf::
   r->d_valid = false;
 }
 
-void StrongSolverTheoryUf::ConflictFind::Region::setRep( Node n, bool valid ){
-  Assert( hasRep( n )!=valid );
-  if( d_nodes.find( n )==d_nodes.end() && valid ){
-    d_nodes[n] = new RegionNodeInfo( d_cf->d_th->getSatContext() );
-  }
-  d_nodes[n]->d_valid = valid;
-  d_reps_size = d_reps_size + ( valid ? 1 : -1 );
-  if( d_testClique.find( n )!=d_testClique.end() && d_testClique[n] ){
-    Assert( !valid );
-    d_testClique[n] = false;
-    d_testCliqueSize = d_testCliqueSize - 1;
-    //remove all splits involving n
-    for( NodeBoolMap::iterator it = d_splits.begin(); it != d_splits.end(); ++it ){
-      if( (*it).second ){
-        if( (*it).first[0]==n || (*it).first[1]==n ){
-          d_splits[ (*it).first ] = false;
-          d_splitsSize = d_splitsSize - 1;
-        }
-      }
-    }
-  }
-}
-
 /** setEqual */
 void StrongSolverTheoryUf::ConflictFind::Region::setEqual( Node a, Node b ){
   Assert( hasRep( a ) && hasRep( b ) );
@@ -170,13 +154,47 @@ void StrongSolverTheoryUf::ConflictFind::Region::setDisequal( Node n1, Node n2,
   }
 }
 
+void StrongSolverTheoryUf::ConflictFind::Region::setRep( Node n, bool valid ){
+  Assert( hasRep( n )!=valid );
+  if( valid && d_nodes.find( n )==d_nodes.end() ){
+    d_nodes[n] = new RegionNodeInfo( d_cf->d_th->getSatContext() );
+  }
+  d_nodes[n]->d_valid = valid;
+  d_reps_size = d_reps_size + ( valid ? 1 : -1 );
+  //removing a member of the test clique from this region
+  if( d_testClique.find( n )!=d_testClique.end() && d_testClique[n] ){
+    Assert( !valid );
+    d_testClique[n] = false;
+    d_testCliqueSize = d_testCliqueSize - 1;
+    //remove all splits involving n
+    for( NodeBoolMap::iterator it = d_splits.begin(); it != d_splits.end(); ++it ){
+      if( (*it).second ){
+        if( (*it).first[0]==n || (*it).first[1]==n ){
+          d_splits[ (*it).first ] = false;
+          d_splitsSize = d_splitsSize - 1;
+        }
+      }
+    }
+  }
+}
+
 bool StrongSolverTheoryUf::ConflictFind::Region::isDisequal( Node n1, Node n2, int type ){
   RegionNodeInfo::DiseqList* del = d_nodes[ n1 ]->d_disequalities[type];
   return del->d_disequalities.find( n2 )!=del->d_disequalities.end() && del->d_disequalities[n2];
 }
 
+struct sortInternalDegree {
+  StrongSolverTheoryUf::ConflictFind::Region* r;
+  bool operator() (Node i,Node j) { return (r->d_nodes[i]->getNumInternalDisequalities()>r->d_nodes[j]->getNumInternalDisequalities());}
+};
+
+struct sortExternalDegree {
+  StrongSolverTheoryUf::ConflictFind::Region* r;
+  bool operator() (Node i,Node j) { return (r->d_nodes[i]->getNumExternalDisequalities()>r->d_nodes[j]->getNumExternalDisequalities());}
+};
+
 bool StrongSolverTheoryUf::ConflictFind::Region::getMustCombine( int cardinality ){
-  if( d_total_diseq_external>=long(cardinality) ){
+  if( Options::current()->ufssRegions && d_total_diseq_external>=long(cardinality) ){
     //The number of external disequalities is greater than or equal to cardinality.
     //Thus, a clique of size cardinality+1 may exist between nodes in d_regions[i] and other regions
     //Check if this is actually the case:  must have n nodes with outgoing degree (cardinality+1-n) for some n>0
@@ -189,7 +207,7 @@ bool StrongSolverTheoryUf::ConflictFind::Region::getMustCombine( int cardinality
           if( outDeg>=cardinality ){
             //we have 1 node of degree greater than (cardinality)
             return true;
-          }else if( outDeg>0 ){
+          }else if( outDeg>=1 ){
             degrees.push_back( outDeg );
             if( (int)degrees.size()>=cardinality ){
               //we have (cardinality) nodes of degree 1
@@ -199,6 +217,12 @@ bool StrongSolverTheoryUf::ConflictFind::Region::getMustCombine( int cardinality
         }
       }
     }
+    //static int gmcCount = 0;
+    //gmcCount++;
+    //if( gmcCount%100==0 ){
+    //  std::cout << gmcCount << " " << cardinality << std::endl;
+    //}
+    //this should happen relatively infrequently....
     std::sort( degrees.begin(), degrees.end() );
     for( int i=0; i<(int)degrees.size(); i++ ){
       if( degrees[i]>=cardinality+1-((int)degrees.size()-i) ){
@@ -209,15 +233,9 @@ bool StrongSolverTheoryUf::ConflictFind::Region::getMustCombine( int cardinality
   return false;
 }
 
-struct sortInternalDegree {
-  StrongSolverTheoryUf::ConflictFind::Region* r;
-  bool operator() (Node i,Node j) { return (r->d_nodes[i]->getNumInternalDisequalities()>r->d_nodes[j]->getNumInternalDisequalities());}
-};
-
-
 bool StrongSolverTheoryUf::ConflictFind::Region::check( Theory::Effort level, int cardinality, std::vector< Node >& clique ){
   if( d_reps_size>long(cardinality) ){
-    if( d_reps_size>long(cardinality) && d_total_diseq_internal==d_reps_size*( d_reps_size - 1 ) ){
+    if( d_total_diseq_internal==d_reps_size*( d_reps_size - 1 ) ){
       //quick clique check, all reps form a clique
       for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
         if( it->second->d_valid ){
@@ -225,7 +243,7 @@ bool StrongSolverTheoryUf::ConflictFind::Region::check( Theory::Effort level, in
         }
       }
       return true;
-    }else{
+    }else if( Options::current()->ufssRegions || Options::current()->ufssEagerSplits || level==Theory::EFFORT_FULL ){
       //build test clique, up to size cardinality+1
       if( d_testCliqueSize<=long(cardinality) ){
         std::vector< Node > newClique;
@@ -233,7 +251,9 @@ bool StrongSolverTheoryUf::ConflictFind::Region::check( Theory::Effort level, in
           for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
             //if not in the test clique, add it to the set of new members
             if( it->second->d_valid && ( d_testClique.find( it->first )==d_testClique.end() || !d_testClique[ it->first ] ) ){
+              //if( it->second->getNumInternalDisequalities()>cardinality || level==Theory::EFFORT_FULL ){
               newClique.push_back( it->first );
+              //}
             }
           }
           //choose remaining nodes with the highest degrees
@@ -282,8 +302,8 @@ bool StrongSolverTheoryUf::ConflictFind::Region::check( Theory::Effort level, in
           d_testCliqueSize = d_testCliqueSize + 1;
         }
       }
-      Assert( d_testCliqueSize==long(cardinality+1) );
-      if( d_splitsSize==0 ){
+      //check if test clique has larger size than cardinality, and forms a clique
+      if( d_testCliqueSize>=long(cardinality+1) && d_splitsSize==0 ){
         //test clique is a clique
         for( NodeBoolMap::iterator it = d_testClique.begin(); it != d_testClique.end(); ++it ){
           if( (*it).second ){
@@ -297,7 +317,31 @@ bool StrongSolverTheoryUf::ConflictFind::Region::check( Theory::Effort level, in
   return false;
 }
 
+void StrongSolverTheoryUf::ConflictFind::Region::getRepresentatives( std::vector< Node >& reps ){
+  for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
+    RegionNodeInfo* rni = it->second;
+    if( rni->d_valid ){
+      reps.push_back( it->first );
+    }
+  }
+}
+
+void StrongSolverTheoryUf::ConflictFind::Region::getNumExternalDisequalities( std::map< Node, int >& num_ext_disequalities ){
+  for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
+    RegionNodeInfo* rni = it->second;
+    if( rni->d_valid ){
+      RegionNodeInfo::DiseqList* del = rni->d_disequalities[0];
+      for( NodeBoolMap::iterator it2 = del->d_disequalities.begin(); it2 != del->d_disequalities.end(); ++it2 ){
+        if( (*it2).second ){
+          num_ext_disequalities[ (*it2).first ]++;
+        }
+      }
+    }
+  }
+}
+
 Node StrongSolverTheoryUf::ConflictFind::Region::getBestSplit(){
+#ifndef USE_SMART_SPLITS
   //take the first split you find
   for( NodeBoolMap::iterator it = d_splits.begin(); it != d_splits.end(); ++it ){
     if( (*it).second ){
@@ -305,6 +349,60 @@ Node StrongSolverTheoryUf::ConflictFind::Region::getBestSplit(){
     }
   }
   return Node::null();
+#else
+  std::vector< Node > splits;
+  for( NodeBoolMap::iterator it = d_splits.begin(); it != d_splits.end(); ++it ){
+    if( (*it).second ){
+      splits.push_back( (*it).first );
+    }
+  }
+  if( splits.size()>1 ){
+    std::map< Node, std::map< Node, bool > > ops;
+    Debug("uf-ss-split") << "Choice for splits: " << std::endl;
+    double maxScore = -1;
+    int maxIndex;
+    for( int i=0; i<(int)splits.size(); i++ ){
+      Debug("uf-ss-split") << "   " << splits[i] << std::endl;
+      for( int j=0; j<2; j++ ){
+        if( ops.find( splits[i][j] )==ops.end() ){
+          EqClassIterator eqc( splits[i][j], ((uf::TheoryUF*)d_cf->d_th)->getEqualityEngine() );
+          while( !eqc.isFinished() ){
+            Node n = (*eqc);
+            if( n.getKind()==APPLY_UF ){
+              ops[ splits[i][j] ][ n.getOperator() ] = true;
+            }
+            ++eqc;
+          }
+        }
+      }
+      //now, compute score
+      int common[2] = { 0, 0 };
+      for( int j=0; j<2; j++ ){
+        int j2 = j==0 ? 1 : 0;
+        for( std::map< Node, bool >::iterator it = ops[ splits[i][j] ].begin(); it != ops[ splits[i][j] ].end(); ++it ){
+          if( ops[ splits[i][j2] ].find( it->first )!=ops[ splits[i][j2] ].end() ){
+            common[0]++;
+          }else{
+            common[1]++;
+          }
+        }
+      }
+      double score = ( 1.0 + (double)common[0] )/( 1.0 + (double)common[1] );
+      if( score>maxScore ){
+        maxScore = score;
+        maxIndex = i;
+      }
+    }
+    //if( maxIndex!=0 ){
+    //  std::cout << "Chose maxIndex = " << maxIndex << std::endl;
+    //}
+    return splits[maxIndex];
+  }else if( !splits.empty() ){
+    return splits[0];
+  }else{
+    return Node::null();
+  }
+#endif
 }
 
 void StrongSolverTheoryUf::ConflictFind::Region::addSplit( OutputChannel* out ){
@@ -324,15 +422,6 @@ void StrongSolverTheoryUf::ConflictFind::Region::addSplit( OutputChannel* out ){
   out->requirePhase( s, true );
 }
 
-void StrongSolverTheoryUf::ConflictFind::Region::getRepresentatives( std::vector< Node >& reps ){
-  for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
-    RegionNodeInfo* rni = it->second;
-    if( rni->d_valid ){
-      reps.push_back( it->first );
-    }
-  }
-}
-
 bool StrongSolverTheoryUf::ConflictFind::Region::minimize( OutputChannel* out ){
   if( hasSplits() ){
     addSplit( out );
@@ -342,20 +431,6 @@ bool StrongSolverTheoryUf::ConflictFind::Region::minimize( OutputChannel* out ){
   }
 }
 
-void StrongSolverTheoryUf::ConflictFind::Region::getNumExternalDisequalities( std::map< Node, int >& num_ext_disequalities ){
-  for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
-    RegionNodeInfo* rni = it->second;
-    if( rni->d_valid ){
-      RegionNodeInfo::DiseqList* del = rni->d_disequalities[0];
-      for( NodeBoolMap::iterator it2 = del->d_disequalities.begin(); it2 != del->d_disequalities.end(); ++it2 ){
-        if( (*it2).second ){
-          num_ext_disequalities[ (*it2).first ]++;
-        }
-      }
-    }
-  }
-}
-
 void StrongSolverTheoryUf::ConflictFind::Region::debugPrint( const char* c, bool incClique ){
   Debug( c ) << "Num reps: " << d_reps_size << std::endl;
   for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
@@ -398,35 +473,6 @@ void StrongSolverTheoryUf::ConflictFind::Region::debugPrint( const char* c, bool
   }
 }
 
-void StrongSolverTheoryUf::ConflictFind::combineRegions( int ai, int bi ){
-  Debug("uf-ss-region") << "uf-ss: Combine Region #" << bi << " with Region #" << ai << std::endl;
-  Assert( isValid( ai ) && isValid( bi ) );
-  for( std::map< Node, Region::RegionNodeInfo* >::iterator it = d_regions[bi]->d_nodes.begin(); it != d_regions[bi]->d_nodes.end(); ++it ){
-    Region::RegionNodeInfo* rni = it->second;
-    if( rni->d_valid ){
-      d_regions_map[ it->first ] = ai;
-    }
-  }
-  //update regions disequal DO_THIS?
-  d_regions[ai]->combine( d_regions[bi] );
-  d_regions[bi]->d_valid = false;
-}
-
-void StrongSolverTheoryUf::ConflictFind::moveNode( Node n, int ri ){
-  Debug("uf-ss-region") << "uf-ss: Move node " << n << " to Region #" << ri << std::endl;
-  Assert( isValid( d_regions_map[ n ] ) );
-  Assert( isValid( ri ) );
-  ////update regions disequal DO_THIS?
-  //Region::RegionNodeInfo::DiseqList* del = d_regions[ d_regions_map[n] ]->d_nodes[n]->d_disequalities[0];
-  //for( NodeBoolMap::iterator it = del->d_disequalities.begin(); it != del->d_disequalities.end(); ++it ){
-  //  if( (*it).second ){
-  //  }
-  //}
-  //move node to region ri
-  d_regions[ri]->takeNode( d_regions[ d_regions_map[n] ], n );
-  d_regions_map[n] = ri;
-}
-
 int StrongSolverTheoryUf::ConflictFind::getNumDisequalitiesToRegion( Node n, int ri ){
   int ni = d_regions_map[n];
   int counter = 0;
@@ -448,10 +494,6 @@ void StrongSolverTheoryUf::ConflictFind::getDisequalitiesToRegions( int ri, std:
       Region::RegionNodeInfo::DiseqList* del = it->second->d_disequalities[0];
       for( NodeBoolMap::iterator it2 = del->d_disequalities.begin(); it2 != del->d_disequalities.end(); ++it2 ){
         if( (*it2).second ){
-          //if( !isValid( d_regions_map[ (*it2).first ] ) ){
-          //  Debug( "uf-ss-temp" ) << "^^^" << ri << " " << d_regions_map[ (*it2).first ].get() << std::endl;
-          //  debugPrint( "uf-ss-temp" );
-          //}
           Assert( isValid( d_regions_map[ (*it2).first ] ) );
           //Notice() << "Found disequality with " << (*it2).first << ", region = " << d_regions_map[ (*it2).first ] << std::endl;
           regions_diseq[ d_regions_map[ (*it2).first ] ]++;
@@ -542,18 +584,21 @@ void StrongSolverTheoryUf::ConflictFind::explainClique( std::vector< Node >& cli
 /** new node */
 void StrongSolverTheoryUf::ConflictFind::newEqClass( Node n ){
   if( d_regions_map.find( n )==d_regions_map.end() ){
+    if( !Options::current()->ufssRegions ){
+      //if not using regions, always add new equivalence classes to region index = 0
+      d_regions_index = 0;
+    }
     d_regions_map[n] = d_regions_index;
     Debug("uf-ss") << "StrongSolverTheoryUf: New Eq Class " << n << std::endl;
     Debug("uf-ss-debug") << d_regions_index << " " << (int)d_regions.size() << std::endl;
     if( d_regions_index<d_regions.size() ){
       d_regions[ d_regions_index ]->debugPrint("uf-ss-debug",true);
       d_regions[ d_regions_index ]->d_valid = true;
-      //Assert( d_regions[ d_regions_index ]->d_valid );
-      Assert( d_regions[ d_regions_index ]->getNumReps()==0 );
+      Assert( !Options::current()->ufssRegions || d_regions[ d_regions_index ]->getNumReps()==0 );
     }else{
       d_regions.push_back( new Region( this, d_th->getSatContext() ) );
     }
-    d_regions[ d_regions_index ]->setRep( n, true );
+    d_regions[ d_regions_index ]->addRep( n );
     d_regions_index = d_regions_index + 1;
     d_reps = d_reps + 1;
   }
@@ -571,14 +616,14 @@ void StrongSolverTheoryUf::ConflictFind::merge( Node a, Node b ){
     int bi = d_regions_map[b];
     Debug("uf-ss") << "   regions: " << ai << " " << bi << std::endl;
     if( ai!=bi ){
-      if( d_regions[ai]->getNumReps()==1 ){
-        combineRegions( bi, ai );
-        d_regions[bi]->setEqual( a, b );
-        checkRegion( bi );
+      if( d_regions[ai]->getNumReps()==1  ){
+        int ri = combineRegions( bi, ai );
+        d_regions[ri]->setEqual( a, b );
+        checkRegion( ri );
       }else if( d_regions[bi]->getNumReps()==1 ){
-        combineRegions( ai, bi );
-        d_regions[ai]->setEqual( a, b );
-        checkRegion( ai );
+        int ri = combineRegions( ai, bi );
+        d_regions[ri]->setEqual( a, b );
+        checkRegion( ri );
       }else{
         // either move a to d_regions[bi], or b to d_regions[ai]
         int aex = d_regions[ai]->d_nodes[a]->getNumInternalDisequalities() - getNumDisequalitiesToRegion( a, bi );
@@ -652,7 +697,7 @@ void StrongSolverTheoryUf::ConflictFind::assertCardinality( int c, bool val ){
   }
 }
 
-bool StrongSolverTheoryUf::ConflictFind::checkRegion( int ri, bool rec ){
+void StrongSolverTheoryUf::ConflictFind::checkRegion( int ri, bool rec ){
   if( isValid(ri) ){
     Assert( d_cardinality>0 );
     //first check if region is in conflict
@@ -660,61 +705,98 @@ bool StrongSolverTheoryUf::ConflictFind::checkRegion( int ri, bool rec ){
     if( d_regions[ri]->check( Theory::EFFORT_STANDARD, d_cardinality, clique ) ){
       //explain clique
       explainClique( clique, &d_th->getOutputChannel() );
-      return false;
     }else if( d_regions[ri]->getMustCombine( d_cardinality ) ){
-      //this region must merge with another
-      Debug("uf-ss-check-region") << "We must combine Region #" << ri << ". " << std::endl;
-      d_regions[ri]->debugPrint("uf-ss-check-region");
       ////alternatively, check if we can reduce the number of external disequalities by moving single nodes
       //for( std::map< Node, bool >::iterator it = d_regions[i]->d_reps.begin(); it != d_regions[i]->d_reps.end(); ++it ){
       //  if( it->second ){
       //    int inDeg = d_regions[i]->d_disequalities_size[1][ it-> first ];
-      //    int outDeg = d_regions[i]->d_disequalities_size[1][ it-> first ];
+      //    int outDeg = d_regions[i]->d_disequalities_size[0][ it-> first ];
       //    if( inDeg<outDeg ){
       //    }
       //  }
       //}
-      //take region with maximum disequality density
-      double maxScore = 0;
-      int maxRegion = -1;
-      std::map< int, int > regions_diseq;
-      getDisequalitiesToRegions( ri, regions_diseq );
-      for( std::map< int, int >::iterator it = regions_diseq.begin(); it != regions_diseq.end(); ++it ){
-        Debug("uf-ss-check-region") << it->first << " : " << it->second << std::endl;
+      int riNew = forceCombineRegion( ri, true );
+      if( riNew>=0 && rec ){
+        checkRegion( riNew, rec );
       }
-      for( std::map< int, int >::iterator it = regions_diseq.begin(); it != regions_diseq.end(); ++it ){
-        Assert( it->first!=ri );
-        Assert( isValid( it->first ) );
-        Assert( d_regions[ it->first ]->getNumReps()>0 );
-        double tempScore = double(it->second)/double(d_regions[it->first]->getNumReps() );
-        if( tempScore>maxScore ){
-          maxRegion = it->first;
-          maxScore = tempScore;
-        }
+    }
+  }
+}
+
+int StrongSolverTheoryUf::ConflictFind::forceCombineRegion( int ri, bool useDensity ){
+  if( !useDensity ){
+    for( int i=0; i<(int)d_regions_index; i++ ){
+      if( ri!=i && d_regions[i]->d_valid ){
+        return combineRegions( ri, i );
       }
-      Assert( maxRegion!=-1 );
+    }
+    return -1;
+  }else{
+    //this region must merge with another
+    Debug("uf-ss-check-region") << "We must combine Region #" << ri << ". " << std::endl;
+    d_regions[ri]->debugPrint("uf-ss-check-region");
+    //take region with maximum disequality density
+    double maxScore = 0;
+    int maxRegion = -1;
+    std::map< int, int > regions_diseq;
+    getDisequalitiesToRegions( ri, regions_diseq );
+    for( std::map< int, int >::iterator it = regions_diseq.begin(); it != regions_diseq.end(); ++it ){
+      Debug("uf-ss-check-region") << it->first << " : " << it->second << std::endl;
+    }
+    for( std::map< int, int >::iterator it = regions_diseq.begin(); it != regions_diseq.end(); ++it ){
+      Assert( it->first!=ri );
+      Assert( isValid( it->first ) );
+      Assert( d_regions[ it->first ]->getNumReps()>0 );
+      double tempScore = double(it->second)/double(d_regions[it->first]->getNumReps() );
+      if( tempScore>maxScore ){
+        maxRegion = it->first;
+        maxScore = tempScore;
+      }
+    }
+    if( maxRegion!=-1 ){
       Debug("uf-ss-check-region") << "Combine with region #" << maxRegion << ":" << std::endl;
       d_regions[maxRegion]->debugPrint("uf-ss-check-region");
-      combineRegions( ri, maxRegion );
-      if( rec ){
-        checkRegion( ri, rec );
-      }
-      //std::vector< Node > clique;
-      //if( d_regions[ri]->check( Theory::EFFORT_STANDARD, cardinality, clique ) ){
-      //  //explain clique
-      //  Notice() << "found clique " << std::endl;
-      //}
-      return true;
+      return combineRegions( ri, maxRegion );
     }
+    return -1;
   }
-  return false;
+}
+
+
+int StrongSolverTheoryUf::ConflictFind::combineRegions( int ai, int bi ){
+#ifdef COMBINE_REGIONS_SMALL_INTO_LARGE
+  if( d_regions[ai]->getNumReps()<d_regions[bi]->getNumReps() ){
+    return combineRegions( bi, ai );
+  }
+#endif
+  Debug("uf-ss-region") << "uf-ss: Combine Region #" << bi << " with Region #" << ai << std::endl;
+  Assert( isValid( ai ) && isValid( bi ) );
+  for( std::map< Node, Region::RegionNodeInfo* >::iterator it = d_regions[bi]->d_nodes.begin(); it != d_regions[bi]->d_nodes.end(); ++it ){
+    Region::RegionNodeInfo* rni = it->second;
+    if( rni->d_valid ){
+      d_regions_map[ it->first ] = ai;
+    }
+  }
+  //update regions disequal DO_THIS?
+  d_regions[ai]->combine( d_regions[bi] );
+  d_regions[bi]->d_valid = false;
+  return ai;
+}
+
+void StrongSolverTheoryUf::ConflictFind::moveNode( Node n, int ri ){
+  Debug("uf-ss-region") << "uf-ss: Move node " << n << " to Region #" << ri << std::endl;
+  Assert( isValid( d_regions_map[ n ] ) );
+  Assert( isValid( ri ) );
+  //move node to region ri
+  d_regions[ri]->takeNode( d_regions[ d_regions_map[n] ], n );
+  d_regions_map[n] = ri;
 }
 
 bool StrongSolverTheoryUf::ConflictFind::disambiguateTerms( OutputChannel* out ){
   Debug("uf-ss-disamb") << "Disambiguate terms." << std::endl;
   bool lemmaAdded = false;
   //otherwise, determine ambiguous pairs of ground terms for relevant sorts
-  TermDb* db = d_th->getQuantifiersEngine()->getTermDatabase();
+  quantifiers::TermDb* db = d_th->getQuantifiersEngine()->getTermDatabase();
   for( std::map< Node, std::vector< Node > >::iterator it = db->d_op_map.begin(); it != db->d_op_map.end(); ++it ){
     Debug("uf-ss-disamb") << "Check " << it->first << std::endl;
     if( it->second.size()>1 ){
@@ -798,22 +880,29 @@ void StrongSolverTheoryUf::ConflictFind::check( Theory::Effort level, OutputChan
           }
         }
       }
-      if( level==Theory::EFFORT_FULL ){
+      bool addedLemma = false;
+      //do splitting on demand
+      if( level==Theory::EFFORT_FULL || Options::current()->ufssEagerSplits ){
         Debug("uf-ss-debug") << "Add splits?" << std::endl;
-        //see if we have any recommended splits
-        bool addedLemma = false;
+        //see if we have any recommended splits from large regions
         for( int i=0; i<(int)d_regions_index; i++ ){
-          if( d_regions[i]->d_valid ){
+          if( d_regions[i]->d_valid && d_regions[i]->getNumReps()>d_cardinality ){
             if( d_regions[i]->hasSplits() ){
               d_regions[i]->addSplit( out );
               addedLemma = true;
               ++( d_th->getStrongSolver()->d_statistics.d_split_lemmas );
+#ifdef ONE_SPLIT_REGION
+              break;
+#endif
             }
           }
         }
+      }
+      //force continuation via term disambiguation or combination of regions
+      if( level==Theory::EFFORT_FULL ){
         if( !addedLemma ){
           Debug("uf-ss") << "No splits added." << std::endl;
-          if( Options::current()->fmfRegionSat ){
+          if( Options::current()->ufssColoringSat ){
             //otherwise, try to disambiguate individual terms
             if( !disambiguateTerms( out ) ){
               //no disequalities can be propagated
@@ -825,18 +914,18 @@ void StrongSolverTheoryUf::ConflictFind::check( Theory::Effort level, OutputChan
               debugPrint("uf-ss-sat");
             }
           }else{
-            //naive strategy. combine the first two valid regions
-            int regIndex = -1;
+            bool recheck = false;
+            //naive strategy, force region combination involving the first valid region
             for( int i=0; i<(int)d_regions_index; i++ ){
               if( d_regions[i]->d_valid ){
-                if( regIndex==-1 ){
-                  regIndex = i;
-                }else{
-                  combineRegions( regIndex, i );
-                  check( level, out );
-                }
+                forceCombineRegion( i, false );
+                recheck = true;
+                break;
               }
             }
+            if( recheck ){
+              check( level, out );
+            }
           }
         }
       }
@@ -846,8 +935,7 @@ void StrongSolverTheoryUf::ConflictFind::check( Theory::Effort level, OutputChan
 
 void StrongSolverTheoryUf::ConflictFind::propagate( Theory::Effort level, OutputChannel* out ){
   Assert( d_cardinality>0 );
-
-  //propagate the current cardinality as a decision literal
+  //propagate the current cardinality as a decision literal, if not already asserted
   Node cn = d_cardinality_literal[ d_cardinality ];
   Debug("uf-ss-prop-as-dec") << "Propagate as decision " << d_type << ", cardinality = " << d_cardinality << std::endl;
   Assert( !cn.isNull() );
@@ -856,7 +944,6 @@ void StrongSolverTheoryUf::ConflictFind::propagate( Theory::Effort level, Output
     Debug("uf-ss-prop-as-dec") << "Propagate as decision " << d_cardinality_literal[ d_cardinality ];
     Debug("uf-ss-prop-as-dec") << " " << d_cardinality_literal[ d_cardinality ][0].getType() << std::endl;
   }
-
 }
 
 void StrongSolverTheoryUf::ConflictFind::debugPrint( const char* c ){
@@ -913,7 +1000,7 @@ void StrongSolverTheoryUf::ConflictFind::setCardinality( int c, OutputChannel* o
 }
 
 void StrongSolverTheoryUf::ConflictFind::getRepresentatives( std::vector< Node >& reps ){
-  if( !Options::current()->fmfRegionSat ){
+  if( !Options::current()->ufssColoringSat ){
     bool foundRegion = false;
     for( int i=0; i<(int)d_regions_index; i++ ){
       //should not have multiple regions at this point
@@ -932,6 +1019,8 @@ void StrongSolverTheoryUf::ConflictFind::getRepresentatives( std::vector< Node >
 }
 
 bool StrongSolverTheoryUf::ConflictFind::minimize( OutputChannel* out ){
+  //ensure that model forms a clique:
+  // if two equivalence classes are neither equal nor disequal, add a split
   int validRegionIndex = -1;
   for( int i=0; i<(int)d_regions_index; i++ ){
     if( d_regions[i]->d_valid ){
@@ -956,10 +1045,9 @@ Node StrongSolverTheoryUf::ConflictFind::getCardinalityLemma(){
   if( d_cardinality_lemma.find( d_cardinality )==d_cardinality_lemma.end() ){
     if( d_cardinality_lemma_term.isNull() ){
       std::stringstream ss;
-      ss << "fmf_term_" << d_type;
+      ss << Expr::setlanguage(Options::current()->outputLanguage);
+      ss << "t_" << d_type;
       d_cardinality_lemma_term = NodeManager::currentNM()->mkVar( ss.str(), d_type );
-      ModelBasisAttribute mba;
-      d_cardinality_lemma_term.setAttribute(mba,true);
     }
     Node lem = NodeManager::currentNM()->mkNode( CARDINALITY_CONSTRAINT, d_cardinality_lemma_term,
                                   NodeManager::currentNM()->mkConst( Rational( d_cardinality ) ) );
@@ -1001,8 +1089,6 @@ void StrongSolverTheoryUf::merge( Node a, Node b ){
     Debug("uf-ss-solver") << "StrongSolverTheoryUf: Merge " << a << " " << b << " " << tn << std::endl;
     c->merge( a, b );
   }
-  //else if( isRelevantType( tn ) ){
-  //}
 }
 
 /** assert terms are disequal */
@@ -1015,8 +1101,6 @@ void StrongSolverTheoryUf::assertDisequal( Node a, Node b, Node reason ){
     //Assert( d_th->d_equalityEngine.getRepresentative( b )==b );
     c->assertDisequal( a, b, reason );
   }
-  //else if( isRelevantType( tn ) ){
-  //}
 }
 
 /** assert a node */
@@ -1187,14 +1271,14 @@ void StrongSolverTheoryUf::getRepresentatives( TypeNode t, std::vector< Node >&
   }
 }
 
-Node StrongSolverTheoryUf::getCardinalityTerm( TypeNode t ){
-  ConflictFind* c = getConflictFind( t );
-  if( c ){
-    return c->getCardinalityTerm();
-  }else{
-    return Node::null();
-  }
-}
+//Node StrongSolverTheoryUf::getCardinalityTerm( TypeNode t ){
+//  ConflictFind* c = getConflictFind( t );
+//  if( c ){
+//    return c->getCardinalityTerm();
+//  }else{
+//    return Node::null();
+//  }
+//}
 
 bool StrongSolverTheoryUf::minimize(){
   for( std::map< TypeNode, ConflictFind* >::iterator it = d_conf_find.begin(); it != d_conf_find.end(); ++it ){
@@ -1252,7 +1336,8 @@ bool StrongSolverTheoryUf::isRelevantType( TypeNode t ){
          t!=NodeManager::currentNM()->realType() &&
          t!=NodeManager::currentNM()->builtinOperatorType() &&
          !t.isFunction() &&
-         !t.isDatatype();
+         !t.isDatatype() &&
+         !t.isArray();
 }
 
 bool StrongSolverTheoryUf::involvesRelevantType( Node n ){
index dde24394a8b4cbb5f49a2038b3495819f9293fc9..bd4c4cb22ce7de1974fa0447f0e8949d8bc1df28 100644 (file)
 
 namespace CVC4 {
 namespace theory {
-
-struct ModelBasisAttributeId {};
-typedef expr::Attribute<ModelBasisAttributeId, bool> ModelBasisAttribute;
-
 namespace uf {
 
 class TheoryUF;
@@ -43,6 +39,7 @@ protected:
   typedef context::CDHashMap<Node, int, NodeHashFunction> NodeIntMap;
   typedef context::CDChunkList<Node> NodeList;
   typedef context::CDList<bool> BoolList;
+  typedef context::CDList<bool> IntList;
   typedef context::CDHashMap<TypeNode, bool, TypeNodeHashFunction> TypeNodeBoolMap;
 public:
   /** information for incremental conflict/clique finding for a particular sort */
@@ -74,7 +71,8 @@ public:
         DiseqList d_external;
       public:
         /** constructor */
-        RegionNodeInfo( context::Context* c ) : d_internal( c ), d_external( c ), d_valid( c, true ){
+        RegionNodeInfo( context::Context* c ) :
+          d_internal( c ), d_external( c ), d_valid( c, true ){
           d_disequalities[0] = &d_internal;
           d_disequalities[1] = &d_external;
         }
@@ -103,6 +101,9 @@ public:
       context::CDO< unsigned > d_total_diseq_external;
       //total disequality size (internal)
       context::CDO< unsigned > d_total_diseq_internal;
+    private:
+      /** set rep */
+      void setRep( Node n, bool valid );
     public:
       //constructor
       Region( ConflictFind* cf, context::Context* c ) : d_cf( cf ), d_testClique( c ), d_testCliqueSize( c, 0 ),
@@ -115,37 +116,40 @@ public:
       //whether region is valid
       context::CDO< bool > d_valid;
     public:
-      //get num reps
-      int getNumReps() { return d_reps_size; }
-      // has representative
-      bool hasRep( Node n ) { return d_nodes.find( n )!=d_nodes.end() && d_nodes[n]->d_valid; }
+      /** add rep */
+      void addRep( Node n );
       //take node from region
       void takeNode( Region* r, Node n );
       //merge with other region
       void combine( Region* r );
-      /** set rep */
-      void setRep( Node n, bool valid );
       /** merge */
       void setEqual( Node a, Node b );
       //set n1 != n2 to value 'valid', type is whether it is internal/external
       void setDisequal( Node n1, Node n2, int type, bool valid );
+    public:
+      //get num reps
+      int getNumReps() { return d_reps_size; }
+      //get test clique size
+      int getTestCliqueSize() { return d_testCliqueSize; }
+      // has representative
+      bool hasRep( Node n ) { return d_nodes.find( n )!=d_nodes.end() && d_nodes[n]->d_valid; }
       // is disequal
       bool isDisequal( Node n1, Node n2, int type );
-    public:
       /** get must merge */
       bool getMustCombine( int cardinality );
-      /** check for cliques */
-      bool check( Theory::Effort level, int cardinality, std::vector< Node >& clique );
       /** has splits */
       bool hasSplits() { return d_splitsSize>0; }
-      /** add split */
-      void addSplit( OutputChannel* out );
       /** get representatives */
       void getRepresentatives( std::vector< Node >& reps );
-      /** minimize */
-      bool minimize( OutputChannel* out );
       /** get external disequalities */
       void getNumExternalDisequalities( std::map< Node, int >& num_ext_disequalities );
+    public:
+      /** check for cliques */
+      bool check( Theory::Effort level, int cardinality, std::vector< Node >& clique );
+      /** add split */
+      void addSplit( OutputChannel* out );
+      /** minimize */
+      bool minimize( OutputChannel* out );
       //print debug
       void debugPrint( const char* c, bool incClique = false );
     };
@@ -167,22 +171,25 @@ public:
     /** whether two terms are ambiguous (indexed by equalities) */
     NodeBoolMap d_term_amb;
   private:
-    /** merge regions */
-    void combineRegions( int ai, int bi );
-    /** move node n to region ri */
-    void moveNode( Node n, int ri );
     /** get number of disequalities from node n to region ri */
     int getNumDisequalitiesToRegion( Node n, int ri );
     /** get number of disequalities from Region r to other regions */
     void getDisequalitiesToRegions( int ri, std::map< int, int >& regions_diseq );
-    /** check if we need to combine region ri */
-    bool checkRegion( int ri, bool rec = true );
     /** explain clique */
     void explainClique( std::vector< Node >& clique, OutputChannel* out );
     /** is valid */
     bool isValid( int ri ) { return ri>=0 && ri<(int)d_regions_index && d_regions[ ri ]->d_valid; }
     /** check ambiguous terms */
     bool disambiguateTerms( OutputChannel* out );
+  private:
+    /** check if we need to combine region ri */
+    void checkRegion( int ri, bool rec = true );
+    /** force combine region */
+    int forceCombineRegion( int ri, bool useDensity = true );
+    /** merge regions */
+    int combineRegions( int ai, int bi );
+    /** move node n to region ri */
+    void moveNode( Node n, int ri );
   private:
     /** cardinality operating with */
     context::CDO< int > d_cardinality;
@@ -226,7 +233,7 @@ public:
     /** get representatives */
     void getRepresentatives( std::vector< Node >& reps );
     /** get model basis term */
-    Node getCardinalityTerm() { return d_cardinality_lemma_term; }
+    //Node getCardinalityTerm() { return d_cardinality_lemma_term; }
     /** minimize */
     bool minimize( OutputChannel* out );
     /** get cardinality lemma */
@@ -293,7 +300,7 @@ public:
   /** get representatives */
   void getRepresentatives( TypeNode t, std::vector< Node >& reps );
   /** get cardinality term */
-  Node getCardinalityTerm( TypeNode t );
+  //Node getCardinalityTerm( TypeNode t );
   /** minimize */
   bool minimize();
 
index 34a8a805b500695af15061b3280dceca591e2b56..d00b69398271ed032684f1842c60e6b33d707c39 100644 (file)
@@ -70,7 +70,69 @@ public:
     }
     return nodeManager->booleanType();
   }
-};/* class UfTypeRule */
+};/* class CardinalityConstraintTypeRule */
+
+class FunctionModelTypeRule {
+public:
+  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+      throw(TypeCheckingExceptionPrivate) {
+    TypeNode tn = n[0].getType(check);
+    if( check ){
+      if( n.getNumChildren()==2 ){
+        if( n[0].getKind()!=kind::FUNCTION_CASE_SPLIT ){
+          throw TypeCheckingExceptionPrivate(n, "improper function model representation : first child must be case split");
+        }
+        TypeNode tn2 = n[1].getType(check);
+        if( tn!=tn2 ){
+          std::stringstream ss;
+          ss << "function model has inconsistent return types : " << tn << " " << tn2;
+          throw TypeCheckingExceptionPrivate(n, ss.str());
+        }
+      }
+    }
+    return tn;
+  }
+};/* class FunctionModelTypeRule */
+
+class FunctionCaseSplitTypeRule {
+public:
+  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+      throw(TypeCheckingExceptionPrivate) {
+    TypeNode retType = n[0][1].getType(check);
+    if( check ){
+      TypeNode argType = n[0][0].getType(check);
+      for( size_t i=0; i<n.getNumChildren(); i++ ){
+        TypeNode argType2 = n[i][0].getType(check);
+        if( argType!=argType2 ){
+          std::stringstream ss;
+          ss << "function case split has inconsistent argument types : " << argType << " " << argType2;
+          throw TypeCheckingExceptionPrivate(n, ss.str());
+        }
+        TypeNode retType2 = n[i][1].getType(check);
+        if( retType!=retType2 ){
+          std::stringstream ss;
+          ss << "function case split has inconsistent return types : " << retType << " " << retType2;
+          throw TypeCheckingExceptionPrivate(n, ss.str());
+        }
+      }
+    }
+    return retType;
+  }
+};/* class FunctionCaseSplitTypeRule */
+
+
+class FunctionCaseTypeRule {
+public:
+  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+      throw(TypeCheckingExceptionPrivate) {
+    TypeNode retType = n[1].getType(check);
+    if( check ){
+      TypeNode argType = n[0].getType(check);
+    }
+    return retType;
+  }
+};/* class FunctionCaseTypeRule */
+
 
 }/* CVC4::theory::uf namespace */
 }/* CVC4::theory namespace */
index ef02f62789af617a3b680bdc9d7df6c420d7b9aa..948a7a1304537f2d905be421819d33e49414811f 100644 (file)
@@ -55,11 +55,6 @@ bool equalityStatusCompatible(EqualityStatus s1, EqualityStatus s2) {
  }
 }
 
-
-Node Valuation::getValue(TNode n) const {
-  return d_engine->getValue(n);
-}
-
 bool Valuation::isSatLiteral(TNode n) const {
   return d_engine->getPropEngine()->isSatLiteral(n);
 }
index 11467c8db8d1714c787f901f96d0359704f4309e..7f3a00ec1181fc406313fa324557da6517704a7b 100644 (file)
@@ -64,8 +64,6 @@ public:
     d_engine(engine) {
   }
 
-  Node getValue(TNode n) const;
-
   /*
    * Return true if n has an associated SAT literal
    */
index cded1e5a34b0b34f4d59587ac99e864a192df745..43cc15ec9203e8630df3b04fd4c538ddf068410b 100644 (file)
@@ -73,7 +73,9 @@ libutil_la_SOURCES = \
        ite_removal.h \
        ite_removal.cpp \
        node_visitor.h \
-       index.h
+       index.h \
+       model.h \
+       model.cpp
 
 libutil_la_LIBADD = \
        @builddir@/libutilcudd.la
index 7318af1a55a84cbde4d3fbb7b28a0088c4ea8fb0..3820924743fd8f565adace6461c93c537af475e6 100644 (file)
@@ -103,7 +103,7 @@ public:
       std::string s = ss.str();
       CVC4dumpstream(getStream(), d_commands)
         << CommentCommand(s + " is " + comment)
-        << DeclareFunctionCommand(s, e.getType());
+        << DeclareFunctionCommand(s, e, e.getType());
     }
   }
 
diff --git a/src/util/model.cpp b/src/util/model.cpp
new file mode 100644 (file)
index 0000000..081624c
--- /dev/null
@@ -0,0 +1,15 @@
+/*********************                                                        */\r
+/*! \file model.cpp\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief implementation of Model class\r
+ **/
\ No newline at end of file
diff --git a/src/util/model.h b/src/util/model.h
new file mode 100644 (file)
index 0000000..7e0f5a7
--- /dev/null
@@ -0,0 +1,42 @@
+/*********************                                                        */\r
+/*! \file model.h\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Model class\r
+ **/\r
+\r
+#include "cvc4_public.h"\r
+\r
+#ifndef __CVC4__MODEL_H\r
+#define __CVC4__MODEL_H\r
+\r
+#include <iostream>\r
+\r
+namespace CVC4 {\r
+\r
+class Model\r
+{\r
+public:\r
+  virtual void toStream(std::ostream& out) = 0;\r
+};/* class Model */\r
+\r
+class ModelBuilder\r
+{\r
+public:\r
+  ModelBuilder(){}\r
+  virtual ~ModelBuilder(){}\r
+  virtual void buildModel( Model* m ) = 0;\r
+};/* class ModelBuilder */\r
+\r
+}/* CVC4 namespace */\r
+\r
+#endif  /* __CVC4__MODEL_H */\r
index 2352ae503c5e5500106b43f798069aae4c363efe..e9efab5dd88cb03b8d3793bc10745fc9d2279648 100644 (file)
@@ -149,14 +149,22 @@ Options::Options() :
   instWhenMode(INST_WHEN_FULL_LAST_CALL),
   eagerInstQuant(false),
   finiteModelFind(false),
-  fmfRegionSat(false),
+  ufssEagerSplits(false),
+  ufssRegions(true),
+  ufssColoringSat(false),
   fmfModelBasedInst(true),
+  fmfInstGen(true),
+  fmfOneInstPerRound(false),
+  fmfInstEngine(false),
+  fmfRelevantDomain(false),
   efficientEMatching(false),
   literalMatchMode(LITERAL_MATCH_NONE),
   cbqi(false),
   cbqiSetByUser(false),
   userPatternsQuant(true),
   flipDecision(false),
+  printInstEngine(false),
+  printModelEngine(false),
   lemmaOutputChannel(NULL),
   lemmaInputChannel(NULL),
   threads(2),// default should be 1 probably, but say 2 for now
@@ -275,6 +283,7 @@ Additional CVC4 options:\n\
    --enable-symmetry-breaker turns on UF symmetry breaker (Deharbe et al.,\n\
                           CADE 2011) [on by default only for QF_UF]\n\
    --disable-symmetry-breaker turns off UF symmetry breaker\n\
+ QUANTIFIERS:\n\
    --disable-miniscope-quant     disable miniscope quantifiers\n\
    --disable-miniscope-quant-fv  disable miniscope quantifiers for ground subformulas\n\
    --disable-prenex-quant disable prenexing of quantified formulas\n\
@@ -282,18 +291,26 @@ Additional CVC4 options:\n\
    --cnf-quant            apply CNF conversion to quantified formulas\n\
    --pre-skolem-quant     apply skolemization eagerly to bodies of quantified formulas\n\
    --disable-smart-triggers   disable smart triggers\n\
-   --register-quant-body-terms  consider terms within bodies of quantified formulas for matching\n\
+   --register-quant-body-terms  consider ground terms within bodies of quantified formulas for matching\n\
    --inst-when=MODE       when to apply instantiation\n\
    --eager-inst-quant     apply quantifier instantiation eagerly\n\
-   --finite-model-find    use finite model finding heuristic for quantifier instantiation\n\
-   --use-fmf-region-sat   use region-based SAT heuristic for finite model finding\n\
-   --disable-fmf-model-inst  disable model-based instantiation for finite model finding\n\
    --efficient-e-matching use efficient E-matching\n\
    --literal-matching=MODE  choose literal matching mode\n\
    --enable-cbqi          turns on counterexample-based quantifier instantiation [off by default]\n\
    --disable-cbqi         turns off counterexample-based quantifier instantiation\n\
    --ignore-user-patterns ignore user-provided patterns for quantifier instantiation\n\
    --enable-flip-decision turns on flip decision heuristic\n\
+ FINITE_MODEL_FINDING:\n\
+   --finite-model-find      use finite model finding heuristic for quantifier instantiation\n\
+   --disable-uf-ss-regions  disable region-based method for discovering cliques and splits in uf strong solver\n\
+   --uf-ss-eager-split      add splits eagerly for uf strong solver\n\
+   --uf-ss-coloring-sat     use coloring-based SAT heuristic for uf strong solver\n\
+   --disable-fmf-mbqi       disable model-based quantifier instantiation for finite model finding\n\
+   --disable-fmf-inst-gen   disable Inst-Gen instantiation techniques for finite model finding\n\
+   --fmf-one-inst-per-round  only add one instantiation per quantifier per round for fmf\n\
+   --fmf-inst-engine        use instantiation engine in conjunction with finite model finding\n\
+   --fmf-relevant-domain    use relevant domain computation, similar to complete instantiation (Ge, deMoura 09)\n\
+ OTHER:\n\
    --disable-dio-solver   turns off Linear Diophantine Equation solver (Griggio, JSAT 2012)\n\
    --disable-arith-rewrite-equalities   turns off the preprocessing rewrite turning equalities into a conjunction of inequalities.\n\
    --threads=N            sets the number of solver threads\n\
@@ -379,6 +396,36 @@ justification-must\n\
 + near leaves (don't expect it to work well) [Unimplemented]\n\
 ";
 
+static const string instWhenHelp = "\
+Modes currently supported by the --inst-when option:\n\
+\n\
+full\n\
++ Run instantiation round at full effort, before theory combination.\n\
+\n\
+full-last-call (default)\n\
++ Alternate running instantiation rounds at full effort and last\n\
+  call.  In other words, interleave instantiation and theory combination.\n\
+\n\
+last-call\n\
++ Run instantiation at last call effort, after theory combination.\n\
+\n\
+";
+
+static const string literalMatchHelp = "\
+Literal match modes currently supported by the --literal-match option:\n\
+\n\
+none (default)\n\
++ Do not use literal matching.\n\
+\n\
+predicate\n\
++ Consider the phase requirements of predicate literals when applying heuristic\n\
+  quantifier instantiation.  For example, the trigger P( x ) in the quantified \n\
+  formula forall( x ). ( P( x ) V ~Q( x ) ) will only be matched with ground\n\
+  terms P( t ) where P( t ) is in the equivalence class of false, and likewise\n\
+  Q( x ) with Q( s ) where Q( s ) is in the equivalence class of true.\n\
+\n\
+";
+
 static const string dumpHelp = "\
 Dump modes currently supported by the --dump option:\n\
 \n\
@@ -581,14 +628,22 @@ enum OptionValue {
   INST_WHEN,
   EAGER_INST_QUANT,
   FINITE_MODEL_FIND,
-  FMF_REGION_SAT,
+  DISABLE_UF_SS_REGIONS,
+  UF_SS_EAGER_SPLIT,
+  UF_SS_COLORING_SAT,
   DISABLE_FMF_MODEL_BASED_INST,
+  DISABLE_FMF_INST_GEN,
+  FMF_ONE_INST_PER_ROUND,
+  FMF_INST_ENGINE,
+  FMF_RELEVANT_DOMAIN,
   EFFICIENT_E_MATCHING,
   LITERAL_MATCHING,
   ENABLE_CBQI,
   DISABLE_CBQI,
   IGNORE_USER_PATTERNS,
   ENABLE_FLIP_DECISION,
+  PRINT_MODEL_ENGINE,
+  PRINT_INST_ENGINE,
   PARALLEL_THREADS,
   PARALLEL_SEPARATE_OUTPUT,
   PORTFOLIO_FILTER_LENGTH,
@@ -710,14 +765,22 @@ static struct option cmdlineOptions[] = {
   { "inst-when", required_argument, NULL, INST_WHEN },
   { "eager-inst-quant", no_argument, NULL, EAGER_INST_QUANT },
   { "finite-model-find", no_argument, NULL, FINITE_MODEL_FIND },
-  { "use-fmf-region-sat", no_argument, NULL, FMF_REGION_SAT },
-  { "disable-fmf-model-inst", no_argument, NULL, DISABLE_FMF_MODEL_BASED_INST },
+  { "disable-uf-ss-regions", no_argument, NULL, DISABLE_UF_SS_REGIONS },
+  { "uf-ss-eager-split", no_argument, NULL, UF_SS_EAGER_SPLIT },
+  { "uf-ss-coloring-sat", no_argument, NULL, UF_SS_COLORING_SAT },
+  { "disable-fmf-mbqi", no_argument, NULL, DISABLE_FMF_MODEL_BASED_INST },
+  { "disable-fmf-inst-gen", no_argument, NULL, DISABLE_FMF_INST_GEN },
+  { "fmf-one-inst-per-round", no_argument, NULL, FMF_ONE_INST_PER_ROUND },
+  { "fmf-inst-engine", no_argument, NULL, FMF_INST_ENGINE },
+  { "fmf-relevant-domain", no_argument, NULL, FMF_RELEVANT_DOMAIN },
   { "efficient-e-matching", no_argument, NULL, EFFICIENT_E_MATCHING },
   { "literal-matching", required_argument, NULL, LITERAL_MATCHING },
   { "enable-cbqi", no_argument, NULL, ENABLE_CBQI },
   { "disable-cbqi", no_argument, NULL, DISABLE_CBQI },
   { "ignore-user-patterns", no_argument, NULL, IGNORE_USER_PATTERNS },
   { "enable-flip-decision", no_argument, NULL, ENABLE_FLIP_DECISION },
+  { "print-m-e", no_argument, NULL, PRINT_MODEL_ENGINE },
+  { "print-i-e", no_argument, NULL, PRINT_INST_ENGINE },
   { "threads", required_argument, NULL, PARALLEL_THREADS },
   { "separate-output", no_argument, NULL, PARALLEL_SEPARATE_OUTPUT },
   { "filter-lemma-length", required_argument, NULL, PORTFOLIO_FILTER_LENGTH },
@@ -1071,7 +1134,7 @@ throw(OptionException) {
       if(i == 0) {
         Warning() << "Decision budget is 0. Consider using internal decision heuristic and "
                   << std::endl << " removing this option." << std::endl;
-                  
+
       }
       decisionOptions.maxRelTimeAsPermille = (unsigned short)i;
     }
@@ -1247,7 +1310,7 @@ throw(OptionException) {
       } else if(!strcmp(optarg, "last-call")) {
         instWhenMode = INST_WHEN_LAST_CALL;
       } else if(!strcmp(optarg, "help")) {
-        //puts(instWhenHelp.c_str());
+        puts(instWhenHelp.c_str());
         exit(1);
       } else {
         throw OptionException(string("unknown option for --inst-when: `") +
@@ -1260,12 +1323,30 @@ throw(OptionException) {
     case FINITE_MODEL_FIND:
       finiteModelFind = true;
       break;
-    case FMF_REGION_SAT:
-      fmfRegionSat = true;
+    case DISABLE_UF_SS_REGIONS:
+      ufssRegions = false;
+      break;
+    case UF_SS_EAGER_SPLIT:
+      ufssEagerSplits = true;
+      break;
+    case UF_SS_COLORING_SAT:
+      ufssColoringSat = true;
       break;
     case DISABLE_FMF_MODEL_BASED_INST:
       fmfModelBasedInst = false;
       break;
+    case DISABLE_FMF_INST_GEN:
+      fmfInstGen = false;
+      break;
+    case FMF_ONE_INST_PER_ROUND:
+      fmfOneInstPerRound = true;
+      break;
+    case FMF_INST_ENGINE:
+      fmfInstEngine = true;
+      break;
+    case FMF_RELEVANT_DOMAIN:
+      fmfRelevantDomain = true;
+      break;
     case EFFICIENT_E_MATCHING:
       efficientEMatching = true;
       break;
@@ -1277,7 +1358,7 @@ throw(OptionException) {
       } else if(!strcmp(optarg, "equality")) {
         literalMatchMode = LITERAL_MATCH_EQUALITY;
       } else if(!strcmp(optarg, "help")) {
-        //puts(literalMatchHelp.c_str());
+        puts(literalMatchHelp.c_str());
         exit(1);
       } else {
         throw OptionException(string("unknown option for --literal-matching: `") +
@@ -1298,6 +1379,12 @@ throw(OptionException) {
     case ENABLE_FLIP_DECISION:
       flipDecision = true;
       break;
+    case PRINT_MODEL_ENGINE:
+      printModelEngine = true;
+      break;
+    case PRINT_INST_ENGINE:
+      printInstEngine = true;
+      break;
     case TIME_LIMIT:
       {
         int i = atoi(optarg);
index f423260b0763ceed41f80f93ada9fe6892963ef8..d89265b55d405ce234977e94b00b166aab6c6417 100644 (file)
@@ -147,7 +147,7 @@ struct CVC4_PUBLIC Options {
   DecisionMode decisionMode;
   /** Whether the user set the decision strategy */
   bool decisionModeSetByUser;
-  /** 
+  /**
    * Extra settings for decision stuff, varies by strategy enabled
    * - With DECISION_STRATEGY_RELEVANCY
    *   > Least significant bit: true if one should only decide on leaves
@@ -414,15 +414,46 @@ struct CVC4_PUBLIC Options {
   bool finiteModelFind;
 
   /**
-   * Whether to use region-based SAT for finite model finding
+   * Whether to use eager splitting on demand for finite model finding
+   */
+  bool ufssEagerSplits;
+
+  /**
+   * Whether to use region-based approach for finite model finding
+   */
+  bool ufssRegions;
+
+  /**
+   * Whether to use coloring-based methods for determining whether a model of
+   * currently cardinality exists.
    */
-  bool fmfRegionSat;
+  bool ufssColoringSat;
 
   /**
    * Whether to use model-based exhaustive instantiation for finite model finding
    */
   bool fmfModelBasedInst;
 
+  /**
+   * Whether to use Inst-Gen techniques for finite model finding
+   */
+  bool fmfInstGen;
+
+  /*
+   * Whether to only add only instantiation per quantifier per round for finite model finding
+   */
+  bool fmfOneInstPerRound;
+
+  /*
+   * Whether to use instantiation engine in conjunction with finite model finding
+   */
+  bool fmfInstEngine;
+
+  /*
+   * Whether to compute relevant domains, in the manner of Complete Instantiation for Quantified Formulas [Ge, deMoura 09]
+   */
+  bool fmfRelevantDomain;
+
   /**
    * Whether to use efficient E-matching
    */
@@ -462,6 +493,12 @@ struct CVC4_PUBLIC Options {
    */
   bool flipDecision;
 
+  /**
+   * print details for instantiation/model engine
+   */
+  bool printInstEngine;
+  bool printModelEngine;
+
   /** The output channel to receive notfication events for new lemmas */
   LemmaOutputChannel* lemmaOutputChannel;
   LemmaInputChannel* lemmaInputChannel;