merging fmf-devel branch, includes refactored datatype theory, updates to model.h...
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Fri, 27 Jul 2012 19:27:45 +0000 (19:27 +0000)
committerAndrew Reynolds <andrew.j.reynolds@gmail.com>
Fri, 27 Jul 2012 19:27:45 +0000 (19:27 +0000)
54 files changed:
src/parser/smt2/Smt2.g
src/theory/Makefile.am
src/theory/arrays/Makefile.am
src/theory/arrays/theory_arrays_instantiator.cpp
src/theory/arrays/theory_arrays_instantiator.h
src/theory/arrays/theory_arrays_model.cpp [new file with mode: 0644]
src/theory/arrays/theory_arrays_model.h [new file with mode: 0644]
src/theory/candidate_generator.cpp [new file with mode: 0644]
src/theory/candidate_generator.h [new file with mode: 0644]
src/theory/datatypes/Makefile.am
src/theory/datatypes/datatypes_rewriter.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/inst_match.cpp
src/theory/inst_match.h
src/theory/inst_match_impl.h [deleted file]
src/theory/model.cpp
src/theory/model.h
src/theory/quantifiers/Makefile.am
src/theory/quantifiers/first_order_model.cpp
src/theory/quantifiers/first_order_model.h
src/theory/quantifiers/model_builder.cpp [new file with mode: 0644]
src/theory/quantifiers/model_builder.h [new file with mode: 0644]
src/theory/quantifiers/model_engine.cpp
src/theory/quantifiers/model_engine.h
src/theory/quantifiers/relevant_domain.cpp
src/theory/quantifiers/rep_set_iterator.cpp
src/theory/quantifiers/rep_set_iterator.h
src/theory/quantifiers/term_database.cpp
src/theory/quantifiers/term_database.h
src/theory/quantifiers_engine.cpp
src/theory/quantifiers_engine.h
src/theory/rr_candidate_generator.cpp [new file with mode: 0644]
src/theory/rr_candidate_generator.h [new file with mode: 0644]
src/theory/rr_inst_match.cpp
src/theory/rr_inst_match_impl.h
src/theory/rr_trigger.cpp
src/theory/theory.h
src/theory/theory_engine.cpp
src/theory/trigger.cpp
src/theory/uf/Makefile.am
src/theory/uf/theory_uf_candidate_generator.cpp [deleted file]
src/theory/uf/theory_uf_candidate_generator.h [deleted file]
src/theory/uf/theory_uf_instantiator.cpp
src/theory/uf/theory_uf_instantiator.h
src/theory/uf/theory_uf_model.cpp
src/theory/uf/theory_uf_model.h
src/theory/uf/theory_uf_strong_solver.cpp
src/theory/uf/theory_uf_strong_solver.h
test/regress/regress0/datatypes/Makefile.am
test/regress/regress0/datatypes/v1l20009.cvc
test/regress/regress0/datatypes/wrong-sel-simp.cvc [new file with mode: 0644]

index 56fa93a94719a4a0bdc4e96f9e86be7ea907e85c..93d596264c523f9a7a07e48e769eb8990842ee3f 100644 (file)
@@ -384,6 +384,7 @@ extendedCommand[CVC4::Command*& cmd]
   : DECLARE_DATATYPES_TOK { PARSER_STATE->checkThatLogicIsSet(); }
     { /* open a scope to keep the UnresolvedTypes contained */
       PARSER_STATE->pushScope(); }
+    LPAREN_TOK RPAREN_TOK  //TODO: parametric datatypes
     LPAREN_TOK ( LPAREN_TOK datatypeDef[dts] RPAREN_TOK )+ RPAREN_TOK
     { PARSER_STATE->popScope();
       cmd = new DatatypeDeclarationCommand(PARSER_STATE->mkMutualDatatypeTypes(dts)); }
@@ -569,7 +570,7 @@ term[CVC4::Expr& expr, CVC4::Expr& expr2]
   Expr f, f2;
   std::string attr;
   Expr attexpr;
-  std::vector<Expr> attexprs;
+  std::vector<Expr> patexprs;
   std::hash_set<std::string, StringHashFunction> names;
   std::vector< std::pair<std::string, Expr> > binders;
 }
@@ -714,8 +715,10 @@ term[CVC4::Expr& expr, CVC4::Expr& expr2]
     /* attributed expressions */
   | LPAREN_TOK ATTRIBUTE_TOK term[expr, f2]
     ( attribute[expr, attexpr,attr]
-      { if(! attexpr.isNull()) {
-          attexprs.push_back(attexpr);
+      { if( attr == ":pattern" && ! attexpr.isNull()) {
+          patexprs.push_back( attexpr );
+        }else if( attr==":axiom" ){
+          //do this?
         }
       }
     )+ RPAREN_TOK
@@ -745,10 +748,15 @@ term[CVC4::Expr& expr, CVC4::Expr& expr2]
         else PARSER_STATE->parseError("Error parsing rewrite rule.");
 
         expr = MK_EXPR( kind, args );
-      } else if(! attexprs.empty()) {
-        if(attexprs[0].getKind() == kind::INST_PATTERN) {
-          expr2 = MK_EXPR(kind::INST_PATTERN_LIST, attexprs);
+      } else if(! patexprs.empty()) {
+        if( !f2.isNull() && f2.getKind()==kind::INST_PATTERN_LIST ){
+          for( size_t i=0; i<f2.getNumChildren(); i++ ){
+            patexprs.push_back( f2[i] );
+          }
         }
+        expr2 = MK_EXPR(kind::INST_PATTERN_LIST, patexprs);
+      }else{
+        expr2 = f2;
       }
     }
     /* constants */
index 2bd85f71201de2b5b51a14f3b3c68e4f842a8a34..9d6939ac9898cac9820473f6755ac9612e4acacf 100644 (file)
@@ -45,12 +45,16 @@ libtheory_la_SOURCES = \
        rr_inst_match.cpp \
        rr_trigger.h \
        rr_trigger.cpp \
+       rr_candidate_generator.h \
+       rr_candidate_generator.cpp \
        inst_match.h \
        inst_match.cpp \
        trigger.h \
        trigger.cpp \
        model.h \
-       model.cpp 
+       model.cpp \
+       candidate_generator.h \
+       candidate_generator.cpp
 
 nodist_libtheory_la_SOURCES = \
        rewriter_tables.h \
index c429fc0c63be71465378e770f055095b45612f33..e4c814660cbe2cc880f5ca0e0eaaa1b0b5131d07 100644 (file)
@@ -18,6 +18,8 @@ libarrays_la_SOURCES = \
        static_fact_manager.h \
        static_fact_manager.cpp \
        theory_arrays_instantiator.h \
-       theory_arrays_instantiator.cpp
+       theory_arrays_instantiator.cpp \
+       theory_arrays_model.h \
+       theory_arrays_model.cpp
 
 EXTRA_DIST = kinds
index ca9001fe5e682a465f0ae693a062ed8c229c995c..67c42d124b513fca568acc6adeea7b151b425d0f 100644 (file)
@@ -17,7 +17,7 @@
 #include "theory/theory_engine.h"
 #include "theory/arrays/theory_arrays_instantiator.h"
 #include "theory/arrays/theory_arrays.h"
-#include "theory/uf/theory_uf_candidate_generator.h"
+#include "theory/rr_candidate_generator.h"
 
 using namespace std;
 using namespace CVC4;
@@ -61,15 +61,19 @@ bool InstantiatorTheoryArrays::hasTerm( Node a ){
 }
 
 bool InstantiatorTheoryArrays::areEqual( Node a, Node b ){
-  if( hasTerm( a ) && hasTerm( b ) ){
+  if( a==b ){
+    return true;
+  }else if( hasTerm( a ) && hasTerm( b ) ){
     return ((TheoryArrays*)d_th)->getEqualityEngine()->areEqual( a, b );
   }else{
-    return a==b;
+    return false;
   }
 }
 
 bool InstantiatorTheoryArrays::areDisequal( Node a, Node b ){
-  if( hasTerm( a ) && hasTerm( b ) ){
+  if( a==b ){
+    return false;
+  }else if( hasTerm( a ) && hasTerm( b ) ){
     return ((TheoryArrays*)d_th)->getEqualityEngine()->areDisequal( a, b, false );
   }else{
     return false;
@@ -84,6 +88,23 @@ Node InstantiatorTheoryArrays::getRepresentative( Node a ){
   }
 }
 
+eq::EqualityEngine* InstantiatorTheoryArrays::getEqualityEngine(){
+  return ((TheoryArrays*)d_th)->getEqualityEngine();
+}
+
+void InstantiatorTheoryArrays::getEquivalenceClass( Node a, std::vector< Node >& eqc ){
+  if( hasTerm( a ) ){
+    a = getEqualityEngine()->getRepresentative( a );
+    eq::EqClassIterator eqc_iter( a, getEqualityEngine() );
+    while( !eqc_iter.isFinished() ){
+      if( std::find( eqc.begin(), eqc.end(), *eqc_iter )==eqc.end() ){
+        eqc.push_back( *eqc_iter );
+      }
+      eqc_iter++;
+    }
+  }
+}
+
 rrinst::CandidateGenerator* InstantiatorTheoryArrays::getRRCanGenClasses(){
   arrays::TheoryArrays* ar = static_cast<arrays::TheoryArrays *>(getTheory());
   eq::EqualityEngine* ee =
index f711229b29810b292a2fef7a164485fd73af51ff..23899afc1d4262844d15b932fec5fbeed6ee05ee 100644 (file)
@@ -49,6 +49,8 @@ public:
   bool areEqual( Node a, Node b );
   bool areDisequal( Node a, Node b );
   Node getRepresentative( Node a );
+  eq::EqualityEngine* getEqualityEngine();
+  void getEquivalenceClass( Node a, std::vector< Node >& eqc );
   /** general creators of candidate generators */
   rrinst::CandidateGenerator* getRRCanGenClasses();
   rrinst::CandidateGenerator* getRRCanGenClass();
diff --git a/src/theory/arrays/theory_arrays_model.cpp b/src/theory/arrays/theory_arrays_model.cpp
new file mode 100644 (file)
index 0000000..49da2f8
--- /dev/null
@@ -0,0 +1,70 @@
+/*********************                                                        */\r
+/*! \file theory_arrays_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_arrays_model class\r
+ **/\r
+\r
+#include "theory/theory_engine.h"\r
+#include "theory/arrays/theory_arrays_model.h"\r
+#include "theory/quantifiers/first_order_model.h"\r
+#include "theory/quantifiers/term_database.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::arrays;\r
+\r
+ArrayModel::ArrayModel( Node arr, quantifiers::FirstOrderModel* m ) : d_model( m ), d_arr( arr ){\r
+  Assert( arr.getKind()!=STORE );\r
+  //look at ground assertions\r
+  Node sel = NodeManager::currentNM()->mkNode( SELECT, arr, NodeManager::currentNM()->mkVar( arr.getType().getArrayIndexType() ) );\r
+  Node sel_op = sel.getOperator();  //FIXME: easier way to do this?\r
+  for( size_t i=0; i<d_model->getTermDatabase()->d_op_map[ sel_op ].size(); i++ ){\r
+    Node n = d_model->getTermDatabase()->d_op_map[ sel_op ][i];\r
+    Assert( n.getKind()==SELECT );\r
+    if( m->areEqual( n[0], arr ) ){\r
+      //d_model->getTermDatabase()->computeModelBasisArgAttribute( n );\r
+      //if( !n.getAttribute(NoMatchAttribute()) || n.getAttribute(ModelBasisArgAttribute())==1 ){\r
+        Node r = d_model->getRepresentative( n );\r
+        Node i = d_model->getRepresentative( n[1] );\r
+        d_values[i] = r;\r
+      //}\r
+    }\r
+  }\r
+}\r
+\r
+Node ArrayModel::getValue( Node n ){\r
+  Assert( n.getKind()==SELECT );\r
+  Assert( n[0]==d_arr );\r
+  std::map< Node, Node >::iterator it = d_values.find( n[0] );\r
+  if( it!=d_values.end() ){\r
+    return it->second;\r
+  }else{\r
+    return n;\r
+    //return d_default_value;   TODO: guarentee I can return this here\r
+  }\r
+}\r
+\r
+void ArrayModel::setDefaultValue( Node v ){\r
+  d_default_value = v;\r
+}\r
+\r
+Node ArrayModel::getArrayValue(){\r
+  Node curr = d_arr;    //TODO: make constant default\r
+  for( std::map< Node, Node >::iterator it = d_values.begin(); it != d_values.end(); ++it ){\r
+    curr = NodeManager::currentNM()->mkNode( STORE, curr, it->first, it->second );\r
+  }\r
+  return curr;\r
+}\r
diff --git a/src/theory/arrays/theory_arrays_model.h b/src/theory/arrays/theory_arrays_model.h
new file mode 100644 (file)
index 0000000..3895388
--- /dev/null
@@ -0,0 +1,62 @@
+/*********************                                                        */\r
+/*! \file theory_arrays_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 of arrays\r
+ **/\r
+\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef __CVC4__THEORY_ARRAYS_MODEL_H\r
+#define __CVC4__THEORY_ARRAYS_MODEL_H\r
+\r
+#include "theory/quantifiers_engine.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+\r
+namespace quantifiers{\r
+  class FirstOrderModel;\r
+}\r
+\r
+namespace arrays {\r
+\r
+class ArrayModel{\r
+protected:\r
+  /** reference to model */\r
+  quantifiers::FirstOrderModel* d_model;\r
+  /** the array this model is for */\r
+  Node d_arr;\r
+public:\r
+  ArrayModel(){}\r
+  ArrayModel( Node arr, quantifiers::FirstOrderModel* m );\r
+  ~ArrayModel() {}\r
+public:\r
+  /** pre-defined values */\r
+  std::map< Node, Node > d_values;\r
+  /** default value */\r
+  Node d_default_value;\r
+  /** get value, return arguments that the value depends on */\r
+  Node getValue( Node n );\r
+  /** set default */\r
+  void setDefaultValue( Node v );\r
+public:\r
+  /** get array value */\r
+  Node getArrayValue();\r
+};/* class ArrayModel */\r
+\r
+}\r
+}\r
+}\r
+\r
+#endif
\ No newline at end of file
diff --git a/src/theory/candidate_generator.cpp b/src/theory/candidate_generator.cpp
new file mode 100644 (file)
index 0000000..ffecaa8
--- /dev/null
@@ -0,0 +1,255 @@
+/*********************                                                        */\r
+/*! \file theory_uf_candidate_generator.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 candidate generator class\r
+ **/\r
+\r
+#include "theory/candidate_generator.h"\r
+#include "theory/theory_engine.h"\r
+#include "theory/uf/theory_uf.h"\r
+#include "theory/quantifiers/term_database.h"\r
+#include "theory/inst_match.h"\r
+#include "theory/quantifiers_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
+using namespace CVC4::theory::inst;\r
+\r
+bool CandidateGenerator::isLegalCandidate( Node n ){\r
+  return ( !n.getAttribute(NoMatchAttribute()) && ( !Options::current()->cbqi || !n.hasAttribute(InstConstantAttribute()) ) );\r
+}\r
+\r
+void CandidateGeneratorQueue::addCandidate( Node n ) {\r
+  if( isLegalCandidate( n ) ){\r
+    d_candidates.push_back( n );\r
+  }\r
+}\r
+\r
+void CandidateGeneratorQueue::reset( Node eqc ){\r
+  if( d_candidate_index>0 ){\r
+    d_candidates.erase( d_candidates.begin(), d_candidates.begin() + d_candidate_index );\r
+    d_candidate_index = 0;\r
+  }\r
+  if( !eqc.isNull() ){\r
+    d_candidates.push_back( eqc );\r
+  }\r
+}\r
+Node CandidateGeneratorQueue::getNextCandidate(){\r
+  if( d_candidate_index<(int)d_candidates.size() ){\r
+    Node n = d_candidates[d_candidate_index];\r
+    d_candidate_index++;\r
+    return n;\r
+  }else{\r
+    d_candidate_index = 0;\r
+    d_candidates.clear();\r
+    return Node::null();\r
+  }\r
+}\r
+\r
+#if 0\r
+\r
+CandidateGeneratorQE::CandidateGeneratorQE( QuantifiersEngine* qe, Node op ) :\r
+  d_op( op ), d_qe( qe ), d_term_iter( -2 ){\r
+  Assert( !d_op.isNull() );\r
+}\r
+void CandidateGeneratorQE::resetInstantiationRound(){\r
+  d_term_iter_limit = d_qe->getTermDatabase()->d_op_map[d_op].size();\r
+}\r
+\r
+void CandidateGeneratorQE::reset( Node eqc ){\r
+  if( eqc.isNull() ){\r
+    d_term_iter = 0;\r
+  }else{\r
+    //create an equivalence class iterator in eq class eqc\r
+    if( d_qe->getEqualityQuery()->getEngine()->hasTerm( eqc ) ){\r
+      eqc = d_qe->getEqualityQuery()->getEngine()->getRepresentative( eqc );\r
+      d_eqc = eq::EqClassIterator( eqc, d_qe->getEqualityQuery()->getEngine() );\r
+      d_retNode = Node::null();\r
+    }else{\r
+      d_retNode = eqc;\r
+    }\r
+    d_term_iter = -1;\r
+  }\r
+}\r
+\r
+Node CandidateGeneratorQE::getNextCandidate(){\r
+  if( d_term_iter>=0 ){\r
+    //get next candidate term in the uf term database\r
+    while( d_term_iter<d_term_iter_limit ){\r
+      Node n = d_qe->getTermDatabase()->d_op_map[d_op][d_term_iter];\r
+      d_term_iter++;\r
+      if( isLegalCandidate( n ) ){\r
+        return n;\r
+      }\r
+    }\r
+  }else if( d_term_iter==-1 ){\r
+    if( d_retNode.isNull() ){\r
+      //get next candidate term in equivalence class\r
+      while( !d_eqc.isFinished() ){\r
+        Node n = (*d_eqc);\r
+        ++d_eqc;\r
+        if( n.hasOperator() && n.getOperator()==d_op ){\r
+          if( isLegalCandidate( n ) ){\r
+            return n;\r
+          }\r
+        }\r
+      }\r
+    }else{\r
+      Node ret;\r
+      if( d_retNode.hasOperator() && d_retNode.getOperator()==d_op ){\r
+        ret = d_retNode;\r
+      }\r
+      d_term_iter = -2; //done returning matches\r
+      return ret;\r
+    }\r
+  }\r
+  return Node::null();\r
+}\r
+\r
+#else\r
+\r
+\r
+CandidateGeneratorQE::CandidateGeneratorQE( QuantifiersEngine* qe, Node op ) :\r
+  d_op( op ), d_qe( qe ), d_term_iter( -1 ){\r
+  Assert( !d_op.isNull() );\r
+}\r
+void CandidateGeneratorQE::resetInstantiationRound(){\r
+  d_term_iter_limit = d_qe->getTermDatabase()->d_op_map[d_op].size();\r
+}\r
+\r
+void CandidateGeneratorQE::reset( Node eqc ){\r
+  d_term_iter = 0;\r
+  if( eqc.isNull() ){\r
+    d_using_term_db = true;\r
+  }else{\r
+    //create an equivalence class iterator in eq class eqc\r
+    d_eqc.clear();\r
+    d_qe->getEqualityQuery()->getEquivalenceClass( eqc, d_eqc );\r
+    d_using_term_db = false;\r
+  }\r
+}\r
+\r
+Node CandidateGeneratorQE::getNextCandidate(){\r
+  if( d_term_iter>=0 ){\r
+    if( d_using_term_db ){\r
+      //get next candidate term in the uf term database\r
+      while( d_term_iter<d_term_iter_limit ){\r
+        Node n = d_qe->getTermDatabase()->d_op_map[d_op][d_term_iter];\r
+        d_term_iter++;\r
+        if( isLegalCandidate( n ) ){\r
+          return n;\r
+        }\r
+      }\r
+    }else{\r
+      while( d_term_iter<(int)d_eqc.size() ){\r
+        Node n = d_eqc[d_term_iter];\r
+        d_term_iter++;\r
+        if( n.hasOperator() && n.getOperator()==d_op ){\r
+          if( isLegalCandidate( n ) ){\r
+            return n;\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+  return Node::null();\r
+}\r
+\r
+#endif\r
+\r
+//CandidateGeneratorQEDisequal::CandidateGeneratorQEDisequal( QuantifiersEngine* qe, Node eqc ) :\r
+//  d_qe( qe ), d_eq_class( eqc ){\r
+//  d_eci = NULL;\r
+//}\r
+//void CandidateGeneratorQEDisequal::resetInstantiationRound(){\r
+//\r
+//}\r
+////we will iterate over all terms that are disequal from eqc\r
+//void CandidateGeneratorQEDisequal::reset( Node eqc ){\r
+//  //Assert( !eqc.isNull() );\r
+//  ////begin iterating over equivalence classes that are disequal from eqc\r
+//  //d_eci = d_ith->getEquivalenceClassInfo( eqc );\r
+//  //if( d_eci ){\r
+//  //  d_eqci_iter = d_eci->d_disequal.begin();\r
+//  //}\r
+//}\r
+//Node CandidateGeneratorQEDisequal::getNextCandidate(){\r
+//  //if( d_eci ){\r
+//  //  while( d_eqci_iter != d_eci->d_disequal.end() ){\r
+//  //    if( (*d_eqci_iter).second ){\r
+//  //      //we have an equivalence class that is disequal from eqc\r
+//  //      d_cg->reset( (*d_eqci_iter).first );\r
+//  //      Node n = d_cg->getNextCandidate();\r
+//  //      //if there is a candidate in this equivalence class, return it\r
+//  //      if( !n.isNull() ){\r
+//  //        return n;\r
+//  //      }\r
+//  //    }\r
+//  //    ++d_eqci_iter;\r
+//  //  }\r
+//  //}\r
+//  return Node::null();\r
+//}\r
+\r
+\r
+CandidateGeneratorQELitEq::CandidateGeneratorQELitEq( QuantifiersEngine* qe, Node mpat ) :\r
+  d_match_pattern( mpat ), d_qe( qe ){\r
+\r
+}\r
+void CandidateGeneratorQELitEq::resetInstantiationRound(){\r
+\r
+}\r
+void CandidateGeneratorQELitEq::reset( Node eqc ){\r
+  d_eq = eq::EqClassesIterator( d_qe->getEqualityQuery()->getEngine() );\r
+}\r
+Node CandidateGeneratorQELitEq::getNextCandidate(){\r
+  while( d_eq.isFinished() ){\r
+    Node n = (*d_eq);\r
+    ++d_eq;\r
+    if( n.getType()==d_match_pattern[0].getType() ){\r
+      //an equivalence class with the same type as the pattern, return reflexive equality\r
+      return NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), n, n );\r
+    }\r
+  }\r
+  return Node::null();\r
+}\r
+\r
+\r
+CandidateGeneratorQELitDeq::CandidateGeneratorQELitDeq( QuantifiersEngine* qe, Node mpat ) :\r
+  d_match_pattern( mpat ), d_qe( qe ){\r
+\r
+}\r
+void CandidateGeneratorQELitDeq::resetInstantiationRound(){\r
+\r
+}\r
+void CandidateGeneratorQELitDeq::reset( Node eqc ){\r
+  Node false_term = d_qe->getEqualityQuery()->getEngine()->getRepresentative( NodeManager::currentNM()->mkConst<bool>(false) );\r
+  d_eqc_false = eq::EqClassIterator( false_term, d_qe->getEqualityQuery()->getEngine() );\r
+}\r
+Node CandidateGeneratorQELitDeq::getNextCandidate(){\r
+  //get next candidate term in equivalence class\r
+  while( !d_eqc_false.isFinished() ){\r
+    Node n = (*d_eqc_false);\r
+    ++d_eqc_false;\r
+    if( n.getKind()==d_match_pattern.getKind() ){\r
+      //found an iff or equality, try to match it\r
+      //DO_THIS: cache to avoid redundancies?\r
+      //DO_THIS: do we need to try the symmetric equality for n?  or will it also exist in the eq class of false?\r
+      return n;\r
+    }\r
+  }\r
+  return Node::null();\r
+}\r
diff --git a/src/theory/candidate_generator.h b/src/theory/candidate_generator.h
new file mode 100644 (file)
index 0000000..2152f1e
--- /dev/null
@@ -0,0 +1,187 @@
+/*********************                                                        */\r
+/*! \file candidate_generator.h\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): mdeters\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009-2012  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 Theory uf candidate generator\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef __CVC4__CANDIDATE_GENERATOR_H\r
+#define __CVC4__CANDIDATE_GENERATOR_H\r
+\r
+#include "theory/theory.h"\r
+#include "theory/uf/equality_engine.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+\r
+class QuantifiersEngine;\r
+\r
+namespace inst {\r
+\r
+/** base class for generating candidates for matching */\r
+class CandidateGenerator {\r
+public:\r
+  CandidateGenerator(){}\r
+  ~CandidateGenerator(){}\r
+\r
+  /** Get candidates functions.  These set up a context to get all match candidates.\r
+      cg->reset( eqc );\r
+      do{\r
+        Node cand = cg->getNextCandidate();\r
+        //.......\r
+      }while( !cand.isNull() );\r
+\r
+      eqc is the equivalence class you are searching in\r
+  */\r
+  virtual void reset( Node eqc ) = 0;\r
+  virtual Node getNextCandidate() = 0;\r
+  /** add candidate to list of nodes returned by this generator */\r
+  virtual void addCandidate( Node n ) {}\r
+  /** call this at the beginning of each instantiation round */\r
+  virtual void resetInstantiationRound() = 0;\r
+public:\r
+  /** legal candidate */\r
+  static bool isLegalCandidate( Node n );\r
+};/* class CandidateGenerator */\r
+\r
+/** candidate generator queue (for manual candidate generation) */\r
+class CandidateGeneratorQueue : public CandidateGenerator {\r
+private:\r
+  std::vector< Node > d_candidates;\r
+  int d_candidate_index;\r
+public:\r
+  CandidateGeneratorQueue() : d_candidate_index( 0 ){}\r
+  ~CandidateGeneratorQueue(){}\r
+\r
+  void addCandidate( Node n );\r
+\r
+  void resetInstantiationRound(){}\r
+  void reset( Node eqc );\r
+  Node getNextCandidate();\r
+};/* class CandidateGeneratorQueue */\r
+\r
+class CandidateGeneratorQEDisequal;\r
+\r
+#if 0\r
+\r
+class CandidateGeneratorQE : public CandidateGenerator\r
+{\r
+  friend class CandidateGeneratorQEDisequal;\r
+private:\r
+  //operator you are looking for\r
+  Node d_op;\r
+  //instantiator pointer\r
+  QuantifiersEngine* d_qe;\r
+  //the equality class iterator\r
+  eq::EqClassIterator d_eqc;\r
+  int d_term_iter;\r
+  int d_term_iter_limit;\r
+private:\r
+  Node d_retNode;\r
+public:\r
+  CandidateGeneratorQE( QuantifiersEngine* qe, Node op );\r
+  ~CandidateGeneratorQE(){}\r
+\r
+  void resetInstantiationRound();\r
+  void reset( Node eqc );\r
+  Node getNextCandidate();\r
+};\r
+\r
+#else\r
+\r
+class CandidateGeneratorQE : public CandidateGenerator\r
+{\r
+  friend class CandidateGeneratorQEDisequal;\r
+private:\r
+  //operator you are looking for\r
+  Node d_op;\r
+  //instantiator pointer\r
+  QuantifiersEngine* d_qe;\r
+  //the equality class iterator\r
+  std::vector< Node > d_eqc;\r
+  int d_term_iter;\r
+  int d_term_iter_limit;\r
+  bool d_using_term_db;\r
+public:\r
+  CandidateGeneratorQE( QuantifiersEngine* qe, Node op );\r
+  ~CandidateGeneratorQE(){}\r
+\r
+  void resetInstantiationRound();\r
+  void reset( Node eqc );\r
+  Node getNextCandidate();\r
+};\r
+\r
+#endif\r
+\r
+//class CandidateGeneratorQEDisequal : public CandidateGenerator\r
+//{\r
+//private:\r
+//  //equivalence class\r
+//  Node d_eq_class;\r
+//  //equivalence class info\r
+//  EqClassInfo* d_eci;\r
+//  //equivalence class iterator\r
+//  EqClassInfo::BoolMap::const_iterator d_eqci_iter;\r
+//  //instantiator pointer\r
+//  QuantifiersEngine* d_qe;\r
+//public:\r
+//  CandidateGeneratorQEDisequal( QuantifiersEngine* qe, Node eqc );\r
+//  ~CandidateGeneratorQEDisequal(){}\r
+//\r
+//  void resetInstantiationRound();\r
+//  void reset( Node eqc );   //should be what you want to be disequal from\r
+//  Node getNextCandidate();\r
+//};\r
+\r
+class CandidateGeneratorQELitEq : public CandidateGenerator\r
+{\r
+private:\r
+  //the equality classes iterator\r
+  eq::EqClassesIterator d_eq;\r
+  //equality you are trying to match equalities for\r
+  Node d_match_pattern;\r
+  //einstantiator pointer\r
+  QuantifiersEngine* d_qe;\r
+public:\r
+  CandidateGeneratorQELitEq( QuantifiersEngine* qe, Node mpat );\r
+  ~CandidateGeneratorQELitEq(){}\r
+\r
+  void resetInstantiationRound();\r
+  void reset( Node eqc );\r
+  Node getNextCandidate();\r
+};\r
+\r
+class CandidateGeneratorQELitDeq : public CandidateGenerator\r
+{\r
+private:\r
+  //the equality class iterator for false\r
+  eq::EqClassIterator d_eqc_false;\r
+  //equality you are trying to match disequalities for\r
+  Node d_match_pattern;\r
+  //einstantiator pointer\r
+  QuantifiersEngine* d_qe;\r
+public:\r
+  CandidateGeneratorQELitDeq( QuantifiersEngine* qe, Node mpat );\r
+  ~CandidateGeneratorQELitDeq(){}\r
+\r
+  void resetInstantiationRound();\r
+  void reset( Node eqc );\r
+  Node getNextCandidate();\r
+};\r
+\r
+}/* CVC4::theory::inst namespace */\r
+}/* CVC4::theory namespace */\r
+}/* CVC4 namespace */\r
+\r
+#endif /* __CVC4__THEORY_UF_INSTANTIATOR_H */\r
index f282ce74dd2a48ada683af4b32efd7ae4f2e0ebd..0e6197ac1cb2370fb5ec6d80fda201506afa7a99 100644 (file)
@@ -16,7 +16,6 @@ libdatatypes_la_SOURCES = \
        explanation_manager.h \
        explanation_manager.cpp \
        theory_datatypes_instantiator.h \
-       theory_datatypes_instantiator.cpp \
-       theory_datatypes_candidate_generator.h
-
+       theory_datatypes_instantiator.cpp
+       
 EXTRA_DIST = kinds
index ea140910813c7b35471a3da1f6ce3427de6967b3..5bae534e1f5a40552daa64280011f30ef1fc36e3 100644 (file)
@@ -74,7 +74,8 @@ public:
                                    << "Rewrite trivial selector " << in
                                    << std::endl;
         return RewriteResponse(REWRITE_DONE, in[0][selectorIndex]);
-      } else {
+      }
+        /*
         Node gt = in.getType().mkGroundTerm();
         TypeNode gtt = gt.getType();
         //Assert( gtt.isDatatype() || gtt.isParametricDatatype() );
@@ -87,7 +88,7 @@ public:
                                    << " to distinguished ground term "
                                    << in.getType().mkGroundTerm() << std::endl;
         return RewriteResponse(REWRITE_DONE,gt );
-      }
+        */
     }
 
     if(in.getKind() == kind::EQUAL && in[0] == in[1]) {
index cb0f75c120167479ee56558bc46c58947167538f..b7f4f39d55422701ff93f0f53f42c2483b6ce58c 100644 (file)
@@ -34,993 +34,682 @@ using namespace CVC4::context;
 using namespace CVC4::theory;
 using namespace CVC4::theory::datatypes;
 
-const DatatypeConstructor& TheoryDatatypes::getConstructor( Node cons )
-{
-  Expr consExpr = cons.toExpr();
-  return Datatype::datatypeOf(consExpr)[ Datatype::indexOf(consExpr) ];
-}
-
-Node TheoryDatatypes::getConstructorForSelector( Node sel )
-{
-  size_t selIndex = Datatype::indexOf( sel.toExpr() );
-  const Datatype& dt = ((DatatypeType)((sel.getType()[0]).toType())).getDatatype();
-  for( unsigned i = 0; i<dt.getNumConstructors(); i++ ){
-    if( dt[i].getNumArgs()>selIndex &&
-        Node::fromExpr( dt[i][selIndex].getSelector() )==sel ){
-      return Node::fromExpr( dt[i].getConstructor() );
+void TheoryDatatypes::printModelDebug(){
+  /*
+  //std::cout << "Datatypes model : " << std::endl;
+  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &d_equalityEngine );
+  while( !eqcs_i.isFinished() ){
+    Node eqc = (*eqcs_i);
+    if( eqc.getType().isDatatype() || eqc.getType().isBoolean() ){
+      //std::cout << eqc << " : " << eqc.getType() << " : " << std::endl;
+      //std::cout << "   { ";
+      //add terms to model
+      eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &d_equalityEngine );
+      while( !eqc_i.isFinished() ){
+        //std::cout << (*eqc_i) << " ";
+        ++eqc_i;
+      }
+      //std::cout << "}" << std::endl;
+      if( eqc.getType().isDatatype() ){
+        EqcInfo* ei = getOrMakeEqcInfo( eqc );
+        if( ei ){
+          //std::cout << "   Instantiated : " << ( ei->d_inst ? "yes" : "no" ) << std::endl;
+          if( ei->d_constructor.get().isNull() ){
+            //std::cout << "   Constructor : " << std::endl;
+            //std::cout << "   Labels : ";
+            if( hasLabel( ei, eqc ) ){
+              //std::cout << getLabel( eqc );
+            }else{
+              NodeListMap::iterator lbl_i = d_labels.find( eqc );
+              if( lbl_i != d_labels.end() ){
+                NodeList* lbl = (*lbl_i).second;
+                for( NodeList::const_iterator j = lbl->begin(); j != lbl->end(); j++ ){
+                  //std::cout << *j << " ";
+                }
+              }
+            }
+            //std::cout << std::endl;
+          }else{
+            //std::cout << "   Constructor : " << ei->d_constructor.get() << std::endl;
+          }
+          //std::cout << "   Selectors : " << ( ei->d_selectors ? "yes" : "no" ) << std::endl;
+        }
+      }
     }
+    ++eqcs_i;
   }
-  Assert( false );
-  return Node::null();
+  */
 }
 
 
 TheoryDatatypes::TheoryDatatypes(Context* c, UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo, QuantifiersEngine* qe) :
   Theory(THEORY_DATATYPES, c, u, out, valuation, logicInfo, qe),
-  d_currAsserts(c),
-  d_currEqualities(c),
-  d_selectors(c),
-  d_reps(c),
-  d_selector_eq(c),
-  d_equivalence_class(c),
-  d_inst_map(c),
   d_cycle_check(c),
   d_hasSeenCycle(c, false),
-  d_labels(c),
-  d_ccChannel(this),
-  d_cc(c, &d_ccChannel),
-  d_unionFind(c),
-  d_disequalities(c),
-  d_em(c),
-  d_cce(&d_cc){
+  d_infer(c),
+  d_infer_exp(c),
+  d_notify( *this ),
+  d_equalityEngine(d_notify, c, "theory::datatypes::TheoryDatatypes"),
+  d_labels( c ),
+  d_conflict( c, false ){
+
+  // The kinds we are treating as function application in congruence
+  d_equalityEngine.addFunctionKind(kind::APPLY_CONSTRUCTOR);
+  d_equalityEngine.addFunctionKind(kind::APPLY_SELECTOR);
+  d_equalityEngine.addFunctionKind(kind::APPLY_TESTER);
 }
 
-
 TheoryDatatypes::~TheoryDatatypes() {
 }
 
-void TheoryDatatypes::addSharedTerm(TNode t) {
-  Debug("datatypes") << "TheoryDatatypes::addSharedTerm(): "
-                     << t << endl;
+TheoryDatatypes::EqcInfo* TheoryDatatypes::getOrMakeEqcInfo( Node n, bool doMake ){
+  std::map< Node, EqcInfo* >::iterator eqc_i = d_eqc_info.find( n );
+  if( !hasEqcInfo( n ) ){
+    if( doMake ){
+      //add to labels
+      NodeList* lbl = new(getSatContext()->getCMM()) NodeList( true, getSatContext(), false,
+                                                             ContextMemoryAllocator<TNode>(getSatContext()->getCMM()) );
+      d_labels.insertDataFromContextMemory( n, lbl );
+      EqcInfo* ei;
+      if( eqc_i!=d_eqc_info.end() ){
+        ei = eqc_i->second;
+      }else{
+        ei = new EqcInfo( getSatContext() );
+        d_eqc_info[n] = ei;
+      }
+      if( n.getKind()==APPLY_CONSTRUCTOR ){
+        ei->d_constructor = n;
+      }
+      return ei;
+    }else{
+      return NULL;
+    }
+  }else{
+    return (*eqc_i).second;
+  }
 }
 
-void TheoryDatatypes::notifyCongruent(TNode lhs, TNode rhs) {
-  Debug("datatypes") << "TheoryDatatypes::notifyCongruent(): "
-                     << lhs << " = " << rhs << endl;
-  if(!hasConflict()) {
-    merge(lhs,rhs);
-  }
-  Debug("datatypes-debug") << "TheoryDatatypes::notifyCongruent(): done." << endl;
+/** propagate */
+void TheoryDatatypes::propagate(Effort effort){
+
 }
 
-void TheoryDatatypes::preRegisterTerm(TNode n) {
-  Debug("datatypes-prereg") << "TheoryDatatypes::preRegisterTerm() " << n << endl;
-  if( n.getType().isDatatype() ){
-    d_preRegTerms.push_back( n );
+/** propagate */
+bool TheoryDatatypes::propagate(TNode literal){
+  Debug("dt::propagate") << "TheoryDatatypes::propagate(" << literal  << ")" << std::endl;
+  // If already in conflict, no more propagation
+  if (d_conflict) {
+    Debug("dt::propagate") << "TheoryDatatypes::propagate(" << literal << "): already in conflict" << std::endl;
+    return false;
   }
+  // Propagate out
+  bool ok = d_out->propagate(literal);
+  if (!ok) {
+    d_conflict = true;
+  }
+  return ok;
 }
 
-
-void TheoryDatatypes::presolve() {
-  Debug("datatypes") << "TheoryDatatypes::presolve()" << endl;
+/** explain */
+void TheoryDatatypes::explain(TNode literal, std::vector<TNode>& assumptions){
+  Debug("datatypes-explain") << "Explain " << literal << std::endl;
+  bool polarity = literal.getKind() != kind::NOT;
+  TNode atom = polarity ? literal : literal[0];
+  if (atom.getKind() == kind::EQUAL || atom.getKind() == kind::IFF) {
+    d_equalityEngine.explainEquality(atom[0], atom[1], polarity, assumptions);
+  } else {
+    d_equalityEngine.explainPredicate(atom, polarity, assumptions);
+  }
 }
 
-void TheoryDatatypes::check(Effort e) {
+Node TheoryDatatypes::explain( TNode literal ){
+  std::vector< TNode > assumptions;
+  explain( literal, assumptions );
+  if( assumptions.empty() ){
+    return NodeManager::currentNM()->mkConst( true );
+  }else if( assumptions.size()==1 ){
+    return assumptions[0];
+  }else{
+    return NodeManager::currentNM()->mkNode( kind::AND, assumptions );
+  }
+}
 
-  for( int i=0; i<(int)d_currAsserts.size(); i++ ) {
-    Debug("datatypes") << "currAsserts[" << i << "] = " << d_currAsserts[i] << endl;
+/** Conflict when merging two constants */
+void TheoryDatatypes::conflict(TNode a, TNode b){
+  if (a.getKind() == kind::CONST_BOOLEAN) {
+    d_conflictNode = explain( a.iffNode(b) );
+  } else {
+    d_conflictNode = explain( a.eqNode(b) );
   }
-  for( int i=0; i<(int)d_currEqualities.size(); i++ ) {
-    Debug("datatypes") << "currEqualities[" << i << "] = " << d_currEqualities[i] << endl;
+  Debug("datatypes-conflict") << "CONFLICT: Eq engine conflict : " << d_conflictNode << std::endl;
+  d_out->conflict( d_conflictNode );
+  d_conflict = true;
+}
+
+/** called when a new equivalance class is created */
+void TheoryDatatypes::eqNotifyNewClass(TNode t){
+  if( t.getKind()==APPLY_CONSTRUCTOR ){
+    getOrMakeEqcInfo( t, true );
   }
+}
 
-  while(!done()) {
-    Node assertion = get();
-    if( Debug.isOn("datatypes") || Debug.isOn("datatypes-split") || Debug.isOn("datatypes-cycles")
-        || Debug.isOn("datatypes-debug-pf") || Debug.isOn("datatypes-conflict") ) {
-      Notice() << "*** TheoryDatatypes::check(): " << assertion << endl;
-      d_currAsserts.push_back( assertion );
-    }
+/** called when two equivalance classes will merge */
+void TheoryDatatypes::eqNotifyPreMerge(TNode t1, TNode t2){
 
-    //clear from the derived map
-    d_checkMap.clear();
-    collectTerms( assertion );
-    if( !hasConflict() ){
-      if( d_em.hasNode( assertion ) ){
-        Debug("datatypes") << "Assertion has already been derived" << endl;
-        d_em.assertTrue( assertion );
-      } else {
-        switch(assertion.getKind()) {
-        case kind::EQUAL:
-        case kind::IFF:
-          addEquality(assertion);
-          break;
-        case kind::APPLY_TESTER:
-          addTester( assertion );
-          break;
-        case kind::NOT:
-          {
-            switch( assertion[0].getKind()) {
-            case kind::EQUAL:
-            case kind::IFF:
-              {
-                Node a = assertion[0][0];
-                Node b = assertion[0][1];
-                addDisequality(assertion[0]);
-                d_cc.addTerm(a);
-                d_cc.addTerm(b);
-                if(Debug.isOn("datatypes")) {
-                  Debug("datatypes") << "       a  == > " << a << endl
-                              << "       b  == > " << b << endl
-                              << "  find(a) == > " << debugFind(a) << endl
-                              << "  find(b) == > " << debugFind(b) << endl;
-                }
-                // There are two ways to get a conflict here.
-                if(!hasConflict()) {
-                  if(find(a) == find(b)) {
-                    // We get a conflict this way if we WERE previously watching
-                    // a, b and were notified previously (via notifyCongruent())
-                    // that they were congruent.
-                    Node ccEq = NodeManager::currentNM()->mkNode( EQUAL, assertion[0][0], assertion[0][1] );
-                    NodeBuilder<> nbc(kind::AND);
-                    nbc << ccEq << assertion;
-                    Node contra = nbc;
-                    d_em.addNode( ccEq, &d_cce );
-                    d_em.addNodeConflict( contra, Reason::contradiction );
-                  } else {
-                    // If we get this far, there should be nothing conflicting due
-                    // to this disequality.
-                    Assert(!d_cc.areCongruent(a, b));
-                  }
-                }
-              }
-              break;
-            case kind::APPLY_TESTER:
-              addTester( assertion );
-              break;
-            default:
-              Unhandled(assertion[0].getKind());
-              break;
+}
+
+/** called when two equivalance classes have merged */
+void TheoryDatatypes::eqNotifyPostMerge(TNode t1, TNode t2){
+  if( t1.getType().isDatatype() ){
+    d_pending_merge.push_back( t1.eqNode( t2 ) );
+  }
+}
+
+void TheoryDatatypes::merge( Node t1, Node t2 ){
+  if( !d_conflict ){
+    Node trep1 = t1;
+    Node trep2 = t2;
+    Debug("datatypes-debug") << "Merge " << t1 << " " << t2 << std::endl;
+    EqcInfo* eqc2 = getOrMakeEqcInfo( t2 );
+    if( eqc2 ){
+      bool checkInst = false;
+      if( !eqc2->d_constructor.get().isNull() ){
+        trep2 = eqc2->d_constructor.get();
+      }
+      EqcInfo* eqc1 = getOrMakeEqcInfo( t1 );
+      if( eqc1 ){
+        if( !eqc1->d_constructor.get().isNull() ){
+          trep1 = eqc1->d_constructor.get();
+        }
+        //check for clash
+        Node cons1 = eqc1->d_constructor;
+        Node cons2 = eqc2->d_constructor;
+        if( !cons1.isNull() && !cons2.isNull() ){
+          Debug("datatypes-debug") << "Constructors : " << cons1 << " " << cons2 << std::endl;
+          if( cons1.getOperator()!=cons2.getOperator() ){
+            //check for clash
+            d_conflictNode = explain( cons1.eqNode( cons2 ) );
+            Debug("datatypes-conflict") << "CONFLICT: Clash conflict : " << d_conflictNode << std::endl;
+            d_out->conflict( d_conflictNode );
+            d_conflict = true;
+            return;
+          }else{
+            //do unification
+            Node unifEq = cons1.eqNode( cons2 );
+            for( int i=0; i<(int)cons1.getNumChildren(); i++ ) {
+              Node eq = cons1[i].eqNode( cons2[i] );
+              d_pending.push_back( eq );
+              d_pending_exp[ eq ] = unifEq;
+              Debug("datatypes-infer") << "DtInfer : " << eq << " by " << unifEq << std::endl;
+              d_infer.push_back( eq );
+              d_infer_exp.push_back( unifEq );
             }
           }
-          break;
-        default:
-          Unhandled(assertion.getKind());
-          break;
         }
-      }
-    }
-    //rules to check for collapse, instantiate
-    while( !hasConflict() && !d_checkMap.empty() ){
-      std::map< Node, bool > temp;
-      temp = d_checkMap;
-      d_checkMap.clear();
-      std::map< Node, bool >::iterator i;
-      for( i = temp.begin(); i != temp.end(); i++ ){
-        Node n = find( i->first );
-        if( temp.find( n )==temp.end() || temp[n] ){
-          if( !hasConflict() ) checkInstantiateEqClass( n );
-          if( !hasConflict() ) updateSelectors( n );
-          temp[n] = false;
+        if( eqc1->d_inst.get().isNull() && !eqc2->d_inst.get().isNull() ){
+          eqc1->d_inst.set( eqc2->d_inst );
         }
+        if( cons1.isNull() && !cons2.isNull() ){
+          checkInst = true;
+          eqc1->d_constructor.set( eqc2->d_constructor );
+        }
+      }else{
+        Debug("datatypes-debug") << "No eqc info for " << t1 << ", must create" << std::endl;
+        //just copy the equivalence class information
+        eqc1 = getOrMakeEqcInfo( t1, true );
+        eqc1->d_inst.set( eqc2->d_inst );
+        eqc1->d_constructor.set( eqc2->d_constructor );
       }
-    }
-    //if there is now a conflict
-    if( hasConflict() ) {
-      Debug("datatypes-conflict") << "Constructing conflict..." << endl;
-      for( int i=0; i<(int)d_currAsserts.size(); i++ ) {
-        Debug("datatypes-conflict") << "currAsserts[" << i << "] = " << d_currAsserts[i] << endl;
-      }
-      //Debug("datatypes-conflict") << d_cc << std::endl;
-      Node conflict = d_em.getConflict();
-      if( Debug.isOn("datatypes") || Debug.isOn("datatypes-split") ||
-          Debug.isOn("datatypes-cycles") || Debug.isOn("datatypes-conflict") ){
-        Notice() << "Conflict constructed : " << conflict << endl;
-      }
-      if( conflict.getKind()!=kind::AND ){
-        conflict = NodeManager::currentNM()->mkNode(kind::AND, conflict, conflict);
-      }
-      d_out->conflict(conflict);
-      return;
-    }
-  }
-
-  if( e == EFFORT_FULL ) {
-    Debug("datatypes-split") << "Check for splits " << e << endl;
-    //do splitting
-    for( EqLists::iterator i = d_labels.begin(); i != d_labels.end(); i++ ) {
-      Node sf = find( (*i).first );
-      if( sf.getKind() != APPLY_CONSTRUCTOR ) {
-        addTermToLabels( sf );
-        EqList* lbl = (sf == (*i).first) ? (*i).second : (*d_labels.find( sf )).second;
-        Debug("datatypes-split") << "Check for splitting " << (*i).first
-                                 << ", label size = " << lbl->size() << endl;
-        if( lbl->empty() || (*lbl)[ lbl->size()-1 ].getKind() == NOT ) {    //there are more than 1 possible constructors for sf
-          const Datatype& dt = ((DatatypeType)(sf.getType()).toType()).getDatatype();
-          vector< bool > possibleCons;
-          possibleCons.resize( dt.getNumConstructors(), true );
-          for( EqList::const_iterator j = lbl->begin(); j != lbl->end(); j++ ) {
-            TNode leqn = (*j);
-            possibleCons[ Datatype::indexOf( leqn[0].getOperator().toExpr() ) ] = false;
-          }
-          Node cons;
-          bool foundSel = false;
-          for( unsigned int j=0; j<possibleCons.size(); j++ ) {
-            if( !foundSel && possibleCons[j] ) {
-              cons = Node::fromExpr( dt[ j ].getConstructor() );
-              //if there is a selector, split
-              for( unsigned int k=0; k<dt[ j ].getNumArgs(); k++ ) {
-                Node s = NodeManager::currentNM()->mkNode( APPLY_SELECTOR, Node::fromExpr( dt[j][k].getSelector() ), sf );
-                if( d_selectors.find( s ) != d_selectors.end() ) {
-                  foundSel = true;
-                  break;
-                }
-              }
-            }
-          }
-          if( !foundSel ){
-            for( unsigned int j=0; j<possibleCons.size(); j++ ) {
-              if( possibleCons[j] && !dt[ j ].isFinite() ) {
-                Debug("datatypes") << "Did not find selector for " << sf
-                                  << " and " << dt[ j ].getConstructor() << " is not finite." << endl;
-                cons = Node::null();
-                break;
-              }
-            }
-          }
-          if( !cons.isNull() ) {
-            const DatatypeConstructor& cn = getConstructor( cons );
-            Debug("datatypes-split") << "*************Split for possible constructor " << cons << endl;
-            Node test = NodeManager::currentNM()->mkNode( APPLY_TESTER, Node::fromExpr( cn.getTester() ), (*i).first );
-            NodeBuilder<> nb(kind::OR);
-            nb << test << test.notNode();
-            Node lemma = nb;
-            Debug("datatypes-split") << "Lemma is " << lemma << endl;
-            d_out->lemma( lemma );
+      //merge labels
+      Debug("datatypes-debug") << "Merge labels from " << eqc2 << " " << t2 << std::endl;
+      NodeListMap::iterator lbl_i = d_labels.find( t2 );
+      if( lbl_i != d_labels.end() ){
+        NodeList* lbl = (*lbl_i).second;
+        for( NodeList::const_iterator j = lbl->begin(); j != lbl->end(); ++j ){
+          addTester( *j, eqc1, t1 );
+          if( d_conflict ){
             return;
           }
         }
-      } else {
-        Debug("datatypes-split") << (*i).first << " is " << sf << endl;
-        Assert( sf != (*i).first );
       }
-    }
-  }
-  if( Debug.isOn("datatypes") || Debug.isOn("datatypes-split") ) {
-    Notice() << "TheoryDatatypes::check(): done" << endl;
-  }
-}
-
-bool TheoryDatatypes::checkTester( Node assertion, Node& conflict, unsigned& r ){
-  Debug("datatypes") << "Check tester " << assertion << endl;
-
-  Node tassertion = ( assertion.getKind() == NOT ) ? assertion[0] : assertion;
-  Assert( find( tassertion[0] ) == tassertion[0] );
-
-  //if argument is a constructor, it is trivial
-  if( tassertion[0].getKind() == APPLY_CONSTRUCTOR ) {
-    size_t tIndex = Datatype::indexOf(tassertion.getOperator().toExpr());
-    size_t cIndex = Datatype::indexOf(tassertion[0].getOperator().toExpr());
-    if( (tIndex==cIndex) == (assertion.getKind() == NOT) ) {
-      conflict = assertion;
-      r = Reason::idt_tclash;
-    }
-    return false;
-  }
-
-  addTermToLabels( tassertion[0] );
-  EqList* lbl = (*d_labels.find( tassertion[0] )).second;
-  //check if empty label (no possible constructors for term)
-  for( EqList::const_iterator i = lbl->begin(); i != lbl->end(); i++ ) {
-    Node leqn = (*i);
-    Debug("datatypes-debug") << "checking " << leqn << std::endl;
-    if( leqn.getKind() == kind::NOT ) {
-      if( leqn[0].getOperator() == tassertion.getOperator() ) {
-        if( assertion.getKind() != NOT ) {
-          conflict = NodeManager::currentNM()->mkNode( AND, leqn, assertion );
-          r = Reason::contradiction;
-          Debug("datatypes") << "Contradictory labels " << conflict << endl;
+      //merge selectors
+      if( !eqc1->d_selectors && eqc2->d_selectors ){
+        eqc1->d_selectors = true;
+        checkInst = true;
+      }
+      if( checkInst ){
+        checkInstantiate( eqc1, t1 );
+        if( d_conflict ){
+          return;
         }
-        return false;
       }
-    }else{
-      if( (leqn.getOperator() == tassertion.getOperator()) == (assertion.getKind() == NOT) ) {
-        conflict = NodeManager::currentNM()->mkNode( AND, leqn, assertion );
-        r = Reason::idt_tclash;
-        Debug("datatypes") << "Contradictory labels(2) " << conflict << endl;
+    }
+    //add this to the transitive closure module
+    Node oldRep = trep2;
+    Node newRep = trep1;
+    if( trep1.getKind()!=APPLY_CONSTRUCTOR && trep2.getKind()==APPLY_CONSTRUCTOR ){
+      oldRep = trep1;
+      newRep = trep2;
+    }
+    bool result = d_cycle_check.addEdgeNode( oldRep, newRep );
+    d_hasSeenCycle.set( d_hasSeenCycle.get() || result );
+    Debug("datatypes-cycles") << "DtCyc: Equal " << oldRep << " -> " << newRep << " " << d_hasSeenCycle.get() << endl;
+    if( d_hasSeenCycle.get() ){
+      checkCycles();
+      if( d_conflict ){
+        return;
       }
-      return false;
     }
   }
-  return true;
 }
 
-void TheoryDatatypes::addTester( Node assertion ){
-  Debug("datatypes") << "addTester " << assertion << endl;
+/** called when two equivalence classes are made disequal */
+void TheoryDatatypes::eqNotifyDisequal(TNode t1, TNode t2, TNode reason){
 
-  //preprocess the tester
-  Node tassertion = ( assertion.getKind() == NOT ) ? assertion[0] : assertion;
-  //add the term into congruence closure consideration
-  d_cc.addTerm( tassertion[0] );
+}
 
-  Node assertionRep;
-  Node tassertionRep;
-  Node tRep = tassertion[0];
-  tRep = find( tRep );
-  //add label instead for the representative (if it is different)
-  if( tRep != tassertion[0] ) {
-    //explanation is trivial (do not add to labels)
-    if( tRep.getKind()==APPLY_CONSTRUCTOR && assertion.getKind()== kind::APPLY_TESTER &&
-        Datatype::indexOf(assertion.getOperator().toExpr())==Datatype::indexOf(tRep.getOperator().toExpr()) ){
-      tassertionRep = NodeManager::currentNM()->mkNode( APPLY_TESTER, tassertion.getOperator(), tRep );
-      assertionRep = tassertionRep;
-      d_em.addNodeAxiom( assertionRep, Reason::idt_taxiom );
-      return;
-    }else{
-      tassertionRep = NodeManager::currentNM()->mkNode( APPLY_TESTER, tassertion.getOperator(), tRep );
-      assertionRep = ( assertion.getKind() == NOT ) ? tassertionRep.notNode() : tassertionRep;
-      //add explanation
-      Node ccEq = NodeManager::currentNM()->mkNode( EQUAL, tRep, tassertion[0] );
-      d_em.addNode( ccEq, &d_cce );
-      NodeBuilder<> nb2(kind::AND);
-      nb2 << assertion << ccEq;
-      Node expl = nb2;
-      d_em.addNode( assertionRep, expl, Reason::idt_tcong );
-    }
-  }else{
-    tassertionRep = tassertion;
-    assertionRep = assertion;
-  }
+TheoryDatatypes::EqcInfo::EqcInfo( context::Context* c ) :
+d_inst( c, Node::null() ), d_constructor( c, Node::null() ), d_selectors( c, false ){
 
-  Node conflict;
-  unsigned r;
-  if( checkTester( assertionRep, conflict, r ) ){
-    //it is not redundant/contradictory, add it to labels
-    EqLists::iterator lbl_i = d_labels.find( tRep );
-    EqList* lbl = (*lbl_i).second;
-    lbl->push_back( assertionRep );
-    Debug("datatypes") << "Add to labels " << assertionRep << endl;
-    if( assertionRep.getKind()==NOT ){
-      const Datatype& dt = Datatype::datatypeOf( tassertion.getOperator().toExpr() );
-      //we can conclude the final one
-      if( lbl->size()==dt.getNumConstructors()-1 ){
-        vector< bool > possibleCons;
-        possibleCons.resize( dt.getNumConstructors(), true );
-        NodeBuilder<> nb(kind::AND);
-        for( EqList::const_iterator i = lbl->begin(); i != lbl->end(); i++ ) {
-          possibleCons[ Datatype::indexOf( (*i)[0].getOperator().toExpr() ) ] = false;
-          nb << (*i);
-        }
-        int testerIndex = -1;
-        for( int i=0; i<(int)possibleCons.size(); i++ ) {
-          if( possibleCons[i] ){
-            testerIndex = i;
-          }
-        }
-        Assert( testerIndex!=-1 );
-        assertionRep = NodeManager::currentNM()->mkNode( APPLY_TESTER, Node::fromExpr( dt[unsigned(testerIndex)].getTester() ), tRep );
-        Node exp = ( nb.getNumChildren() == 1 ) ? nb.getChild( 0 ) : nb;
-        d_em.addNode( assertionRep, exp, Reason::idt_texhaust );
-        addTester( assertionRep );    //add stronger statement
-        return;
-      }
-    }
-    if( assertionRep.getKind()==APPLY_TESTER ){
-      d_checkMap[ tRep ] = true;
-    }
-  }else if( !conflict.isNull() ){
-    d_em.addNodeConflict( conflict, r );
-  }
 }
 
-//if only one constructor remaining for t, this function will return it
-Node TheoryDatatypes::getInstantiateCons( Node t ){
-  if( t.getKind() != APPLY_CONSTRUCTOR ){
-    Assert( t == find( t ) );
-    addTermToLabels( t );
-    EqLists::iterator lbl_i = d_labels.find( t );
-    if( lbl_i!=d_labels.end() ) {
-      EqList* lbl = (*lbl_i).second;
-      if( !lbl->empty() && (*lbl)[ lbl->size()-1 ].getKind() != NOT ) {
-        const Datatype& dt = ((DatatypeType)(t.getType()).toType()).getDatatype();
-        size_t testerIndex = Datatype::indexOf( (*lbl)[ lbl->size()-1 ].getOperator().toExpr() );
-        return Node::fromExpr( dt[ testerIndex ].getConstructor() );
-      }
+bool TheoryDatatypes::hasLabel( EqcInfo* eqc, Node n ){
+  return !eqc->d_constructor.get().isNull() || !getLabel( n ).isNull();
+}
+
+Node TheoryDatatypes::getLabel( Node n ) {
+  NodeListMap::iterator lbl_i = d_labels.find( n );
+  if( lbl_i != d_labels.end() ){
+    NodeList* lbl = (*lbl_i).second;
+    if( !(*lbl).empty() && (*lbl)[ (*lbl).size() - 1 ].getKind()==kind::APPLY_TESTER ){
+      return (*lbl)[ (*lbl).size() - 1 ];
     }
   }
   return Node::null();
 }
 
-void TheoryDatatypes::checkInstantiateEqClass( Node t ) {
-  Debug("datatypes") << "TheoryDatatypes::checkInstantiateEqClass() " << t << endl;
-  Assert( t == find( t ) );
-
-  //if labels were created for t, and t has not been instantiated
-  Node cons = getInstantiateCons( t );
-  if( !cons.isNull() ){
-    //for each term in equivalance class
-    initializeEqClass( t );
-    EqListN* eqc = (*d_equivalence_class.find( t )).second;
-    for( EqListN::const_iterator iter = eqc->begin(); iter != eqc->end(); iter++ ) {
-      Node te = *iter;
-      Assert( find( te ) == t );
-      if( checkInstantiate( te, cons ) ){
-        return;
-      }
-    }
+int TheoryDatatypes::getLabelIndex( EqcInfo* eqc, Node n ){
+  if( !eqc->d_constructor.get().isNull() ){
+    return Datatype::indexOf( eqc->d_constructor.get().getOperator().toExpr() );
+  }else{
+    return Datatype::indexOf( getLabel( n ).getOperator().toExpr() );
   }
 }
 
-//pre condition: find( te ) has been proven to be the constructor cons
-//that is, is_[cons]( find( te ) ) is stored in d_labels
-bool TheoryDatatypes::checkInstantiate( Node te, Node cons )
-{
-  Debug("datatypes") << "TheoryDatatypes::checkInstantiate() " << te << endl;
-  //if term has not yet been instantiated
-  if( d_inst_map.find( te ) == d_inst_map.end() ) {
-    //find if selectors have been applied to t
-    vector< Node > selectorVals;
-    selectorVals.push_back( cons );
-    bool foundSel = false;
-    const DatatypeConstructor& cn = getConstructor( cons );
-    for( unsigned int i=0; i<cn.getNumArgs(); i++ ) {
-      Node s = NodeManager::currentNM()->mkNode( APPLY_SELECTOR, Node::fromExpr( cn[i].getSelector() ), te );
-      if( d_selectors.find( s ) != d_selectors.end() ) {
-        foundSel = true;
-        s = find( s );
-      }
-      selectorVals.push_back( s );
-    }
-    if( cn.isFinite() || foundSel ) {
-      d_inst_map[ te ] = true;
-      Node val = NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, selectorVals );
-      //instantiate, add equality
-      if( val.getType()!=te.getType() ){ //IDT-param
-        Assert( Datatype::datatypeOf( cons.toExpr() ).isParametric() );
-        Debug("datatypes-gt") << "Inst: ambiguous type for " << cons << ", ascribe to " << te.getType() << std::endl;
-        const DatatypeConstructor& dtc = Datatype::datatypeOf(cons.toExpr())[Datatype::indexOf(cons.toExpr())];
-        Debug("datatypes-gt") << "constructor is " << dtc << std::endl;
-        Type tspec = dtc.getSpecializedConstructorType(te.getType().toType());
-        Debug("datatypes-gt") << "tpec is " << tspec << std::endl;
-        selectorVals[0] = NodeManager::currentNM()->mkNode(kind::APPLY_TYPE_ASCRIPTION,
-                                            NodeManager::currentNM()->mkConst(AscriptionType(tspec)), cons);
-        val = NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, selectorVals );
-      }
-      if( find( val ) != find( te ) ) {
-        //build explaination
-        NodeBuilder<> nb(kind::AND);
-        //explanation for tester
-        Node t = find( te );
-        addTermToLabels( t );
-        Assert( d_labels.find( t )!=d_labels.end() );
-        EqList* lbl = (*d_labels.find( t )).second;
-        nb << (*lbl)[ lbl->size()-1 ];    //this should be changed to be tester for te, not t for fine-grained
-        //explanation for arguments
-        for( unsigned int i=0; i<cn.getNumArgs(); i++ ) {
-          Node s = NodeManager::currentNM()->mkNode( APPLY_SELECTOR, Node::fromExpr( cn[i].getSelector() ), te );
-          if( selectorVals[i+1]!=s ){
-            Node ccEq = NodeManager::currentNM()->mkNode( EQUAL, selectorVals[i+1], s );
-            d_em.addNode( ccEq, &d_cce );
-            nb << ccEq;
-          }else{
-            //reflexive for s, if we want idt_inst to be fined grained
-            //Node eq = NodeManager::currentNM()->mkNode( EQUAL, s, s );
-            //d_em.addNodeAxiom( s, Reason::refl );
-          }
-        }
-        Node jeq = ( nb.getNumChildren() == 1 ) ? nb.getChild( 0 ) : nb;
-        Node newEq = NodeManager::currentNM()->mkNode( EQUAL, val, te );
-        Debug("datatypes") << "Instantiate: " << newEq << "." << endl;
-        d_em.addNode( newEq, jeq, Reason::idt_inst_coarse );
-        //collect terms of instantiation term
-        collectTerms( val, false );
-        //add equality for the instantiation
-        addEquality( newEq );
-        return true;
+void TheoryDatatypes::getPossibleCons( EqcInfo* eqc, Node n, std::vector< bool >& pcons ){
+  const Datatype& dt = ((DatatypeType)(n.getType()).toType()).getDatatype();
+  pcons.resize( dt.getNumConstructors(), !hasLabel( eqc, n ) );
+  if( hasLabel( eqc, n ) ){
+    pcons[ getLabelIndex( eqc, n ) ] = true;
+  }else{
+    NodeListMap::iterator lbl_i = d_labels.find( n );
+    if( lbl_i != d_labels.end() ){
+      NodeList* lbl = (*lbl_i).second;
+      for( NodeList::const_iterator i = lbl->begin(); i != lbl->end(); i++ ) {
+        Assert( (*i).getKind()==NOT );
+        pcons[ Datatype::indexOf( (*i)[0].getOperator().toExpr() ) ] = false;
       }
-    } else {
-      Debug("datatypes") << "Do not Instantiate: infinite constructor, no selectors " << cons << endl;
     }
-  }else{
-    Debug("datatypes") << "Do not Instantiate: " << te << " already instantiated" << endl;
   }
-  return false;
 }
 
-bool TheoryDatatypes::collapseSelector( Node t ) {
-  if( !hasConflict() && t.getKind() == APPLY_SELECTOR ) {
-    //collapse constructor
-    TypeNode retTyp = t.getType();
-    TypeNode typ = t[0].getType();
-    Node sel = t.getOperator();
-    TypeNode selType = sel.getType();
-    Node cons = getConstructorForSelector( sel );
-    const DatatypeConstructor& cn = getConstructor( cons );
-    Node tmp = find( t[0] );
-    Node retNode = t;
-    if( tmp.getKind() == APPLY_CONSTRUCTOR ) {
-      if( tmp.getOperator() == cons ) {
-        Debug("datatypes") << "Applied selector " << t << " to correct constructor." << endl;
-        retNode = tmp[ Datatype::indexOf( sel.toExpr() ) ];
-      } else {
-        Debug("datatypes") << "Applied selector " << t << " to wrong constructor." << endl;
-        retNode = retTyp.mkGroundTerm();    //IDT-param
+void TheoryDatatypes::addTester( Node t, EqcInfo* eqc, Node n ){
+  if( !d_conflict ){
+    Debug("datatypes-labels") << "Add tester " << t << " " << eqc << std::endl;
+    bool tpolarity = t.getKind()!=NOT;
+    Node tt = ( t.getKind() == NOT ) ? t[0] : t;
+    int ttindex = Datatype::indexOf( tt.getOperator().toExpr() );
+    Node j, jt;
+    if( hasLabel( eqc, n ) ){
+      int jtindex = getLabelIndex( eqc, n );
+      if( (jtindex==ttindex)!=tpolarity ){
+        d_conflict = true;
+        if( !eqc->d_constructor.get().isNull() ){
+          std::vector< TNode > assumptions;
+          explain( t, assumptions );
+          explain( eqc->d_constructor.get().eqNode( tt[0] ), assumptions );
+          d_conflictNode = NodeManager::currentNM()->mkNode( AND, assumptions );
+          Debug("datatypes-conflict") << "CONFLICT: Tester eq conflict : " << d_conflictNode << std::endl;
+          d_out->conflict( d_conflictNode );
+          return;
+        }else{
+          j = getLabel( n );
+          jt = j;
+        }
+      }else{
+        return;
       }
-      if( tmp!=t[0] ){
-        t = NodeManager::currentNM()->mkNode( APPLY_SELECTOR, t.getOperator(), tmp );
+    }else{
+      NodeListMap::iterator lbl_i = d_labels.find( n );
+      Assert( lbl_i != d_labels.end() );
+      NodeList* lbl = (*lbl_i).second;
+      for( NodeList::const_iterator i = lbl->begin(); i != lbl->end(); i++ ) {
+        Assert( (*i).getKind()==NOT );
+        j = *i;
+        jt = j[0];
+        int jtindex = Datatype::indexOf( jt.getOperator().toExpr() );
+        if( jtindex==ttindex ){
+          if( tpolarity ){  //we are in conflict
+            d_conflict = true;
+            break;
+          }else{            //it is redundant
+            return;
+          }
+        }
       }
-      Node neq = NodeManager::currentNM()->mkNode( EQUAL, retNode, t );
-      d_em.addNodeAxiom( neq, Reason::idt_collapse );
-      Debug("datatypes") << "Add collapse equality " << neq << endl;
-      addEquality( neq );
-      return true;
-    } else {
-      //see whether we can prove that the selector is applied to the wrong tester
-      Node tester = NodeManager::currentNM()->mkNode( APPLY_TESTER, Node::fromExpr( cn.getTester() ), tmp );
-      Node conflict;
-      unsigned r;
-      checkTester( tester, conflict, r );
-      if( !conflict.isNull() ) {
-        Debug("datatypes") << "Applied selector " << t << " to provably wrong constructor. " << retTyp << endl;
-        //conflict is c ^ tester, where conflict => false, but we want to say c => ~tester
-        //must remove tester from conflict
-        if( conflict.getKind()==kind::AND ){
-          NodeBuilder<> jt(kind::AND);
-          for( int i=0; i<(int)conflict.getNumChildren(); i++ ){
-            if( conflict[i]!=tester ){
-              jt << conflict[i];
+      if( !d_conflict ){
+        Debug("datatypes-labels") << "Add to labels " << t << std::endl;
+        lbl->push_back( t );
+        const Datatype& dt = ((DatatypeType)(tt[0].getType()).toType()).getDatatype();
+        Debug("datatypes-labels") << "Labels at " << lbl->size() << " / " << dt.getNumConstructors() << std::endl;
+        if( tpolarity ){
+          checkInstantiate( eqc, n );
+        }else{
+          //check if we have reached the maximum number of testers
+          // in this case, add the positive tester
+          if( lbl->size()==dt.getNumConstructors()-1 ){
+            std::vector< bool > pcons;
+            getPossibleCons( eqc, n, pcons );
+            int testerIndex = -1;
+            for( int i=0; i<(int)pcons.size(); i++ ) {
+              if( pcons[i] ){
+                testerIndex = i;
+                break;
+              }
             }
+            Assert( testerIndex!=-1 );
+            std::vector< Node > eq_terms;
+            NodeBuilder<> nb(kind::AND);
+            for( NodeList::const_iterator i = lbl->begin(); i != lbl->end(); i++ ) {
+              nb << (*i);
+              if( std::find( eq_terms.begin(), eq_terms.end(), (*i)[0][0] )==eq_terms.end() ){
+                eq_terms.push_back( (*i)[0][0] );
+                if( (*i)[0][0]!=tt[0] ){
+                  nb << (*i)[0][0].eqNode( tt[0] );
+                }
+              }
+            }
+            Node t_concl = NodeManager::currentNM()->mkNode( APPLY_TESTER, Node::fromExpr( dt[unsigned(testerIndex)].getTester() ), tt[0] );
+            Node t_concl_exp = ( nb.getNumChildren() == 1 ) ? nb.getChild( 0 ) : nb;
+            d_pending.push_back( t_concl );
+            d_pending_exp[ t_concl ] = t_concl_exp;
+            Debug("datatypes-infer") << "DtInfer : " << t_concl << " by " << t_concl_exp << std::endl;
+            d_infer.push_back( t_concl );
+            d_infer_exp.push_back( t_concl_exp );
+            return;
           }
-          conflict = ( jt.getNumChildren()==1 ) ? jt.getChild( 0 ) : jt;
-        }else{
-          Assert( conflict==tester );
-          conflict = Node::null();
-        }
-        if( conflict!=tester.notNode() ){
-          d_em.addNode( tester.notNode(), conflict, r );    //note that application of r is non-standard (TODO: fix)
         }
-
-        if( tmp != t[0] ) {
-          Node teq = NodeManager::currentNM()->mkNode( EQUAL, tmp, t[0] );
-          d_em.addNode( teq, &d_cce );
-          Node exp = NodeManager::currentNM()->mkNode( AND, tester.notNode(), teq );
-          tester = NodeManager::currentNM()->mkNode( APPLY_TESTER, Node::fromExpr( cn.getTester() ), t[0] );
-          d_em.addNode( tester.notNode(), exp, Reason::idt_tcong );
-        }
-        retNode = retTyp.mkGroundTerm();    //IDT-param
-        Node neq = NodeManager::currentNM()->mkNode( EQUAL, retNode, t );
-
-        d_em.addNode( neq, tester.notNode(), Reason::idt_collapse2 );
-        addEquality( neq );
-        return true;
       }
     }
-  }
-  return false;
-}
-
-//this function will test if each selector whose argument is in the equivalence class of "a" can be collapsed
-void TheoryDatatypes::updateSelectors( Node a ) {
-  Debug("datatypes") << "updateSelectors: " << a << endl;
-  EqListsN::iterator sel_a_i = d_selector_eq.find( a );
-  if( sel_a_i != d_selector_eq.end() ) {
-    EqListN* sel_a = (*sel_a_i).second;
-    for( EqListN::const_iterator i = sel_a->begin(); i != sel_a->end(); i++ ) {
-      Node s = (*i);
-      //if a is still a representative, and s has not yet been collapsed
-      if( find( a )==a && !d_selectors[s] ){
-        Assert( s.getKind()==APPLY_SELECTOR && find( s[0] ) == a );
-        if( a != s[0] ) {
-          s = NodeManager::currentNM()->mkNode( APPLY_SELECTOR, s.getOperator(), a );
-          collectTerms( s, false );
-        }
-        d_selectors[s] = collapseSelector( s );
-      }
+    if( d_conflict ){
+      std::vector< TNode > assumptions;
+      explain( j, assumptions );
+      explain( t, assumptions );
+      explain( jt[0].eqNode( tt[0] ), assumptions );
+      d_conflictNode = NodeManager::currentNM()->mkNode( AND, assumptions );
+      Debug("datatypes-conflict") << "CONFLICT: Tester conflict : " << d_conflictNode << std::endl;
+      d_out->conflict( d_conflictNode );
     }
   }
 }
 
-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 );
-  }
-}
 
-void TheoryDatatypes::merge(TNode a, TNode b) {
-  if( !d_merge_pending.empty() ) {
-    //Debug("datatypes") << "Append to merge pending list " << d_merge_pending.size() << endl;
-    d_merge_pending[d_merge_pending.size()-1].push_back( pair< Node, Node >( a, b ) );
-    return;
-  }
-  Assert(!hasConflict());
-  a = find(a);
-  b = find(b);
-  if( a == b) {
-    return;
-  }
-  Debug("datatypes") << "Merge "<< a << " " << b << endl;
-
-  // make "a" the one with shorter diseqList
-  EqLists::iterator deq_ia = d_disequalities.find(a);
-  EqLists::iterator deq_ib = d_disequalities.find(b);
+void TheoryDatatypes::check(Effort e) {
 
-  if(deq_ia != d_disequalities.end()) {
-    if(deq_ib == d_disequalities.end() ||
-       (*deq_ia).second->size() > (*deq_ib).second->size()) {
-      TNode tmp = a;
-      a = b;
-      b = tmp;
-    }
-  }
+  while(!done() && !d_conflict) {
+    // Get all the assertions
+    Assertion assertion = get();
+    TNode fact = assertion.assertion;
+    Debug("datatypes-assert") << "Assert " << fact << std::endl;
 
-  //if b is a selector, swap a and b
-  if( b.getKind() == APPLY_SELECTOR && a.getKind() != APPLY_SELECTOR ) {
-    TNode tmp = a;
-    a = b;
-    b = tmp;
-  }
-  //make constructors the representatives
-  if( a.getKind() == APPLY_CONSTRUCTOR ) {
-    TNode tmp = a;
-    a = b;
-    b = tmp;
-  }
-  //make sure skolem variable is not representative
-  if( b.getKind() == SKOLEM ) {
-    TNode tmp = a;
-    a = b;
-    b = tmp;
+    //reset the maps
+    d_pending.clear();
+    d_pending_exp.clear();
+    //assert the fact
+    assertFact( fact, fact );
+    flushPendingFacts();
   }
 
-  //check for clash
-  NodeBuilder<> explanation(kind::AND);
-  if( a.getKind() == kind::APPLY_CONSTRUCTOR && b.getKind() == kind::APPLY_CONSTRUCTOR
-      && a.getOperator()!=b.getOperator() ){
-    Node ccEq = NodeManager::currentNM()->mkNode( EQUAL, a, b );
-    d_em.addNode( ccEq, &d_cce );
-    d_em.addNodeConflict( ccEq, Reason::idt_clash );
-    Debug("datatypes") << "Clash " << a << " " << b << endl;
-    return;
-  }
-  Debug("datatypes-debug") << "Done clash" << endl;
-
-  Debug("datatypes-ae") << "Set canon: "<< a << " " << b << endl;
-  // b becomes the canon of a
-  d_unionFind.setCanon(a, b);
-  d_reps[a] = false;
-  d_reps[b] = true;
-
-  //add this to the transitive closure module
-  bool result = d_cycle_check.addEdgeNode( a, b );
-  d_hasSeenCycle.set( d_hasSeenCycle.get() || result );
-  Debug("datatypes-cycles") << "Equal " << a << " -> " << b << " " << d_hasSeenCycle.get() << endl;
-  if( d_hasSeenCycle.get() ){
-    checkCycles();
-    if( hasConflict() ){
-      return;
+  if( e == EFFORT_FULL ) {
+    Debug("datatypes-split") << "Check for splits " << e << endl;
+    eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &d_equalityEngine );
+    while( !eqcs_i.isFinished() ){
+      Node n = (*eqcs_i);
+      if( n.getType().isDatatype() ){
+        EqcInfo* eqc = getOrMakeEqcInfo( n, true );
+        //if there are more than 1 possible constructors for eqc
+        if( eqc->d_constructor.get().isNull() && !hasLabel( eqc, n ) ) {
+          const Datatype& dt = ((DatatypeType)(n.getType()).toType()).getDatatype();
+          //if only one constructor, then this term must be this constructor
+          if( dt.getNumConstructors()==1 ){
+            Node t = NodeManager::currentNM()->mkNode( APPLY_TESTER, Node::fromExpr( dt[0].getTester() ), n );
+            d_pending.push_back( t );
+            d_pending_exp[ t ] = NodeManager::currentNM()->mkConst( true );
+            Debug("datatypes-infer") << "DtInfer : " << t << ", trivial" << std::endl;
+            d_infer.push_back( t );
+          }else{
+            std::vector< bool > pcons;
+            getPossibleCons( eqc, n, pcons );
+            //std::cout << "pcons " << n << " = ";
+            //for( int i=0; i<(int)pcons.size(); i++ ){ //std::cout << pcons[i] << " "; }
+            //std::cout << std::endl;
+            //check if we do not need to resolve the constructor type for this equivalence class.
+            // this is if there are no selectors for this equivalence class, its type is infinite,
+            //  and we are not producing a model, then do not split.
+            int consIndex = -1;
+            bool needSplit = true;
+            for( unsigned int j=0; j<pcons.size(); j++ ) {
+              if( pcons[j] ) {
+                if( consIndex==-1 ){
+                  consIndex = j;
+                }
+                if( !dt[ j ].isFinite() && !eqc->d_selectors ) {//&& !Options::current()->produceModels && !Options::current()->finiteModelFind ){
+                  needSplit = false;
+                }
+              }
+            }
+            if( needSplit && consIndex!=-1 ) {
+              Node test = NodeManager::currentNM()->mkNode( APPLY_TESTER, Node::fromExpr( dt[consIndex].getTester() ), n );
+              Debug("datatypes-split") << "*************Split for possible constructor " << test << " for " << n <<  endl;
+              NodeBuilder<> nb(kind::OR);
+              nb << test << test.notNode();
+              Node lemma = nb;
+              d_out->lemma( lemma );
+              d_out->requirePhase( test, true );
+              return;
+            }else{
+              Debug("datatypes-split") << "Do not split constructor for " << n << std::endl;
+            }
+          }
+        }
+      }
+      ++eqcs_i;
     }
-  }
-  //else{
-  //  checkCycles();
-  //  if( hasConflict() ){
-  //    for( int i=0; i<(int)d_currEqualities.size(); i++ ) {
-  //      Debug("datatypes-cycles") << "currEqualities[" << i << "] = " << d_currEqualities[i] << endl;
-  //    }
-  //    d_cycle_check.debugPrint();
-  //    Assert( false );
-  //  }
-  //}
-  Debug("datatypes-debug") << "Done cycles" << endl;
-
-  //merge equivalence classes
-  initializeEqClass( b );
-  EqListN* eqc_b = (*d_equivalence_class.find( b )).second;
-  EqListsN::iterator eqc_a_i = d_equivalence_class.find( a );
-  if( eqc_a_i!=d_equivalence_class.end() ){
-    EqListN* eqc_a = (*eqc_a_i).second;
-    for( EqListN::const_iterator i = eqc_a->begin(); i != eqc_a->end(); i++ ) {
-      eqc_b->push_back( *i );
+    flushPendingFacts();
+    if( !d_conflict ){
+      printModelDebug();
     }
-  }else{
-    eqc_b->push_back( a );
   }
-  //merge selector lists
-  EqListsN::iterator sel_a_i = d_selector_eq.find( a );
-  if( sel_a_i != d_selector_eq.end() ) {
-    EqListsN::iterator sel_b_i = d_selector_eq.find( b );
-    EqListN* sel_b;
-    if( sel_b_i == d_selector_eq.end() ) {
-      sel_b = new(getSatContext()->getCMM()) EqListN(true, getSatContext(), false,
-                                          ContextMemoryAllocator<Node>(getSatContext()->getCMM()));
-      d_selector_eq.insertDataFromContextMemory(b, sel_b);
-    } else {
-      sel_b = (*sel_b_i).second;
-    }
-    EqListN* sel_a = (*sel_a_i).second;
-    for( EqListN::const_iterator i = sel_a->begin(); i != sel_a->end(); i++ ) {
-      sel_b->push_back( *i );
-    }
-    if( !sel_a->empty() ){
-      d_checkMap[ b ] = true;
-    }
+  if( Debug.isOn("datatypes") || Debug.isOn("datatypes-split") ) {
+    Notice() << "TheoryDatatypes::check(): done" << endl;
   }
+}
 
-  deq_ia = d_disequalities.find(a);
-  map<TNode, TNode> alreadyDiseqs;
-  if(deq_ia != d_disequalities.end()) {
-    /*
-     * Collecting the disequalities of b, no need to check for conflicts
-     * since the representative of b does not change and we check all the things
-     * in a's class when we look at the diseq list of find(a)
-     */
-    EqLists::iterator deq_ib = d_disequalities.find(b);
-    if(deq_ib != d_disequalities.end()) {
-      EqList* deq = (*deq_ib).second;
-      for(EqList::const_iterator j = deq->begin(); j != deq->end(); j++) {
-        TNode deqn = *j;
-        TNode s = deqn[0];
-        TNode t = deqn[1];
-        TNode sp = find(s);
-        TNode tp = find(t);
-        Assert(sp == b || tp == b, "test1");
-        if(sp == b) {
-          alreadyDiseqs[tp] = deqn;
-        } else {
-          alreadyDiseqs[sp] = deqn;
-        }
-      }
-    }
-
-    /*
-     * Looking for conflicts in the a disequality list. Note
-     * that at this point a and b are already merged. Also has
-     * the side effect that it adds them to the list of b (which
-     * became the canonical representative)
-     */
-    EqList* deqa = (*deq_ia).second;
-    for(EqList::const_iterator i = deqa->begin(); i != deqa->end(); i++) {
-      TNode deqn = (*i);
-      Assert(deqn.getKind() == kind::EQUAL || deqn.getKind() == kind::IFF);
-      TNode s = deqn[0];
-      TNode t = deqn[1];
-
-      TNode sp = find(s);
-      TNode tp = find(t);
-      if(sp == tp) {
-        Debug("datatypes") << "Construct standard conflict " << deqn << " " << sp << endl;
-        d_em.addNode( deqn, &d_cce );
-        d_em.addNodeConflict( NodeManager::currentNM()->mkNode( kind::AND, deqn, deqn.notNode() ), Reason::contradiction );
-        return;
-      }
-      Assert( sp == b || tp == b, "test2");
-
-      // make sure not to add duplicates
-      if(sp == b) {
-        if(alreadyDiseqs.find(tp) == alreadyDiseqs.end()) {
-          appendToDiseqList(b, deqn);
-          alreadyDiseqs[tp] = deqn;
-        }
-      } else {
-        if(alreadyDiseqs.find(sp) == alreadyDiseqs.end()) {
-          appendToDiseqList(b, deqn);
-          alreadyDiseqs[sp] = deqn;
-        }
-      }
-
-    }
+void TheoryDatatypes::assertFact( Node fact, Node exp ){
+  Assert( d_pending_merge.empty() );
+  bool polarity = fact.getKind() != kind::NOT;
+  TNode atom = polarity ? fact : fact[0];
+  if (atom.getKind() == kind::EQUAL) {
+    d_equalityEngine.assertEquality( atom, polarity, exp );
+  }else{
+    d_equalityEngine.assertPredicate( atom, polarity, exp );
+  }
+  //do all pending merges
+  int i=0;
+  while( i<(int)d_pending_merge.size() ){
+    Assert( d_pending_merge[i].getKind()==EQUAL || d_pending_merge[i].getKind()==IFF );
+    merge( d_pending_merge[i][0], d_pending_merge[i][1] );
+    i++;
+  }
+  d_pending_merge.clear();
+  //add to tester if applicable
+  if( atom.getKind()==kind::APPLY_TESTER ){
+    Node rep = getRepresentative( atom[0] );
+    EqcInfo* eqc = getOrMakeEqcInfo( rep, true );
+    addTester( fact, eqc, rep );
   }
+}
 
-  //merge labels
-  EqLists::iterator lbl_i = d_labels.find( a );
-  if(lbl_i != d_labels.end()) {
-    EqList* lbl = (*lbl_i).second;
-    for( EqList::const_iterator i = lbl->begin(); i != lbl->end(); i++ ) {
-      addTester( *i );
-      if( hasConflict() ) {
-        return;
-      }
-    }
+void TheoryDatatypes::flushPendingFacts(){
+  //also assert the pending facts
+  int i = 0;
+  while( !d_conflict && i<(int)d_pending.size() ){
+    assertFact( d_pending[i], d_pending_exp[ d_pending[i] ] );
+    i++;
   }
-  Debug("datatypes-debug") << "Done merge labels" << endl;
+  d_pending.clear();
+  d_pending_exp.clear();
+}
 
-  //do unification
-  if( a.getKind() == APPLY_CONSTRUCTOR && b.getKind() == APPLY_CONSTRUCTOR &&
-      a.getOperator() == b.getOperator() ) {
-    Debug("datatypes") << "Unification: " << a << " and " << b << "." << endl;
-    for( int i=0; i<(int)a.getNumChildren(); i++ ) {
-      if( find( a[i] ) != find( b[i] ) ) {
-        Node ccEq = NodeManager::currentNM()->mkNode( EQUAL, a, b );
-        Node newEq = NodeManager::currentNM()->mkNode( EQUAL, a[i], b[i] );
-        d_em.addNode( ccEq, &d_cce );
-        d_em.addNode( newEq, ccEq, Reason::idt_unify );
-        addEquality( newEq );
-        if( hasConflict() ) {
-          return;
-        }
-      }
+void TheoryDatatypes::preRegisterTerm(TNode n) {
+  Debug("datatypes-prereg") << "TheoryDatatypes::preRegisterTerm() " << n << endl;
+  collectTerms( n );
+  switch (n.getKind()) {
+  case kind::EQUAL:
+    // Add the trigger for equality
+    d_equalityEngine.addTriggerEquality(n);
+    break;
+  case kind::APPLY_TESTER:
+    // Get triggered for both equal and dis-equal
+    d_equalityEngine.addTriggerPredicate(n);
+    break;
+  default:
+    // Maybe it's a predicate
+    if (n.getType().isBoolean()) {
+      // Get triggered for both equal and dis-equal
+      d_equalityEngine.addTriggerPredicate(n);
+    } else {
+      // Function applications/predicates
+      d_equalityEngine.addTerm(n);
     }
+    break;
   }
+  Assert( d_pending.empty() );
+}
 
-  Debug("datatypes-debug") << "merge(): Done" << endl;
+void TheoryDatatypes::presolve() {
+  Debug("datatypes") << "TheoryDatatypes::presolve()" << endl;
 }
 
-void TheoryDatatypes::addTermToLabels( Node t ) {
-  if( t.getType().isDatatype() ) {
-    Debug("datatypes-debug") << "Add term to labels " << t << std::endl;
-    Node tmp = find( t );
-    if( tmp == t ) {
-      //add to labels
-      EqLists::iterator lbl_i = d_labels.find(t);
-      if(lbl_i == d_labels.end()) {
-        EqList* lbl = new(getSatContext()->getCMM()) EqList(true, getSatContext(), false,
-                                                ContextMemoryAllocator<TNode>(getSatContext()->getCMM()));
-        //if there is only one constructor, then it must be
-        const Datatype& dt = ((DatatypeType)(t.getType()).toType()).getDatatype();
-        if( dt.getNumConstructors()==1 ){
-          Node tester = NodeManager::currentNM()->mkNode( APPLY_TESTER, Node::fromExpr( dt[0].getTester() ), t );
-          lbl->push_back( tester );
-          d_checkMap[ t ] = true;
-          d_em.addNodeAxiom( tester, Reason::idt_texhaust );
-        }
-        d_labels.insertDataFromContextMemory(tmp, lbl);
-      }
-    }
-  }
+void TheoryDatatypes::addSharedTerm(TNode t) {
+  Debug("datatypes") << "TheoryDatatypes::addSharedTerm(): "
+                     << t << endl;
 }
 
-void TheoryDatatypes::initializeEqClass( Node t ) {
-  EqListsN::iterator eqc_i = d_equivalence_class.find( t );
-  if( eqc_i == d_equivalence_class.end() ) {
-    EqListN* eqc = new(getSatContext()->getCMM()) EqListN(true, getSatContext(), false,
-                                          ContextMemoryAllocator<Node>(getSatContext()->getCMM()));
-    eqc->push_back( t );
-    d_equivalence_class.insertDataFromContextMemory(t, eqc);
-  }
+void TheoryDatatypes::collectModelInfo( TheoryModel* m ){
+  printModelDebug();
+  m->assertEqualityEngine( &d_equalityEngine );
 }
 
-void TheoryDatatypes::collectTerms( Node n, bool recurse ) {
-  if( recurse ){
-    for( int i=0; i<(int)n.getNumChildren(); i++ ) {
-      collectTerms( n[i] );
-    }
+
+void TheoryDatatypes::collectTerms( Node n ) {
+  for( int i=0; i<(int)n.getNumChildren(); i++ ) {
+    collectTerms( n[i] );
   }
   if( n.getKind() == APPLY_CONSTRUCTOR ){
     for( int i=0; i<(int)n.getNumChildren(); i++ ) {
-      Debug("datatypes-cycles") << "Subterm " << n << " -> " << n[i] << endl;
-      bool result CVC4_UNUSED = d_cycle_check.addEdgeNode( n, n[i] );
-      Assert( !result );    //this should not create any new cycles (relevant terms should have been recorded before)
+      Debug("datatypes-cycles") << "DtCyc: Subterm " << n << " -> " << n[i] << endl;
+      bool result = d_cycle_check.addEdgeNode( n, n[i] );
+      d_hasSeenCycle.set( d_hasSeenCycle.get() || result );
+    }
+  }else if( n.getKind() == APPLY_SELECTOR ){
+    Debug("datatypes") << "  Found selector " << n << endl;
+    if (n.getType().isBoolean()) {
+      d_equalityEngine.addTriggerPredicate( n );
+    }else{
+      d_equalityEngine.addTerm( n );
     }
-  }else{
-    if( n.getKind() == APPLY_SELECTOR && d_selectors.find( n ) == d_selectors.end() ) {
-      Debug("datatypes") << "  Found selector " << n << endl;
-      d_selectors[ n ] = false;
-      d_cc.addTerm( n );
-      Node tmp = find( n[0] );
-      d_checkMap[ tmp ] = true;
-
-      //add selector to selector eq list
-      Debug("datatypes") << "  Add selector to list " << tmp << " " << n << endl;
-      EqListsN::iterator sel_i = d_selector_eq.find( tmp );
-      EqListN* sel;
-      if( sel_i == d_selector_eq.end() ) {
-        sel = new(getSatContext()->getCMM()) EqListN(true, getSatContext(), false,
-                                          ContextMemoryAllocator<Node>(getSatContext()->getCMM()));
-        d_selector_eq.insertDataFromContextMemory(tmp, sel);
-      } else {
-        sel = (*sel_i).second;
-      }
-      sel->push_back( n );
+    Node rep = getRepresentative( n[0] );
+    EqcInfo* eqc = getOrMakeEqcInfo( rep, true );
+    if( !eqc->d_selectors ){
+      eqc->d_selectors = true;
+      checkInstantiate( eqc, rep );
     }
-    addTermToLabels( n );
   }
 }
 
-void TheoryDatatypes::appendToDiseqList(TNode of, TNode eq) {
-  Debug("datatypes") << "appending " << eq << endl
-              << "  to diseq list of " << of << endl;
-  Assert(eq.getKind() == kind::EQUAL ||
-         eq.getKind() == kind::IFF);
-  Assert(of == debugFind(of));
-  EqLists::iterator deq_i = d_disequalities.find(of);
-  EqList* deq;
-  if(deq_i == d_disequalities.end()) {
-    deq = new(getSatContext()->getCMM()) EqList(true, getSatContext(), false,
-                                             ContextMemoryAllocator<TNode>(getSatContext()->getCMM()));
-    d_disequalities.insertDataFromContextMemory(of, deq);
-  } else {
-    deq = (*deq_i).second;
-  }
-  deq->push_back(eq);
-  //if(Debug.isOn("uf")) {
-  //  Debug("uf") << "  size is now " << deq->size() << endl;
-  //}
+Node TheoryDatatypes::getInstantiateCons( Node n, const Datatype& dt, int index ){
+  //add constructor to equivalence class
+  std::vector< Node > children;
+  children.push_back( Node::fromExpr( dt[index].getConstructor() ) );
+  for( int i=0; i<(int)dt[index].getNumArgs(); i++ ){
+    children.push_back( NodeManager::currentNM()->mkNode( APPLY_SELECTOR, Node::fromExpr( dt[index][i].getSelector() ), n ) );
+  }
+  Node n_ic = NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, children );
+  collectTerms( n_ic );
+  //add type ascription for ambiguous constructor types
+  if( n_ic.getType()!=n.getType() ){
+    Assert( dt.isParametric() );
+    Debug("datatypes-parametric") << "DtInstantiate: ambiguous type for " << n_ic << ", ascribe to " << n.getType() << std::endl;
+    Debug("datatypes-parametric") << "Constructor is " << dt[index] << std::endl;
+    Type tspec = dt[index].getSpecializedConstructorType(n.getType().toType());
+    Debug("datatypes-parametric") << "Type specification is " << tspec << std::endl;
+    children[0] = NodeManager::currentNM()->mkNode(kind::APPLY_TYPE_ASCRIPTION,
+                                                   NodeManager::currentNM()->mkConst(AscriptionType(tspec)), children[0] );
+    n_ic = NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, children );
+    Assert( n_ic.getType()==n.getType() );
+  }
+  return n_ic;
 }
 
-void TheoryDatatypes::addEquality(TNode eq) {
-  Assert(eq.getKind() == kind::EQUAL ||
-         eq.getKind() == kind::IFF);
-  if( !hasConflict() && find( eq[0] ) != find( eq[1] ) ) {
-    Debug("datatypes") << "Add equality " << eq << "." << endl;
-    Debug("datatypes-debug-pf") << "Add equality " << eq << "." << endl;
-#if 1    //for delayed merging
-    //setup merge pending list
-    d_merge_pending.push_back( vector< pair< Node, Node > >() );
-
-    d_cce.assertTrue(eq);
-    d_cc.addTerm(eq[0]);
-    d_cc.addTerm(eq[1]);
-
-    //record which nodes are waiting to be merged
-    vector< pair< Node, Node > > mp;
-    mp.insert( mp.begin(),
-               d_merge_pending[d_merge_pending.size()-1].begin(),
-               d_merge_pending[d_merge_pending.size()-1].end() );
-    d_merge_pending.pop_back();
-
-    //merge original nodes
-    if( !hasConflict() ) {
-      merge( eq[0], eq[1] );
+void TheoryDatatypes::checkInstantiate( EqcInfo* eqc, Node n ){
+  //add constructor to equivalence class if not done so already
+  if( hasLabel( eqc, n ) && eqc->d_inst.get().isNull() ){
+    Node exp;
+    Node tt;
+    if( !eqc->d_constructor.get().isNull() ){
+      exp = NodeManager::currentNM()->mkConst( true );
+      tt = eqc->d_constructor;
     }else{
-      Debug("datatypes-debug-pf") << "Forget merge " << eq << std::endl;
-    }
-    //merge nodes waiting to be merged
-    for( int i=0; i<(int)mp.size(); i++ ) {
-      if( !hasConflict() ) {
-        merge( mp[i].first, mp[i].second );
-      }else{
-        Debug("datatypes-debug-pf") << "Forget merge " << mp[i].first << " " << mp[i].second << std::endl;
+      exp = getLabel( n );
+      tt = exp[0];
+    }
+    int index = getLabelIndex( eqc, n );
+    const Datatype& dt = ((DatatypeType)(tt.getType()).toType()).getDatatype();
+    //must be finite or have a selector
+    if( eqc->d_selectors || dt[ index ].isFinite() ){
+      eqc->d_inst.set( NodeManager::currentNM()->mkConst( true ) );
+      Node tt_cons = getInstantiateCons( tt, dt, index );
+      Node eq;
+      if( tt!=tt_cons ){
+        eq = tt.eqNode( tt_cons );
+        Debug("datatypes-inst") << "DtInstantiate : " << eqc << " " << eq << std::endl;
+        d_pending.push_back( eq );
+        d_pending_exp[ eq ] = exp;
+        Debug("datatypes-infer") << "DtInfer : " << eq << " by " << exp << std::endl;
+        //eqc->d_inst.set( eq );
+        d_infer.push_back( eq );
+        d_infer_exp.push_back( exp );
       }
     }
-#elif 0
-    Debug("datatypes-ae") << "Add equality " << eq << "." << endl;
-    Debug("datatypes-ae") << "   Find is " << find( eq[0] ) << " = " << find( eq[1] ) << std::endl;
-    //merge original nodes
-    merge( eq[0], eq[1] );
-    d_cce.assertTrue(eq);
-    d_cc.addTerm(eq[0]);
-    d_cc.addTerm(eq[1]);
-#else
-    Debug("datatypes-ae") << "Add equality " << eq << "." << endl;
-    Debug("datatypes-ae") << "   Find is " << find( eq[0] ) << " = " << find( eq[1] ) << std::endl;
-    merge( eq[0], eq[1] );
-    if( !hasConflict() ){
-      d_cce.assertTrue(eq);
-      d_cc.addTerm(eq[0]);
-      d_cc.addTerm(eq[1]);
-    }
-#endif
-    if( Debug.isOn("datatypes") || Debug.isOn("datatypes-cycles") ){
-      d_currEqualities.push_back(eq);
-    }
   }
 }
 
-void TheoryDatatypes::addDisequality(TNode eq) {
-  Assert(eq.getKind() == kind::EQUAL ||
-         eq.getKind() == kind::IFF);
-
-  TNode a = eq[0];
-  TNode b = eq[1];
-
-  appendToDiseqList(find(a), eq);
-  appendToDiseqList(find(b), eq);
-}
-
 void TheoryDatatypes::checkCycles() {
-  for( BoolMap::iterator i = d_reps.begin(); i != d_reps.end(); i++ ) {
-    if( (*i).second ) {
-      map< Node, bool > visited;
-      NodeBuilder<> explanation(kind::AND);
-      if( searchForCycle( (*i).first, (*i).first, visited, explanation ) ) {
-        Node cCycle = explanation.getNumChildren() == 1 ? explanation.getChild( 0 ) : explanation;
-        d_em.addNodeConflict( cCycle, Reason::idt_cycle_coarse );
-        Debug("datatypes") << "Detected cycle for " << (*i).first << endl;
-        Debug("datatypes") << "Conflict is " << cCycle << endl;
-        return;
-      }
+  Debug("datatypes-cycle-check") << "Check cycles" << std::endl;
+  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &d_equalityEngine );
+  while( !eqcs_i.isFinished() ){
+    Node eqc = (*eqcs_i);
+    map< Node, bool > visited;
+    NodeBuilder<> explanation(kind::AND);
+    if( searchForCycle( eqc, eqc, visited, explanation ) ) {
+      d_conflictNode = explanation.getNumChildren() == 1 ? explanation.getChild( 0 ) : explanation;
+      Debug("datatypes-conflict") << "CONFLICT: Cycle conflict : " << d_conflictNode << std::endl;
+      d_out->conflict( d_conflictNode );
+      d_conflict = true;
+      return;
     }
+    ++eqcs_i;
   }
 }
 
@@ -1028,25 +717,28 @@ void TheoryDatatypes::checkCycles() {
 bool TheoryDatatypes::searchForCycle( Node n, Node on,
                                       map< Node, bool >& visited,
                                       NodeBuilder<>& explanation ) {
-  //Debug("datatypes") << "Search for cycle " << n << " " << on << endl;
-  if( n.getKind() == APPLY_CONSTRUCTOR ) {
-    for( int i=0; i<(int)n.getNumChildren(); i++ ) {
-      Node nn = find( n[i] );
-      if( visited.find( nn ) == visited.end() ) {
-        visited[nn] = true;
-        if( nn == on || searchForCycle( nn, on, visited, explanation ) ) {
-          if( Debug.isOn("datatypes-cycles") && !d_cycle_check.isConnectedNode( n, n[i] ) ){
-            Debug("datatypes-cycles") << "Cycle subterm: " << n << " is not -> " << n[i] << "!!!!" << std::endl;
-          }
-          if( nn != n[i] ) {
-            if( Debug.isOn("datatypes-cycles") && !d_cycle_check.isConnectedNode( n[i], nn ) ){
-              Debug("datatypes-cycles") << "Cycle equality: " << n[i] << " is not -> " << nn << "!!!!" << std::endl;
+  Debug("datatypes-cycle-check") << "Search for cycle " << n << " " << on << endl;
+  Node ncons;
+  EqcInfo* eqc = getOrMakeEqcInfo( n );
+  if( eqc ){
+    Node ncons = eqc->d_constructor.get();
+    if( !ncons.isNull() ) {
+      for( int i=0; i<(int)ncons.getNumChildren(); i++ ) {
+        Node nn = getRepresentative( ncons[i] );
+        if( visited.find( nn ) == visited.end() ) {
+          visited[nn] = true;
+          if( nn == on || searchForCycle( nn, on, visited, explanation ) ) {
+            if( Debug.isOn("datatypes-cycles") && !d_cycle_check.isConnectedNode( n, ncons[i] ) ){
+              Debug("datatypes-cycles") << "Cycle subterm: " << n << " is not -> " << ncons[i] << "!!!!" << std::endl;
+            }
+            if( nn != ncons[i] ) {
+              if( Debug.isOn("datatypes-cycles") && !d_cycle_check.isConnectedNode( ncons[i], nn ) ){
+                Debug("datatypes-cycles") << "Cycle equality: " << ncons[i] << " is not -> " << nn << "!!!!" << std::endl;
+              }
+              explanation << NodeManager::currentNM()->mkNode( EQUAL, nn, ncons[i] );
             }
-            Node ccEq = NodeManager::currentNM()->mkNode( EQUAL, nn, n[i] );
-            d_em.addNode( ccEq, &d_cce );
-            explanation << ccEq;
+            return true;
           }
-          return true;
         }
       }
     }
@@ -1055,62 +747,33 @@ bool TheoryDatatypes::searchForCycle( Node n, Node on,
 }
 
 bool TheoryDatatypes::hasTerm( Node a ){
-  return false;
+  return d_equalityEngine.hasTerm( a );
 }
 
 bool TheoryDatatypes::areEqual( Node a, Node b ){
-  Node ar = find( a );
-  Node br = find( b );
-  if( ar==br ){
+  if( a==b ){
     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 if( hasTerm( a ) && hasTerm( b ) ){
+    return d_equalityEngine.areEqual( a, b );
   }else{
     return false;
   }
 }
 
 bool TheoryDatatypes::areDisequal( Node a, Node b ){
-  Node ar = find( a );
-  Node br = find( b );
-  if( ar==br ){
+  if( a==b ){
     return false;
-  }else if( ar.getKind()==APPLY_CONSTRUCTOR && br.getKind()==APPLY_CONSTRUCTOR &&
-            ar.getOperator()!=br.getOperator() ){
-    return true;
+  }else if( hasTerm( a ) && hasTerm( b ) ){
+    return d_equalityEngine.areDisequal( a, b, false );
   }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 );
+  if( hasTerm( a ) ){
+    return d_equalityEngine.getRepresentative( a );
+  }else{
+    return a;
+  }
 }
-
index 80c20a7d9466207d0ffa785efef48dacd61754dc..6d9672f95f6f6c4e33144b574736ba72eb9565f6 100644 (file)
@@ -28,6 +28,7 @@
 #include "util/hash.h"
 #include "util/trans_closure.h"
 #include "theory/datatypes/explanation_manager.h"
+#include "theory/uf/equality_engine.h"
 
 #include <ext/hash_set>
 #include <iostream>
@@ -40,177 +41,192 @@ namespace datatypes {
 class InstantiatorTheoryDatatypes;
 class EqualityQueryTheory;
 
-namespace rrinst{
-  class CandidateGeneratorTheoryClass;
-}
-
 class TheoryDatatypes : public Theory {
   friend class InstantiatorTheoryDatatypes;
   friend class EqualityQueryTheory;
-  friend class rrinst::CandidateGeneratorTheoryClass;
-
 private:
-  typedef context::CDChunkList<TNode> EqList;
-  typedef context::CDHashMap<Node, EqList*, NodeHashFunction> EqLists;
-  typedef context::CDChunkList<Node> EqListN;
-  typedef context::CDHashMap<Node, EqListN*, NodeHashFunction> EqListsN;
+  typedef context::CDChunkList<Node> NodeList;
+  typedef context::CDHashMap<Node, NodeList*, NodeHashFunction> NodeListMap;
   typedef context::CDHashMap< Node, bool, NodeHashFunction > BoolMap;
 
-  /** for debugging */
-  context::CDList<Node> d_currAsserts;
-  context::CDList<Node> d_currEqualities;
-
-  /** keeps track of all selectors we care about, value is whether they have been collapsed */
-  BoolMap d_selectors;
-  /** keeps track of which nodes are representatives */
-  BoolMap d_reps;
-  /** map from (representative) nodes to a list of selectors whose arguments are
-      in the equivalence class of that node */
-  EqListsN d_selector_eq;
-  /** map from (representative) nodes to list of nodes in their eq class */
-  EqListsN d_equivalence_class;
-  /** map from nodes to whether they have been instantiated */
-  BoolMap d_inst_map;
   /** transitive closure to record equivalence/subterm relation.  */
   TransitiveClosureNode d_cycle_check;
   /** has seen cycle */
   context::CDO< bool > d_hasSeenCycle;
-  /** get the constructor for the node */
-  const DatatypeConstructor& getConstructor( Node cons );
-  /** get the constructor for the selector */
-  Node getConstructorForSelector( Node sel );
-
-  /**
-   * map from (representative) nodes to testers that hold for that node
-   * for each t, this is either a list of equations of the form
+  /** inferences */
+  NodeList d_infer;
+  NodeList d_infer_exp;
+private:
+  //notification class for equality engine
+  class NotifyClass : public eq::EqualityEngineNotify {
+    TheoryDatatypes& d_dt;
+  public:
+    NotifyClass(TheoryDatatypes& dt): d_dt(dt) {}
+    bool eqNotifyTriggerEquality(TNode equality, bool value) {
+      Debug("dt") << "NotifyClass::eqNotifyTriggerEquality(" << equality << ", " << (value ? "true" : "false" )<< ")" << std::endl;
+      if (value) {
+        return d_dt.propagate(equality);
+      } else {
+        // We use only literal triggers so taking not is safe
+        return d_dt.propagate(equality.notNode());
+      }
+    }
+    bool eqNotifyTriggerPredicate(TNode predicate, bool value) {
+      Debug("dt") << "NotifyClass::eqNotifyTriggerPredicate(" << predicate << ", " << (value ? "true" : "false") << ")" << std::endl;
+      if (value) {
+        return d_dt.propagate(predicate);
+      } else {
+       return d_dt.propagate(predicate.notNode());
+      }
+    }
+    bool eqNotifyTriggerTermEquality(TheoryId tag, TNode t1, TNode t2, bool value) {
+      Debug("dt") << "NotifyClass::eqNotifyTriggerTermMerge(" << tag << ", " << t1 << ", " << t2 << ")" << std::endl;
+      if (value) {
+        return d_dt.propagate(t1.eqNode(t2));
+      } else {
+        return d_dt.propagate(t1.eqNode(t2).notNode());
+      }
+    }
+    void eqNotifyConstantTermMerge(TNode t1, TNode t2) {
+      Debug("dt") << "NotifyClass::eqNotifyConstantTermMerge(" << t1 << ", " << t2 << ")" << std::endl;
+      d_dt.conflict(t1, t2);
+    }
+    void eqNotifyNewClass(TNode t) {
+      Debug("dt") << "NotifyClass::eqNotifyNewClass(" << t << std::endl;
+      d_dt.eqNotifyNewClass(t);
+    }
+    void eqNotifyPreMerge(TNode t1, TNode t2) {
+      Debug("dt") << "NotifyClass::eqNotifyPreMerge(" << t1 << ", " << t2 << std::endl;
+      d_dt.eqNotifyPreMerge(t1, t2);
+    }
+    void eqNotifyPostMerge(TNode t1, TNode t2) {
+      Debug("dt") << "NotifyClass::eqNotifyPostMerge(" << t1 << ", " << t2 << std::endl;
+      d_dt.eqNotifyPostMerge(t1, t2);
+    }
+    void eqNotifyDisequal(TNode t1, TNode t2, TNode reason) {
+      Debug("dt") << "NotifyClass::eqNotifyDisequal(" << t1 << ", " << t2 << ", " << reason << std::endl;
+      d_dt.eqNotifyDisequal(t1, t2, reason);
+    }
+  };/* class TheoryDatatypes::NotifyClass */
+private:
+  /** equivalence class info
+   * d_inst is whether the instantiate rule has been applied,
+   * d_constructor is a node of kind APPLY_CONSTRUCTOR (if any) in this equivalence class,
+   * d_selectors is whether a selector has been applied to this equivalence class.
+   */
+  class EqcInfo
+  {
+  public:
+    EqcInfo( context::Context* c );
+    ~EqcInfo(){}
+    //whether we have instantiatied this eqc
+    context::CDO< Node > d_inst;
+    //constructor equal to this eqc
+    context::CDO< Node > d_constructor;
+    //all selectors whose argument is this eqc
+    context::CDO< bool > d_selectors;
+  };
+  /** does eqc of n have a label? */
+  bool hasLabel( EqcInfo* eqc, Node n );
+  /** get the label associated to n */
+  Node getLabel( Node n );
+  /** get the index of the label associated to n */
+  int getLabelIndex( EqcInfo* eqc, Node n );
+  /** get the possible constructors for n */
+  void getPossibleCons( EqcInfo* eqc, Node n, std::vector< bool >& cons );
+private:
+  /** The notify class */
+  NotifyClass d_notify;
+  /** Equaltity engine */
+  eq::EqualityEngine d_equalityEngine;
+  /** information necessary for equivalence classes */
+  std::map< Node, EqcInfo* > d_eqc_info;
+  /** labels for each equivalence class
+   * for each eqc n, d_labels[n] is testers that hold for this equivalence class, either:
+   * a list of equations of the form
    *   NOT is_[constructor_1]( t )...NOT is_[constructor_n]( t ), each of which are unique testers
    *   and n is less than the number of possible constructors for t minus one,
    * or a list of equations of the form
    *   NOT is_[constructor_1]( t )...NOT is_[constructor_n]( t )  followed by
    *   is_[constructor_(n+1)]( t ), each of which is a unique tester.
-   */
-  EqLists d_labels;
-
-  class CongruenceChannel {
-    TheoryDatatypes* d_datatypes;
-
-  public:
-    CongruenceChannel(TheoryDatatypes* datatypes) : d_datatypes(datatypes) {}
-    void notifyCongruent(TNode a, TNode b) {
-      d_datatypes->notifyCongruent(a, b);
-    }
-  };/* class CongruenceChannel */
-  friend class CongruenceChannel;
-
-  /**
-   * Output channel connected to the congruence closure module.
-   */
-  CongruenceChannel d_ccChannel;
-
-  /**
-   * Instance of the congruence closure module.
-   */
-  CongruenceClosure<CongruenceChannel, CONGRUENCE_OPERATORS_2 (kind::APPLY_CONSTRUCTOR, kind::APPLY_SELECTOR)> d_cc;
-
-  /**
-   * Union find for storing the equalities.
-   */
-  UnionFind<Node, NodeHashFunction> d_unionFind;
-
-  /**
-   * Received a notification from the congruence closure algorithm that the two nodes
-   * a and b have been merged.
-   */
-  void notifyCongruent(TNode a, TNode b);
-
-  /**
-   * List of all disequalities this theory has seen.
-   * Maintaints the invariant that if a is in the
-   * disequality list of b, then b is in that of a.
-   * */
-  EqLists d_disequalities;
-
-  /**
-   * information for delayed merging (is this necessary?)
-   */
-  std::vector< std::vector< std::pair< Node, Node > > > d_merge_pending;
-
-  /**
-   * Terms that currently need to be checked for collapse/instantiation rules
-   */
-  std::map< Node, bool > d_checkMap;
-
-  /**
-   * explanation manager
-   */
-  ExplanationManager d_em;
-
-  /**
-   * explanation manager for the congruence closure module
-   */
-  CongruenceClosureExplainer<CongruenceChannel, CONGRUENCE_OPERATORS_2 (kind::APPLY_CONSTRUCTOR, kind::APPLY_SELECTOR)> d_cce;
-
-  //temporary
-  std::vector< Node > d_preRegTerms;
+  */
+  NodeListMap d_labels;
+  /** Are we in conflict */
+  context::CDO<bool> d_conflict;
+  /** The conflict node */
+  Node d_conflictNode;
+  /** pending assertions/merges */
+  std::vector< Node > d_pending;
+  std::map< Node, Node > d_pending_exp;
+  std::vector< Node > d_pending_merge;
+private:
+  /** assert fact */
+  void assertFact( Node fact, Node exp );
+  /** flush pending facts */
+  void flushPendingFacts();
+  /** get or make eqc info */
+  EqcInfo* getOrMakeEqcInfo( Node n, bool doMake = false );
+  /** has eqc info */
+  bool hasEqcInfo( Node n ) { return d_labels.find( n )!=d_labels.end(); }
 public:
-  TheoryDatatypes(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo, QuantifiersEngine* qe);
+  TheoryDatatypes(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation,
+                  const LogicInfo& logicInfo, QuantifiersEngine* qe);
   ~TheoryDatatypes();
+  /** propagate */
+  void propagate(Effort effort);
+  /** propagate */
+  bool propagate(TNode literal);
+  /** explain */
+  void explain( TNode literal, std::vector<TNode>& assumptions );
+  Node explain( TNode literal );
+  /** Conflict when merging two constants */
+  void conflict(TNode a, TNode b);
+  /** called when a new equivalance class is created */
+  void eqNotifyNewClass(TNode t);
+  /** called when two equivalance classes will merge */
+  void eqNotifyPreMerge(TNode t1, TNode t2);
+  /** called when two equivalance classes have merged */
+  void eqNotifyPostMerge(TNode t1, TNode t2);
+  /** called when two equivalence classes are made disequal */
+  void eqNotifyDisequal(TNode t1, TNode t2, TNode reason);
+
+  void check(Effort e);
   void preRegisterTerm(TNode n);
   void presolve();
-
   void addSharedTerm(TNode t);
-  void check(Effort e);
   void collectModelInfo( TheoryModel* m );
   void shutdown() { }
   std::string identify() const { return std::string("TheoryDatatypes"); }
-
 private:
-  /* Helper methods */
-  bool checkTester( Node assertion, Node& conflict, unsigned& r );
-  void addTester( Node assertion );
-  Node getInstantiateCons( Node t );
-  void checkInstantiateEqClass( Node t );
-  bool checkInstantiate( Node te, Node cons );
-  bool collapseSelector( Node t );
-  void updateSelectors( Node a );
-  void addTermToLabels( Node t );
-  void initializeEqClass( Node t );
-  void collectTerms( Node n, bool recurse = true );
-  bool hasConflict();
-
-  /* from uf_morgan */
-  void merge(TNode a, TNode b);
-  inline TNode find(TNode a);
-  inline TNode debugFind(TNode a) const;
-  void appendToDiseqList(TNode of, TNode eq);
-  void addDisequality(TNode eq);
-  void addEquality(TNode eq);
-
+  /** add tester to equivalence class info */
+  void addTester( Node t, EqcInfo* eqc, Node n );
+  /** merge the equivalence class info of t1 and t2 */
+  void merge( Node t1, Node t2 );
+  /** for checking if cycles exist */
   void checkCycles();
   bool searchForCycle( Node n, Node on,
                        std::map< Node, bool >& visited,
                        NodeBuilder<>& explanation );
-public:
+  /** collect terms */
+  void collectTerms( Node n );
+  /** get instantiate cons */
+  Node getInstantiateCons( Node n, const Datatype& dt, int index );
+  /** check instantiate */
+  void checkInstantiate( EqcInfo* eqc, Node n );
+  /** debug print */
+  void printModelDebug();
+
+private:
   //equality queries
   bool hasTerm( Node a );
   bool areEqual( Node a, Node b );
   bool areDisequal( Node a, Node b );
   Node getRepresentative( Node a );
+public:
+  /** get equality engine */
+  eq::EqualityEngine* getEqualityEngine() { return &d_equalityEngine; }
 };/* class TheoryDatatypes */
 
-inline bool TheoryDatatypes::hasConflict() {
-  return d_em.hasConflict();
-}
-
-inline TNode TheoryDatatypes::find(TNode a) {
-  return d_unionFind.find(a);
-}
-
-inline TNode TheoryDatatypes::debugFind(TNode a) const {
-  return d_unionFind.debugFind(a);
-}
-
-
 }/* CVC4::theory::datatypes namespace */
 }/* CVC4::theory namespace */
 }/* CVC4 namespace */
index 57e9324dff9c1644b27a75f1423511bc9d4d8901..b4b85c9fbd38ae503e2dde4372625bf98e8bb92e 100644 (file)
  **/
 
 #include "theory/datatypes/theory_datatypes_instantiator.h"
-#include "theory/datatypes/theory_datatypes_candidate_generator.h"
 #include "theory/datatypes/theory_datatypes.h"
 #include "theory/theory_engine.h"
 #include "theory/quantifiers/term_database.h"
+#include "theory/rr_candidate_generator.h"
 
 using namespace std;
 using namespace CVC4;
@@ -55,6 +55,7 @@ int InstantiatorTheoryDatatypes::process( Node f, Theory::Effort effort, int e )
     if( e<2 ){
       return InstStrategy::STATUS_UNFINISHED;
     }else if( e==2 ){
+      /*
       InstMatch m;
       for( int j = 0; j<(int)d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); j++ ){
         Node i = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );
@@ -65,12 +66,15 @@ int InstantiatorTheoryDatatypes::process( Node f, Theory::Effort effort, int e )
         }
       }
       d_quantEngine->addInstantiation( f, m );
+      */
     }
   }
   return InstStrategy::STATUS_UNKNOWN;
 }
 
 Node InstantiatorTheoryDatatypes::getValueFor( Node n ){
+  return n;
+  /*  FIXME
   //simply get the ground value for n in the current model, if it exists,
   //  or return an arbitrary ground term otherwise
   Debug("quant-datatypes-debug")  << "get value for " << n << std::endl;
@@ -142,6 +146,7 @@ Node InstantiatorTheoryDatatypes::getValueFor( Node n ){
       }
     }
   }
+  */
 }
 
 InstantiatorTheoryDatatypes::Statistics::Statistics():
@@ -155,22 +160,57 @@ InstantiatorTheoryDatatypes::Statistics::~Statistics(){
 }
 
 bool InstantiatorTheoryDatatypes::hasTerm( Node a ){
-  return ((TheoryDatatypes*)d_th)->hasTerm( a );
+  return ((TheoryDatatypes*)d_th)->getEqualityEngine()->hasTerm( a );
 }
 
 bool InstantiatorTheoryDatatypes::areEqual( Node a, Node b ){
-  return ((TheoryDatatypes*)d_th)->areEqual( a, b );
+  if( a==b ){
+    return true;
+  }else if( hasTerm( a ) && hasTerm( b ) ){
+    return ((TheoryDatatypes*)d_th)->getEqualityEngine()->areEqual( a, b );
+  }else{
+    return false;
+  }
 }
 
 bool InstantiatorTheoryDatatypes::areDisequal( Node a, Node b ){
-  return ((TheoryDatatypes*)d_th)->areDisequal( a, b );
+  if( a==b ){
+    return false;
+  }else if( hasTerm( a ) && hasTerm( b ) ){
+    return ((TheoryDatatypes*)d_th)->getEqualityEngine()->areDisequal( a, b, false );
+  }else{
+    return false;
+  }
 }
 
 Node InstantiatorTheoryDatatypes::getRepresentative( Node a ){
-  return ((TheoryDatatypes*)d_th)->getRepresentative( a );
+  if( hasTerm( a ) ){
+    return ((TheoryDatatypes*)d_th)->getEqualityEngine()->getRepresentative( a );
+  }else{
+    return a;
+  }
+}
+
+eq::EqualityEngine* InstantiatorTheoryDatatypes::getEqualityEngine(){
+  return &((TheoryDatatypes*)d_th)->d_equalityEngine;
+}
+
+void InstantiatorTheoryDatatypes::getEquivalenceClass( Node a, std::vector< Node >& eqc ){
+  if( hasTerm( a ) ){
+    a = getEqualityEngine()->getRepresentative( a );
+    eq::EqClassIterator eqc_iter( a, getEqualityEngine() );
+    while( !eqc_iter.isFinished() ){
+      if( std::find( eqc.begin(), eqc.end(), *eqc_iter )==eqc.end() ){
+        eqc.push_back( *eqc_iter );
+      }
+      eqc_iter++;
+    }
+  }
 }
 
 CVC4::theory::rrinst::CandidateGenerator* InstantiatorTheoryDatatypes::getRRCanGenClass(){
-  TheoryDatatypes* th = static_cast<TheoryDatatypes *>(getTheory());
-  return new datatypes::rrinst::CandidateGeneratorTheoryClass(th);
+  datatypes::TheoryDatatypes* dt = static_cast<datatypes::TheoryDatatypes*>(getTheory());
+  eq::EqualityEngine* ee =
+    static_cast<eq::EqualityEngine*>(dt->getEqualityEngine());
+  return new eq::rrinst::CandidateGeneratorTheoryEeClass(ee);
 }
index fd7190a220c7495500db0aaac472e76843fa8e6c..fe43f2cfce6ece23de4c12547a432f6dbdefe90c 100644 (file)
@@ -61,6 +61,8 @@ public:
   bool areEqual( Node a, Node b );
   bool areDisequal( Node a, Node b );
   Node getRepresentative( Node a );
+  eq::EqualityEngine* getEqualityEngine();
+  void getEquivalenceClass( Node a, std::vector< Node >& eqc );
     /** general creators of candidate generators */
   CVC4::theory::rrinst::CandidateGenerator* getRRCanGenClass();
 };/* class InstantiatiorTheoryDatatypes  */
index 4f1bfe67e8bebcd85ce257e7a32c3b0f5c3ddd9c..c90483fa3c0e9f6c9475e3e719404d4eb0acb7f0 100644 (file)
@@ -17,8 +17,8 @@
 #include "theory/inst_match.h"
 #include "theory/theory_engine.h"
 #include "theory/quantifiers_engine.h"
+#include "theory/candidate_generator.h"
 #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"
@@ -33,38 +33,6 @@ using namespace CVC4::theory;
 using namespace CVC4::theory::inst;
 
 
-bool CandidateGenerator::isLegalCandidate( Node n ){
-  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 ) {
-  if( isLegalCandidate( n ) ){
-    d_candidates.push_back( n );
-  }
-}
-
-void CandidateGeneratorQueue::reset( Node eqc ){
-  if( d_candidate_index>0 ){
-    d_candidates.erase( d_candidates.begin(), d_candidates.begin() + d_candidate_index );
-    d_candidate_index = 0;
-  }
-  if( !eqc.isNull() ){
-    d_candidates.push_back( eqc );
-  }
-}
-Node CandidateGeneratorQueue::getNextCandidate(){
-  if( d_candidate_index<(int)d_candidates.size() ){
-    Node n = d_candidates[d_candidate_index];
-    d_candidate_index++;
-    return n;
-  }else{
-    d_candidate_index = 0;
-    d_candidates.clear();
-    return Node::null();
-  }
-}
-
 InstMatch::InstMatch() {
 }
 
@@ -130,18 +98,21 @@ void InstMatch::debugPrint( const char* c ){
 
 void InstMatch::makeComplete( Node f, QuantifiersEngine* qe ){
   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] );
+    Node ic = qe->getTermDatabase()->d_inst_constants[f][i];
+    if( d_map.find( ic )==d_map.end() ){
+      d_map[ ic ] = qe->getTermDatabase()->getFreeVariableForInstConstant( ic );
     }
   }
 }
 
 void InstMatch::makeInternal( QuantifiersEngine* qe ){
-  for( std::map< Node, Node >::iterator it = d_map.begin(); it != d_map.end(); ++it ){
-    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->getTermDatabase()->getFreeVariableForInstConstant( it->first );
+  if( Options::current()->cbqi ){
+    for( std::map< Node, Node >::iterator it = d_map.begin(); it != d_map.end(); ++it ){
+      if( it->second.hasAttribute(InstConstantAttribute()) ){
+        d_map[ it->first ] = qe->getEqualityQuery()->getInternalRepresentative( it->second );
+        if( it->second.hasAttribute(InstConstantAttribute()) ){
+          d_map[ it->first ] = qe->getTermDatabase()->getFreeVariableForInstConstant( it->first );
+        }
       }
     }
   }
@@ -203,9 +174,9 @@ 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( ((uf::TheoryUF*)qe->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine()->getRepresentative( n ),
-                                ((uf::TheoryUF*)qe->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine() );
+      if( qe->getEqualityQuery()->getEngine()->hasTerm( n ) ){
+        eq::EqClassIterator eqc( qe->getEqualityQuery()->getEngine()->getRepresentative( n ),
+                                 qe->getEqualityQuery()->getEngine() );
         while( !eqc.isFinished() ){
           Node en = (*eqc);
           if( en!=n ){
@@ -310,10 +281,10 @@ void InstMatchGenerator::initializePattern( Node pat, QuantifiersEngine* qe ){
     //we will be producing candidates via literal matching heuristics
     if( d_pattern.getKind()!=NOT ){
       //candidates will be all equalities
-      d_cg = new uf::inst::CandidateGeneratorTheoryUfLitEq( ith, d_match_pattern );
+      d_cg = new inst::CandidateGeneratorQELitEq( qe, d_match_pattern );
     }else{
       //candidates will be all disequalities
-      d_cg = new uf::inst::CandidateGeneratorTheoryUfLitDeq( ith, d_match_pattern );
+      d_cg = new inst::CandidateGeneratorQELitDeq( qe, d_match_pattern );
     }
   }else if( d_pattern.getKind()==EQUAL || d_pattern.getKind()==IFF || d_pattern.getKind()==NOT ){
     Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
@@ -322,7 +293,7 @@ void InstMatchGenerator::initializePattern( Node pat, QuantifiersEngine* qe ){
     }else{
       Assert( Trigger::isAtomicTrigger( d_match_pattern ) );
       //we are matching only in a particular equivalence class
-      d_cg = new uf::inst::CandidateGeneratorTheoryUf( ith, d_match_pattern.getOperator() );
+      d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
       //store the equivalence class that we will call d_cg->reset( ... ) on
       d_eq_class = d_pattern[1];
     }
@@ -331,7 +302,7 @@ void InstMatchGenerator::initializePattern( Node pat, QuantifiersEngine* qe ){
       //Warning() << "Currently efficient e matching is not taken into account for quantifiers: " << d_pattern << std::endl;
     //}
     //we will be scanning lists trying to find d_match_pattern.getOperator()
-    d_cg = new uf::inst::CandidateGeneratorTheoryUf( ith, d_match_pattern.getOperator() );
+    d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
   }else{
     d_cg = new CandidateGeneratorQueue;
     if( !Trigger::getPatternArithmetic( d_match_pattern.getAttribute(InstConstantAttribute()), d_match_pattern, d_arith_coeffs ) ){
@@ -785,9 +756,9 @@ void InstMatchGeneratorMulti::processNewInstantiations( QuantifiersEngine* qe, I
       }
       if( modEq ){
         //check modulo equality for other possible instantiations
-        if( ((uf::TheoryUF*)qe->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine()->hasTerm( n ) ){
-          eq::EqClassIterator eqc( qe->getEqualityQuery()->getRepresentative( n ),
-                                  ((uf::TheoryUF*)qe->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine() );
+        if( qe->getEqualityQuery()->getEngine()->hasTerm( n ) ){
+          eq::EqClassIterator eqc( qe->getEqualityQuery()->getEngine()->getRepresentative( n ),
+                                   qe->getEqualityQuery()->getEngine() );
           while( !eqc.isFinished() ){
             Node en = (*eqc);
             if( en!=n ){
index 31a59b2612580e419de52786d43a96b17d68b24c..2b402779d3e8ba772bc11f47bbade9a9f96eaa6d 100644 (file)
 #ifndef __CVC4__INST_MATCH_H
 #define __CVC4__INST_MATCH_H
 
-#include "theory/theory.h"
 #include "util/hash.h"
 
 #include <ext/hash_set>
 #include <iostream>
 #include <map>
 
-#include "theory/uf/equality_engine.h"
-#include "theory/uf/theory_uf.h"
 #include "context/cdlist.h"
+#include "theory/candidate_generator.h"
 
 //#define USE_EFFICIENT_E_MATCHING
 
@@ -76,48 +74,6 @@ namespace uf{
 
 namespace inst {
 
-class CandidateGenerator
-{
-public:
-  CandidateGenerator(){}
-  ~CandidateGenerator(){}
-
-  /** Get candidates functions.  These set up a context to get all match candidates.
-      cg->reset( eqc );
-      do{
-        Node cand = cg->getNextCandidate();
-        //.......
-      }while( !cand.isNull() );
-
-      eqc is the equivalence class you are searching in
-  */
-  virtual void reset( Node eqc ) = 0;
-  virtual Node getNextCandidate() = 0;
-  /** add candidate to list of nodes returned by this generator */
-  virtual void addCandidate( Node n ) {}
-  /** call this at the beginning of each instantiation round */
-  virtual void resetInstantiationRound() = 0;
-public:
-  /** legal candidate */
-  static bool isLegalCandidate( Node n );
-};/* class CandidateGenerator */
-
-/** candidate generator queue (for manual candidate generation) */
-class CandidateGeneratorQueue : public CandidateGenerator {
-private:
-  std::vector< Node > d_candidates;
-  int d_candidate_index;
-public:
-  CandidateGeneratorQueue() : d_candidate_index( 0 ){}
-  ~CandidateGeneratorQueue(){}
-
-  void addCandidate( Node n );
-
-  void resetInstantiationRound(){}
-  void reset( Node eqc );
-  Node getNextCandidate();
-};/* class CandidateGeneratorQueue */
-
 class EqualityQuery {
 public:
   EqualityQuery(){}
@@ -135,6 +91,10 @@ public:
       not contain instantiation constants, if such a term exists.
    */
   virtual Node getInternalRepresentative( Node a ) = 0;
+  /** get the equality engine associated with this query */
+  virtual eq::EqualityEngine* getEngine() = 0;
+  /** get the equivalence class of a */
+  virtual void getEquivalenceClass( Node a, std::vector< Node >& eqc ) = 0;
 };/* class EqualityQuery */
 
 /** basic class defining an instantiation */
diff --git a/src/theory/inst_match_impl.h b/src/theory/inst_match_impl.h
deleted file mode 100644 (file)
index 8ac5fd3..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*********************                                                        */
-/*! \file inst_match_impl.h
- ** \verbatim
- ** Original author: bobot
- ** Major contributors: none
- ** Minor contributors (to current version): taking, mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012  The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief inst match class
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__INST_MATCH_IMPL_H
-#define __CVC4__INST_MATCH_IMPL_H
-
-#include "theory/inst_match.h"
-#include "theory/theory_engine.h"
-#include "theory/quantifiers_engine.h"
-#include "theory/uf/theory_uf_instantiator.h"
-#include "theory/uf/theory_uf_candidate_generator.h"
-#include "theory/uf/equality_engine.h"
-
-namespace CVC4 {
-namespace theory {
-
-template<bool modEq>
-InstMatchTrie2<modEq>::InstMatchTrie2(context::Context* c,  QuantifiersEngine* qe):
-  d_data(c->getLevel()), d_context(c), d_mods(c) {
-  d_eQ = qe->getEqualityQuery();
-  d_eE = ((uf::TheoryUF*)qe->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine();
-};
-
-/** add match m for quantifier f starting at index, take into account equalities q, return true if successful */
-template<bool modEq>
-void InstMatchTrie2<modEq>::addSubTree( Tree * root, mapIter current, mapIter end, size_t currLevel ) {
-  if( current == end ) return;
-
-  Assert(root->e.find(current->second) == root->e.end());
-  Tree * root2 = new Tree(currLevel);
-  root->e.insert(std::make_pair(current->second, root2));
-  addSubTree(root2, ++current, end, currLevel );
-}
-
-/** exists match */
-template<bool modEq>
-bool InstMatchTrie2<modEq>::existsInstMatch(InstMatchTrie2<modEq>::Tree * root,
-                                            mapIter & current, mapIter & end,
-                                            Tree * & e, mapIter & diverge) const{
-  if( current == end ) {
-    Debug("Trie2") << "Trie2 Bottom " << std::endl;
-    --current;
-    return true;
-  }; //Already their
-
-  if (current->first > diverge->first){
-    // this point is the deepest point currently seen map are ordered
-    e = root;
-    diverge = current;
-  };
-
-  TNode n = current->second;
-  typename InstMatchTrie2<modEq>::Tree::MLevel::iterator it =
-    root->e.find( n );
-  if( it!=root->e.end() &&
-      existsInstMatch( (*it).second, ++current, end, e, diverge) ){
-    Debug("Trie2") << "Trie2 Directly here " << n << std::endl;
-    --current;
-    return true;
-  }
-  Assert( it==root->e.end() || e != root );
-
-  // Even if n is in the trie others of the equivalence class
-  // can also be in it since the equality can have appeared
-  // after they have been added
-  if( modEq && d_eE->hasTerm( n ) ){
-    //check modulo equality if any other instantiation match exists
-    eq::EqClassIterator eqc( d_eQ->getRepresentative( n ), d_eE );
-    for( ;!eqc.isFinished();++eqc ){
-      TNode en = (*eqc);
-      if( en == n ) continue; // already tested
-      typename InstMatchTrie2<modEq>::Tree::MLevel::iterator itc =
-        root->e.find( en );
-      if( itc!=root->e.end() &&
-          existsInstMatch( (*itc).second, ++current, end, e, diverge) ){
-        Debug("Trie2") << "Trie2 Indirectly here by equality " << n << " = " << en << std::endl;
-        --current;
-        return true;
-      }
-      Assert( itc==root->e.end() || e != root );
-    }
-  }
-  --current;
-  return false;
-}
-
-template<bool modEq>
-bool InstMatchTrie2<modEq>::addInstMatch( InstMatch& m ) {
- mapIter begin = m.d_map.begin();
- mapIter end = m.d_map.end();
- typename InstMatchTrie2<modEq>::Tree * e = &d_data;
- mapIter diverge = begin;
- if( !existsInstMatch(e, begin, end, e, diverge ) ){
-   Assert(!diverge->second.isNull());
-   size_t currLevel = d_context->getLevel();
-   addSubTree( e, diverge, end, currLevel );
-   if(e->level != currLevel)
-     //If same level that e, will be removed at the same time than e
-     d_mods.push_back(std::make_pair(e,diverge->second));
-   return true;
- }else{
-   return false;
- }
-}
-
-}/* CVC4::theory namespace */
-
-}/* CVC4 namespace */
-
-#endif /*  __CVC4__INST_MATCH_IMPL_H */
index 609275a98a4d9bb3e8aa44e355f0cf77c75a623d..aa2c2d938edbf41a6ab752fbb0f663984588d3e4 100644 (file)
@@ -17,6 +17,8 @@
 #include "theory/model.h"\r
 #include "theory/quantifiers_engine.h"\r
 #include "theory/theory_engine.h"\r
+#include "util/datatype.h"\r
+#include "theory/uf/theory_uf_model.h"\r
 \r
 using namespace std;\r
 using namespace CVC4;\r
@@ -72,6 +74,11 @@ d_equalityEngine( c, name ){
   d_false = NodeManager::currentNM()->mkConst( false );\r
 }\r
 \r
+void TheoryModel::reset(){\r
+  d_reps.clear();\r
+  d_rep_set.clear();\r
+}\r
+\r
 void TheoryModel::addDefineFunction( Node n ){\r
   d_define_funcs.push_back( n );\r
   d_defines.push_back( 0 );\r
@@ -84,31 +91,32 @@ void TheoryModel::addDefineType( TypeNode tn ){
 \r
 void TheoryModel::toStreamFunction( Node n, std::ostream& out ){\r
   out << "(" << n;\r
-  //out << " : " << n.getType();\r
+  out << " : " << n.getType();\r
   out << " ";\r
   Node value = getValue( n );\r
+  /*\r
   if( n.getType().isSort() ){\r
-    int index = d_ra.getIndexFor( value );\r
+    int index = d_rep_set.getIndexFor( value );\r
     if( index!=-1 ){\r
       out << value.getType() << "_" << index;\r
     }else{\r
       out << value;\r
     }\r
   }else{\r
-    out << value;\r
-  }\r
+  */\r
+  out << value;\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
+    if( d_rep_set.d_type_reps.find( tn )!=d_rep_set.d_type_reps.end() ){\r
+      out << " " << d_rep_set.d_type_reps[tn].size();\r
       //out << " (";\r
-      //for( size_t i=0; i<d_ra.d_type_reps[tn].size(); i++ ){\r
+      //for( size_t i=0; i<d_rep_set.d_type_reps[tn].size(); i++ ){\r
       //  if( i>0 ){ out << " "; }\r
-      //  out << d_ra.d_type_reps[tn][i];\r
+      //  out << d_rep_set.d_type_reps[tn][i];\r
       //}\r
       //out << ")";\r
     }\r
@@ -117,6 +125,22 @@ void TheoryModel::toStreamType( TypeNode tn, std::ostream& out ){
 }\r
 \r
 void TheoryModel::toStream( std::ostream& out ){\r
+  /*//for debugging\r
+  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &d_equalityEngine );\r
+  while( !eqcs_i.isFinished() ){\r
+    Node eqc = (*eqcs_i);\r
+    Debug("get-model-debug") << eqc << " : " << eqc.getType() << " : " << std::endl;\r
+    out << "   ";\r
+    //add terms to model\r
+    eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &d_equalityEngine );\r
+    while( !eqc_i.isFinished() ){\r
+      out << (*eqc_i) << " ";\r
+      ++eqc_i;\r
+    }\r
+    out << std::endl;\r
+    ++eqcs_i;\r
+  }\r
+  */\r
   int funcIndex = 0;\r
   int typeIndex = 0;\r
   for( size_t i=0; i<d_defines.size(); i++ ){\r
@@ -178,22 +202,14 @@ Node TheoryModel::getValue( TNode n ){
     //otherwise, get the interpreted value in the model\r
     return getInterpretedValue( nn );\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
+  if( d_rep_set.d_type_reps.find( tn )!=d_rep_set.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
+    for( size_t i=0; i<d_rep_set.d_type_reps[tn].size(); i++ ){\r
+      if( std::find( exclude.begin(), exclude.end(), d_rep_set.d_type_reps[tn][i] )==exclude.end() ){\r
+        return d_rep_set.d_type_reps[tn][i];\r
       }\r
     }\r
   }\r
@@ -203,10 +219,10 @@ Node TheoryModel::getDomainValue( TypeNode tn, std::vector< Node >& exclude ){
 //FIXME: use the theory enumerator to generate constants here\r
 Node TheoryModel::getNewDomainValue( TypeNode tn ){\r
   if( tn==NodeManager::currentNM()->booleanType() ){\r
-    if( d_ra.d_type_reps[tn].empty() ){\r
+    if( d_rep_set.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 if( d_rep_set.d_type_reps[tn].size()==1 ){\r
+      return NodeManager::currentNM()->mkConst( areEqual( d_rep_set.d_type_reps[tn][0], d_false ) );\r
     }else{\r
       return Node::null();\r
     }\r
@@ -214,7 +230,7 @@ Node TheoryModel::getNewDomainValue( TypeNode tn ){
     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
+      if( std::find( d_rep_set.d_type_reps[tn].begin(), d_rep_set.d_type_reps[tn].end(), r )==d_rep_set.d_type_reps[tn].end() &&\r
           !d_equalityEngine.hasTerm( r ) ){\r
         return r;\r
       }\r
@@ -272,7 +288,8 @@ bool TheoryModel::hasTerm( Node a ){
 \r
 Node TheoryModel::getRepresentative( Node a ){\r
   if( d_equalityEngine.hasTerm( a ) ){\r
-    return d_reps[ d_equalityEngine.getRepresentative( a ) ];\r
+    Node r = d_equalityEngine.getRepresentative( a );\r
+    return d_reps[ r ];\r
   }else{\r
     return a;\r
   }\r
@@ -326,15 +343,49 @@ void TheoryModel::printRepresentative( std::ostream& out, Node r ){
   }\r
 }\r
 \r
-DefaultModel::DefaultModel( context::Context* c, std::string name ) : TheoryModel( c, name ){\r
+DefaultModel::DefaultModel( context::Context* c, std::string name, bool enableFuncModels ) :\r
+TheoryModel( c, name ), d_enableFuncModels( enableFuncModels ){\r
+\r
+}\r
+\r
+void DefaultModel::addTerm( Node n ){\r
+  //must collect UF terms\r
+  if( d_enableFuncModels && n.getKind()==APPLY_UF ){\r
+    d_uf_terms[ n.getOperator() ].push_back( n );\r
+  }\r
+}\r
 \r
+void DefaultModel::reset(){\r
+  d_uf_terms.clear();\r
+  d_uf_models.clear();\r
+  TheoryModel::reset();\r
 }\r
 \r
 Node DefaultModel::getInterpretedValue( TNode n ){\r
   TypeNode type = n.getType();\r
   if( type.isFunction() || type.isPredicate() ){\r
-    //DO_THIS?\r
-    return n;\r
+    //for function models\r
+    if( d_enableFuncModels ){\r
+      if( d_uf_models.find( n )==d_uf_models.end() ){\r
+        uf::UfModelTree ufmt( n );\r
+        Node default_v;\r
+        for( size_t i=0; i<d_uf_terms[n].size(); i++ ){\r
+          Node un = d_uf_terms[n][i];\r
+          Node v = getRepresentative( un );\r
+          ufmt.setValue( this, un, v );\r
+          default_v = v;\r
+        }\r
+        if( default_v.isNull() ){\r
+          default_v = getInterpretedValue( NodeManager::currentNM()->mkVar( type.getRangeType() ) );\r
+        }\r
+        ufmt.setDefaultValue( this, default_v );\r
+        ufmt.simplify();\r
+        d_uf_models[n] = ufmt.getFunctionValue();\r
+      }\r
+      return d_uf_models[n];\r
+    }else{\r
+      return n;\r
+    }\r
   }else{\r
     //first, see if the representative is defined\r
     if( d_equalityEngine.hasTerm( n ) ){\r
@@ -370,67 +421,195 @@ TheoryEngineModelBuilder::TheoryEngineModelBuilder( TheoryEngine* te ) : d_te( t
 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
+  tm->reset();\r
   //collect model info from the theory engine\r
+  Debug( "model-builder" ) << "TheoryEngineModelBuilder: Collect model info..." << std::endl;\r
   d_te->collectModelInfo( tm );\r
+  //unresolved equivalence classes\r
+  std::map< Node, bool > unresolved_eqc;\r
+  std::map< TypeNode, bool > unresolved_types;\r
+  std::map< Node, std::vector< Node > > selects;\r
+  std::map< Node, Node > apply_constructors;\r
   Debug( "model-builder" ) << "TheoryEngineModelBuilder: Build representatives..." << std::endl;\r
-  //populate term database, store representatives\r
+  //populate term database, store constant 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
+    TypeNode eqct = eqc.getType();\r
+    //initialize unresolved type information\r
+    initializeType( eqct, unresolved_types );\r
+    //add terms to model, get constant rep if possible\r
+    Node const_rep;\r
     eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &tm->d_equalityEngine );\r
     while( !eqc_i.isFinished() ){\r
-      tm->addTerm( *eqc_i );\r
+      Node n = *eqc_i;\r
+      //check if this is constant, if so, we will use it as representative\r
+      if( n.getMetaKind()==kind::metakind::CONSTANT ){\r
+        const_rep = n;\r
+      }\r
+      //theory-specific information needed\r
+      if( n.getKind()==SELECT ){\r
+        selects[ n[0] ].push_back( n );\r
+      }else if( n.getKind()==APPLY_CONSTRUCTOR ){\r
+        apply_constructors[ eqc ] = n;\r
+      }\r
+      //model-specific processing of the term, this will include\r
+      tm->addTerm( n );\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
+    if( !const_rep.isNull() ){\r
+      //Message() << "Constant rep " << const_rep << " for " << eqc << std::endl;\r
+      tm->d_reps[ eqc ] = const_rep;\r
+      tm->d_rep_set.add( const_rep );\r
+    }else{\r
+      //Message() << "** unresolved eqc " << eqc << std::endl;\r
+      unresolved_eqc[ eqc ] = true;\r
+      unresolved_types[ eqct ] = true;\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
+  //choose representatives for unresolved equivalence classes\r
+  Debug( "model-builder" ) << "TheoryEngineModelBuilder: Complete model..." << std::endl;\r
+  bool fixedPoint;\r
+  do{\r
+    fixedPoint = true;\r
+    //for calculating unresolved types\r
+    std::map< TypeNode, bool > unresolved_types_next;\r
+    for( std::map< TypeNode, bool >::iterator it = unresolved_types.begin(); it != unresolved_types.end(); ++it ){\r
+      unresolved_types_next[ it->first ] = false;\r
+    }\r
+    //try to resolve each unresolved equivalence class\r
+    for( std::map< Node, bool >::iterator it = unresolved_eqc.begin(); it != unresolved_eqc.end(); ++it ){\r
+      if( it->second ){\r
+        Node n = it->first;\r
+        TypeNode tn = n.getType();\r
+        Node rep;\r
+        bool mkRep = true;\r
+        if( tn.isArray() ){\r
+          TypeNode index_t = tn.getArrayIndexType();\r
+          TypeNode elem_t = tn.getArrayConstituentType();\r
+          if( !unresolved_types[ index_t ] && !unresolved_types[ elem_t ] ){\r
+            //collect all relevant set values of n\r
+            std::vector< Node > arr_selects;\r
+            std::vector< Node > arr_select_values;\r
+            Node nbase = n;\r
+            while( nbase.getKind()==STORE ){\r
+              arr_selects.push_back( tm->getRepresentative( nbase[1] ) );\r
+              arr_select_values.push_back( tm->getRepresentative( nbase[2] ) );\r
+              nbase = nbase[0];\r
+            }\r
+            eq::EqClassIterator eqc_i = eq::EqClassIterator( n, &tm->d_equalityEngine );\r
+            while( !eqc_i.isFinished() ){\r
+              for( int i=0; i<(int)selects[ *eqc_i ].size(); i++ ){\r
+                Node r = tm->getRepresentative( selects[ *eqc_i ][i][1] );\r
+                if( std::find( arr_selects.begin(), arr_selects.end(), r )==arr_selects.end() ){\r
+                  arr_selects.push_back( r );\r
+                  arr_select_values.push_back( tm->getRepresentative( selects[ *eqc_i ][i] ) );\r
+                }\r
+              }\r
+              ++eqc_i;\r
+            }\r
+            //now, construct based on select/value pairs\r
+            //TODO: make this a constant\r
+            rep = chooseRepresentative( tm, nbase );\r
+            for( int i=0; i<(int)arr_selects.size(); i++ ){\r
+              rep = NodeManager::currentNM()->mkNode( STORE, rep, arr_selects[i], arr_select_values[i] );\r
+            }\r
+          }\r
+          mkRep = false;\r
+        }else if( tn.isDatatype() ){\r
+          if( apply_constructors.find( n )!=apply_constructors.end() ){\r
+            Node ac = apply_constructors[n];\r
+            std::vector< Node > children;\r
+            children.push_back( ac.getOperator() );\r
+            for( size_t i = 0; i<ac.getNumChildren(); i++ ){\r
+              Node acir = ac[i];\r
+              if( tm->d_equalityEngine.hasTerm( acir ) ){\r
+                acir = tm->d_equalityEngine.getRepresentative( acir );\r
+              }\r
+              if( unresolved_eqc.find( acir )==unresolved_eqc.end() ){\r
+                Message() << "TheoryEngineModelBuilder::buildModel : Datatype argument does not exist in the model " << acir << std::endl;\r
+                acir = Node::null();\r
+              }\r
+              if( acir.isNull() || unresolved_eqc[ acir ] ){\r
+                mkRep = false;\r
+                break;\r
+              }else{\r
+                children.push_back( tm->getRepresentative( acir ) );\r
+              }\r
+            }\r
+            if( mkRep ){\r
+              rep = NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, children );\r
+            }\r
+          }else{\r
+            Message() << "TheoryEngineModelBuilder::buildModel : Do not know how to resolve datatype equivalence class " << n << std::endl;\r
+          }\r
+          mkRep = false;\r
+        }\r
+        if( mkRep ){\r
+          rep = chooseRepresentative( tm, n );\r
+        }\r
+        if( !rep.isNull() ){\r
+          tm->assertEquality( n, rep, true );\r
+          tm->d_reps[ n ] = rep;\r
+          tm->d_rep_set.add( rep );\r
+          unresolved_eqc[ n ] = false;\r
+          fixedPoint = false;\r
+        }else{\r
+          unresolved_types_next[ tn ] = true;\r
+        }\r
+      }\r
+    }\r
+    //for calculating unresolved types\r
+    for( std::map< TypeNode, bool >::iterator it = unresolved_types.begin(); it != unresolved_types.end(); ++it ){\r
+      unresolved_types[ it->first ] = unresolved_types_next[ it->first ];\r
+    }\r
+  }while( !fixedPoint );\r
+\r
+  //for all unresolved equivalence classes, just get new domain value\r
+  //  this should typically never happen (all equivalence classes should be resolved at this point)\r
+  for( std::map< Node, bool >::iterator it = unresolved_eqc.begin(); it != unresolved_eqc.end(); ++it ){\r
+    if( it->second ){\r
+      Node n = it->first;\r
+      Node rep = chooseRepresentative( tm, n );\r
+      tm->assertEquality( n, rep, true );\r
+      tm->d_reps[ n ] = rep;\r
+      tm->d_rep_set.add( rep );\r
+      //FIXME: Assertion failure here?\r
+      Message() << "Warning : Unresolved eqc, assigning " << rep << " for eqc( " << n << " ), type = " << n.getType() << std::endl;\r
+    }\r
+  }\r
+\r
+  //model-specific initialization\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
+void TheoryEngineModelBuilder::initializeType( TypeNode tn, std::map< TypeNode, bool >& unresolved_types ){\r
+  if( unresolved_types.find( tn )==unresolved_types.end() ){\r
+    unresolved_types[tn] = false;\r
+    if( tn.isArray() ){\r
+      initializeType( tn.getArrayIndexType(), unresolved_types );\r
+      initializeType( tn.getArrayConstituentType(), unresolved_types );\r
+    }else if( tn.isDatatype() ){\r
+      const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();\r
+      for( size_t i = 0; i<dt.getNumConstructors(); i++ ){\r
+        for( size_t j = 0; j<dt[i].getNumArgs(); j++ ){\r
+          initializeType( TypeNode::fromType( dt[i][j].getType() ), unresolved_types );\r
+        }\r
+      }\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 );\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
+Node TheoryEngineModelBuilder::chooseRepresentative( TheoryModel* m, Node eqc ){\r
+  //try to get a new domain value\r
+  Node rep = m->getNewDomainValue( eqc.getType() );\r
+  if( !rep.isNull() ){\r
+    return rep;\r
+  }else{\r
+    //if we can't get new domain value, just return eqc itself (this typically should not happen)\r
+    //FIXME: Assertion failure here?\r
+    return eqc;\r
   }\r
 }\r
index 278f85dfe86852dc5674e1fb8ce3ff22fe2fd49f..415b008ef7f150d6e14fa656fa64517dece3a5ce 100644 (file)
@@ -60,16 +60,23 @@ class TheoryModel : public Model
 {\r
   friend class TheoryEngineModelBuilder;\r
 protected:\r
-  /** add term */\r
+  /** add term function\r
+    *   This should be called on all terms that exist in the model.\r
+    *   addTerm( n ) will do any model-specific processing necessary for n,\r
+    *   such as contraining the interpretation of uninterpretted functions.\r
+    */\r
   virtual void addTerm( Node n ) {}\r
 private:\r
-  /** definitions */\r
+  /** List of definitions that the user has given\r
+    *  This is necessary for supporting the get-model command.\r
+    */\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
+  /** print the value of the function n to stream */\r
   virtual void toStreamFunction( Node n, std::ostream& out );\r
+  /** print the value of the type tn to stream */\r
   virtual void toStreamType( TypeNode tn, std::ostream& out );\r
 public:\r
   TheoryModel( context::Context* c, std::string name );\r
@@ -78,83 +85,102 @@ public:
   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
+  /** stores set of representatives for each type */\r
+  RepSet d_rep_set;\r
+  /** true/false nodes */\r
   Node d_true;\r
   Node d_false;\r
 public:\r
-  /** add defined function */\r
+  /** reset the model */\r
+  virtual void reset();\r
+  /** get interpreted value\r
+    *  This function is called when the value of the node cannot be determined by the theory rewriter\r
+    *  This should function should return a representative in d_reps\r
+    */\r
+  virtual Node getInterpretedValue( TNode n ) = 0;\r
+public:\r
+  /** add defined function (for get-model) */\r
   void addDefineFunction( Node n );\r
-  /** add defined type */\r
+  /** add defined type (for get-model) */\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
+  /** get existing domain value, with possible exclusions\r
+    *   This function returns a term in d_rep_set.d_type_reps[tn] but not in exclude\r
+    */\r
   Node getDomainValue( TypeNode tn, std::vector< Node >& exclude );\r
-  /** get new domain value */\r
+  /** get new domain value\r
+    *   This function returns a constant term of type tn that is not in d_rep_set.d_type_reps[tn]\r
+    *   If it cannot find such a node, it returns null.\r
+    */\r
   Node getNewDomainValue( TypeNode tn );\r
 public:\r
-  /** assert equality */\r
+  /** assert equality holds in the model */\r
   void assertEquality( Node a, Node b, bool polarity );\r
-  /** assert predicate */\r
+  /** assert predicate holds in the model */\r
   void assertPredicate( Node a, bool polarity );\r
-  /** assert equality engine */\r
+  /** assert all equalities/predicates in equality engine hold in the model */\r
   void assertEqualityEngine( eq::EqualityEngine* ee );\r
 public:\r
-  //queries about equality\r
+  /** general queries */\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
+  /** print representative debug function */\r
   void printRepresentativeDebug( const char* c, Node r );\r
+  /** print representative function */\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
+/** Default model class\r
+  *   The getInterpretedValue function will choose an existing value arbitrarily.\r
+  *   If none are found, then it will create a new value.\r
+  */\r
 class DefaultModel : public TheoryModel\r
 {\r
+protected:\r
+  /** whether function models are enabled */\r
+  bool d_enableFuncModels;\r
+  /** add term */\r
+  void addTerm( Node n );\r
 public:\r
-  DefaultModel( context::Context* c, std::string name );\r
+  DefaultModel( context::Context* c, std::string name, bool enableFuncModels );\r
   virtual ~DefaultModel(){}\r
+  //necessary information for function models\r
+  std::map< Node, std::vector< Node > > d_uf_terms;\r
+  std::map< Node, Node > d_uf_models;\r
 public:\r
+  void reset();\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
+/** TheoryEngineModelBuilder class\r
+  *    This model builder will consult all theories in a theory engine for\r
+  *    collectModelInfo( ... ) when building a model.\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
+  /** choose representative for unresolved equivalence class */\r
+  void initializeType( TypeNode tn, std::map< TypeNode, bool >& unresolved_types );\r
+  /** process build model */\r
+  virtual void processBuildModel( TheoryModel* m ){}\r
+  /** choose representative for unconstrained equivalence class */\r
+  virtual Node chooseRepresentative( TheoryModel* m, Node eqc );\r
 public:\r
   TheoryEngineModelBuilder( TheoryEngine* te );\r
   virtual ~TheoryEngineModelBuilder(){}\r
-  /**\r
-   *  Build model function.\r
+  /** Build model function.\r
+   *    Should be called only on TheoryModels m\r
    */\r
   void buildModel( Model* m );\r
 };\r
index ae5b99c0683e849c2a3cb39c192701c48b460d7a..316e2fbff773f877e8bb7cc137cf9d3f6bf1fcc0 100644 (file)
@@ -24,6 +24,8 @@ libquantifiers_la_SOURCES = \
        term_database.h \
        term_database.cpp \
        first_order_model.h \
-       first_order_model.cpp
+       first_order_model.cpp \
+       model_builder.h \
+       model_builder.cpp
 
 EXTRA_DIST = kinds
\ No newline at end of file
index 71a48b33d1b9583fad7e1f3df2dc9b6684f54984..766bd31ae9a44720e8545a2c2945e265f5b1c7e7 100644 (file)
@@ -17,7 +17,7 @@
 #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
+#include "theory/quantifiers/term_database.h"\r
 \r
 using namespace std;\r
 using namespace CVC4;\r
@@ -26,25 +26,37 @@ using namespace CVC4::context;
 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
+FirstOrderModel::FirstOrderModel( QuantifiersEngine* qe, context::Context* c, std::string name ) : DefaultModel( c, name, true ),\r
 d_term_db( qe->getTermDatabase() ), d_forall_asserts( c ){\r
 \r
 }\r
 \r
-void FirstOrderModel::initialize(){\r
+void FirstOrderModel::reset(){\r
   //rebuild models\r
-  d_uf_model.clear();\r
+  d_uf_model_tree.clear();\r
+  d_uf_model_gen.clear();\r
   d_array_model.clear();\r
+  DefaultModel::reset();\r
+}\r
+\r
+void FirstOrderModel::addTerm( Node n ){\r
+  //std::vector< Node > added;\r
+  //d_term_db->addTerm( n, added, false );\r
+  DefaultModel::addTerm( n );\r
+}\r
+\r
+void FirstOrderModel::initialize(){\r
+  //this is called after representatives have been chosen and the equality engine has been built\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
+    //initialize relevant models within bodies of all quantifiers\r
     initializeModelForTerm( f[1] );\r
   }\r
-\r
+  //for debugging\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
+    for( std::map< TypeNode, std::vector< Node > >::iterator it = d_rep_set.d_type_reps.begin(); it != d_rep_set.d_type_reps.end(); ++it ){\r
+      if( it->first.isSort() ){\r
         Message() << "Cardinality( " << it->first << " )" << " = " << it->second.size() << std::endl;\r
       }\r
     }\r
@@ -54,33 +66,44 @@ void FirstOrderModel::initialize(){
 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
+    if( d_uf_model_tree.find( op )==d_uf_model_tree.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
+      //only generate models for predicates and functions with uninterpreted range types\r
+      if( tn==NodeManager::currentNM()->booleanType() || tn.isSort() ){\r
+        d_uf_model_tree[ op ] = uf::UfModelTree( op );\r
+        d_uf_model_gen[ op ].clear();\r
       }\r
     }\r
   }\r
-  if( n.getKind()!=STORE && n.getType().isArray() ){\r
-    d_array_model[n] = Node::null();\r
+  /*\r
+  if( n.getType().isArray() ){\r
+    while( n.getKind()==STORE ){\r
+      n = n[0];\r
+    }\r
+    Node nn = getRepresentative( n );\r
+    if( d_array_model.find( nn )==d_array_model.end() ){\r
+      d_array_model[nn] = arrays::ArrayModel( nn, this );\r
+    }\r
   }\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
+  /*\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
+  }else if( d_array_model.find( n )!=d_array_model.end() ){\r
+    Node value = d_array_model[n].getArrayValue();\r
+    out << "(" << n << " " << value << ")" << std::endl;\r
   }\r
+  */\r
+  DefaultModel::toStreamFunction( n, out );\r
 }\r
 \r
 void FirstOrderModel::toStreamType( TypeNode tn, std::ostream& out ){\r
@@ -91,14 +114,29 @@ Node FirstOrderModel::getInterpretedValue( TNode n ){
   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
+    if( d_uf_models.find( n )==d_uf_models.end() ){\r
+      //use the model tree to generate the model\r
+      Node fn = d_uf_model_tree[n].getFunctionValue();\r
+      d_uf_models[n] = fn;\r
+      return fn;\r
+    }\r
+  /*\r
+  }else if( type.isArray() ){\r
+    if( d_array_model.find( n )!=d_array_model.end() ){\r
+      return d_array_model[n].getArrayValue();\r
     }else{\r
-      return n;\r
+      //std::cout << "no array model generated for " << n << std::endl;\r
     }\r
+  */\r
   }else if( n.getKind()==APPLY_UF ){\r
-    int depIndex;\r
-    return d_uf_model[ n.getOperator() ].getValue( n, depIndex );\r
+    Node op = n.getOperator();\r
+    if( d_uf_model_tree.find( op )!=d_uf_model_tree.end() ){\r
+      //consult the uf model\r
+      int depIndex;\r
+      return d_uf_model_tree[ op ].getValue( this, n, depIndex );\r
+    }\r
+  }else if( n.getKind()==SELECT ){\r
+\r
   }\r
   return DefaultModel::getInterpretedValue( n );\r
 }\r
@@ -113,14 +151,14 @@ void FirstOrderModel::toStream(std::ostream& out){
 #if 0\r
   out << "---Current Model---" << std::endl;\r
   out << "Representatives: " << std::endl;\r
-  d_ra.toStream( out );\r
+  d_rep_set.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
+  d_rep_set.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
index 832acbee3236b6f3a3498b622ee19f88dd8e7fb6..825518ed0119ef1fc485c804abd0062fa799f21b 100644 (file)
@@ -21,6 +21,7 @@
 \r
 #include "theory/model.h"\r
 #include "theory/uf/theory_uf_model.h"\r
+#include "theory/arrays/theory_arrays_model.h"\r
 \r
 namespace CVC4 {\r
 namespace theory {\r
@@ -43,6 +44,8 @@ class FirstOrderModel : public DefaultModel
 private:\r
   //pointer to term database\r
   TermDb* d_term_db;\r
+  //add term function\r
+  void addTerm( Node n );\r
   //for initialize model\r
   void initializeModelForTerm( Node n );\r
   /** to stream functions */\r
@@ -50,10 +53,12 @@ private:
   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
+  std::map< Node, uf::UfModelTree > d_uf_model_tree;\r
+  //model generators\r
+  std::map< Node, uf::UfModelTreeGenerator > d_uf_model_gen;\r
 public: //for Theory Arrays:\r
   //default value for each non-store array\r
-  std::map< Node, Node > d_array_model;\r
+  std::map< Node, arrays::ArrayModel > 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
@@ -64,11 +69,13 @@ public: //for Theory Quantifiers:
 public:\r
   FirstOrderModel( QuantifiersEngine* qe, context::Context* c, std::string name );\r
   virtual ~FirstOrderModel(){}\r
-  // initialize the model\r
-  void initialize();\r
+  // reset the model\r
+  void reset();\r
   /** get interpreted value */\r
   Node getInterpretedValue( TNode n );\r
 public:\r
+  // initialize the model\r
+  void initialize();\r
   /** get term database */\r
   TermDb* getTermDatabase();\r
   /** to stream function */\r
diff --git a/src/theory/quantifiers/model_builder.cpp b/src/theory/quantifiers/model_builder.cpp
new file mode 100644 (file)
index 0000000..9cd5020
--- /dev/null
@@ -0,0 +1,417 @@
+/*********************                                                        */
+/*! \file model_builder.cpp
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Implementation of model builder class
+ **/
+
+#include "theory/quantifiers/model_engine.h"
+#include "theory/theory_engine.h"
+#include "theory/uf/equality_engine.h"
+#include "theory/uf/theory_uf.h"
+#include "theory/uf/theory_uf_model.h"
+#include "theory/uf/theory_uf_instantiator.h"
+#include "theory/arrays/theory_arrays_model.h"
+#include "theory/quantifiers/first_order_model.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/model_builder.h"
+
+//#define ME_PRINT_WARNINGS
+
+#define RECONSIDER_FUNC_CONSTANT
+//#define ONE_QUANT_PER_ROUND_INST_GEN
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+
+ModelEngineBuilder::ModelEngineBuilder( QuantifiersEngine* qe ) :
+TheoryEngineModelBuilder( qe->getTheoryEngine() ),
+d_qe( qe ){
+
+}
+
+Node ModelEngineBuilder::chooseRepresentative( TheoryModel* m, Node eqc ){
+  Assert( m->d_equalityEngine.hasTerm( eqc ) );
+  Assert( m->d_equalityEngine.getRepresentative( eqc )==eqc );
+  //avoid interpreted symbols
+  if( isBadRepresentative( eqc ) ){
+    eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &m->d_equalityEngine );
+    while( !eqc_i.isFinished() ){
+      if( !isBadRepresentative( *eqc_i ) ){
+        return *eqc_i;
+      }
+      ++eqc_i;
+    }
+    //otherwise, make new value?
+    //Message() << "Warning: Bad rep " << eqc << std::endl;
+  }
+  return eqc;
+}
+
+bool ModelEngineBuilder::isBadRepresentative( Node n ){
+  return n.getKind()==SELECT || n.getKind()==APPLY_SELECTOR;
+}
+
+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 functions
+    analyzeModel( fm );
+    //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;
+          }
+        }
+      }
+      if( Options::current()->printModelEngine ){
+        if( d_addedLemmas>0 ){
+          Message() << "InstGen, added lemmas = " << d_addedLemmas << std::endl;
+        }else{
+          Message() << "No InstGen lemmas..." << std::endl;
+        }
+      }
+      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 );
+    }
+  }
+}
+
+void ModelEngineBuilder::analyzeModel( FirstOrderModel* fm ){
+  //determine if any functions are constant
+  for( std::map< Node, uf::UfModelTree >::iterator it = fm->d_uf_model_tree.begin(); it != fm->d_uf_model_tree.end(); ++it ){
+    Node op = it->first;
+    for( size_t i=0; i<fm->d_uf_terms[op].size(); i++ ){
+      Node n = fm->d_uf_terms[op][i];
+      if( !n.getAttribute(NoMatchAttribute()) ){
+        Node v = fm->getRepresentative( n );
+        if( i==0 ){
+          d_uf_prefs[op].d_const_val = v;
+        }else if( v!=d_uf_prefs[op].d_const_val ){
+          d_uf_prefs[op].d_const_val = Node::null();
+          break;
+        }
+      }
+    }
+    if( !d_uf_prefs[op].d_const_val.isNull() ){
+      fm->d_uf_model_gen[op].setDefaultValue( d_uf_prefs[op].d_const_val );
+      fm->d_uf_model_gen[op].makeModel( fm, it->second );
+      Debug("fmf-model-cons") << "Function " << op << " is the constant function ";
+      fm->printRepresentativeDebug( "fmf-model-cons", d_uf_prefs[op].d_const_val );
+      Debug("fmf-model-cons") << std::endl;
+      d_uf_model_constructed[op] = true;
+    }else{
+      d_uf_model_constructed[op] = false;
+    }
+  }
+}
+
+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{
+          pref = -1;
+        }
+      }
+      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 = !d_uf_prefs[gn.getOperator()].d_const_val.isNull();
+        }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_tree.find( op )!=fm->d_uf_model_tree.end() ){
+                  uf_terms.push_back( gn[j] );
+                  isConst = isConst && !d_uf_prefs[op].d_const_val.isNull();
+                }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{
+          int pcIndex = pref==1 ? 0 : 1;
+          for( int j=0; j<(int)uf_terms.size(); j++ ){
+            pro_con[pcIndex].push_back( uf_terms[j] );
+          }
+        }
+      }
+    }
+    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{
+      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 );
+        }
+      }
+    }
+  }
+  Debug("fmf-model-prefs") << "Pre-Model Completion: Quantifiers SAT: " << quantSatInit << " / " << (quantSatInit+nquantSatInit) << std::endl;
+}
+
+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( 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 applicable, try to add exceptions here
+    if( !tr_terms.empty() ){
+      //make a trigger for these terms, add instantiations
+      inst::Trigger* tr = inst::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 ModelEngineBuilder::finishBuildModel( FirstOrderModel* fm ){
+  //build model for UF
+  for( std::map< Node, uf::UfModelTree >::iterator it = fm->d_uf_model_tree.begin(); it != fm->d_uf_model_tree.end(); ++it ){
+    finishBuildModelUf( fm, it->first );
+  }
+  /*
+  //build model for arrays
+  for( std::map< Node, arrays::ArrayModel >::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.setDefaultValue( fm->getRepresentative( selModelBasis ) );
+  }
+  */
+  Debug("fmf-model-debug") << "Done building models." << std::endl;
+}
+
+void ModelEngineBuilder::finishBuildModelUf( FirstOrderModel* fm, Node op ){
+#ifdef RECONSIDER_FUNC_CONSTANT
+  if( d_uf_model_constructed[op] ){
+    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 v = d_uf_prefs[op].d_const_val;
+      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;
+        fm->d_uf_model_tree[op].clear();
+        fm->d_uf_model_gen[op].clear();
+        d_uf_model_constructed[op] = false;
+      }
+    }
+  }
+#endif
+  if( !d_uf_model_constructed[op] ){
+    //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<fm->d_uf_terms[op].size(); i++ ){
+      Node n = fm->d_uf_terms[op][i];
+      fm->getTermDatabase()->computeModelBasisArgAttribute( n );
+      if( !n.getAttribute(NoMatchAttribute()) || n.getAttribute(ModelBasisArgAttribute())==1 ){
+        Node v = fm->getRepresentative( n );
+        //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 << " = ";
+        fm->printRepresentativeDebug( "fmf-model-cons", v );
+        Debug("fmf-model-cons") << std::endl;
+        //set it as ground value
+        fm->d_uf_model_gen[op].setValue( fm, n, v );
+        if( fm->d_uf_model_gen[op].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 ){
+            fm->d_uf_model_gen[op].setValue( fm, n, v, false );
+            if( n==defaultTerm ){
+              //incidentally already set, we will not need to find a default value
+              setDefaultVal = false;
+            }
+          }
+        }else{
+          if( n==defaultTerm ){
+            fm->d_uf_model_gen[op].setValue( fm, n, v, false );
+            //incidentally already set, we will not need to find a default value
+            setDefaultVal = 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() );
+      fm->d_uf_model_gen[op].setValue( fm, defaultTerm, defaultVal, false );
+    }
+    Debug("fmf-model-cons") << "  Making model...";
+    fm->d_uf_model_gen[op].makeModel( fm, fm->d_uf_model_tree[op] );
+    d_uf_model_constructed[op] = true;
+    Debug("fmf-model-cons") << "  Finished constructing model for " << op << "." << std::endl;
+  }
+}
+
+void ModelEngineBuilder::finishProcessBuildModel( TheoryModel* m ){
+  for( std::map< Node, Node >::iterator it = m->d_reps.begin(); it != m->d_reps.end(); ++it ){
+    //build proper representatives (TODO)
+  }
+}
+
+bool ModelEngineBuilder::optUseModel() {
+  return Options::current()->fmfModelBasedInst;
+}
+
+bool ModelEngineBuilder::optInstGen(){
+  return Options::current()->fmfInstGen;
+}
+
+bool ModelEngineBuilder::optOneQuantPerRoundInstGen(){
+#ifdef ONE_QUANT_PER_ROUND_INST_GEN
+  return true;
+#else
+  return false;
+#endif
+}
+
+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);
+}
+
+ModelEngineBuilder::Statistics::~Statistics(){
+  StatisticsRegistry::unregisterStat(&d_pre_sat_quant);
+  StatisticsRegistry::unregisterStat(&d_pre_nsat_quant);
+}
diff --git a/src/theory/quantifiers/model_builder.h b/src/theory/quantifiers/model_builder.h
new file mode 100644 (file)
index 0000000..13d500d
--- /dev/null
@@ -0,0 +1,91 @@
+/*********************                                                        */\r
+/*! \file model_builder.h\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: mdeters\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009-2012  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 Builder class\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef __CVC4__QUANTIFIERS_MODEL_BUILDER_H\r
+#define __CVC4__QUANTIFIERS_MODEL_BUILDER_H\r
+\r
+#include "theory/quantifiers_engine.h"\r
+#include "theory/model.h"\r
+#include "theory/uf/theory_uf_model.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+namespace quantifiers {\r
+\r
+//the model builder\r
+class ModelEngineBuilder : public TheoryEngineModelBuilder\r
+{\r
+protected:\r
+  //quantifiers engine\r
+  QuantifiersEngine* d_qe;\r
+  //map from operators to model preference data\r
+  std::map< Node, uf::UfModelPreferenceData > d_uf_prefs;\r
+  //built model uf\r
+  std::map< Node, bool > d_uf_model_constructed;\r
+  /** process build model */\r
+  void processBuildModel( TheoryModel* m );\r
+  /** choose representative for unconstrained equivalence class */\r
+  Node chooseRepresentative( TheoryModel* m, Node eqc );\r
+  /** bad representative */\r
+  bool isBadRepresentative( Node n );\r
+protected:\r
+  //analyze model\r
+  void analyzeModel( FirstOrderModel* fm );\r
+  //analyze quantifiers\r
+  void analyzeQuantifiers( FirstOrderModel* fm );\r
+  //build model\r
+  void finishBuildModel( FirstOrderModel* fm );\r
+  //theory-specific build models\r
+  void finishBuildModelUf( FirstOrderModel* fm, Node op );\r
+  //do InstGen techniques for quantifier, return number of lemmas produced\r
+  int doInstGen( FirstOrderModel* fm, Node f );\r
+public:\r
+  ModelEngineBuilder( QuantifiersEngine* qe );\r
+  virtual ~ModelEngineBuilder(){}\r
+  /** finish model */\r
+  void finishProcessBuildModel( TheoryModel* m );\r
+public:\r
+  /** number of lemmas generated while building model */\r
+  int d_addedLemmas;\r
+  //map from quantifiers to if are constant SAT\r
+  std::map< Node, bool > d_quant_sat;\r
+  //map from quantifiers to the instantiation literals that their model is dependent upon\r
+  std::map< Node, std::vector< Node > > d_quant_selection_lits;\r
+public:\r
+  //map from quantifiers to model basis match\r
+  std::map< Node, InstMatch > d_quant_basis_match;\r
+  //options\r
+  bool optUseModel();\r
+  bool optInstGen();\r
+  bool optOneQuantPerRoundInstGen();\r
+  /** statistics class */\r
+  class Statistics {\r
+  public:\r
+    IntStat d_pre_sat_quant;\r
+    IntStat d_pre_nsat_quant;\r
+    Statistics();\r
+    ~Statistics();\r
+  };\r
+  Statistics d_statistics;\r
+};\r
+\r
+}\r
+}\r
+}\r
+\r
+#endif\r
index 663f270eb8ce0b438a62d425641c6298ed152455..ddaaa5b6f9b3b515e99168bbd5c0f4276201415a 100644 (file)
 #include "theory/uf/theory_uf.h"
 #include "theory/uf/theory_uf_strong_solver.h"
 #include "theory/uf/theory_uf_instantiator.h"
+#include "theory/arrays/theory_arrays_model.h"
 #include "theory/quantifiers/first_order_model.h"
 #include "theory/quantifiers/term_database.h"
 
 //#define ME_PRINT_WARNINGS
 
-//#define DISABLE_EVAL_SKIP_MULTIPLE
-
-#define RECONSIDER_FUNC_CONSTANT
 #define EVAL_FAIL_SKIP_MULTIPLE
-//#define ONE_QUANT_PER_ROUND_INST_GEN
 //#define ONE_QUANT_PER_ROUND
 
 using namespace std;
@@ -41,324 +38,6 @@ using namespace CVC4::theory;
 using namespace CVC4::theory::quantifiers;
 using namespace CVC4::theory::inst;
 
-ModelEngineBuilder::ModelEngineBuilder( QuantifiersEngine* qe ) :
-TheoryEngineModelBuilder( qe->getTheoryEngine() ),
-d_qe( qe ){
-
-}
-
-Node ModelEngineBuilder::chooseRepresentative( TheoryModel* tm, Node eqc ){
-  return eqc;
-}
-
-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;
-          }
-        }
-      }
-      if( Options::current()->printModelEngine ){
-        if( d_addedLemmas>0 ){
-          Message() << "InstGen, added lemmas = " << d_addedLemmas << std::endl;
-        }else{
-          Message() << "No InstGen lemmas..." << std::endl;
-        }
-      }
-      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 );
-    }
-  }
-}
-
-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{
-          pref = -1;
-        }
-      }
-      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{
-          int pcIndex = pref==1 ? 0 : 1;
-          for( int j=0; j<(int)uf_terms.size(); j++ ){
-            pro_con[pcIndex].push_back( uf_terms[j] );
-          }
-        }
-      }
-    }
-    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{
-      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 );
-        }
-      }
-    }
-  }
-  Debug("fmf-model-prefs") << "Pre-Model Completion: Quantifiers SAT: " << quantSatInit << " / " << (quantSatInit+nquantSatInit) << std::endl;
-}
-
-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( 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 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 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 );
-  }
-  //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;
-}
-
-void ModelEngineBuilder::finishBuildModelUf( FirstOrderModel* fm, uf::UfModel& model ){
-  Node op = model.getOperator();
-#ifdef RECONSIDER_FUNC_CONSTANT
-  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_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
-  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 << " = ";
-      fm->printRepresentativeDebug( "fmf-model-cons", v );
-      Debug("fmf-model-cons") << std::endl;
-      //set it as ground value
-      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{
-        if( n==defaultTerm ){
-          model.setValue( n, v, false );
-          //incidentally already set, we will not need to find a default value
-          setDefaultVal = 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...";
-    model.setModel();
-    Debug("fmf-model-cons") << "  Finished constructing model for " << op << "." << std::endl;
-  }
-}
-
-bool ModelEngineBuilder::optUseModel() {
-  return Options::current()->fmfModelBasedInst;
-}
-
-bool ModelEngineBuilder::optInstGen(){
-  return Options::current()->fmfInstGen;
-}
-
-bool ModelEngineBuilder::optOneQuantPerRoundInstGen(){
-#ifdef ONE_QUANT_PER_ROUND_INST_GEN
-  return true;
-#else
-  return false;
-#endif
-}
-
-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);
-}
-
-ModelEngineBuilder::Statistics::~Statistics(){
-  StatisticsRegistry::unregisterStat(&d_pre_sat_quant);
-  StatisticsRegistry::unregisterStat(&d_pre_nsat_quant);
-}
-
 //Model Engine constructor
 ModelEngine::ModelEngine( QuantifiersEngine* qe ) :
 QuantifiersModule( qe ),
@@ -448,6 +127,8 @@ void ModelEngine::check( Theory::Effort e ){
       //CVC4 will answer SAT
       Debug("fmf-consistent") << std::endl;
       debugPrint("fmf-consistent");
+      // finish building the model in the standard way
+      d_builder.finishProcessBuildModel( d_quantEngine->getModel() );
     }else{
       //otherwise, the search will continue
       d_quantEngine->flushLemmas( &d_quantEngine->getOutputChannel() );
@@ -601,12 +282,13 @@ int ModelEngine::exhaustiveInstantiate( Node f, bool useRelInstDomain ){
     }
   }
   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;
+  d_statistics.d_eval_lits += reval.d_eval_lits;
+  d_statistics.d_eval_lits_unknown += reval.d_eval_lits_unknown;
   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();
+    totalInst = totalInst * (int)d_quantEngine->getModel()->d_rep_set.d_type_reps[ f[0][i].getType() ].size();
     relevantInst = relevantInst * (int)riter.d_domain[i].size();
   }
   d_totalLemmas += totalInst;
@@ -658,15 +340,17 @@ void ModelEngine::debugPrint( const char* c ){
 ModelEngine::Statistics::Statistics():
   d_inst_rounds("ModelEngine::Inst_Rounds", 0),
   d_eval_formulas("ModelEngine::Eval_Formulas", 0 ),
-  d_eval_eqs("ModelEngine::Eval_Equalities", 0 ),
   d_eval_uf_terms("ModelEngine::Eval_Uf_Terms", 0 ),
+  d_eval_lits("ModelEngine::Eval_Lits", 0 ),
+  d_eval_lits_unknown("ModelEngine::Eval_Lits_Unknown", 0 ),
   d_num_quants_init("ModelEngine::Num_Quants", 0 ),
   d_num_quants_init_fail("ModelEngine::Num_Quants_No_Basis", 0 )
 {
   StatisticsRegistry::registerStat(&d_inst_rounds);
   StatisticsRegistry::registerStat(&d_eval_formulas);
-  StatisticsRegistry::registerStat(&d_eval_eqs);
   StatisticsRegistry::registerStat(&d_eval_uf_terms);
+  StatisticsRegistry::registerStat(&d_eval_lits);
+  StatisticsRegistry::registerStat(&d_eval_lits_unknown);
   StatisticsRegistry::registerStat(&d_num_quants_init);
   StatisticsRegistry::registerStat(&d_num_quants_init_fail);
 }
@@ -674,8 +358,9 @@ ModelEngine::Statistics::Statistics():
 ModelEngine::Statistics::~Statistics(){
   StatisticsRegistry::unregisterStat(&d_inst_rounds);
   StatisticsRegistry::unregisterStat(&d_eval_formulas);
-  StatisticsRegistry::unregisterStat(&d_eval_eqs);
   StatisticsRegistry::unregisterStat(&d_eval_uf_terms);
+  StatisticsRegistry::unregisterStat(&d_eval_lits);
+  StatisticsRegistry::unregisterStat(&d_eval_lits_unknown);
   StatisticsRegistry::unregisterStat(&d_num_quants_init);
   StatisticsRegistry::unregisterStat(&d_num_quants_init_fail);
 }
index b0113982664c37042f762c68bc82deb6caeb35bb..1139332fe659b76707dcef716f79901dfb3a293c 100644 (file)
  ** See the file COPYING in the top-level source directory for licensing
  ** information.\endverbatim
  **
- ** \brief Model Engine classes
+ ** \brief Model Engine class
  **/
 
 #include "cvc4_private.h"
 
-#ifndef __CVC4__MODEL_ENGINE_H
-#define __CVC4__MODEL_ENGINE_H
+#ifndef __CVC4__QUANTIFIERS_MODEL_ENGINE_H
+#define __CVC4__QUANTIFIERS_MODEL_ENGINE_H
 
 #include "theory/quantifiers_engine.h"
-#include "theory/quantifiers/theory_quantifiers.h"
+#include "theory/quantifiers/model_builder.h"
 #include "theory/model.h"
-#include "theory/uf/theory_uf_model.h"
 #include "theory/quantifiers/relevant_domain.h"
 
 namespace CVC4 {
 namespace theory {
-
-namespace uf{
-  class StrongSolverTheoryUf;
-}
-
 namespace quantifiers {
 
-
-//the model builder
-class ModelEngineBuilder : public TheoryEngineModelBuilder
-{
-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 uf::UfModel;
   friend class RepSetIterator;
 private:
   /** builder class */
@@ -128,8 +72,9 @@ public:
   public:
     IntStat d_inst_rounds;
     IntStat d_eval_formulas;
-    IntStat d_eval_eqs;
     IntStat d_eval_uf_terms;
+    IntStat d_eval_lits;
+    IntStat d_eval_lits_unknown;
     IntStat d_num_quants_init;
     IntStat d_num_quants_init_fail;
     Statistics();
index e7ae1d1c75287403662629ae9186692a88bb00de..12206e148c2a9d02c1ae46ec374bb9ba140dce27 100644 (file)
@@ -37,16 +37,16 @@ void RelevantDomain::compute(){
     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
+  for( std::map< Node, uf::UfModelTree >::iterator it = d_model->d_uf_model_tree.begin();\r
+       it != d_model->d_uf_model_tree.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
+    for( size_t i=0; i<d_model->d_uf_terms[op].size(); i++ ){\r
+      Node n = d_model->d_uf_terms[op][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
+        if( d_model->d_rep_set.hasType( n[j].getType() ) ){\r
           Node ra = d_model->getRepresentative( n[j] );\r
-          int raIndex = d_model->d_ra.getIndexFor( ra );\r
+          int raIndex = d_model->d_rep_set.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
@@ -54,8 +54,8 @@ void RelevantDomain::compute(){
         }\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
+      Node r = d_model->getRepresentative( n );\r
+      int raIndex = d_model->d_rep_set.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
@@ -104,10 +104,10 @@ bool RelevantDomain::computeRelevantInstantiationDomain( Node n, Node parent, in
     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
+      if( d_model->d_rep_set.hasType( tn ) ){\r
+        if( rd[vi].size()!=d_model->d_rep_set.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
+          for( size_t i=0; i<d_model->d_rep_set.d_type_reps[tn].size(); i++ ){\r
             rd[vi].push_back( i );\r
             domainChanged = true;\r
           }\r
@@ -166,7 +166,7 @@ bool RelevantDomain::extendFunctionDomains( Node n, RepDomain& range ){
       }\r
     }else{\r
       Node r = d_model->getRepresentative( n );\r
-      range.push_back( d_model->d_ra.getIndexFor( r ) );\r
+      range.push_back( d_model->d_rep_set.getIndexFor( r ) );\r
     }\r
     return domainChanged;\r
   }\r
index a29f815dbf8d38531f855f3771d43f2359662277..516f8585795774a1812ee1f7a5d785f44a10ec78 100644 (file)
@@ -38,8 +38,28 @@ RepSetIterator::RepSetIterator( Node f, FirstOrderModel* model ) : d_f( f ), d_m
     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
+    TypeNode tn = d_f[0][i].getType();\r
+    if( tn.isSort() ){\r
+      if( d_model->d_rep_set.hasType( tn ) ){\r
+        for( int j=0; j<(int)d_model->d_rep_set.d_type_reps[d_f[0][i].getType()].size(); j++ ){\r
+          d_domain[i].push_back( j );\r
+        }\r
+      }else{\r
+        Unimplemented("Cannot create instantiation iterator for unknown uninterpretted sort");\r
+      }\r
+    }else if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){\r
+      Unimplemented("Cannot create instantiation iterator for arithmetic quantifier");\r
+    }else if( tn.isDatatype() ){\r
+      const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();\r
+      //if finite, then use type enumerator\r
+      if( dt.isFinite() ){\r
+        //DO_THIS: use type enumerator\r
+        Unimplemented("Not yet implemented: instantiation iterator for finite datatype quantifier");\r
+      }else{\r
+        Unimplemented("Cannot create instantiation iterator for infinite datatype quantifier");\r
+      }\r
+    }else{\r
+      Unimplemented("Cannot create instantiation iterator for quantifier");\r
     }\r
   }\r
 }\r
@@ -103,9 +123,9 @@ void RepSetIterator::getMatch( QuantifiersEngine* qe, InstMatch& m ){
 \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
+  Assert( d_model->d_rep_set.d_type_reps.find( tn )!=d_model->d_rep_set.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
+  return d_model->d_rep_set.d_type_reps[tn][d_domain[index][d_index[index]]];\r
 }\r
 \r
 void RepSetIterator::debugPrint( const char* c ){\r
@@ -123,14 +143,18 @@ void RepSetIterator::debugPrintSmall( const char* c ){
 }\r
 \r
 RepSetEvaluator::RepSetEvaluator( FirstOrderModel* m, RepSetIterator* ri ) : d_model( m ), d_riter( ri ){\r
-\r
+  d_eval_formulas = 0;\r
+  d_eval_uf_terms = 0;\r
+  d_eval_lits = 0;\r
+  d_eval_lits_unknown = 0;\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
+//if evaluate( n ) = eVal,\r
+// let n' = d_riter * n be the formula n instantiated with the current values in r_iter\r
+// if eVal = 1, then n' is true, if eVal = -1, then n' is false,\r
+// if eVal = 0, then n' cannot be proven to be equal to phaseReq\r
+// if eVal is not 0, then\r
+//   each n{d_riter->d_index[0]/x_0...d_riter->d_index[depIndex]/x_depIndex, */x_(depIndex+1) ... */x_n } is equivalent 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
@@ -208,6 +232,7 @@ int RepSetEvaluator::evaluate( Node n, int& depIndex ){
   }else if( n.getKind()==FORALL ){\r
     return 0;\r
   }else{\r
+    ++d_eval_lits;\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
@@ -215,89 +240,46 @@ int RepSetEvaluator::evaluate( Node n, int& depIndex ){
     //  }\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
+    Node val = evaluateTerm( n, depIndex );\r
+    if( !val.isNull() ){\r
+      if( d_model->areEqual( val, d_model->d_true ) ){\r
+        retVal = 1;\r
+      }else if( d_model->areEqual( val, d_model->d_false ) ){\r
+        retVal = -1;\r
+      }else{\r
+        if( val.getKind()==EQUAL ){\r
+          if( d_model->areEqual( val[0], val[1] ) ){\r
+            retVal = 1;\r
+          }else if( d_model->areDisequal( val[0], val[1] ) ){\r
+            retVal = -1;\r
+          }\r
         }\r
       }\r
     }\r
     if( retVal!=0 ){\r
-      Debug("fmf-eval-debug") << "Evaluate literal: return " << retVal << ", depends = " << depIndex << std::endl;\r
+      Debug("fmf-eval-debug") << "Evaluate literal: return " << retVal << ", depIndex = " << depIndex << std::endl;\r
     }else{\r
+      ++d_eval_lits_unknown;\r
       Debug("fmf-eval-amb") << "Neither true nor false : " << n << std::endl;\r
       //std::cout << "Neither true nor false : " << n << std::endl;\r
+      //std::cout << "  Value : " << val << std::endl;\r
+      //for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+      //  std::cout << "   " << i << " : " << n[i].getType() << std::endl;\r
+      //}\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
+  //Message() << "Eval term " << n << std::endl;\r
+  if( !n.hasAttribute(InstConstantAttribute()) ){\r
+    //if evaluating a ground term, just consult the standard getValue functionality\r
+    depIndex = -1;\r
+    return d_model->getValue( n );\r
+  }else{\r
     Node val;\r
     depIndex = d_riter->getNumTerms()-1;\r
     //check the type of n\r
@@ -311,7 +293,7 @@ Node RepSetEvaluator::evaluateTerm( Node n, int& depIndex ){
       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
+        Node val2 = evaluateTerm( n[ 2 ], depIndex2 );\r
         if( val1==val2 ){\r
           val = val1;\r
           depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;\r
@@ -323,19 +305,24 @@ Node RepSetEvaluator::evaluateTerm( Node n, int& depIndex ){
         depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;\r
       }\r
     }else{\r
-#if 0\r
+      std::vector< int > children_depIndex;\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
+#if 1\r
+        //std::cout << "Evaluate " << n << std::endl;\r
+        Node sel = evaluateTerm( n[1], depIndex );\r
+        if( sel.isNull() ){\r
           depIndex = d_riter->getNumTerms()-1;\r
           return Node::null();\r
         }\r
-        Node arr = n[0];\r
+        Node arr = d_model->getRepresentative( n[0] );\r
+        //if( n[0]!=d_model->getRepresentative( n[0] ) ){\r
+        //  std::cout << n[0] << " is " << d_model->getRepresentative( n[0] ) << std::endl;\r
+        //}\r
+        int tempIndex;\r
         int eval = 1;\r
         while( arr.getKind()==STORE && eval!=0 ){\r
-          int tempIndex;\r
-          eval = evaluateEquality( selIndex, arr[1], tempIndex );\r
+          eval = evaluate( sel.eqNode( arr[1] ), tempIndex );\r
           depIndex = tempIndex > depIndex ? tempIndex : depIndex;\r
           if( eval==1 ){\r
             val = evaluateTerm( arr[2], tempIndex );\r
@@ -345,90 +332,97 @@ Node RepSetEvaluator::evaluateTerm( Node n, int& depIndex ){
             arr = arr[0];\r
           }\r
         }\r
-        n = NodeManager::currentNM()->mkNode( SELECT, arr, selIndex );\r
-      }\r
+        arr = evaluateTerm( arr, tempIndex );\r
+        depIndex = tempIndex > depIndex ? tempIndex : depIndex;\r
+        val = NodeManager::currentNM()->mkNode( SELECT, arr, sel );\r
+#else\r
+        val = evaluateTermDefault( n, depIndex, children_depIndex );\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
+      }else{\r
+        //default term evaluate : evaluate all children, recreate the value\r
+        val = evaluateTermDefault( n, depIndex, children_depIndex );\r
+      }\r
+      if( !val.isNull() ){\r
+        bool setVal = false;\r
+        //custom ways of evaluating terms\r
+        if( n.getKind()==APPLY_UF ){\r
+          Node op = n.getOperator();\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
+          //if it is a defined UF, then consult the interpretation\r
+          if( d_model->d_uf_model_tree.find( op )!=d_model->d_uf_model_tree.end() ){\r
+            ++d_eval_uf_terms;\r
+            int argDepIndex = 0;\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_tree[op].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
+            //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
+            setVal = true;\r
+          }\r
+        }else if( n.getKind()==SELECT ){\r
+          //we are free to interpret this term however we want\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
+        //if not set already, rewrite and consult model for interpretation\r
+        if( !setVal ){\r
+          val = Rewriter::rewrite( val );\r
+          if( val.getMetaKind()!=kind::metakind::CONSTANT ){\r
+            //FIXME: we cannot do this until we trust all theories collectModelInfo!\r
+            //val = d_model->getInterpretedValue( val );\r
+            //val = d_model->getRepresentative( val );\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
+  if( n.getNumChildren()==0 ){\r
+    return n;\r
+  }else{\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
+    //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
+    Node val = NodeManager::currentNM()->mkNode( n.getKind(), children );\r
+    return val;\r
   }\r
-  //recreate the value\r
-  return NodeManager::currentNM()->mkNode( n.getKind(), children );\r
 }\r
 \r
 void RepSetEvaluator::clearEvalFailed( int index ){\r
@@ -443,8 +437,8 @@ void RepSetEvaluator::makeEvalUfModel( Node n ){
     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
+      d_eval_uf_model[n] = uf::UfModelTree( op, d_eval_term_index_order[n] );\r
+      d_model->d_uf_model_gen[op].makeModel( d_model, 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
index 308d09a38fb7b75dc6b333cd6f4ebf6eea2908ea..f6312ae5c4f66eeb9d6fe35a10f1457c4240b200 100644 (file)
@@ -85,7 +85,7 @@ private:
 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
+  std::map< Node, uf::UfModelTree > 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
@@ -103,13 +103,13 @@ public:
   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
+  int d_eval_lits;\r
+  int d_eval_lits_unknown;\r
 };\r
 \r
 \r
index 55715353dd3ab13ef51a4d371efe8c365290ff62..945c82bf9360280deabbf60f1a21a069af76243a 100644 (file)
@@ -45,7 +45,7 @@ using namespace CVC4::theory::inst;
    }
  }
 
-void addTermEfficient( Node n, std::set< Node >& added){
+void TermDb::addTermEfficient( Node n, std::set< Node >& added){
   static AvailableInTermDb aitdi;
   if (Trigger::isAtomicTrigger( n ) && !n.getAttribute(aitdi)){
     //Already processed but new in this branch
@@ -60,70 +60,69 @@ void addTermEfficient( Node n, std::set< Node >& added){
 
 
 void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant ){
-   //don't add terms in quantifier bodies
+  //don't add terms in quantifier bodies
   if( withinQuant && !Options::current()->registerQuantBodyTerms ){
     return;
   }
-     if( d_processed.find( n )==d_processed.end() ){
+  if( d_processed.find( n )==d_processed.end() ){
     ++(d_quantEngine->d_statistics.d_term_in_termdb);
     d_processed.insert(n);
+    d_type_map[ n.getType() ].push_back( n );
     n.setAttribute(AvailableInTermDb(),true);
-       //if this is an atomic trigger, consider adding it
+    //if this is an atomic trigger, consider adding it
     //Call the children?
-    if( Trigger::isAtomicTrigger( n ) || n.getKind() == kind::APPLY_CONSTRUCTOR ){
-         if( !n.hasAttribute(InstConstantAttribute()) ){
-           Debug("term-db") << "register trigger term " << n << std::endl;
+    if( Trigger::isAtomicTrigger( n ) ){
+      if( !n.hasAttribute(InstConstantAttribute()) ){
+        Debug("term-db") << "register trigger term " << n << std::endl;
         //std::cout << "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 );
+        Node op = n.getOperator();
+        d_op_map[op].push_back( n );
         added.insert( 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 );
+        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 );
               Assert(!getParents(n[i],op,i).empty());
-             }
-           }
-           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() );
-             }
-           }
-         }
-       }
+            }
+          }
+          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() );
+            }
+          }
+        }
+      }
     }else{
-       for( int i=0; i<(int)n.getNumChildren(); i++ ){
-         addTerm( n[i], added, withinQuant );
-       }
-     }
+      for( int i=0; i<(int)n.getNumChildren(); i++ ){
+        addTerm( n[i], added, withinQuant );
+      }
+    }
   }else{
-     if( Options::current()->efficientEMatching &&
-         !n.hasAttribute(InstConstantAttribute())){
-       //Efficient e-matching must be notified
-       //The term in triggers are not important here
-       Debug("term-db") << "New in this branch term " << n << std::endl;
-       addTermEfficient(n,added);
-   }
- }
-};
+    if( Options::current()->efficientEMatching && !n.hasAttribute(InstConstantAttribute())){
+      //Efficient e-matching must be notified
+      //The term in triggers are not important here
+      Debug("term-db") << "New in this branch term " << n << std::endl;
+      addTermEfficient(n,added);
+    }
+  }
+}
 
  void TermDb::reset( Theory::Effort effort ){
    int nonCongruentCount = 0;
@@ -158,7 +157,7 @@ void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant ){
    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() );
+                              d_quantEngine->getEqualityQuery()->getEngine() );
      while( !eqc.isFinished() ){
        Node en = (*eqc);
        if( en.getKind()==APPLY_UF && !en.hasAttribute(InstConstantAttribute()) ){
@@ -194,12 +193,18 @@ void TermDb::registerModelBasis( Node n, Node gn ){
 
 Node TermDb::getModelBasisTerm( TypeNode tn, int i ){
   if( d_model_basis_term.find( tn )==d_model_basis_term.end() ){
-    std::stringstream ss;
-    ss << Expr::setlanguage(Options::current()->outputLanguage);
-    ss << "e_" << tn;
-    d_model_basis_term[tn] = NodeManager::currentNM()->mkVar( ss.str(), tn );
+    Node mbt;
+    if( d_type_map[ tn ].empty() ){
+      std::stringstream ss;
+      ss << Expr::setlanguage(Options::current()->outputLanguage);
+      ss << "e_" << tn;
+      mbt = NodeManager::currentNM()->mkVar( ss.str(), tn );
+    }else{
+      mbt = d_type_map[ tn ][ 0 ];
+    }
     ModelBasisAttribute mba;
-    d_model_basis_term[tn].setAttribute(mba,true);
+    mbt.setAttribute(mba,true);
+    d_model_basis_term[tn] = mbt;
   }
   return d_model_basis_term[tn];
 }
index 5004a82dc1b668ca539cbae62e03cb8229c7f941..1ebba49b5fc0befe8d11a5bbe7329cee3dd78422 100644 (file)
@@ -68,6 +68,9 @@ public:
   void setMatchingActive( bool a ) { d_matching_active = a; }\r
   /** get active */\r
   bool getMatchingActive() { return d_matching_active; }\r
+private:\r
+  /** for efficient e-matching */\r
+  void addTermEfficient( Node n, std::set< Node >& added);\r
 public:\r
   /** parent structure (for efficient E-matching):\r
       n -> op -> index -> L\r
index 448224b81c02439b60f6d467f9eff321fb9641a9..471bc9ac185f07295b8bc72fb00b7aa4ca9b5c87 100644 (file)
@@ -26,6 +26,7 @@
 #include "theory/quantifiers/instantiation_engine.h"
 #include "theory/quantifiers/first_order_model.h"
 #include "theory/quantifiers/term_database.h"
+#include "theory/rr_candidate_generator.h"
 
 using namespace std;
 using namespace CVC4;
@@ -720,6 +721,30 @@ Node EqualityQueryQuantifiersEngine::getInternalRepresentative( Node a ){
   return d_qe->getInstantiator( THEORY_UF )->getInternalRepresentative( a );
 }
 
+eq::EqualityEngine* EqualityQueryQuantifiersEngine::getEngine(){
+  return ((uf::TheoryUF*)d_qe->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine();
+}
+
+void EqualityQueryQuantifiersEngine::getEquivalenceClass( Node a, std::vector< Node >& eqc ){
+  eq::EqualityEngine* ee = d_qe->getTheoryEngine()->getSharedTermsDatabase()->getEqualityEngine();
+  if( ee->hasTerm( a ) ){
+    Node rep = ee->getRepresentative( a );
+    eq::EqClassIterator eqc_iter( rep, ee );
+    while( !eqc_iter.isFinished() ){
+      eqc.push_back( *eqc_iter );
+      eqc_iter++;
+    }
+  }
+  for( theory::TheoryId i=theory::THEORY_FIRST; i<theory::THEORY_LAST; ++i ){
+    if( d_qe->getInstantiator( i ) ){
+      d_qe->getInstantiator( i )->getEquivalenceClass( a, eqc );
+    }
+  }
+  if( eqc.empty() ){
+    eqc.push_back( a );
+  }
+}
+
 inst::EqualityQuery* QuantifiersEngine::getEqualityQuery(TypeNode t) {
   /** Should use skeleton (in order to have the type and the kind
       or any needed other information) instead of only the type */
@@ -745,171 +770,6 @@ inst::EqualityQuery* QuantifiersEngine::getEqualityQuery(TypeNode t) {
 }
 
 
-// // Just iterate amoung the equivalence class of the given node
-// // node::Null() *can't* be given to reset
-// class CandidateGeneratorClassGeneric : public CandidateGenerator{
-// private:
-//   //instantiator pointer
-//   EqualityEngine* d_ee;
-//   //the equality class iterator
-//   eq::EqClassIterator d_eqc;
-//   /* For the case where the given term doesn't exists in uf */
-//   Node d_retNode;
-// public:
-//   CandidateGeneratorTheoryEeClass( EqualityEngine* ee): d_ee( ee ){}
-//   ~CandidateGeneratorTheoryEeClass(){}
-//   void resetInstantiationRound(){};
-//   void reset( TNode eqc ){
-//     Assert(!eqc.isNull());
-//     if( d_ee->hasTerm( eqc ) ){
-//       /* eqc is in uf  */
-//       eqc = d_ee->getRepresentative( eqc );
-//       d_eqc = eq::EqClassIterator( eqc, d_ee );
-//       d_retNode = Node::null();
-//     }else{
-//       /* If eqc if not a term known by uf, it is the only one in its
-//          equivalence class. So we will return only it */
-//       d_retNode = eqc;
-//       d_eqc = eq::EqClassIterator();
-//     }
-//   }; //* the argument is not used
-//   TNode getNextCandidate(){
-//     if(d_retNode.isNull()){
-//       if( !d_eqc.isFinished() ) return (*(d_eqc++));
-//       else return Node::null();
-//     }else{
-//       /* the case where eqc not in uf */
-//       Node ret = d_retNode;
-//       d_retNode = Node::null(); /* d_eqc.isFinished() must be true */
-//       return ret;
-//     }
-//   };
-// };
-
-
-class GenericCandidateGeneratorClasses: public rrinst::CandidateGenerator{
-
-  /** The candidate generators */
-  rrinst::CandidateGenerator* d_can_gen[theory::THEORY_LAST];
-  /** The current theory which candidategenerator is used */
-  TheoryId d_can_gen_id;
-
-public:
-  GenericCandidateGeneratorClasses(QuantifiersEngine * qe){
-    for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
-      if(qe->getInstantiator(i) != NULL)
-        d_can_gen[i] = qe->getInstantiator(i)->getRRCanGenClasses();
-      else d_can_gen[i] = NULL;
-    };
-  }
-
-  ~GenericCandidateGeneratorClasses(){
-    for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
-      delete(d_can_gen[i]);
-    };
-  }
-
-  void resetInstantiationRound(){
-    for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
-      if(d_can_gen[i] != NULL) d_can_gen[i]->resetInstantiationRound();
-    };
-    d_can_gen_id=THEORY_FIRST;
-  }
-
-  void reset(TNode eqc){
-    Assert(eqc.isNull());
-    for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
-      if(d_can_gen[i] != NULL) d_can_gen[i]->reset(eqc);
-    };
-    d_can_gen_id=THEORY_FIRST;
-    lookForNextTheory();
-  }
-
-  TNode getNextCandidate(){
-    Assert(THEORY_FIRST <= d_can_gen_id && d_can_gen_id <= THEORY_LAST);
-    /** No more */
-    if(d_can_gen_id == THEORY_LAST) return TNode::null();
-    /** Try with this theory */
-    TNode cand = d_can_gen[d_can_gen_id]->getNextCandidate();
-    if( !cand.isNull() ) return cand;
-    lookForNextTheory();
-    return getNextCandidate();
-  }
-
-  void lookForNextTheory(){
-    do{ /* look for the next available generator */
-      ++d_can_gen_id;
-    } while( d_can_gen_id < THEORY_LAST && d_can_gen[d_can_gen_id] == NULL);
-  }
-
-};
-
-class GenericCandidateGeneratorClass: public rrinst::CandidateGenerator{
-
-  /** The candidate generators */
-  rrinst::CandidateGenerator* d_can_gen[theory::THEORY_LAST];
-  /** The current theory which candidategenerator is used */
-  TheoryId d_can_gen_id;
-  /** current node to look for equivalence class */
-  Node d_node;
-  /** QuantifierEngine */
-  QuantifiersEngine* d_qe;
-
-public:
-  GenericCandidateGeneratorClass(QuantifiersEngine * qe): d_qe(qe) {
-    for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
-      if(d_qe->getInstantiator(i) != NULL)
-        d_can_gen[i] = d_qe->getInstantiator(i)->getRRCanGenClass();
-      else d_can_gen[i] = NULL;
-    };
-  }
-
-  ~GenericCandidateGeneratorClass(){
-    for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
-      delete(d_can_gen[i]);
-    };
-  }
-
-  void resetInstantiationRound(){
-    for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
-      if(d_can_gen[i] != NULL) d_can_gen[i]->resetInstantiationRound();
-    };
-    d_can_gen_id=THEORY_FIRST;
-  }
-
-  void reset(TNode eqc){
-    for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
-      if(d_can_gen[i] != NULL) d_can_gen[i]->reset(eqc);
-    };
-    d_can_gen_id=THEORY_FIRST;
-    d_node = eqc;
-    lookForNextTheory();
-  }
-
-  TNode getNextCandidate(){
-    Assert(THEORY_FIRST <= d_can_gen_id && d_can_gen_id <= THEORY_LAST);
-    /** No more */
-    if(d_can_gen_id == THEORY_LAST) return TNode::null();
-    /** Try with this theory */
-    TNode cand = d_can_gen[d_can_gen_id]->getNextCandidate();
-    if( !cand.isNull() ) return cand;
-    lookForNextTheory();
-    return getNextCandidate();
-  }
-
-  void lookForNextTheory(){
-    do{ /* look for the next available generator, where the element is */
-      ++d_can_gen_id;
-    } while(
-            d_can_gen_id < THEORY_LAST &&
-            (d_can_gen[d_can_gen_id] == NULL ||
-             !d_qe->getInstantiator( d_can_gen_id )->hasTerm( d_node ))
-            );
-  }
-
-};
-
-
 rrinst::CandidateGenerator* QuantifiersEngine::getRRCanGenClasses() {
   return new GenericCandidateGeneratorClasses(this);
 }
@@ -932,4 +792,4 @@ rrinst::CandidateGenerator* QuantifiersEngine::getRRCanGenClass(TypeNode t) {
   // if(eq == NULL) return getInstantiator(id)->getRRCanGenClass();
   // else return eq;
   return getRRCanGenClass();
-}
+}
\ No newline at end of file
index 157c0ac5398d20688cbb8ffcc5c4e9d242cf807c..2ae620e3d29e36acf4c812e6efd730f752e6116e 100644 (file)
@@ -342,6 +342,8 @@ public:
   bool areEqual( Node a, Node b );
   bool areDisequal( Node a, Node b );
   Node getInternalRepresentative( Node a );
+  eq::EqualityEngine* getEngine();
+  void getEquivalenceClass( Node a, std::vector< Node >& eqc );
 }; /* EqualityQueryQuantifiersEngine */
 
 }/* CVC4::theory namespace */
diff --git a/src/theory/rr_candidate_generator.cpp b/src/theory/rr_candidate_generator.cpp
new file mode 100644 (file)
index 0000000..a2e895c
--- /dev/null
@@ -0,0 +1,125 @@
+/*********************                                                        */
+/*! \file rr_candidate_generator.cpp
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: bobot
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Implementation of rr candidate generator class
+ **/
+
+#include "theory/rr_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;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::rrinst;
+
+GenericCandidateGeneratorClasses::GenericCandidateGeneratorClasses(QuantifiersEngine * qe){
+  for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+    if(qe->getInstantiator(i) != NULL)
+      d_can_gen[i] = qe->getInstantiator(i)->getRRCanGenClasses();
+    else d_can_gen[i] = NULL;
+  }
+}
+
+GenericCandidateGeneratorClasses::~GenericCandidateGeneratorClasses(){
+  for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+    delete(d_can_gen[i]);
+  }
+}
+
+void GenericCandidateGeneratorClasses::resetInstantiationRound(){
+  for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+    if(d_can_gen[i] != NULL) d_can_gen[i]->resetInstantiationRound();
+  }
+  d_can_gen_id=THEORY_FIRST;
+}
+
+void GenericCandidateGeneratorClasses::reset(TNode eqc){
+  Assert(eqc.isNull());
+  for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+    if(d_can_gen[i] != NULL) d_can_gen[i]->reset(eqc);
+  }
+  d_can_gen_id=THEORY_FIRST;
+  lookForNextTheory();
+}
+
+TNode GenericCandidateGeneratorClasses::getNextCandidate(){
+  Assert(THEORY_FIRST <= d_can_gen_id && d_can_gen_id <= THEORY_LAST);
+  /** No more */
+  if(d_can_gen_id == THEORY_LAST) return TNode::null();
+  /** Try with this theory */
+  TNode cand = d_can_gen[d_can_gen_id]->getNextCandidate();
+  if( !cand.isNull() ) return cand;
+  lookForNextTheory();
+  return getNextCandidate();
+}
+
+void GenericCandidateGeneratorClasses::lookForNextTheory(){
+  do{ /* look for the next available generator */
+    ++d_can_gen_id;
+  } while( d_can_gen_id < THEORY_LAST && d_can_gen[d_can_gen_id] == NULL);
+}
+
+GenericCandidateGeneratorClass::GenericCandidateGeneratorClass(QuantifiersEngine * qe): d_qe(qe) {
+  for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+    if(d_qe->getInstantiator(i) != NULL)
+      d_can_gen[i] = d_qe->getInstantiator(i)->getRRCanGenClass();
+    else d_can_gen[i] = NULL;
+  }
+}
+
+GenericCandidateGeneratorClass::~GenericCandidateGeneratorClass(){
+  for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+    delete(d_can_gen[i]);
+  }
+}
+
+void GenericCandidateGeneratorClass::resetInstantiationRound(){
+  for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+    if(d_can_gen[i] != NULL) d_can_gen[i]->resetInstantiationRound();
+  }
+  d_can_gen_id=THEORY_FIRST;
+}
+
+void GenericCandidateGeneratorClass::reset(TNode eqc){
+  for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+    if(d_can_gen[i] != NULL) d_can_gen[i]->reset(eqc);
+  }
+  d_can_gen_id=THEORY_FIRST;
+  d_node = eqc;
+  lookForNextTheory();
+}
+
+TNode GenericCandidateGeneratorClass::getNextCandidate(){
+  Assert(THEORY_FIRST <= d_can_gen_id && d_can_gen_id <= THEORY_LAST);
+  /** No more */
+  if(d_can_gen_id == THEORY_LAST) return TNode::null();
+  /** Try with this theory */
+  TNode cand = d_can_gen[d_can_gen_id]->getNextCandidate();
+  if( !cand.isNull() ) return cand;
+  lookForNextTheory();
+  return getNextCandidate();
+}
+
+void GenericCandidateGeneratorClass::lookForNextTheory(){
+  do{ /* look for the next available generator, where the element is */
+    ++d_can_gen_id;
+  } while(
+          d_can_gen_id < THEORY_LAST &&
+          (d_can_gen[d_can_gen_id] == NULL ||
+           !d_qe->getInstantiator( d_can_gen_id )->hasTerm( d_node ))
+          );
+}
diff --git a/src/theory/rr_candidate_generator.h b/src/theory/rr_candidate_generator.h
new file mode 100644 (file)
index 0000000..30f6c06
--- /dev/null
@@ -0,0 +1,209 @@
+/*********************                                                        */
+/*! \file rr_candidate_generator.h
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: bobot
+ ** Minor contributors (to current version): mdeters
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2012  The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief rr candidate generator
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY_UF_CANDIDATE_GENERATOR_H
+#define __CVC4__THEORY_UF_CANDIDATE_GENERATOR_H
+
+#include "theory/quantifiers_engine.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/rr_inst_match.h"
+
+using namespace CVC4::theory::quantifiers;
+
+namespace CVC4 {
+namespace theory {
+namespace eq {
+
+namespace rrinst{
+typedef CVC4::theory::rrinst::CandidateGenerator CandidateGenerator;
+
+//New CandidateGenerator. They have a simpler semantic than the old one
+
+// Just iterate amoung the equivalence classes
+// node::Null() must be given to reset
+class CandidateGeneratorTheoryEeClasses : public CandidateGenerator{
+private:
+  //the equality classes iterator
+  eq::EqClassesIterator d_eq;
+  //equalityengine pointer
+  EqualityEngine* d_ee;
+public:
+  CandidateGeneratorTheoryEeClasses( EqualityEngine * ee): d_ee( ee ){}
+  ~CandidateGeneratorTheoryEeClasses(){}
+  void resetInstantiationRound(){};
+  void reset( TNode eqc ){
+    Assert(eqc.isNull());
+    d_eq = eq::EqClassesIterator( d_ee );
+  }; //* the argument is not used
+  TNode getNextCandidate(){
+    if( !d_eq.isFinished() ) return (*(d_eq++));
+    else return Node::null();
+  };
+};
+
+// Just iterate amoung the equivalence class of the given node
+// node::Null() *can't* be given to reset
+class CandidateGeneratorTheoryEeClass : public CandidateGenerator{
+private:
+  //instantiator pointer
+  EqualityEngine* d_ee;
+  //the equality class iterator
+  eq::EqClassIterator d_eqc;
+  /* For the case where the given term doesn't exists in uf */
+  Node d_retNode;
+public:
+  CandidateGeneratorTheoryEeClass( EqualityEngine* ee): d_ee( ee ){}
+  ~CandidateGeneratorTheoryEeClass(){}
+  void resetInstantiationRound(){};
+  void reset( TNode eqc ){
+    Assert(!eqc.isNull());
+    if( d_ee->hasTerm( eqc ) ){
+      /* eqc is in uf  */
+      eqc = d_ee->getRepresentative( eqc );
+      d_eqc = eq::EqClassIterator( eqc, d_ee );
+      d_retNode = Node::null();
+    }else{
+      /* If eqc if not a term known by uf, it is the only one in its
+         equivalence class. So we will return only it */
+      d_retNode = eqc;
+      d_eqc = eq::EqClassIterator();
+    }
+  }; //* the argument is not used
+  TNode getNextCandidate(){
+    if(d_retNode.isNull()){
+      if( !d_eqc.isFinished() ) return (*(d_eqc++));
+      else return Node::null();
+    }else{
+      /* the case where eqc not in uf */
+      Node ret = d_retNode;
+      d_retNode = Node::null(); /* d_eqc.isFinished() must be true */
+      return ret;
+    }
+  };
+};
+
+
+} /* namespace rrinst */
+} /* namespace eq */
+
+namespace uf{
+namespace rrinst {
+
+typedef CVC4::theory::rrinst::CandidateGenerator CandidateGenerator;
+
+class CandidateGeneratorTheoryUfOp : public CandidateGenerator{
+private:
+  Node d_op;
+  //instantiator pointer
+  TermDb* d_tdb;
+  // Since new term can appears we restrict ourself to the one that
+  // exists at resetInstantiationRound
+  size_t d_term_iter_limit;
+  size_t d_term_iter;
+public:
+  CandidateGeneratorTheoryUfOp(Node op, TermDb* tdb): d_op(op), d_tdb( tdb ){}
+  ~CandidateGeneratorTheoryUfOp(){}
+  void resetInstantiationRound(){
+    d_term_iter_limit = d_tdb->d_op_map[d_op].size();
+  };
+  void reset( TNode eqc ){
+    Assert(eqc.isNull());
+    d_term_iter = 0;
+  }; //* the argument is not used
+  TNode getNextCandidate(){
+    if( d_term_iter<d_term_iter_limit ){
+      TNode n = d_tdb->d_op_map[d_op][d_term_iter];
+      ++d_term_iter;
+      return n;
+    } else return Node::null();
+  };
+};
+
+class CandidateGeneratorTheoryUfType : public CandidateGenerator{
+private:
+  TypeNode d_type;
+  //instantiator pointer
+  TermDb* d_tdb;
+  // Since new term can appears we restrict ourself to the one that
+  // exists at resetInstantiationRound
+  size_t d_term_iter_limit;
+  size_t d_term_iter;
+public:
+  CandidateGeneratorTheoryUfType(TypeNode type, TermDb* tdb): d_type(type), d_tdb( tdb ){}
+  ~CandidateGeneratorTheoryUfType(){}
+  void resetInstantiationRound(){
+    d_term_iter_limit = d_tdb->d_type_map[d_type].size();
+  };
+  void reset( TNode eqc ){
+    Assert(eqc.isNull());
+    d_term_iter = 0;
+  }; //* the argument is not used
+  TNode getNextCandidate(){
+    if( d_term_iter<d_term_iter_limit ){
+      TNode n = d_tdb->d_type_map[d_type][d_term_iter];
+      ++d_term_iter;
+      return n;
+    } else return Node::null();
+  };
+};
+
+} /* namespace rrinst */
+} /* namespace uf */
+
+class GenericCandidateGeneratorClasses: public rrinst::CandidateGenerator{
+
+  /** The candidate generators */
+  rrinst::CandidateGenerator* d_can_gen[theory::THEORY_LAST];
+  /** The current theory which candidategenerator is used */
+  TheoryId d_can_gen_id;
+
+public:
+  GenericCandidateGeneratorClasses(QuantifiersEngine * qe);
+  ~GenericCandidateGeneratorClasses();
+
+  void resetInstantiationRound();
+  void reset(TNode eqc);
+  TNode getNextCandidate();
+  void lookForNextTheory();
+};
+
+class GenericCandidateGeneratorClass: public rrinst::CandidateGenerator{
+
+  /** The candidate generators */
+  rrinst::CandidateGenerator* d_can_gen[theory::THEORY_LAST];
+  /** The current theory which candidategenerator is used */
+  TheoryId d_can_gen_id;
+  /** current node to look for equivalence class */
+  Node d_node;
+  /** QuantifierEngine */
+  QuantifiersEngine* d_qe;
+
+public:
+  GenericCandidateGeneratorClass(QuantifiersEngine * qe);
+  ~GenericCandidateGeneratorClass();
+  void resetInstantiationRound();
+
+  void reset(TNode eqc);
+  TNode getNextCandidate();
+  void lookForNextTheory();
+};
+
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
+
+#endif /* __CVC4__THEORY_UF_INSTANTIATOR_H */
index 3ba0c8d32918b5cf87dd4ba847c9b0bf8abfeb98..287f7475ad1aa6e96972c49a23453b0376425e4a 100644 (file)
  **/
 
 #include "theory/inst_match.h"
-#include "theory/rr_inst_match.h"
-#include "theory/rr_trigger.h"
-#include "theory/rr_inst_match_impl.h"
 #include "theory/theory_engine.h"
 #include "theory/quantifiers_engine.h"
 #include "theory/uf/theory_uf_instantiator.h"
-#include "theory/uf/theory_uf_candidate_generator.h"
-#include "theory/datatypes/theory_datatypes_candidate_generator.h"
 #include "theory/uf/equality_engine.h"
 #include "theory/arrays/theory_arrays.h"
+#include "theory/datatypes/theory_datatypes.h"
+#include "theory/rr_inst_match.h"
+#include "theory/rr_trigger.h"
+#include "theory/rr_inst_match_impl.h"
+#include "theory/rr_candidate_generator.h"
 
 using namespace CVC4;
 using namespace CVC4::kind;
@@ -437,8 +437,7 @@ class OpMatcher: public Matcher{
     AuxMatcher2 am2(am3,LegalOpTest(pat.getOperator()));
     /** Iter on the equivalence class of the given term */
     uf::TheoryUF* uf = static_cast<uf::TheoryUF *>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF ));
-    eq::EqualityEngine* ee =
-      static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
+    eq::EqualityEngine* ee = static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
     CandidateGeneratorTheoryEeClass cdtUfEq(ee);
     /* Create a matcher from the candidate generator */
     AuxMatcher1 am1(cdtUfEq,am2);
@@ -474,7 +473,7 @@ class DatatypesMatcher: public Matcher{
   /* The matcher */
   typedef ApplyMatcher AuxMatcher3;
   typedef TestMatcher< AuxMatcher3, LegalOpTest > AuxMatcher2;
-  typedef CandidateGeneratorMatcher< datatypes::rrinst::CandidateGeneratorTheoryClass, AuxMatcher2> AuxMatcher1;
+  typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClass, AuxMatcher2> AuxMatcher1;
   AuxMatcher1 d_cgm;
   static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
     Assert( pat.getKind() == kind::APPLY_CONSTRUCTOR,
@@ -485,7 +484,8 @@ class DatatypesMatcher: public Matcher{
     AuxMatcher2 am2(am3,LegalOpTest(pat.getOperator()));
     /** Iter on the equivalence class of the given term */
     datatypes::TheoryDatatypes* dt = static_cast<datatypes::TheoryDatatypes *>(qe->getTheoryEngine()->getTheory( theory::THEORY_DATATYPES ));
-    datatypes::rrinst::CandidateGeneratorTheoryClass cdtDtEq(dt);
+    eq::EqualityEngine* ee = static_cast<eq::EqualityEngine*>(dt->getEqualityEngine());
+    CandidateGeneratorTheoryEeClass cdtDtEq(ee);
     /* Create a matcher from the candidate generator */
     AuxMatcher1 am1(cdtDtEq,am2);
     return am1;
index 04a15d41fac03c9ea509c1af94bf0ba76ba30efe..28bc8c7eb3d28dc7fe3464292c30bfab3285dcab 100644 (file)
@@ -22,7 +22,7 @@
 #include "theory/rr_inst_match.h"
 #include "theory/theory_engine.h"
 #include "theory/quantifiers_engine.h"
-#include "theory/uf/theory_uf_candidate_generator.h"
+#include "theory/rr_candidate_generator.h"
 #include "theory/uf/equality_engine.h"
 
 namespace CVC4 {
index 579608b59adf0686700e383847e40e68b1e69759..52e7efcc23177485a9a0698fa509c425e236043c 100644 (file)
@@ -18,7 +18,7 @@
 #include "theory/theory_engine.h"
 #include "theory/quantifiers_engine.h"
 #include "theory/uf/theory_uf_instantiator.h"
-#include "theory/uf/theory_uf_candidate_generator.h"
+#include "theory/rr_candidate_generator.h"
 #include "theory/uf/equality_engine.h"
 
 using namespace std;
index 0cf7a87743d2d3c5201bbff6e956b303fb300f1a..24551637b9d9cabf200521d6bc5ed9632b5992be 100644 (file)
@@ -777,6 +777,10 @@ public:
 
 std::ostream& operator<<(std::ostream& os, Theory::Effort level);
 
+namespace eq{
+  class EqualityEngine;
+}
+
 class Instantiator {
   friend class QuantifiersEngine;
 protected:
@@ -838,6 +842,8 @@ public:
   virtual bool areDisequal( Node a, Node b ) { return false; }
   virtual Node getRepresentative( Node a ) { return a; }
   virtual Node getInternalRepresentative( Node a ) { return getRepresentative( a ); }
+  virtual eq::EqualityEngine* getEqualityEngine() { return NULL; }
+  virtual void getEquivalenceClass( Node a, std::vector< Node >& eqc ) {}
 public:
   /** A Creator of CandidateGenerator for classes (one element in each
       equivalence class) and class (every element of one equivalence
index 8729243854c230a32533afe5f49132cefd4cc9c4..1fb7305d4518a49d60b11e9fc0e3201cec1aad1d 100644 (file)
@@ -86,7 +86,7 @@ TheoryEngine::TheoryEngine(context::Context* context,
   d_quantEngine = new QuantifiersEngine(context, this);
 
   //build model information if applicable
-  d_curr_model = new theory::DefaultModel( context, "DefaultModel" );
+  d_curr_model = new theory::DefaultModel( context, "DefaultModel", false );
   d_curr_model_builder = new theory::TheoryEngineModelBuilder( this );
 
   Rewriter::init();
@@ -409,8 +409,8 @@ void TheoryEngine::combineTheories() {
 
     Assert(d_sharedTerms.isShared(carePair.a) || carePair.a.isConst());
     Assert(d_sharedTerms.isShared(carePair.b) || carePair.b.isConst());
-    Assert(!d_sharedTerms.areEqual(carePair.a, carePair.b), "Please don't care about stuff you were notified about");
-    Assert(!d_sharedTerms.areDisequal(carePair.a, carePair.b), "Please don't care about stuff you were notified about");
+    //AJR-temp Assert(!d_sharedTerms.areEqual(carePair.a, carePair.b), "Please don't care about stuff you were notified about");
+    //AJR-temp Assert(!d_sharedTerms.areDisequal(carePair.a, carePair.b), "Please don't care about stuff you were notified about");
 
     // The equality in question
     Node equality = carePair.a < carePair.b ?
index 14ba88ba180310d7a63daa160b3ae36bbb8b885a..92573d46446a48d14721bd314854cf9f1ce1b7c1 100644 (file)
@@ -18,7 +18,7 @@
 #include "theory/theory_engine.h"
 #include "theory/quantifiers_engine.h"
 #include "theory/uf/theory_uf_instantiator.h"
-#include "theory/uf/theory_uf_candidate_generator.h"
+#include "theory/candidate_generator.h"
 #include "theory/uf/equality_engine.h"
 
 using namespace std;
@@ -284,7 +284,8 @@ bool Trigger::isUsableTrigger( Node n, Node f ){
 }
 
 bool Trigger::isAtomicTrigger( Node n ){
-  return n.getKind()==APPLY_UF || n.getKind()==SELECT || n.getKind()==STORE;
+  return n.getKind()==APPLY_UF || n.getKind()==SELECT || n.getKind()==STORE ||
+         n.getKind()==APPLY_CONSTRUCTOR || n.getKind()==APPLY_SELECTOR || n.getKind()==APPLY_TESTER;
 }
 bool Trigger::isSimpleTrigger( Node n ){
   if( isAtomicTrigger( n ) ){
index b8446761c8d2c7dc9dd3ec54bbbed4fa4b9cb430..61330bbde350dce71c9687223a1332d4d1332366 100644 (file)
@@ -19,11 +19,9 @@ libuf_la_SOURCES = \
        theory_uf_instantiator.cpp \
        theory_uf_strong_solver.h \
        theory_uf_strong_solver.cpp \
-       theory_uf_candidate_generator.h \
-       theory_uf_candidate_generator.cpp \
        inst_strategy.h \
        inst_strategy.cpp \
        theory_uf_model.h \
-       theory_uf_model.cpp
+       theory_uf_model.cpp 
 
 EXTRA_DIST = kinds
diff --git a/src/theory/uf/theory_uf_candidate_generator.cpp b/src/theory/uf/theory_uf_candidate_generator.cpp
deleted file mode 100644 (file)
index 80151d1..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*********************                                                        */
-/*! \file theory_uf_candidate_generator.cpp
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Implementation of theory uf candidate generator class
- **/
-
-#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;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::uf;
-
-namespace CVC4{
-namespace theory{
-namespace uf{
-namespace inst{
-
-CandidateGeneratorTheoryUf::CandidateGeneratorTheoryUf( InstantiatorTheoryUf* ith, Node op ) :
-  d_op( op ), d_ith( ith ), d_term_iter( -2 ){
-  Assert( !d_op.isNull() );
-}
-void CandidateGeneratorTheoryUf::resetInstantiationRound(){
-  d_term_iter_limit = d_ith->getQuantifiersEngine()->getTermDatabase()->d_op_map[d_op].size();
-}
-
-void CandidateGeneratorTheoryUf::reset( Node eqc ){
-  if( eqc.isNull() ){
-    d_term_iter = 0;
-  }else{
-    //create an equivalence class iterator in eq class eqc
-    if( ((TheoryUF*)d_ith->getTheory())->getEqualityEngine()->hasTerm( eqc ) ){
-      eqc = ((TheoryUF*)d_ith->getTheory())->getEqualityEngine()->getRepresentative( eqc );
-      d_eqc = eq::EqClassIterator( eqc, ((TheoryUF*)d_ith->getTheory())->getEqualityEngine() );
-      d_retNode = Node::null();
-    }else{
-      d_retNode = eqc;
-
-    }
-    d_term_iter = -1;
-  }
-}
-
-Node CandidateGeneratorTheoryUf::getNextCandidate(){
-  if( d_term_iter>=0 ){
-    //get next candidate term in the uf term database
-    while( d_term_iter<d_term_iter_limit ){
-      Node n = d_ith->getQuantifiersEngine()->getTermDatabase()->d_op_map[d_op][d_term_iter];
-      d_term_iter++;
-      if( isLegalCandidate( n ) ){
-        return n;
-      }
-    }
-  }else if( d_term_iter==-1 ){
-    if( d_retNode.isNull() ){
-      //get next candidate term in equivalence class
-      while( !d_eqc.isFinished() ){
-        Node n = (*d_eqc);
-        ++d_eqc;
-        if( n.getKind()==APPLY_UF && n.getOperator()==d_op ){
-          if( isLegalCandidate( n ) ){
-            return n;
-          }
-        }
-      }
-    }else{
-      Node ret;
-      if( d_retNode.hasOperator() && d_retNode.getOperator()==d_op ){
-        ret = d_retNode;
-      }
-      d_term_iter = -2; //done returning matches
-      return ret;
-    }
-  }
-  return Node::null();
-}
-
-
-//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 ){
-//  //Assert( !eqc.isNull() );
-//  ////begin iterating over equivalence classes that are disequal from eqc
-//  //d_eci = d_ith->getEquivalenceClassInfo( eqc );
-//  //if( d_eci ){
-//  //  d_eqci_iter = d_eci->d_disequal.begin();
-//  //}
-//}
-//Node CandidateGeneratorTheoryUfDisequal::getNextCandidate(){
-//  //if( d_eci ){
-//  //  while( d_eqci_iter != d_eci->d_disequal.end() ){
-//  //    if( (*d_eqci_iter).second ){
-//  //      //we have an equivalence class that is disequal from eqc
-//  //      d_cg->reset( (*d_eqci_iter).first );
-//  //      Node n = d_cg->getNextCandidate();
-//  //      //if there is a candidate in this equivalence class, return it
-//  //      if( !n.isNull() ){
-//  //        return n;
-//  //      }
-//  //    }
-//  //    ++d_eqci_iter;
-//  //  }
-//  //}
-//  return Node::null();
-//}
-
-
-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() );
-}
-Node CandidateGeneratorTheoryUfLitEq::getNextCandidate(){
-  while( d_eq.isFinished() ){
-    Node n = (*d_eq);
-    ++d_eq;
-    if( n.getType()==d_match_pattern[0].getType() ){
-      //an equivalence class with the same type as the pattern, return reflexive equality
-      return NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), n, n );
-    }
-  }
-  return Node::null();
-}
-
-
-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(
-                      NodeManager::currentNM()->mkConst<bool>(false) );
-  d_eqc_false = eq::EqClassIterator( false_term, ((TheoryUF*)d_ith->getTheory())->getEqualityEngine() );
-}
-Node CandidateGeneratorTheoryUfLitDeq::getNextCandidate(){
-  //get next candidate term in equivalence class
-  while( !d_eqc_false.isFinished() ){
-    Node n = (*d_eqc_false);
-    ++d_eqc_false;
-    if( n.getKind()==d_match_pattern.getKind() ){
-      //found an iff or equality, try to match it
-      //DO_THIS: cache to avoid redundancies?
-      //DO_THIS: do we need to try the symmetric equality for n?  or will it also exist in the eq class of false?
-      return n;
-    }
-  }
-  return Node::null();
-}
-
-}
-}
-}
-}
diff --git a/src/theory/uf/theory_uf_candidate_generator.h b/src/theory/uf/theory_uf_candidate_generator.h
deleted file mode 100644 (file)
index a06f04f..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/*********************                                                        */
-/*! \file theory_uf_candidate_generator.h
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012  The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Theory uf candidate generator
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__THEORY_UF_CANDIDATE_GENERATOR_H
-#define __CVC4__THEORY_UF_CANDIDATE_GENERATOR_H
-
-#include "theory/quantifiers_engine.h"
-#include "theory/quantifiers/term_database.h"
-#include "theory/uf/theory_uf_instantiator.h"
-#include "theory/rr_inst_match.h"
-
-using namespace CVC4::theory::quantifiers;
-
-namespace CVC4 {
-namespace theory {
-namespace eq {
-
-namespace rrinst{
-typedef CVC4::theory::rrinst::CandidateGenerator CandidateGenerator;
-
-//New CandidateGenerator. They have a simpler semantic than the old one
-
-// Just iterate amoung the equivalence classes
-// node::Null() must be given to reset
-class CandidateGeneratorTheoryEeClasses : public CandidateGenerator{
-private:
-  //the equality classes iterator
-  eq::EqClassesIterator d_eq;
-  //equalityengine pointer
-  EqualityEngine* d_ee;
-public:
-  CandidateGeneratorTheoryEeClasses( EqualityEngine * ee): d_ee( ee ){}
-  ~CandidateGeneratorTheoryEeClasses(){}
-  void resetInstantiationRound(){};
-  void reset( TNode eqc ){
-    Assert(eqc.isNull());
-    d_eq = eq::EqClassesIterator( d_ee );
-  }; //* the argument is not used
-  TNode getNextCandidate(){
-    if( !d_eq.isFinished() ) return (*(d_eq++));
-    else return Node::null();
-  };
-};
-
-// Just iterate amoung the equivalence class of the given node
-// node::Null() *can't* be given to reset
-class CandidateGeneratorTheoryEeClass : public CandidateGenerator{
-private:
-  //instantiator pointer
-  EqualityEngine* d_ee;
-  //the equality class iterator
-  eq::EqClassIterator d_eqc;
-  /* For the case where the given term doesn't exists in uf */
-  Node d_retNode;
-public:
-  CandidateGeneratorTheoryEeClass( EqualityEngine* ee): d_ee( ee ){}
-  ~CandidateGeneratorTheoryEeClass(){}
-  void resetInstantiationRound(){};
-  void reset( TNode eqc ){
-    Assert(!eqc.isNull());
-    if( d_ee->hasTerm( eqc ) ){
-      /* eqc is in uf  */
-      eqc = d_ee->getRepresentative( eqc );
-      d_eqc = eq::EqClassIterator( eqc, d_ee );
-      d_retNode = Node::null();
-    }else{
-      /* If eqc if not a term known by uf, it is the only one in its
-         equivalence class. So we will return only it */
-      d_retNode = eqc;
-      d_eqc = eq::EqClassIterator();
-    }
-  }; //* the argument is not used
-  TNode getNextCandidate(){
-    if(d_retNode.isNull()){
-      if( !d_eqc.isFinished() ) return (*(d_eqc++));
-      else return Node::null();
-    }else{
-      /* the case where eqc not in uf */
-      Node ret = d_retNode;
-      d_retNode = Node::null(); /* d_eqc.isFinished() must be true */
-      return ret;
-    }
-  };
-};
-
-
-} /* namespace rrinst */
-} /* namespace eq */
-
-namespace uf {
-namespace rrinst {
-
-typedef CVC4::theory::rrinst::CandidateGenerator CandidateGenerator;
-
-class CandidateGeneratorTheoryUfOp : public CandidateGenerator{
-private:
-  Node d_op;
-  //instantiator pointer
-  TermDb* d_tdb;
-  // Since new term can appears we restrict ourself to the one that
-  // exists at resetInstantiationRound
-  size_t d_term_iter_limit;
-  size_t d_term_iter;
-public:
-  CandidateGeneratorTheoryUfOp(Node op, TermDb* tdb): d_op(op), d_tdb( tdb ){}
-  ~CandidateGeneratorTheoryUfOp(){}
-  void resetInstantiationRound(){
-    d_term_iter_limit = d_tdb->d_op_map[d_op].size();
-  };
-  void reset( TNode eqc ){
-    Assert(eqc.isNull());
-    d_term_iter = 0;
-  }; //* the argument is not used
-  TNode getNextCandidate(){
-    if( d_term_iter<d_term_iter_limit ){
-      TNode n = d_tdb->d_op_map[d_op][d_term_iter];
-      ++d_term_iter;
-      return n;
-    } else return Node::null();
-  };
-};
-
-class CandidateGeneratorTheoryUfType : public CandidateGenerator{
-private:
-  TypeNode d_type;
-  //instantiator pointer
-  TermDb* d_tdb;
-  // Since new term can appears we restrict ourself to the one that
-  // exists at resetInstantiationRound
-  size_t d_term_iter_limit;
-  size_t d_term_iter;
-public:
-  CandidateGeneratorTheoryUfType(TypeNode type, TermDb* tdb): d_type(type), d_tdb( tdb ){}
-  ~CandidateGeneratorTheoryUfType(){}
-  void resetInstantiationRound(){
-    d_term_iter_limit = d_tdb->d_type_map[d_type].size();
-  };
-  void reset( TNode eqc ){
-    Assert(eqc.isNull());
-    d_term_iter = 0;
-  }; //* the argument is not used
-  TNode getNextCandidate(){
-    if( d_term_iter<d_term_iter_limit ){
-      TNode n = d_tdb->d_type_map[d_type][d_term_iter];
-      ++d_term_iter;
-      return n;
-    } else return Node::null();
-  };
-};
-
-} /* namespace rrinst */
-
-namespace inst{
-typedef CVC4::theory::inst::CandidateGenerator CandidateGenerator;
-
-//Old CandidateGenerator
-
-class CandidateGeneratorTheoryUfDisequal;
-
-class CandidateGeneratorTheoryUf : public CandidateGenerator
-{
-  friend class CandidateGeneratorTheoryUfDisequal;
-private:
-  //operator you are looking for
-  Node d_op;
-  //instantiator pointer
-  InstantiatorTheoryUf* d_ith;
-  //the equality class iterator
-  eq::EqClassIterator d_eqc;
-  int d_term_iter;
-  int d_term_iter_limit;
-private:
-  Node d_retNode;
-public:
-  CandidateGeneratorTheoryUf( InstantiatorTheoryUf* ith, Node op );
-  ~CandidateGeneratorTheoryUf(){}
-
-  void resetInstantiationRound();
-  void reset( Node eqc );
-  Node getNextCandidate();
-};
-
-//class CandidateGeneratorTheoryUfDisequal : public CandidateGenerator
-//{
-//private:
-//  //equivalence class 
-//  Node d_eq_class;
-//  //equivalence class info
-//  EqClassInfo* d_eci;
-//  //equivalence class iterator
-//  EqClassInfo::BoolMap::const_iterator d_eqci_iter;
-//  //instantiator pointer
-//  InstantiatorTheoryUf* d_ith;
-//public:
-//  CandidateGeneratorTheoryUfDisequal( InstantiatorTheoryUf* ith, Node eqc );
-//  ~CandidateGeneratorTheoryUfDisequal(){}
-//
-//  void resetInstantiationRound();
-//  void reset( Node eqc );   //should be what you want to be disequal from
-//  Node getNextCandidate();
-//};
-
-class CandidateGeneratorTheoryUfLitEq : public CandidateGenerator
-{
-private:
-  //the equality classes iterator
-  eq::EqClassesIterator d_eq;
-  //equality you are trying to match equalities for
-  Node d_match_pattern;
-  //einstantiator pointer
-  InstantiatorTheoryUf* d_ith;
-public:
-  CandidateGeneratorTheoryUfLitEq( InstantiatorTheoryUf* ith, Node mpat );
-  ~CandidateGeneratorTheoryUfLitEq(){}
-
-  void resetInstantiationRound();
-  void reset( Node eqc );
-  Node getNextCandidate();
-};
-
-class CandidateGeneratorTheoryUfLitDeq : public CandidateGenerator
-{
-private:
-  //the equality class iterator for false
-  eq::EqClassIterator d_eqc_false;
-  //equality you are trying to match disequalities for
-  Node d_match_pattern;
-  //einstantiator pointer
-  InstantiatorTheoryUf* d_ith;
-public:
-  CandidateGeneratorTheoryUfLitDeq( InstantiatorTheoryUf* ith, Node mpat );
-  ~CandidateGeneratorTheoryUfLitDeq(){}
-
-  void resetInstantiationRound();
-  void reset( Node eqc );
-  Node getNextCandidate();
-};
-
-
-}/* CVC4::theory::uf::inst namespace */
-}/* CVC4::theory::uf namespace */
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
-
-#endif /* __CVC4__THEORY_UF_INSTANTIATOR_H */
index 257bed0a27d5737383bdb9ba12d01db9c745d9b3..48092b340260d856b18286dd371407318c899c97 100644 (file)
@@ -17,7 +17,7 @@
 #include "theory/uf/theory_uf_instantiator.h"
 #include "theory/theory_engine.h"
 #include "theory/uf/theory_uf.h"
-#include "theory/uf/theory_uf_candidate_generator.h"
+#include "theory/rr_candidate_generator.h"
 #include "theory/uf/equality_engine.h"
 #include "theory/quantifiers/term_database.h"
 
@@ -160,15 +160,19 @@ bool InstantiatorTheoryUf::hasTerm( Node a ){
 }
 
 bool InstantiatorTheoryUf::areEqual( Node a, Node b ){
-  if( hasTerm( a ) && hasTerm( b ) ){
+  if( a==b ){
+    return true;
+  }else if( hasTerm( a ) && hasTerm( b ) ){
     return ((TheoryUF*)d_th)->d_equalityEngine.areEqual( a, b );
   }else{
-    return a==b;
+    return false;
   }
 }
 
 bool InstantiatorTheoryUf::areDisequal( Node a, Node b ){
-  if( hasTerm( a ) && hasTerm( b ) ){
+  if( a==b ){
+    return false;
+  }else if( hasTerm( a ) && hasTerm( b ) ){
     return ((TheoryUF*)d_th)->d_equalityEngine.areDisequal( a, b, false );
   }else{
     return false;
@@ -195,7 +199,7 @@ Node InstantiatorTheoryUf::getInternalRepresentative( Node a ){
         return rep;
       }else{
         //otherwise, must search eq class
-        eq::EqClassIterator eqc_iter( rep, &((TheoryUF*)d_th)->d_equalityEngine );
+        eq::EqClassIterator eqc_iter( rep, getEqualityEngine() );
         rep = Node::null();
         while( !eqc_iter.isFinished() ){
           if( !(*eqc_iter).hasAttribute(InstConstantAttribute()) ){
@@ -211,6 +215,23 @@ Node InstantiatorTheoryUf::getInternalRepresentative( Node a ){
   return d_ground_reps[a];
 }
 
+eq::EqualityEngine* InstantiatorTheoryUf::getEqualityEngine(){
+  return &((TheoryUF*)d_th)->d_equalityEngine;
+}
+
+void InstantiatorTheoryUf::getEquivalenceClass( Node a, std::vector< Node >& eqc ){
+  if( hasTerm( a ) ){
+    a = getEqualityEngine()->getRepresentative( a );
+    eq::EqClassIterator eqc_iter( a, getEqualityEngine() );
+    while( !eqc_iter.isFinished() ){
+      if( std::find( eqc.begin(), eqc.end(), *eqc_iter )==eqc.end() ){
+        eqc.push_back( *eqc_iter );
+      }
+      eqc_iter++;
+    }
+  }
+}
+
 InstantiatorTheoryUf::Statistics::Statistics():
   //d_instantiations("InstantiatorTheoryUf::Total_Instantiations", 0),
   d_instantiations_ce_solved("InstantiatorTheoryUf::Instantiations_CE-Solved", 0),
@@ -527,7 +548,7 @@ void InstantiatorTheoryUf::collectTermsIps( Ips& ips, SetNode& terms, int index
 
 bool InstantiatorTheoryUf::collectParentsTermsIps( Node n, Node f, int arg, SetNode & terms, bool addRep, bool modEq ){ //modEq default true
   bool addedTerm = false;
-  
+
   if( modEq && ((TheoryUF*)d_th)->d_equalityEngine.hasTerm( n )){
     Assert( getRepresentative( n )==n );
     //collect modulo equality
@@ -731,7 +752,7 @@ void InstantiatorTheoryUf::registerEfficientHandler( EfficientHandler& handler,
     d_pat_cand_gens[pats[i]].first->addPcDispatcher(&handler,i);
     d_pat_cand_gens[pats[i]].second->addPpDispatcher(&handler,i,i);
     d_cand_gens[op].addNewTermDispatcher(&handler,i);
-    
+
     combineMultiPpIpsMap(pp_ips_map,multi_pp_ips_map,handler,i,pats);
 
     pp_ips_map.clear();
index 3a2a5cc0ed0e399e8269bb4b5a0159e3afe524c2..d15c0103b0029cb451bf10fb1bf6afce4f907d3f 100644 (file)
@@ -431,6 +431,8 @@ public:
   bool areDisequal( Node a, Node b );
   Node getRepresentative( Node a );
   Node getInternalRepresentative( Node a );
+  eq::EqualityEngine* getEqualityEngine();
+  void getEquivalenceClass( Node a, std::vector< Node >& eqc );
   /** general creators of candidate generators */
   rrinst::CandidateGenerator* getRRCanGenClasses();
   rrinst::CandidateGenerator* getRRCanGenClass();
@@ -520,6 +522,8 @@ public:
   bool areEqual( Node a, Node b ) { return d_ith->areEqual( a, b ); }
   bool areDisequal( Node a, Node b ) { return d_ith->areDisequal( a, b ); }
   Node getInternalRepresentative( Node a ) { return d_ith->getInternalRepresentative( a ); }
+  eq::EqualityEngine* getEngine() { return d_ith->getEqualityEngine(); }
+  void getEquivalenceClass( Node a, std::vector< Node >& eqc ) { d_ith->getEquivalenceClass( a, eqc ); }
 }; /* EqualityQueryInstantiatorTheoryUf */
 
 }
index a85dea9975e0c1b0f9eaff24bbf5884b0aa3e90b..f68ab1429f8a1e38999f5f6da846dd82f88c8932 100644 (file)
@@ -34,12 +34,12 @@ using namespace CVC4::theory;
 using namespace CVC4::theory::uf;\r
 \r
 //clear\r
-void UfModelTree::clear(){\r
+void UfModelTreeNode::clear(){\r
   d_data.clear();\r
   d_value = Node::null();\r
 }\r
 \r
-bool UfModelTree::hasConcreteArgumentDefinition(){\r
+bool UfModelTreeNode::hasConcreteArgumentDefinition(){\r
   if( d_data.size()>1 ){\r
     return true;\r
   }else if( d_data.empty() ){\r
@@ -51,16 +51,16 @@ bool UfModelTree::hasConcreteArgumentDefinition(){
 }\r
 \r
 //set value function\r
-void UfModelTree::setValue( TheoryModel* m, Node n, Node v, std::vector< int >& indexOrder, bool ground, int argIndex ){\r
+void UfModelTreeNode::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
+  if( argIndex<(int)indexOrder.size() ){\r
     //take r = null when argument is the model basis\r
     Node r;\r
-    if( ground || !n[ indexOrder[argIndex] ].getAttribute(ModelBasisAttribute()) ){\r
+    if( ground || ( !n.isNull() && !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
@@ -68,7 +68,7 @@ void UfModelTree::setValue( TheoryModel* m, Node n, Node v, std::vector< int >&
 }\r
 \r
 //get value function\r
-Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int& depIndex, int argIndex ){\r
+Node UfModelTreeNode::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
@@ -82,7 +82,7 @@ Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrd
       if( i==0 ){\r
         r = m->getRepresentative( n[ indexOrder[argIndex] ] );\r
       }\r
-      std::map< Node, UfModelTree >::iterator it = d_data.find( r );\r
+      std::map< Node, UfModelTreeNode >::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
@@ -101,7 +101,7 @@ Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrd
   }\r
 }\r
 \r
-Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, std::vector< int >& depIndex, int argIndex ){\r
+Node UfModelTreeNode::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
@@ -113,7 +113,7 @@ Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrd
       if( i==0 ){\r
         r = m->getRepresentative( n[ indexOrder[argIndex] ] );\r
       }\r
-      std::map< Node, UfModelTree >::iterator it = d_data.find( r );\r
+      std::map< Node, UfModelTreeNode >::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
@@ -136,11 +136,11 @@ Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrd
   }\r
 }\r
 \r
-Node UfModelTree::getFunctionValue(){\r
+Node UfModelTreeNode::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
+    for( std::map< Node, UfModelTreeNode >::iterator it = d_data.begin(); it != d_data.end(); ++it ){\r
       if( it->first.isNull() ){\r
         defaultValue = it->second.getFunctionValue();\r
       }else{\r
@@ -166,12 +166,12 @@ Node UfModelTree::getFunctionValue(){
 }\r
 \r
 //simplify function\r
-void UfModelTree::simplify( Node op, Node defaultVal, int argIndex ){\r
+void UfModelTreeNode::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
+    std::map< Node, UfModelTreeNode >::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
@@ -188,7 +188,7 @@ void UfModelTree::simplify( Node op, Node defaultVal, int argIndex ){
       }\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
+    for( std::map< Node, UfModelTreeNode >::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
@@ -207,12 +207,12 @@ void UfModelTree::simplify( Node op, Node defaultVal, int argIndex ){
 }\r
 \r
 //is total function\r
-bool UfModelTree::isTotal( Node op, int argIndex ){\r
+bool UfModelTreeNode::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
+    std::map< Node, UfModelTreeNode >::iterator it = d_data.find( r );\r
     if( it!=d_data.end() ){\r
       return it->second.isTotal( op, argIndex+1 );\r
     }else{\r
@@ -221,7 +221,7 @@ bool UfModelTree::isTotal( Node op, int argIndex ){
   }\r
 }\r
 \r
-Node UfModelTree::getConstantValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int argIndex ){\r
+Node UfModelTreeNode::getConstantValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int argIndex ){\r
   return d_value;\r
 }\r
 \r
@@ -231,9 +231,9 @@ void indent( std::ostream& out, int ind ){
   }\r
 }\r
 \r
-void UfModelTree::debugPrint( std::ostream& out, TheoryModel* m, std::vector< int >& indexOrder, int ind, int arg ){\r
+void UfModelTreeNode::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
+    for( std::map< Node, UfModelTreeNode >::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
@@ -247,54 +247,36 @@ void UfModelTree::debugPrint( std::ostream& out, TheoryModel* m, std::vector< in
     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
+Node UfModelTree::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
-    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
+  }else{\r
+    return fm_node;\r
   }\r
 }\r
 \r
-Node UfModel::getIntersection( Node n1, Node n2, bool& isGround ){\r
+\r
+Node UfModelTreeGenerator::getIntersection( TheoryModel* m, Node n1, Node n2, bool& isGround ){\r
   //Notice() << "Get intersection " << n1 << " " << n2 << std::endl;\r
   isGround = true;\r
   std::vector< Node > children;\r
@@ -309,7 +291,7 @@ Node UfModel::getIntersection( Node n1, Node n2, bool& isGround ){
       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
+    }else if( m->areEqual( n1[i], n2[i] ) ){\r
       children.push_back( n1[i] );\r
     }else{\r
       return Node::null();\r
@@ -318,7 +300,7 @@ Node UfModel::getIntersection( Node n1, Node n2, bool& isGround ){
   return NodeManager::currentNM()->mkNode( APPLY_UF, children );\r
 }\r
 \r
-void UfModel::setValue( Node n, Node v, bool ground, bool isReq ){\r
+void UfModelTreeGenerator::setValue( TheoryModel* m, 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
@@ -332,13 +314,13 @@ void UfModel::setValue( Node n, Node v, bool ground, bool isReq ){
         //  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
+        Node ni = getIntersection( m, 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
+            setValue( m, ni, v, isGround, false );\r
           }\r
         }\r
       }\r
@@ -350,36 +332,21 @@ void UfModel::setValue( Node n, Node v, bool ground, bool isReq ){
   }\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
+void UfModelTreeGenerator::makeModel( TheoryModel* m, UfModelTree& 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( m, it->first, it->second, k==1 );\r
+      }\r
+    }\r
   }\r
-}\r
-\r
-Node UfModel::getFunctionValue(){\r
-  if( d_func_value.isNull() && d_model_constructed ){\r
-    d_func_value = d_tree.getFunctionValue();\r
+  if( !d_default_value.isNull() ){\r
+    tree.setDefaultValue( m, d_default_value );\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
+  tree.simplify();\r
 }\r
 \r
-bool UfModel::optUsePartialDefaults(){\r
+bool UfModelTreeGenerator::optUsePartialDefaults(){\r
 #ifdef USE_PARTIAL_DEFAULT_VALUES\r
   return true;\r
 #else\r
@@ -387,114 +354,14 @@ bool UfModel::optUsePartialDefaults(){
 #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
+void UfModelTreeGenerator::clear(){\r
+  d_default_value = Node::null();\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
+  d_defaults.clear();\r
 }\r
 \r
 \r
index 406c7ff3cbaea69f98ffd8be8cbbc5256c6a8bf0..47b149867889460bd847bff421ebda7d19fa9c80 100644 (file)
 \r
 namespace CVC4 {\r
 namespace theory {\r
-\r
-namespace quantifiers{\r
-  class FirstOrderModel;\r
-}\r
-\r
 namespace uf {\r
 \r
-class UfModelTree\r
+class UfModelTreeNode\r
 {\r
 public:\r
-  UfModelTree(){}\r
+  UfModelTreeNode(){}\r
   /** the data */\r
-  std::map< Node, UfModelTree > d_data;\r
+  std::map< Node, UfModelTreeNode > 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
@@ -45,150 +40,137 @@ public:
   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
+  /** setValue function */\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
+  /**  getValue function */\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
+  /** getConstant Value function */\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
+  /** 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
+class UfModelTree\r
 {\r
 private:\r
+  //the op this model is for\r
   Node d_op;\r
+  //the order we will treat the arguments\r
   std::vector< int > d_index_order;\r
-  UfModelTree d_tree;\r
+  //the data\r
+  UfModelTreeNode d_tree;\r
 public:\r
-  UfModelTreeOrdered(){}\r
-  UfModelTreeOrdered( Node op ) : d_op( op ){\r
+  //constructors\r
+  UfModelTree(){}\r
+  UfModelTree( 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
+  UfModelTree( 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
+  /** clear/reset the function */\r
   void clear() { d_tree.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, bool ground = true ){\r
     d_tree.setValue( m, n, v, d_index_order, ground, 0 );\r
   }\r
+  /** setDefaultValue function */\r
+  void setDefaultValue( TheoryModel* m, Node v ){\r
+    d_tree.setValue( m, Node::null(), v, d_index_order, false, 0 );\r
+  }\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
+    *\r
+    */\r
   Node getValue( TheoryModel* m, Node n, int& depIndex ){\r
     return d_tree.getValue( m, n, d_index_order, depIndex, 0 );\r
   }\r
+  /** -> implementation incomplete */\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
+  /** getConstantValue function\r
+    *\r
+    * given term n, where n may contain "all value" arguments, aka model basis arguments\r
+    *   if n is null, then every argument of n is considered "all value"\r
+    * if n is constant for the entire domain specified by n, then this function returns the value of its domain\r
+    * otherwise, it returns null\r
+    * for example, say the term e represents "all values"\r
+    *   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
+    *  -> implementation incomplete\r
+    */\r
   Node getConstantValue( TheoryModel* m, Node n ) {\r
     return d_tree.getConstantValue( m, n, d_index_order, 0 );\r
   }\r
+  /** getFunctionValue\r
+    *   Returns a compact representation of this function, of kind FUNCTION_MODEL.\r
+    *   See documentation in theory/uf/kinds\r
+    */\r
   Node getFunctionValue(){\r
     return d_tree.getFunctionValue();\r
   }\r
+  /** simplify the tree */\r
   void simplify() { d_tree.simplify( d_op, Node::null(), 0 ); }\r
+  /** is this tree total? */\r
   bool isTotal() { return d_tree.isTotal( d_op, 0 ); }\r
+  /** is this function constant? */\r
+  bool isConstant( TheoryModel* m ) { return !getConstantValue( m, Node::null() ).isNull(); }\r
+  /** is this tree empty? */\r
+  bool isEmpty() { return d_tree.isEmpty(); }\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
+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
-class UfModel\r
+class UfModelTreeGenerator\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
+  Node d_default_value;\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
+  Node getIntersection( TheoryModel* m, 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
+  UfModelTreeGenerator(){}\r
+  ~UfModelTreeGenerator(){}\r
+  /** set default value */\r
+  void setDefaultValue( Node v ) { d_default_value = v; }\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
+  void setValue( TheoryModel* m, Node n, Node v, bool ground = true, bool isReq = true );\r
+  /** make model */\r
+  void makeModel( TheoryModel* m, UfModelTree& tree );\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
+  /** reset */\r
+  void clear();\r
 };\r
 \r
 //this class stores temporary information useful to model engine for constructing model\r
@@ -197,6 +179,7 @@ class UfModelPreferenceData
 public:\r
   UfModelPreferenceData() : d_reconsiderModel( false ){}\r
   virtual ~UfModelPreferenceData(){}\r
+  Node d_const_val;\r
   // preferences for default values\r
   std::vector< Node > d_values;\r
   std::map< Node, std::vector< Node > > d_value_pro_con[2];\r
index e5cb7e4f85be47637521297a2b8bd2228a650373..895a7d05692920f98da6d675f3b00f068a251010 100644 (file)
@@ -1077,7 +1077,7 @@ void StrongSolverTheoryUf::newEqClass( Node n ){
     Debug("uf-ss-solver") << "StrongSolverTheoryUf: New eq class " << n << " " << tn << std::endl;
     c->newEqClass( n );
   }
-  //else if( isRelevantType( tn ) ){
+  //else if( tn.isSort() ){
   //  //Debug("uf-ss-solver") << "WAIT: StrongSolverTheoryUf: New eq class " << n << " " << tn << std::endl;
   //  //d_new_eq_class_waiting[tn].push_back( n );
   //}
@@ -1111,7 +1111,7 @@ void StrongSolverTheoryUf::assertNode( Node n, bool isDecision ){
   if( n.getKind()==CARDINALITY_CONSTRAINT ){
     TypeNode tn = n[0].getType();
     Assert( d_conf_find[tn]->getCardinality()>0 );
-    Assert( isRelevantType( tn ) );
+    Assert( tn.isSort() );
     Assert( d_conf_find[tn] );
     long nCard = n[1].getConst<Rational>().getNumerator().getLong();
     d_conf_find[tn]->assertCardinality( nCard, true );
@@ -1124,7 +1124,7 @@ void StrongSolverTheoryUf::assertNode( Node n, bool isDecision ){
     //must add new lemma
     Node nn = n[0];
     TypeNode tn = nn[0].getType();
-    Assert( isRelevantType( tn ) );
+    Assert( tn.isSort() );
     Assert( d_conf_find[tn] );
     long nCard = nn[1].getConst<Rational>().getNumerator().getLong();
     d_conf_find[tn]->assertCardinality( nCard, false );
@@ -1177,7 +1177,7 @@ void StrongSolverTheoryUf::propagate( Theory::Effort level ){
 void StrongSolverTheoryUf::preRegisterTerm( TNode n ){
   //shouldn't have to preregister this type (it may be that there are no quantifiers over tn)  FIXME
   TypeNode tn = n.getType();
-  if( isRelevantType( tn ) ){
+  if( tn.isSort() ){
     preRegisterType( tn );
   }
 }
@@ -1187,9 +1187,10 @@ void StrongSolverTheoryUf::registerQuantifier( Node f ){
   //must ensure the quantifier does not quantify over arithmetic
   for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
     TypeNode tn = f[0][i].getType();
-    if( isRelevantType( tn ) ){
+    if( tn.isSort() ){
       preRegisterType( tn );
     }else{
+      /*
       if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){
         Debug("uf-ss-na") << "Error: Cannot perform finite model finding on arithmetic quantifier";
         Debug("uf-ss-na") << " (" << f << ")";
@@ -1201,6 +1202,7 @@ void StrongSolverTheoryUf::registerQuantifier( Node f ){
         Debug("uf-ss-na") << std::endl;
         Unimplemented("Cannot perform finite model finding on datatype quantifier");
       }
+      */
     }
   }
 }
@@ -1233,7 +1235,7 @@ StrongSolverTheoryUf::ConflictFind* StrongSolverTheoryUf::getConflictFind( TypeN
   std::map< TypeNode, ConflictFind* >::iterator it = d_conf_find.find( tn );
   //pre-register the type if not done already
   if( it==d_conf_find.end() ){
-    if( isRelevantType( tn ) ){
+    if( tn.isSort() ){
       preRegisterType( tn );
       it = d_conf_find.find( tn );
     }
@@ -1332,20 +1334,10 @@ StrongSolverTheoryUf::Statistics::~Statistics(){
   StatisticsRegistry::unregisterStat(&d_max_model_size);
 }
 
-bool StrongSolverTheoryUf::isRelevantType( TypeNode t ){
-  return t!=NodeManager::currentNM()->booleanType() &&
-         t!=NodeManager::currentNM()->integerType() &&
-         t!=NodeManager::currentNM()->realType() &&
-         t!=NodeManager::currentNM()->builtinOperatorType() &&
-         !t.isFunction() &&
-         !t.isDatatype() &&
-         !t.isArray();
-}
-
 bool StrongSolverTheoryUf::involvesRelevantType( Node n ){
   if( n.getKind()==APPLY_UF ){
     for( int i=0; i<(int)n.getNumChildren(); i++ ){
-      if( isRelevantType( n[i].getType() ) ){
+      if( n[i].getType().isSort() ){
         return true;
       }
     }
index bd4c4cb22ce7de1974fa0447f0e8949d8bc1df28..479fea05f9ede7c922a671712702af3fd04a4bc4 100644 (file)
@@ -316,8 +316,6 @@ public:
   /** statistics class */
   Statistics d_statistics;
 
-  /** is relevant type */
-  static bool isRelevantType( TypeNode t );
   /** involves relevant type */
   static bool involvesRelevantType( Node n );
 };/* class StrongSolverTheoryUf */
index 8785ae0dbcbe3b74e925cafdee932086e4e89421..f3ea1171d1b42cbe498f198dae943d29dc097dba 100644 (file)
@@ -36,7 +36,8 @@ TESTS =       \
        v2l40025.cvc \
        v3l60006.cvc \
        v5l30058.cvc \
-       bug286.cvc
+       bug286.cvc \
+       wrong-sel-simp.cvc
 
 FAILING_TESTS = rec5.cvc
 
index 0adba1da76414ae5a4597a0d6bb572fbf3799631..64469cbd66f094ec62ef266f1de6319325aa42b7 100644 (file)
@@ -1,5 +1,5 @@
-% EXPECT: valid
-% EXIT: 20
+% EXPECT: invalid
+% EXIT: 10
 DATATYPE
   nat = succ(pred : nat) | zero,
   list = cons(car : tree, cdr : list) | null,
diff --git a/test/regress/regress0/datatypes/wrong-sel-simp.cvc b/test/regress/regress0/datatypes/wrong-sel-simp.cvc
new file mode 100644 (file)
index 0000000..3ba3249
--- /dev/null
@@ -0,0 +1,7 @@
+% EXPECT: invalid
+% EXIT: 10
+DATATYPE
+  nat = succ(pred : nat) | zero
+END;
+
+QUERY pred(zero) = zero;