summaryrefslogtreecommitdiff
path: root/src/theory
diff options
context:
space:
mode:
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>2012-07-27 19:27:45 +0000
committerAndrew Reynolds <andrew.j.reynolds@gmail.com>2012-07-27 19:27:45 +0000
commit9a994c449d65e64d574a423ad9caad519f8c2148 (patch)
tree3c4571098d1771f8d277406c9f6e9c5b09dcd1da /src/theory
parent4bfa927dac67bbcadf219f70e61f1d123e33944b (diff)
merging fmf-devel branch, includes refactored datatype theory, updates to model.h/cpp to prepare for release, and major refactoring of quantifiers/finite model finding. Note that new datatype theory does not insist upon any interpretation for selectors applied to incorrect constructors and consequently some answers may differ with previous version
Diffstat (limited to 'src/theory')
-rw-r--r--src/theory/Makefile.am6
-rw-r--r--src/theory/arrays/Makefile.am4
-rw-r--r--src/theory/arrays/theory_arrays_instantiator.cpp29
-rw-r--r--src/theory/arrays/theory_arrays_instantiator.h2
-rw-r--r--src/theory/arrays/theory_arrays_model.cpp70
-rw-r--r--src/theory/arrays/theory_arrays_model.h62
-rw-r--r--src/theory/candidate_generator.cpp255
-rw-r--r--src/theory/candidate_generator.h187
-rw-r--r--src/theory/datatypes/Makefile.am5
-rw-r--r--src/theory/datatypes/datatypes_rewriter.h5
-rw-r--r--src/theory/datatypes/theory_datatypes.cpp1525
-rw-r--r--src/theory/datatypes/theory_datatypes.h288
-rw-r--r--src/theory/datatypes/theory_datatypes_instantiator.cpp54
-rw-r--r--src/theory/datatypes/theory_datatypes_instantiator.h2
-rw-r--r--src/theory/inst_match.cpp71
-rw-r--r--src/theory/inst_match.h50
-rw-r--r--src/theory/inst_match_impl.h125
-rw-r--r--src/theory/model.cpp317
-rw-r--r--src/theory/model.h98
-rw-r--r--src/theory/quantifiers/Makefile.am4
-rw-r--r--src/theory/quantifiers/first_order_model.cpp88
-rw-r--r--src/theory/quantifiers/first_order_model.h15
-rw-r--r--src/theory/quantifiers/model_builder.cpp417
-rw-r--r--src/theory/quantifiers/model_builder.h91
-rw-r--r--src/theory/quantifiers/model_engine.cpp339
-rw-r--r--src/theory/quantifiers/model_engine.h67
-rw-r--r--src/theory/quantifiers/relevant_domain.cpp24
-rw-r--r--src/theory/quantifiers/rep_set_iterator.cpp298
-rw-r--r--src/theory/quantifiers/rep_set_iterator.h6
-rw-r--r--src/theory/quantifiers/term_database.cpp121
-rw-r--r--src/theory/quantifiers/term_database.h3
-rw-r--r--src/theory/quantifiers_engine.cpp192
-rw-r--r--src/theory/quantifiers_engine.h2
-rw-r--r--src/theory/rr_candidate_generator.cpp125
-rw-r--r--src/theory/rr_candidate_generator.h (renamed from src/theory/uf/theory_uf_candidate_generator.h)111
-rw-r--r--src/theory/rr_inst_match.cpp18
-rw-r--r--src/theory/rr_inst_match_impl.h2
-rw-r--r--src/theory/rr_trigger.cpp2
-rw-r--r--src/theory/theory.h6
-rw-r--r--src/theory/theory_engine.cpp6
-rw-r--r--src/theory/trigger.cpp5
-rw-r--r--src/theory/uf/Makefile.am4
-rw-r--r--src/theory/uf/theory_uf_candidate_generator.cpp182
-rw-r--r--src/theory/uf/theory_uf_instantiator.cpp35
-rw-r--r--src/theory/uf/theory_uf_instantiator.h4
-rw-r--r--src/theory/uf/theory_uf_model.cpp249
-rw-r--r--src/theory/uf/theory_uf_model.h169
-rw-r--r--src/theory/uf/theory_uf_strong_solver.cpp26
-rw-r--r--src/theory/uf/theory_uf_strong_solver.h2
49 files changed, 2957 insertions, 2811 deletions
diff --git a/src/theory/Makefile.am b/src/theory/Makefile.am
index 2bd85f712..9d6939ac9 100644
--- a/src/theory/Makefile.am
+++ b/src/theory/Makefile.am
@@ -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 \
diff --git a/src/theory/arrays/Makefile.am b/src/theory/arrays/Makefile.am
index c429fc0c6..e4c814660 100644
--- a/src/theory/arrays/Makefile.am
+++ b/src/theory/arrays/Makefile.am
@@ -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
diff --git a/src/theory/arrays/theory_arrays_instantiator.cpp b/src/theory/arrays/theory_arrays_instantiator.cpp
index ca9001fe5..67c42d124 100644
--- a/src/theory/arrays/theory_arrays_instantiator.cpp
+++ b/src/theory/arrays/theory_arrays_instantiator.cpp
@@ -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 =
diff --git a/src/theory/arrays/theory_arrays_instantiator.h b/src/theory/arrays/theory_arrays_instantiator.h
index f711229b2..23899afc1 100644
--- a/src/theory/arrays/theory_arrays_instantiator.h
+++ b/src/theory/arrays/theory_arrays_instantiator.h
@@ -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
index 000000000..49da2f851
--- /dev/null
+++ b/src/theory/arrays/theory_arrays_model.cpp
@@ -0,0 +1,70 @@
+/********************* */
+/*! \file theory_arrays_model.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_arrays_model class
+ **/
+
+#include "theory/theory_engine.h"
+#include "theory/arrays/theory_arrays_model.h"
+#include "theory/quantifiers/first_order_model.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::arrays;
+
+ArrayModel::ArrayModel( Node arr, quantifiers::FirstOrderModel* m ) : d_model( m ), d_arr( arr ){
+ Assert( arr.getKind()!=STORE );
+ //look at ground assertions
+ Node sel = NodeManager::currentNM()->mkNode( SELECT, arr, NodeManager::currentNM()->mkVar( arr.getType().getArrayIndexType() ) );
+ Node sel_op = sel.getOperator(); //FIXME: easier way to do this?
+ for( size_t i=0; i<d_model->getTermDatabase()->d_op_map[ sel_op ].size(); i++ ){
+ Node n = d_model->getTermDatabase()->d_op_map[ sel_op ][i];
+ Assert( n.getKind()==SELECT );
+ if( m->areEqual( n[0], arr ) ){
+ //d_model->getTermDatabase()->computeModelBasisArgAttribute( n );
+ //if( !n.getAttribute(NoMatchAttribute()) || n.getAttribute(ModelBasisArgAttribute())==1 ){
+ Node r = d_model->getRepresentative( n );
+ Node i = d_model->getRepresentative( n[1] );
+ d_values[i] = r;
+ //}
+ }
+ }
+}
+
+Node ArrayModel::getValue( Node n ){
+ Assert( n.getKind()==SELECT );
+ Assert( n[0]==d_arr );
+ std::map< Node, Node >::iterator it = d_values.find( n[0] );
+ if( it!=d_values.end() ){
+ return it->second;
+ }else{
+ return n;
+ //return d_default_value; TODO: guarentee I can return this here
+ }
+}
+
+void ArrayModel::setDefaultValue( Node v ){
+ d_default_value = v;
+}
+
+Node ArrayModel::getArrayValue(){
+ Node curr = d_arr; //TODO: make constant default
+ for( std::map< Node, Node >::iterator it = d_values.begin(); it != d_values.end(); ++it ){
+ curr = NodeManager::currentNM()->mkNode( STORE, curr, it->first, it->second );
+ }
+ return curr;
+}
diff --git a/src/theory/arrays/theory_arrays_model.h b/src/theory/arrays/theory_arrays_model.h
new file mode 100644
index 000000000..3895388e3
--- /dev/null
+++ b/src/theory/arrays/theory_arrays_model.h
@@ -0,0 +1,62 @@
+/********************* */
+/*! \file theory_arrays_model.h
+ ** \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 MODEL for theory of arrays
+ **/
+
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY_ARRAYS_MODEL_H
+#define __CVC4__THEORY_ARRAYS_MODEL_H
+
+#include "theory/quantifiers_engine.h"
+
+namespace CVC4 {
+namespace theory {
+
+namespace quantifiers{
+ class FirstOrderModel;
+}
+
+namespace arrays {
+
+class ArrayModel{
+protected:
+ /** reference to model */
+ quantifiers::FirstOrderModel* d_model;
+ /** the array this model is for */
+ Node d_arr;
+public:
+ ArrayModel(){}
+ ArrayModel( Node arr, quantifiers::FirstOrderModel* m );
+ ~ArrayModel() {}
+public:
+ /** pre-defined values */
+ std::map< Node, Node > d_values;
+ /** default value */
+ Node d_default_value;
+ /** get value, return arguments that the value depends on */
+ Node getValue( Node n );
+ /** set default */
+ void setDefaultValue( Node v );
+public:
+ /** get array value */
+ Node getArrayValue();
+};/* class ArrayModel */
+
+}
+}
+}
+
+#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
index 000000000..ffecaa8da
--- /dev/null
+++ b/src/theory/candidate_generator.cpp
@@ -0,0 +1,255 @@
+/********************* */
+/*! \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/candidate_generator.h"
+#include "theory/theory_engine.h"
+#include "theory/uf/theory_uf.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/inst_match.h"
+#include "theory/quantifiers_engine.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::inst;
+
+bool CandidateGenerator::isLegalCandidate( Node n ){
+ return ( !n.getAttribute(NoMatchAttribute()) && ( !Options::current()->cbqi || !n.hasAttribute(InstConstantAttribute()) ) );
+}
+
+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();
+ }
+}
+
+#if 0
+
+CandidateGeneratorQE::CandidateGeneratorQE( QuantifiersEngine* qe, Node op ) :
+ d_op( op ), d_qe( qe ), d_term_iter( -2 ){
+ Assert( !d_op.isNull() );
+}
+void CandidateGeneratorQE::resetInstantiationRound(){
+ d_term_iter_limit = d_qe->getTermDatabase()->d_op_map[d_op].size();
+}
+
+void CandidateGeneratorQE::reset( Node eqc ){
+ if( eqc.isNull() ){
+ d_term_iter = 0;
+ }else{
+ //create an equivalence class iterator in eq class eqc
+ if( d_qe->getEqualityQuery()->getEngine()->hasTerm( eqc ) ){
+ eqc = d_qe->getEqualityQuery()->getEngine()->getRepresentative( eqc );
+ d_eqc = eq::EqClassIterator( eqc, d_qe->getEqualityQuery()->getEngine() );
+ d_retNode = Node::null();
+ }else{
+ d_retNode = eqc;
+ }
+ d_term_iter = -1;
+ }
+}
+
+Node CandidateGeneratorQE::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_qe->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.hasOperator() && 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();
+}
+
+#else
+
+
+CandidateGeneratorQE::CandidateGeneratorQE( QuantifiersEngine* qe, Node op ) :
+ d_op( op ), d_qe( qe ), d_term_iter( -1 ){
+ Assert( !d_op.isNull() );
+}
+void CandidateGeneratorQE::resetInstantiationRound(){
+ d_term_iter_limit = d_qe->getTermDatabase()->d_op_map[d_op].size();
+}
+
+void CandidateGeneratorQE::reset( Node eqc ){
+ d_term_iter = 0;
+ if( eqc.isNull() ){
+ d_using_term_db = true;
+ }else{
+ //create an equivalence class iterator in eq class eqc
+ d_eqc.clear();
+ d_qe->getEqualityQuery()->getEquivalenceClass( eqc, d_eqc );
+ d_using_term_db = false;
+ }
+}
+
+Node CandidateGeneratorQE::getNextCandidate(){
+ if( d_term_iter>=0 ){
+ if( d_using_term_db ){
+ //get next candidate term in the uf term database
+ while( d_term_iter<d_term_iter_limit ){
+ Node n = d_qe->getTermDatabase()->d_op_map[d_op][d_term_iter];
+ d_term_iter++;
+ if( isLegalCandidate( n ) ){
+ return n;
+ }
+ }
+ }else{
+ while( d_term_iter<(int)d_eqc.size() ){
+ Node n = d_eqc[d_term_iter];
+ d_term_iter++;
+ if( n.hasOperator() && n.getOperator()==d_op ){
+ if( isLegalCandidate( n ) ){
+ return n;
+ }
+ }
+ }
+ }
+ }
+ return Node::null();
+}
+
+#endif
+
+//CandidateGeneratorQEDisequal::CandidateGeneratorQEDisequal( QuantifiersEngine* qe, Node eqc ) :
+// d_qe( qe ), d_eq_class( eqc ){
+// d_eci = NULL;
+//}
+//void CandidateGeneratorQEDisequal::resetInstantiationRound(){
+//
+//}
+////we will iterate over all terms that are disequal from eqc
+//void CandidateGeneratorQEDisequal::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 CandidateGeneratorQEDisequal::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();
+//}
+
+
+CandidateGeneratorQELitEq::CandidateGeneratorQELitEq( QuantifiersEngine* qe, Node mpat ) :
+ d_match_pattern( mpat ), d_qe( qe ){
+
+}
+void CandidateGeneratorQELitEq::resetInstantiationRound(){
+
+}
+void CandidateGeneratorQELitEq::reset( Node eqc ){
+ d_eq = eq::EqClassesIterator( d_qe->getEqualityQuery()->getEngine() );
+}
+Node CandidateGeneratorQELitEq::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();
+}
+
+
+CandidateGeneratorQELitDeq::CandidateGeneratorQELitDeq( QuantifiersEngine* qe, Node mpat ) :
+ d_match_pattern( mpat ), d_qe( qe ){
+
+}
+void CandidateGeneratorQELitDeq::resetInstantiationRound(){
+
+}
+void CandidateGeneratorQELitDeq::reset( Node eqc ){
+ Node false_term = d_qe->getEqualityQuery()->getEngine()->getRepresentative( NodeManager::currentNM()->mkConst<bool>(false) );
+ d_eqc_false = eq::EqClassIterator( false_term, d_qe->getEqualityQuery()->getEngine() );
+}
+Node CandidateGeneratorQELitDeq::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/candidate_generator.h b/src/theory/candidate_generator.h
new file mode 100644
index 000000000..2152f1ef6
--- /dev/null
+++ b/src/theory/candidate_generator.h
@@ -0,0 +1,187 @@
+/********************* */
+/*! \file 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__CANDIDATE_GENERATOR_H
+#define __CVC4__CANDIDATE_GENERATOR_H
+
+#include "theory/theory.h"
+#include "theory/uf/equality_engine.h"
+
+namespace CVC4 {
+namespace theory {
+
+class QuantifiersEngine;
+
+namespace inst {
+
+/** base class for generating candidates for matching */
+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 CandidateGeneratorQEDisequal;
+
+#if 0
+
+class CandidateGeneratorQE : public CandidateGenerator
+{
+ friend class CandidateGeneratorQEDisequal;
+private:
+ //operator you are looking for
+ Node d_op;
+ //instantiator pointer
+ QuantifiersEngine* d_qe;
+ //the equality class iterator
+ eq::EqClassIterator d_eqc;
+ int d_term_iter;
+ int d_term_iter_limit;
+private:
+ Node d_retNode;
+public:
+ CandidateGeneratorQE( QuantifiersEngine* qe, Node op );
+ ~CandidateGeneratorQE(){}
+
+ void resetInstantiationRound();
+ void reset( Node eqc );
+ Node getNextCandidate();
+};
+
+#else
+
+class CandidateGeneratorQE : public CandidateGenerator
+{
+ friend class CandidateGeneratorQEDisequal;
+private:
+ //operator you are looking for
+ Node d_op;
+ //instantiator pointer
+ QuantifiersEngine* d_qe;
+ //the equality class iterator
+ std::vector< Node > d_eqc;
+ int d_term_iter;
+ int d_term_iter_limit;
+ bool d_using_term_db;
+public:
+ CandidateGeneratorQE( QuantifiersEngine* qe, Node op );
+ ~CandidateGeneratorQE(){}
+
+ void resetInstantiationRound();
+ void reset( Node eqc );
+ Node getNextCandidate();
+};
+
+#endif
+
+//class CandidateGeneratorQEDisequal : 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
+// QuantifiersEngine* d_qe;
+//public:
+// CandidateGeneratorQEDisequal( QuantifiersEngine* qe, Node eqc );
+// ~CandidateGeneratorQEDisequal(){}
+//
+// void resetInstantiationRound();
+// void reset( Node eqc ); //should be what you want to be disequal from
+// Node getNextCandidate();
+//};
+
+class CandidateGeneratorQELitEq : 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
+ QuantifiersEngine* d_qe;
+public:
+ CandidateGeneratorQELitEq( QuantifiersEngine* qe, Node mpat );
+ ~CandidateGeneratorQELitEq(){}
+
+ void resetInstantiationRound();
+ void reset( Node eqc );
+ Node getNextCandidate();
+};
+
+class CandidateGeneratorQELitDeq : 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
+ QuantifiersEngine* d_qe;
+public:
+ CandidateGeneratorQELitDeq( QuantifiersEngine* qe, Node mpat );
+ ~CandidateGeneratorQELitDeq(){}
+
+ void resetInstantiationRound();
+ void reset( Node eqc );
+ Node getNextCandidate();
+};
+
+}/* CVC4::theory::inst namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
+
+#endif /* __CVC4__THEORY_UF_INSTANTIATOR_H */
diff --git a/src/theory/datatypes/Makefile.am b/src/theory/datatypes/Makefile.am
index f282ce74d..0e6197ac1 100644
--- a/src/theory/datatypes/Makefile.am
+++ b/src/theory/datatypes/Makefile.am
@@ -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
diff --git a/src/theory/datatypes/datatypes_rewriter.h b/src/theory/datatypes/datatypes_rewriter.h
index ea1409108..5bae534e1 100644
--- a/src/theory/datatypes/datatypes_rewriter.h
+++ b/src/theory/datatypes/datatypes_rewriter.h
@@ -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]) {
diff --git a/src/theory/datatypes/theory_datatypes.cpp b/src/theory/datatypes/theory_datatypes.cpp
index cb0f75c12..b7f4f39d5 100644
--- a/src/theory/datatypes/theory_datatypes.cpp
+++ b/src/theory/datatypes/theory_datatypes.cpp
@@ -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;
+ }
}
-
diff --git a/src/theory/datatypes/theory_datatypes.h b/src/theory/datatypes/theory_datatypes.h
index 80c20a7d9..6d9672f95 100644
--- a/src/theory/datatypes/theory_datatypes.h
+++ b/src/theory/datatypes/theory_datatypes.h
@@ -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 */
diff --git a/src/theory/datatypes/theory_datatypes_instantiator.cpp b/src/theory/datatypes/theory_datatypes_instantiator.cpp
index 57e9324df..b4b85c9fb 100644
--- a/src/theory/datatypes/theory_datatypes_instantiator.cpp
+++ b/src/theory/datatypes/theory_datatypes_instantiator.cpp
@@ -15,10 +15,10 @@
**/
#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);
}
diff --git a/src/theory/datatypes/theory_datatypes_instantiator.h b/src/theory/datatypes/theory_datatypes_instantiator.h
index fd7190a22..fe43f2cfc 100644
--- a/src/theory/datatypes/theory_datatypes_instantiator.h
+++ b/src/theory/datatypes/theory_datatypes_instantiator.h
@@ -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 */
diff --git a/src/theory/inst_match.cpp b/src/theory/inst_match.cpp
index 4f1bfe67e..c90483fa3 100644
--- a/src/theory/inst_match.cpp
+++ b/src/theory/inst_match.cpp
@@ -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 ){
diff --git a/src/theory/inst_match.h b/src/theory/inst_match.h
index 31a59b261..2b402779d 100644
--- a/src/theory/inst_match.h
+++ b/src/theory/inst_match.h
@@ -19,16 +19,14 @@
#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
index 8ac5fd34f..000000000
--- a/src/theory/inst_match_impl.h
+++ /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 */
diff --git a/src/theory/model.cpp b/src/theory/model.cpp
index 609275a98..aa2c2d938 100644
--- a/src/theory/model.cpp
+++ b/src/theory/model.cpp
@@ -17,6 +17,8 @@
#include "theory/model.h"
#include "theory/quantifiers_engine.h"
#include "theory/theory_engine.h"
+#include "util/datatype.h"
+#include "theory/uf/theory_uf_model.h"
using namespace std;
using namespace CVC4;
@@ -72,6 +74,11 @@ d_equalityEngine( c, name ){
d_false = NodeManager::currentNM()->mkConst( false );
}
+void TheoryModel::reset(){
+ d_reps.clear();
+ d_rep_set.clear();
+}
+
void TheoryModel::addDefineFunction( Node n ){
d_define_funcs.push_back( n );
d_defines.push_back( 0 );
@@ -84,31 +91,32 @@ void TheoryModel::addDefineType( TypeNode tn ){
void TheoryModel::toStreamFunction( Node n, std::ostream& out ){
out << "(" << n;
- //out << " : " << n.getType();
+ out << " : " << n.getType();
out << " ";
Node value = getValue( n );
+ /*
if( n.getType().isSort() ){
- int index = d_ra.getIndexFor( value );
+ int index = d_rep_set.getIndexFor( value );
if( index!=-1 ){
out << value.getType() << "_" << index;
}else{
out << value;
}
}else{
- out << value;
- }
+ */
+ out << value;
out << ")" << std::endl;
}
void TheoryModel::toStreamType( TypeNode tn, std::ostream& out ){
out << "(" << tn;
if( tn.isSort() ){
- if( d_ra.d_type_reps.find( tn )!=d_ra.d_type_reps.end() ){
- out << " " << d_ra.d_type_reps[tn].size();
+ if( d_rep_set.d_type_reps.find( tn )!=d_rep_set.d_type_reps.end() ){
+ out << " " << d_rep_set.d_type_reps[tn].size();
//out << " (";
- //for( size_t i=0; i<d_ra.d_type_reps[tn].size(); i++ ){
+ //for( size_t i=0; i<d_rep_set.d_type_reps[tn].size(); i++ ){
// if( i>0 ){ out << " "; }
- // out << d_ra.d_type_reps[tn][i];
+ // out << d_rep_set.d_type_reps[tn][i];
//}
//out << ")";
}
@@ -117,6 +125,22 @@ void TheoryModel::toStreamType( TypeNode tn, std::ostream& out ){
}
void TheoryModel::toStream( std::ostream& out ){
+ /*//for debugging
+ eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &d_equalityEngine );
+ while( !eqcs_i.isFinished() ){
+ Node eqc = (*eqcs_i);
+ Debug("get-model-debug") << eqc << " : " << eqc.getType() << " : " << std::endl;
+ out << " ";
+ //add terms to model
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &d_equalityEngine );
+ while( !eqc_i.isFinished() ){
+ out << (*eqc_i) << " ";
+ ++eqc_i;
+ }
+ out << std::endl;
+ ++eqcs_i;
+ }
+ */
int funcIndex = 0;
int typeIndex = 0;
for( size_t i=0; i<d_defines.size(); i++ ){
@@ -178,22 +202,14 @@ Node TheoryModel::getValue( TNode n ){
//otherwise, get the interpreted value in the model
return getInterpretedValue( nn );
}
-
- ////case for equality
- //if( n.getKind()==EQUAL ){
- // Debug("model") << "-> Equality." << std::endl;
- // Node n1 = getValue( n[0] );
- // Node n2 = getValue( n[1] );
- // return NodeManager::currentNM()->mkConst( n1==n2 );
- //}
}
Node TheoryModel::getDomainValue( TypeNode tn, std::vector< Node >& exclude ){
- if( d_ra.d_type_reps.find( tn )!=d_ra.d_type_reps.end() ){
+ if( d_rep_set.d_type_reps.find( tn )!=d_rep_set.d_type_reps.end() ){
//try to find a pre-existing arbitrary element
- for( size_t i=0; i<d_ra.d_type_reps[tn].size(); i++ ){
- if( std::find( exclude.begin(), exclude.end(), d_ra.d_type_reps[tn][i] )==exclude.end() ){
- return d_ra.d_type_reps[tn][i];
+ for( size_t i=0; i<d_rep_set.d_type_reps[tn].size(); i++ ){
+ if( std::find( exclude.begin(), exclude.end(), d_rep_set.d_type_reps[tn][i] )==exclude.end() ){
+ return d_rep_set.d_type_reps[tn][i];
}
}
}
@@ -203,10 +219,10 @@ Node TheoryModel::getDomainValue( TypeNode tn, std::vector< Node >& exclude ){
//FIXME: use the theory enumerator to generate constants here
Node TheoryModel::getNewDomainValue( TypeNode tn ){
if( tn==NodeManager::currentNM()->booleanType() ){
- if( d_ra.d_type_reps[tn].empty() ){
+ if( d_rep_set.d_type_reps[tn].empty() ){
return d_false;
- }else if( d_ra.d_type_reps[tn].size()==1 ){
- return NodeManager::currentNM()->mkConst( areEqual( d_ra.d_type_reps[tn][0], d_false ) );
+ }else if( d_rep_set.d_type_reps[tn].size()==1 ){
+ return NodeManager::currentNM()->mkConst( areEqual( d_rep_set.d_type_reps[tn][0], d_false ) );
}else{
return Node::null();
}
@@ -214,7 +230,7 @@ Node TheoryModel::getNewDomainValue( TypeNode tn ){
int val = 0;
do{
Node r = NodeManager::currentNM()->mkConst( Rational(val) );
- 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() &&
+ 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() &&
!d_equalityEngine.hasTerm( r ) ){
return r;
}
@@ -272,7 +288,8 @@ bool TheoryModel::hasTerm( Node a ){
Node TheoryModel::getRepresentative( Node a ){
if( d_equalityEngine.hasTerm( a ) ){
- return d_reps[ d_equalityEngine.getRepresentative( a ) ];
+ Node r = d_equalityEngine.getRepresentative( a );
+ return d_reps[ r ];
}else{
return a;
}
@@ -326,15 +343,49 @@ void TheoryModel::printRepresentative( std::ostream& out, Node r ){
}
}
-DefaultModel::DefaultModel( context::Context* c, std::string name ) : TheoryModel( c, name ){
+DefaultModel::DefaultModel( context::Context* c, std::string name, bool enableFuncModels ) :
+TheoryModel( c, name ), d_enableFuncModels( enableFuncModels ){
+
+}
+
+void DefaultModel::addTerm( Node n ){
+ //must collect UF terms
+ if( d_enableFuncModels && n.getKind()==APPLY_UF ){
+ d_uf_terms[ n.getOperator() ].push_back( n );
+ }
+}
+void DefaultModel::reset(){
+ d_uf_terms.clear();
+ d_uf_models.clear();
+ TheoryModel::reset();
}
Node DefaultModel::getInterpretedValue( TNode n ){
TypeNode type = n.getType();
if( type.isFunction() || type.isPredicate() ){
- //DO_THIS?
- return n;
+ //for function models
+ if( d_enableFuncModels ){
+ if( d_uf_models.find( n )==d_uf_models.end() ){
+ uf::UfModelTree ufmt( n );
+ Node default_v;
+ for( size_t i=0; i<d_uf_terms[n].size(); i++ ){
+ Node un = d_uf_terms[n][i];
+ Node v = getRepresentative( un );
+ ufmt.setValue( this, un, v );
+ default_v = v;
+ }
+ if( default_v.isNull() ){
+ default_v = getInterpretedValue( NodeManager::currentNM()->mkVar( type.getRangeType() ) );
+ }
+ ufmt.setDefaultValue( this, default_v );
+ ufmt.simplify();
+ d_uf_models[n] = ufmt.getFunctionValue();
+ }
+ return d_uf_models[n];
+ }else{
+ return n;
+ }
}else{
//first, see if the representative is defined
if( d_equalityEngine.hasTerm( n ) ){
@@ -370,67 +421,195 @@ TheoryEngineModelBuilder::TheoryEngineModelBuilder( TheoryEngine* te ) : d_te( t
void TheoryEngineModelBuilder::buildModel( Model* m ){
TheoryModel* tm = (TheoryModel*)m;
//reset representative information
- tm->d_reps.clear();
- tm->d_ra.clear();
- Debug( "model-builder" ) << "TheoryEngineModelBuilder: Collect model info..." << std::endl;
+ tm->reset();
//collect model info from the theory engine
+ Debug( "model-builder" ) << "TheoryEngineModelBuilder: Collect model info..." << std::endl;
d_te->collectModelInfo( tm );
+ //unresolved equivalence classes
+ std::map< Node, bool > unresolved_eqc;
+ std::map< TypeNode, bool > unresolved_types;
+ std::map< Node, std::vector< Node > > selects;
+ std::map< Node, Node > apply_constructors;
Debug( "model-builder" ) << "TheoryEngineModelBuilder: Build representatives..." << std::endl;
- //populate term database, store representatives
+ //populate term database, store constant representatives
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &tm->d_equalityEngine );
while( !eqcs_i.isFinished() ){
Node eqc = (*eqcs_i);
- //add terms to model
+ TypeNode eqct = eqc.getType();
+ //initialize unresolved type information
+ initializeType( eqct, unresolved_types );
+ //add terms to model, get constant rep if possible
+ Node const_rep;
eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &tm->d_equalityEngine );
while( !eqc_i.isFinished() ){
- tm->addTerm( *eqc_i );
+ Node n = *eqc_i;
+ //check if this is constant, if so, we will use it as representative
+ if( n.getMetaKind()==kind::metakind::CONSTANT ){
+ const_rep = n;
+ }
+ //theory-specific information needed
+ if( n.getKind()==SELECT ){
+ selects[ n[0] ].push_back( n );
+ }else if( n.getKind()==APPLY_CONSTRUCTOR ){
+ apply_constructors[ eqc ] = n;
+ }
+ //model-specific processing of the term, this will include
+ tm->addTerm( n );
++eqc_i;
}
- //choose representative for this equivalence class
- Node rep = chooseRepresentative( tm, eqc );
//store representative in representative set
- if( !rep.isNull() ){
- tm->d_reps[ eqc ] = rep;
- tm->d_ra.add( rep );
+ if( !const_rep.isNull() ){
+ //Message() << "Constant rep " << const_rep << " for " << eqc << std::endl;
+ tm->d_reps[ eqc ] = const_rep;
+ tm->d_rep_set.add( const_rep );
+ }else{
+ //Message() << "** unresolved eqc " << eqc << std::endl;
+ unresolved_eqc[ eqc ] = true;
+ unresolved_types[ eqct ] = true;
}
++eqcs_i;
}
- //do model-builder specific initialization
- // this should include choosing representatives for equivalence classes that have not yet been
- // assigned representatives
+ //choose representatives for unresolved equivalence classes
+ Debug( "model-builder" ) << "TheoryEngineModelBuilder: Complete model..." << std::endl;
+ bool fixedPoint;
+ do{
+ fixedPoint = true;
+ //for calculating unresolved types
+ std::map< TypeNode, bool > unresolved_types_next;
+ for( std::map< TypeNode, bool >::iterator it = unresolved_types.begin(); it != unresolved_types.end(); ++it ){
+ unresolved_types_next[ it->first ] = false;
+ }
+ //try to resolve each unresolved equivalence class
+ for( std::map< Node, bool >::iterator it = unresolved_eqc.begin(); it != unresolved_eqc.end(); ++it ){
+ if( it->second ){
+ Node n = it->first;
+ TypeNode tn = n.getType();
+ Node rep;
+ bool mkRep = true;
+ if( tn.isArray() ){
+ TypeNode index_t = tn.getArrayIndexType();
+ TypeNode elem_t = tn.getArrayConstituentType();
+ if( !unresolved_types[ index_t ] && !unresolved_types[ elem_t ] ){
+ //collect all relevant set values of n
+ std::vector< Node > arr_selects;
+ std::vector< Node > arr_select_values;
+ Node nbase = n;
+ while( nbase.getKind()==STORE ){
+ arr_selects.push_back( tm->getRepresentative( nbase[1] ) );
+ arr_select_values.push_back( tm->getRepresentative( nbase[2] ) );
+ nbase = nbase[0];
+ }
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( n, &tm->d_equalityEngine );
+ while( !eqc_i.isFinished() ){
+ for( int i=0; i<(int)selects[ *eqc_i ].size(); i++ ){
+ Node r = tm->getRepresentative( selects[ *eqc_i ][i][1] );
+ if( std::find( arr_selects.begin(), arr_selects.end(), r )==arr_selects.end() ){
+ arr_selects.push_back( r );
+ arr_select_values.push_back( tm->getRepresentative( selects[ *eqc_i ][i] ) );
+ }
+ }
+ ++eqc_i;
+ }
+ //now, construct based on select/value pairs
+ //TODO: make this a constant
+ rep = chooseRepresentative( tm, nbase );
+ for( int i=0; i<(int)arr_selects.size(); i++ ){
+ rep = NodeManager::currentNM()->mkNode( STORE, rep, arr_selects[i], arr_select_values[i] );
+ }
+ }
+ mkRep = false;
+ }else if( tn.isDatatype() ){
+ if( apply_constructors.find( n )!=apply_constructors.end() ){
+ Node ac = apply_constructors[n];
+ std::vector< Node > children;
+ children.push_back( ac.getOperator() );
+ for( size_t i = 0; i<ac.getNumChildren(); i++ ){
+ Node acir = ac[i];
+ if( tm->d_equalityEngine.hasTerm( acir ) ){
+ acir = tm->d_equalityEngine.getRepresentative( acir );
+ }
+ if( unresolved_eqc.find( acir )==unresolved_eqc.end() ){
+ Message() << "TheoryEngineModelBuilder::buildModel : Datatype argument does not exist in the model " << acir << std::endl;
+ acir = Node::null();
+ }
+ if( acir.isNull() || unresolved_eqc[ acir ] ){
+ mkRep = false;
+ break;
+ }else{
+ children.push_back( tm->getRepresentative( acir ) );
+ }
+ }
+ if( mkRep ){
+ rep = NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, children );
+ }
+ }else{
+ Message() << "TheoryEngineModelBuilder::buildModel : Do not know how to resolve datatype equivalence class " << n << std::endl;
+ }
+ mkRep = false;
+ }
+ if( mkRep ){
+ rep = chooseRepresentative( tm, n );
+ }
+ if( !rep.isNull() ){
+ tm->assertEquality( n, rep, true );
+ tm->d_reps[ n ] = rep;
+ tm->d_rep_set.add( rep );
+ unresolved_eqc[ n ] = false;
+ fixedPoint = false;
+ }else{
+ unresolved_types_next[ tn ] = true;
+ }
+ }
+ }
+ //for calculating unresolved types
+ for( std::map< TypeNode, bool >::iterator it = unresolved_types.begin(); it != unresolved_types.end(); ++it ){
+ unresolved_types[ it->first ] = unresolved_types_next[ it->first ];
+ }
+ }while( !fixedPoint );
+
+ //for all unresolved equivalence classes, just get new domain value
+ // this should typically never happen (all equivalence classes should be resolved at this point)
+ for( std::map< Node, bool >::iterator it = unresolved_eqc.begin(); it != unresolved_eqc.end(); ++it ){
+ if( it->second ){
+ Node n = it->first;
+ Node rep = chooseRepresentative( tm, n );
+ tm->assertEquality( n, rep, true );
+ tm->d_reps[ n ] = rep;
+ tm->d_rep_set.add( rep );
+ //FIXME: Assertion failure here?
+ Message() << "Warning : Unresolved eqc, assigning " << rep << " for eqc( " << n << " ), type = " << n.getType() << std::endl;
+ }
+ }
+
+ //model-specific initialization
processBuildModel( tm );
}
-Node TheoryEngineModelBuilder::chooseRepresentative( TheoryModel* tm, Node eqc ){
- eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &tm->d_equalityEngine );
- while( !eqc_i.isFinished() ){
- //if constant, use this as representative
- if( (*eqc_i).getMetaKind()==kind::metakind::CONSTANT ){
- return *eqc_i;
+void TheoryEngineModelBuilder::initializeType( TypeNode tn, std::map< TypeNode, bool >& unresolved_types ){
+ if( unresolved_types.find( tn )==unresolved_types.end() ){
+ unresolved_types[tn] = false;
+ if( tn.isArray() ){
+ initializeType( tn.getArrayIndexType(), unresolved_types );
+ initializeType( tn.getArrayConstituentType(), unresolved_types );
+ }else if( tn.isDatatype() ){
+ const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ for( size_t i = 0; i<dt.getNumConstructors(); i++ ){
+ for( size_t j = 0; j<dt[i].getNumArgs(); j++ ){
+ initializeType( TypeNode::fromType( dt[i][j].getType() ), unresolved_types );
+ }
+ }
}
- ++eqc_i;
}
- return Node::null();
}
-void TheoryEngineModelBuilder::processBuildModel( TheoryModel* tm ){
- Debug( "model-builder" ) << "TheoryEngineModelBuilder: Complete model..." << std::endl;
- //create constants for all unresolved equivalence classes
- eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &tm->d_equalityEngine );
- while( !eqcs_i.isFinished() ){
- Node n = *eqcs_i;
- if( tm->d_reps.find( n )!=tm->d_reps.end() ){
- TypeNode tn = n.getType();
- //add new constant to equivalence class
- Node rep = tm->getNewDomainValue( tn );
- if( !rep.isNull() ){
- tm->assertEquality( n, rep, true );
- }else{
- rep = n;
- }
- tm->d_reps[ n ] = rep;
- tm->d_ra.add( rep );
- }
- ++eqcs_i;
+Node TheoryEngineModelBuilder::chooseRepresentative( TheoryModel* m, Node eqc ){
+ //try to get a new domain value
+ Node rep = m->getNewDomainValue( eqc.getType() );
+ if( !rep.isNull() ){
+ return rep;
+ }else{
+ //if we can't get new domain value, just return eqc itself (this typically should not happen)
+ //FIXME: Assertion failure here?
+ return eqc;
}
}
diff --git a/src/theory/model.h b/src/theory/model.h
index 278f85dfe..415b008ef 100644
--- a/src/theory/model.h
+++ b/src/theory/model.h
@@ -60,16 +60,23 @@ class TheoryModel : public Model
{
friend class TheoryEngineModelBuilder;
protected:
- /** add term */
+ /** add term function
+ * This should be called on all terms that exist in the model.
+ * addTerm( n ) will do any model-specific processing necessary for n,
+ * such as contraining the interpretation of uninterpretted functions.
+ */
virtual void addTerm( Node n ) {}
private:
- /** definitions */
+ /** List of definitions that the user has given
+ * This is necessary for supporting the get-model command.
+ */
std::vector< Node > d_define_funcs;
std::vector< TypeNode > d_define_types;
std::vector< int > d_defines;
protected:
- /** to stream functions */
+ /** print the value of the function n to stream */
virtual void toStreamFunction( Node n, std::ostream& out );
+ /** print the value of the type tn to stream */
virtual void toStreamType( TypeNode tn, std::ostream& out );
public:
TheoryModel( context::Context* c, std::string name );
@@ -78,83 +85,102 @@ public:
eq::EqualityEngine d_equalityEngine;
/** map of representatives of equality engine to used representatives in representative set */
std::map< Node, Node > d_reps;
- /** representative alphabet */
- RepSet d_ra;
- //true/false nodes
+ /** stores set of representatives for each type */
+ RepSet d_rep_set;
+ /** true/false nodes */
Node d_true;
Node d_false;
public:
- /** add defined function */
+ /** reset the model */
+ virtual void reset();
+ /** get interpreted value
+ * This function is called when the value of the node cannot be determined by the theory rewriter
+ * This should function should return a representative in d_reps
+ */
+ virtual Node getInterpretedValue( TNode n ) = 0;
+public:
+ /** add defined function (for get-model) */
void addDefineFunction( Node n );
- /** add defined type */
+ /** add defined type (for get-model) */
void addDefineType( TypeNode tn );
/**
* Get value function. This should be called only after a ModelBuilder has called buildModel(...)
* on this model.
*/
Node getValue( TNode n );
- /** get interpreted value, should be a representative in d_reps */
- virtual Node getInterpretedValue( TNode n ) = 0;
- /** get existing domain value, with possible exclusions */
+ /** get existing domain value, with possible exclusions
+ * This function returns a term in d_rep_set.d_type_reps[tn] but not in exclude
+ */
Node getDomainValue( TypeNode tn, std::vector< Node >& exclude );
- /** get new domain value */
+ /** get new domain value
+ * This function returns a constant term of type tn that is not in d_rep_set.d_type_reps[tn]
+ * If it cannot find such a node, it returns null.
+ */
Node getNewDomainValue( TypeNode tn );
public:
- /** assert equality */
+ /** assert equality holds in the model */
void assertEquality( Node a, Node b, bool polarity );
- /** assert predicate */
+ /** assert predicate holds in the model */
void assertPredicate( Node a, bool polarity );
- /** assert equality engine */
+ /** assert all equalities/predicates in equality engine hold in the model */
void assertEqualityEngine( eq::EqualityEngine* ee );
public:
- //queries about equality
+ /** general queries */
bool hasTerm( Node a );
Node getRepresentative( Node a );
bool areEqual( Node a, Node b );
bool areDisequal( Node a, Node b );
public:
- /** print representative function */
+ /** print representative debug function */
void printRepresentativeDebug( const char* c, Node r );
+ /** print representative function */
void printRepresentative( std::ostream& out, Node r );
/** to stream function */
void toStream( std::ostream& out );
};
-//default model class: extends model arbitrarily
+/** Default model class
+ * The getInterpretedValue function will choose an existing value arbitrarily.
+ * If none are found, then it will create a new value.
+ */
class DefaultModel : public TheoryModel
{
+protected:
+ /** whether function models are enabled */
+ bool d_enableFuncModels;
+ /** add term */
+ void addTerm( Node n );
public:
- DefaultModel( context::Context* c, std::string name );
+ DefaultModel( context::Context* c, std::string name, bool enableFuncModels );
virtual ~DefaultModel(){}
+ //necessary information for function models
+ std::map< Node, std::vector< Node > > d_uf_terms;
+ std::map< Node, Node > d_uf_models;
public:
+ void reset();
Node getInterpretedValue( TNode n );
};
-//incomplete model class: does not extend model
-class IncompleteModel : public TheoryModel
-{
-public:
- IncompleteModel( context::Context* c, std::string name ) : TheoryModel( c, name ){}
- virtual ~IncompleteModel(){}
-public:
- Node getInterpretedValue( TNode n ) { return Node::null(); }
-};
-
-
+/** TheoryEngineModelBuilder class
+ * This model builder will consult all theories in a theory engine for
+ * collectModelInfo( ... ) when building a model.
+ */
class TheoryEngineModelBuilder : public ModelBuilder
{
protected:
/** pointer to theory engine */
TheoryEngine* d_te;
- /** choose representative */
- virtual Node chooseRepresentative( TheoryModel* tm, Node eqc );
- /** representatives that are current not set */
- virtual void processBuildModel( TheoryModel* tm );
+ /** choose representative for unresolved equivalence class */
+ void initializeType( TypeNode tn, std::map< TypeNode, bool >& unresolved_types );
+ /** process build model */
+ virtual void processBuildModel( TheoryModel* m ){}
+ /** choose representative for unconstrained equivalence class */
+ virtual Node chooseRepresentative( TheoryModel* m, Node eqc );
public:
TheoryEngineModelBuilder( TheoryEngine* te );
virtual ~TheoryEngineModelBuilder(){}
- /**
- * Build model function.
+ /** Build model function.
+ * Should be called only on TheoryModels m
*/
void buildModel( Model* m );
};
diff --git a/src/theory/quantifiers/Makefile.am b/src/theory/quantifiers/Makefile.am
index ae5b99c06..316e2fbff 100644
--- a/src/theory/quantifiers/Makefile.am
+++ b/src/theory/quantifiers/Makefile.am
@@ -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
diff --git a/src/theory/quantifiers/first_order_model.cpp b/src/theory/quantifiers/first_order_model.cpp
index 71a48b33d..766bd31ae 100644
--- a/src/theory/quantifiers/first_order_model.cpp
+++ b/src/theory/quantifiers/first_order_model.cpp
@@ -17,7 +17,7 @@
#include "theory/quantifiers/first_order_model.h"
#include "theory/quantifiers/rep_set_iterator.h"
#include "theory/quantifiers/model_engine.h"
-#include "theory/uf/theory_uf_strong_solver.h"
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
@@ -26,25 +26,37 @@ using namespace CVC4::context;
using namespace CVC4::theory;
using namespace CVC4::theory::quantifiers;
-FirstOrderModel::FirstOrderModel( QuantifiersEngine* qe, context::Context* c, std::string name ) : DefaultModel( c, name ),
+FirstOrderModel::FirstOrderModel( QuantifiersEngine* qe, context::Context* c, std::string name ) : DefaultModel( c, name, true ),
d_term_db( qe->getTermDatabase() ), d_forall_asserts( c ){
}
-void FirstOrderModel::initialize(){
+void FirstOrderModel::reset(){
//rebuild models
- d_uf_model.clear();
+ d_uf_model_tree.clear();
+ d_uf_model_gen.clear();
d_array_model.clear();
+ DefaultModel::reset();
+}
+
+void FirstOrderModel::addTerm( Node n ){
+ //std::vector< Node > added;
+ //d_term_db->addTerm( n, added, false );
+ DefaultModel::addTerm( n );
+}
+
+void FirstOrderModel::initialize(){
+ //this is called after representatives have been chosen and the equality engine has been built
//for each quantifier, collect all operators we care about
for( int i=0; i<getNumAssertedQuantifiers(); i++ ){
Node f = getAssertedQuantifier( i );
- //initialize model for term
+ //initialize relevant models within bodies of all quantifiers
initializeModelForTerm( f[1] );
}
-
+ //for debugging
if( Options::current()->printModelEngine ){
- for( std::map< TypeNode, std::vector< Node > >::iterator it = d_ra.d_type_reps.begin(); it != d_ra.d_type_reps.end(); ++it ){
- if( uf::StrongSolverTheoryUf::isRelevantType( it->first ) ){
+ 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 ){
+ if( it->first.isSort() ){
Message() << "Cardinality( " << it->first << " )" << " = " << it->second.size() << std::endl;
}
}
@@ -54,33 +66,44 @@ void FirstOrderModel::initialize(){
void FirstOrderModel::initializeModelForTerm( Node n ){
if( n.getKind()==APPLY_UF ){
Node op = n.getOperator();
- if( d_uf_model.find( op )==d_uf_model.end() ){
+ if( d_uf_model_tree.find( op )==d_uf_model_tree.end() ){
TypeNode tn = op.getType();
tn = tn[ (int)tn.getNumChildren()-1 ];
- if( tn==NodeManager::currentNM()->booleanType() || uf::StrongSolverTheoryUf::isRelevantType( tn ) ){
- d_uf_model[ op ] = uf::UfModel( op, this );
+ //only generate models for predicates and functions with uninterpreted range types
+ if( tn==NodeManager::currentNM()->booleanType() || tn.isSort() ){
+ d_uf_model_tree[ op ] = uf::UfModelTree( op );
+ d_uf_model_gen[ op ].clear();
}
}
}
- if( n.getKind()!=STORE && n.getType().isArray() ){
- d_array_model[n] = Node::null();
+ /*
+ if( n.getType().isArray() ){
+ while( n.getKind()==STORE ){
+ n = n[0];
+ }
+ Node nn = getRepresentative( n );
+ if( d_array_model.find( nn )==d_array_model.end() ){
+ d_array_model[nn] = arrays::ArrayModel( nn, this );
+ }
}
+ */
for( int i=0; i<(int)n.getNumChildren(); i++ ){
initializeModelForTerm( n[i] );
}
}
void FirstOrderModel::toStreamFunction( Node n, std::ostream& out ){
+ /*
if( d_uf_model.find( n )!=d_uf_model.end() ){
//d_uf_model[n].toStream( out );
Node value = d_uf_model[n].getFunctionValue();
out << "(" << n << " " << value << ")";
- //}else if( d_array_model.find( n )!=d_array_model.end() ){
- //out << "(" << n << " " << d_array_model[n] << ")" << std::endl;
- // out << "(" << n << " Array)" << std::endl;
- }else{
- DefaultModel::toStreamFunction( n, out );
+ }else if( d_array_model.find( n )!=d_array_model.end() ){
+ Node value = d_array_model[n].getArrayValue();
+ out << "(" << n << " " << value << ")" << std::endl;
}
+ */
+ DefaultModel::toStreamFunction( n, out );
}
void FirstOrderModel::toStreamType( TypeNode tn, std::ostream& out ){
@@ -91,14 +114,29 @@ Node FirstOrderModel::getInterpretedValue( TNode n ){
Debug("fo-model") << "get interpreted value " << n << std::endl;
TypeNode type = n.getType();
if( type.isFunction() || type.isPredicate() ){
- if( d_uf_model.find( n )!=d_uf_model.end() ){
- return d_uf_model[n].getFunctionValue();
+ if( d_uf_models.find( n )==d_uf_models.end() ){
+ //use the model tree to generate the model
+ Node fn = d_uf_model_tree[n].getFunctionValue();
+ d_uf_models[n] = fn;
+ return fn;
+ }
+ /*
+ }else if( type.isArray() ){
+ if( d_array_model.find( n )!=d_array_model.end() ){
+ return d_array_model[n].getArrayValue();
}else{
- return n;
+ //std::cout << "no array model generated for " << n << std::endl;
}
+ */
}else if( n.getKind()==APPLY_UF ){
- int depIndex;
- return d_uf_model[ n.getOperator() ].getValue( n, depIndex );
+ Node op = n.getOperator();
+ if( d_uf_model_tree.find( op )!=d_uf_model_tree.end() ){
+ //consult the uf model
+ int depIndex;
+ return d_uf_model_tree[ op ].getValue( this, n, depIndex );
+ }
+ }else if( n.getKind()==SELECT ){
+
}
return DefaultModel::getInterpretedValue( n );
}
@@ -113,14 +151,14 @@ void FirstOrderModel::toStream(std::ostream& out){
#if 0
out << "---Current Model---" << std::endl;
out << "Representatives: " << std::endl;
- d_ra.toStream( out );
+ d_rep_set.toStream( out );
out << "Functions: " << std::endl;
for( std::map< Node, uf::UfModel >::iterator it = d_uf_model.begin(); it != d_uf_model.end(); ++it ){
it->second.toStream( out );
out << std::endl;
}
#elif 0
- d_ra.toStream( out );
+ d_rep_set.toStream( out );
//print everything not related to UF in equality engine
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &d_equalityEngine );
while( !eqcs_i.isFinished() ){
diff --git a/src/theory/quantifiers/first_order_model.h b/src/theory/quantifiers/first_order_model.h
index 832acbee3..825518ed0 100644
--- a/src/theory/quantifiers/first_order_model.h
+++ b/src/theory/quantifiers/first_order_model.h
@@ -21,6 +21,7 @@
#include "theory/model.h"
#include "theory/uf/theory_uf_model.h"
+#include "theory/arrays/theory_arrays_model.h"
namespace CVC4 {
namespace theory {
@@ -43,6 +44,8 @@ class FirstOrderModel : public DefaultModel
private:
//pointer to term database
TermDb* d_term_db;
+ //add term function
+ void addTerm( Node n );
//for initialize model
void initializeModelForTerm( Node n );
/** to stream functions */
@@ -50,10 +53,12 @@ private:
void toStreamType( TypeNode tn, std::ostream& out );
public: //for Theory UF:
//models for each UF operator
- std::map< Node, uf::UfModel > d_uf_model;
+ std::map< Node, uf::UfModelTree > d_uf_model_tree;
+ //model generators
+ std::map< Node, uf::UfModelTreeGenerator > d_uf_model_gen;
public: //for Theory Arrays:
//default value for each non-store array
- std::map< Node, Node > d_array_model;
+ std::map< Node, arrays::ArrayModel > d_array_model;
public: //for Theory Quantifiers:
/** list of quantifiers asserted in the current context */
context::CDList<Node> d_forall_asserts;
@@ -64,11 +69,13 @@ public: //for Theory Quantifiers:
public:
FirstOrderModel( QuantifiersEngine* qe, context::Context* c, std::string name );
virtual ~FirstOrderModel(){}
- // initialize the model
- void initialize();
+ // reset the model
+ void reset();
/** get interpreted value */
Node getInterpretedValue( TNode n );
public:
+ // initialize the model
+ void initialize();
/** get term database */
TermDb* getTermDatabase();
/** to stream function */
diff --git a/src/theory/quantifiers/model_builder.cpp b/src/theory/quantifiers/model_builder.cpp
new file mode 100644
index 000000000..9cd5020fb
--- /dev/null
+++ b/src/theory/quantifiers/model_builder.cpp
@@ -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
index 000000000..13d500d8e
--- /dev/null
+++ b/src/theory/quantifiers/model_builder.h
@@ -0,0 +1,91 @@
+/********************* */
+/*! \file model_builder.h
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: mdeters
+ ** Minor contributors (to current version): none
+ ** 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 Model Builder class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__QUANTIFIERS_MODEL_BUILDER_H
+#define __CVC4__QUANTIFIERS_MODEL_BUILDER_H
+
+#include "theory/quantifiers_engine.h"
+#include "theory/model.h"
+#include "theory/uf/theory_uf_model.h"
+
+namespace CVC4 {
+namespace theory {
+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;
+ //built model uf
+ std::map< Node, bool > d_uf_model_constructed;
+ /** process build model */
+ void processBuildModel( TheoryModel* m );
+ /** choose representative for unconstrained equivalence class */
+ Node chooseRepresentative( TheoryModel* m, Node eqc );
+ /** bad representative */
+ bool isBadRepresentative( Node n );
+protected:
+ //analyze model
+ void analyzeModel( FirstOrderModel* fm );
+ //analyze quantifiers
+ void analyzeQuantifiers( FirstOrderModel* fm );
+ //build model
+ void finishBuildModel( FirstOrderModel* fm );
+ //theory-specific build models
+ void finishBuildModelUf( FirstOrderModel* fm, Node op );
+ //do InstGen techniques for quantifier, return number of lemmas produced
+ int doInstGen( FirstOrderModel* fm, Node f );
+public:
+ ModelEngineBuilder( QuantifiersEngine* qe );
+ virtual ~ModelEngineBuilder(){}
+ /** finish model */
+ void finishProcessBuildModel( TheoryModel* m );
+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;
+};
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/model_engine.cpp b/src/theory/quantifiers/model_engine.cpp
index 663f270eb..ddaaa5b6f 100644
--- a/src/theory/quantifiers/model_engine.cpp
+++ b/src/theory/quantifiers/model_engine.cpp
@@ -21,16 +21,13 @@
#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);
}
diff --git a/src/theory/quantifiers/model_engine.h b/src/theory/quantifiers/model_engine.h
index b01139826..1139332fe 100644
--- a/src/theory/quantifiers/model_engine.h
+++ b/src/theory/quantifiers/model_engine.h
@@ -11,81 +11,25 @@
** 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();
diff --git a/src/theory/quantifiers/relevant_domain.cpp b/src/theory/quantifiers/relevant_domain.cpp
index e7ae1d1c7..12206e148 100644
--- a/src/theory/quantifiers/relevant_domain.cpp
+++ b/src/theory/quantifiers/relevant_domain.cpp
@@ -37,16 +37,16 @@ void RelevantDomain::compute(){
d_quant_inst_domain[f].resize( f[0].getNumChildren() );
}
//add ground terms to domain (rule 1 of complete instantiation essentially uf fragment)
- for( std::map< Node, uf::UfModel >::iterator it = d_model->d_uf_model.begin();
- it != d_model->d_uf_model.end(); ++it ){
+ for( std::map< Node, uf::UfModelTree >::iterator it = d_model->d_uf_model_tree.begin();
+ it != d_model->d_uf_model_tree.end(); ++it ){
Node op = it->first;
- for( int i=0; i<(int)it->second.d_ground_asserts.size(); i++ ){
- Node n = it->second.d_ground_asserts[i];
+ for( size_t i=0; i<d_model->d_uf_terms[op].size(); i++ ){
+ Node n = d_model->d_uf_terms[op][i];
//add arguments to domain
for( int j=0; j<(int)n.getNumChildren(); j++ ){
- if( d_model->d_ra.hasType( n[j].getType() ) ){
+ if( d_model->d_rep_set.hasType( n[j].getType() ) ){
Node ra = d_model->getRepresentative( n[j] );
- int raIndex = d_model->d_ra.getIndexFor( ra );
+ int raIndex = d_model->d_rep_set.getIndexFor( ra );
Assert( raIndex!=-1 );
if( std::find( d_active_domain[op][j].begin(), d_active_domain[op][j].end(), raIndex )==d_active_domain[op][j].end() ){
d_active_domain[op][j].push_back( raIndex );
@@ -54,8 +54,8 @@ void RelevantDomain::compute(){
}
}
//add to range
- Node r = it->second.d_ground_asserts_reps[i];
- int raIndex = d_model->d_ra.getIndexFor( r );
+ Node r = d_model->getRepresentative( n );
+ int raIndex = d_model->d_rep_set.getIndexFor( r );
Assert( raIndex!=-1 );
if( std::find( d_active_range[op].begin(), d_active_range[op].end(), raIndex )==d_active_range[op].end() ){
d_active_range[op].push_back( raIndex );
@@ -104,10 +104,10 @@ bool RelevantDomain::computeRelevantInstantiationDomain( Node n, Node parent, in
if( !domainSet ){
//otherwise, we must consider the entire domain
TypeNode tn = n.getType();
- if( d_model->d_ra.hasType( tn ) ){
- if( rd[vi].size()!=d_model->d_ra.d_type_reps[tn].size() ){
+ if( d_model->d_rep_set.hasType( tn ) ){
+ if( rd[vi].size()!=d_model->d_rep_set.d_type_reps[tn].size() ){
rd[vi].clear();
- for( size_t i=0; i<d_model->d_ra.d_type_reps[tn].size(); i++ ){
+ for( size_t i=0; i<d_model->d_rep_set.d_type_reps[tn].size(); i++ ){
rd[vi].push_back( i );
domainChanged = true;
}
@@ -166,7 +166,7 @@ bool RelevantDomain::extendFunctionDomains( Node n, RepDomain& range ){
}
}else{
Node r = d_model->getRepresentative( n );
- range.push_back( d_model->d_ra.getIndexFor( r ) );
+ range.push_back( d_model->d_rep_set.getIndexFor( r ) );
}
return domainChanged;
}
diff --git a/src/theory/quantifiers/rep_set_iterator.cpp b/src/theory/quantifiers/rep_set_iterator.cpp
index a29f815db..516f85857 100644
--- a/src/theory/quantifiers/rep_set_iterator.cpp
+++ b/src/theory/quantifiers/rep_set_iterator.cpp
@@ -38,8 +38,28 @@ RepSetIterator::RepSetIterator( Node f, FirstOrderModel* model ) : d_f( f ), d_m
d_var_order[i] = i;
//store default domain
d_domain.push_back( RepDomain() );
- for( int j=0; j<(int)d_model->d_ra.d_type_reps[d_f[0][i].getType()].size(); j++ ){
- d_domain[i].push_back( j );
+ TypeNode tn = d_f[0][i].getType();
+ if( tn.isSort() ){
+ if( d_model->d_rep_set.hasType( tn ) ){
+ for( int j=0; j<(int)d_model->d_rep_set.d_type_reps[d_f[0][i].getType()].size(); j++ ){
+ d_domain[i].push_back( j );
+ }
+ }else{
+ Unimplemented("Cannot create instantiation iterator for unknown uninterpretted sort");
+ }
+ }else if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){
+ Unimplemented("Cannot create instantiation iterator for arithmetic quantifier");
+ }else if( tn.isDatatype() ){
+ const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ //if finite, then use type enumerator
+ if( dt.isFinite() ){
+ //DO_THIS: use type enumerator
+ Unimplemented("Not yet implemented: instantiation iterator for finite datatype quantifier");
+ }else{
+ Unimplemented("Cannot create instantiation iterator for infinite datatype quantifier");
+ }
+ }else{
+ Unimplemented("Cannot create instantiation iterator for quantifier");
}
}
}
@@ -103,9 +123,9 @@ void RepSetIterator::getMatch( QuantifiersEngine* qe, InstMatch& m ){
Node RepSetIterator::getTerm( int i ){
TypeNode tn = d_f[0][d_index_order[i]].getType();
- Assert( d_model->d_ra.d_type_reps.find( tn )!=d_model->d_ra.d_type_reps.end() );
+ Assert( d_model->d_rep_set.d_type_reps.find( tn )!=d_model->d_rep_set.d_type_reps.end() );
int index = d_index_order[i];
- return d_model->d_ra.d_type_reps[tn][d_domain[index][d_index[index]]];
+ return d_model->d_rep_set.d_type_reps[tn][d_domain[index][d_index[index]]];
}
void RepSetIterator::debugPrint( const char* c ){
@@ -123,14 +143,18 @@ void RepSetIterator::debugPrintSmall( const char* c ){
}
RepSetEvaluator::RepSetEvaluator( FirstOrderModel* m, RepSetIterator* ri ) : d_model( m ), d_riter( ri ){
-
+ d_eval_formulas = 0;
+ d_eval_uf_terms = 0;
+ d_eval_lits = 0;
+ d_eval_lits_unknown = 0;
}
-//if evaluate( n, phaseReq ) = eVal,
-// if eVal = d_riter->d_index.size()
-// then the formula n instantiated with d_riter cannot be proven to be equal to phaseReq
-// otherwise,
-// 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
+//if evaluate( n ) = eVal,
+// let n' = d_riter * n be the formula n instantiated with the current values in r_iter
+// if eVal = 1, then n' is true, if eVal = -1, then n' is false,
+// if eVal = 0, then n' cannot be proven to be equal to phaseReq
+// if eVal is not 0, then
+// 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
int RepSetEvaluator::evaluate( Node n, int& depIndex ){
++d_eval_formulas;
//Debug("fmf-eval-debug") << "Evaluate " << n << " " << phaseReq << std::endl;
@@ -208,6 +232,7 @@ int RepSetEvaluator::evaluate( Node n, int& depIndex ){
}else if( n.getKind()==FORALL ){
return 0;
}else{
+ ++d_eval_lits;
////if we know we will fail again, immediately return
//if( d_eval_failed.find( n )!=d_eval_failed.end() ){
// if( d_eval_failed[n] ){
@@ -215,89 +240,46 @@ int RepSetEvaluator::evaluate( Node n, int& depIndex ){
// }
//}
//Debug("fmf-eval-debug") << "Evaluate literal " << n << std::endl;
- //this should be a literal
- //Node gn = n.substitute( d_riter->d_ic.begin(), d_riter->d_ic.end(), d_riter->d_terms.begin(), d_riter->d_terms.end() );
- //Debug("fmf-eval-debug") << " Ground version = " << gn << std::endl;
int retVal = 0;
depIndex = d_riter->getNumTerms()-1;
- if( n.getKind()==APPLY_UF ){
- //case for boolean predicates
- Node val = evaluateTerm( n, depIndex );
- if( d_model->hasTerm( val ) ){
- if( d_model->areEqual( val, d_model->d_true ) ){
- retVal = 1;
- }else{
- retVal = -1;
- }
- }
- }else if( n.getKind()==EQUAL ){
- //case for equality
- retVal = evaluateEquality( n[0], n[1], depIndex );
- }else{
- std::vector< int > cdi;
- Node val = evaluateTermDefault( n, depIndex, cdi );
- if( !val.isNull() ){
- val = Rewriter::rewrite( val );
- if( val==d_model->d_true ){
- retVal = 1;
- }else if( val==d_model->d_false ){
- retVal = -1;
+ Node val = evaluateTerm( n, depIndex );
+ if( !val.isNull() ){
+ if( d_model->areEqual( val, d_model->d_true ) ){
+ retVal = 1;
+ }else if( d_model->areEqual( val, d_model->d_false ) ){
+ retVal = -1;
+ }else{
+ if( val.getKind()==EQUAL ){
+ if( d_model->areEqual( val[0], val[1] ) ){
+ retVal = 1;
+ }else if( d_model->areDisequal( val[0], val[1] ) ){
+ retVal = -1;
+ }
}
}
}
if( retVal!=0 ){
- Debug("fmf-eval-debug") << "Evaluate literal: return " << retVal << ", depends = " << depIndex << std::endl;
+ Debug("fmf-eval-debug") << "Evaluate literal: return " << retVal << ", depIndex = " << depIndex << std::endl;
}else{
+ ++d_eval_lits_unknown;
Debug("fmf-eval-amb") << "Neither true nor false : " << n << std::endl;
//std::cout << "Neither true nor false : " << n << std::endl;
+ //std::cout << " Value : " << val << std::endl;
+ //for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ // std::cout << " " << i << " : " << n[i].getType() << std::endl;
+ //}
}
return retVal;
}
}
-int RepSetEvaluator::evaluateEquality( Node n1, Node n2, int& depIndex ){
- ++d_eval_eqs;
- //Notice() << "Eval eq " << n1 << " " << n2 << std::endl;
- Debug("fmf-eval-debug") << "Evaluate equality: " << std::endl;
- Debug("fmf-eval-debug") << " " << n1 << " = " << n2 << std::endl;
- int depIndex1, depIndex2;
- Node val1 = evaluateTerm( n1, depIndex1 );
- Node val2 = evaluateTerm( n2, depIndex2 );
- Debug("fmf-eval-debug") << " Values : ";
- d_model->printRepresentativeDebug( "fmf-eval-debug", val1 );
- Debug("fmf-eval-debug") << " = ";
- d_model->printRepresentativeDebug( "fmf-eval-debug", val2 );
- Debug("fmf-eval-debug") << std::endl;
- int retVal = 0;
- if( !val1.isNull() && !val2.isNull() ){
- if( d_model->areEqual( val1, val2 ) ){
- retVal = 1;
- }else if( d_model->areDisequal( val1, val2 ) ){
- retVal = -1;
- }else{
- Node eq = val1.eqNode( val2 );
- eq = Rewriter::rewrite( eq );
- if( eq==d_model->d_true ){
- retVal = 1;
- }else if( eq==d_model->d_false ){
- retVal = -1;
- }
- }
- }
- if( retVal!=0 ){
- depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
- Debug("fmf-eval-debug") << " value = " << (retVal==1) << ", depIndex = " << depIndex << std::endl;
- }else{
- depIndex = d_riter->getNumTerms()-1;
- Debug("fmf-eval-amb") << "Neither equal nor disequal : " << n1 << " , " << n2 << std::endl;
- //std::cout << "Neither equal nor disequal : " << n1 << " , " << n2 << std::endl;
- }
- return retVal;
-}
-
Node RepSetEvaluator::evaluateTerm( Node n, int& depIndex ){
- //Notice() << "Eval term " << n << std::endl;
- if( n.hasAttribute(InstConstantAttribute()) ){
+ //Message() << "Eval term " << n << std::endl;
+ if( !n.hasAttribute(InstConstantAttribute()) ){
+ //if evaluating a ground term, just consult the standard getValue functionality
+ depIndex = -1;
+ return d_model->getValue( n );
+ }else{
Node val;
depIndex = d_riter->getNumTerms()-1;
//check the type of n
@@ -311,7 +293,7 @@ Node RepSetEvaluator::evaluateTerm( Node n, int& depIndex ){
if( eval==0 ){
//evaluate children to see if they are the same
Node val1 = evaluateTerm( n[ 1 ], depIndex1 );
- Node val2 = evaluateTerm( n[ 1 ], depIndex1 );
+ Node val2 = evaluateTerm( n[ 2 ], depIndex2 );
if( val1==val2 ){
val = val1;
depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
@@ -323,19 +305,24 @@ Node RepSetEvaluator::evaluateTerm( Node n, int& depIndex ){
depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
}
}else{
-#if 0
+ std::vector< int > children_depIndex;
//for select, pre-process read over writes
if( n.getKind()==SELECT ){
- Node selIndex = evaluateTerm( n[1], depIndex );
- if( selIndex.isNull() ){
+#if 1
+ //std::cout << "Evaluate " << n << std::endl;
+ Node sel = evaluateTerm( n[1], depIndex );
+ if( sel.isNull() ){
depIndex = d_riter->getNumTerms()-1;
return Node::null();
}
- Node arr = n[0];
+ Node arr = d_model->getRepresentative( n[0] );
+ //if( n[0]!=d_model->getRepresentative( n[0] ) ){
+ // std::cout << n[0] << " is " << d_model->getRepresentative( n[0] ) << std::endl;
+ //}
+ int tempIndex;
int eval = 1;
while( arr.getKind()==STORE && eval!=0 ){
- int tempIndex;
- eval = evaluateEquality( selIndex, arr[1], tempIndex );
+ eval = evaluate( sel.eqNode( arr[1] ), tempIndex );
depIndex = tempIndex > depIndex ? tempIndex : depIndex;
if( eval==1 ){
val = evaluateTerm( arr[2], tempIndex );
@@ -345,90 +332,97 @@ Node RepSetEvaluator::evaluateTerm( Node n, int& depIndex ){
arr = arr[0];
}
}
- n = NodeManager::currentNM()->mkNode( SELECT, arr, selIndex );
- }
+ arr = evaluateTerm( arr, tempIndex );
+ depIndex = tempIndex > depIndex ? tempIndex : depIndex;
+ val = NodeManager::currentNM()->mkNode( SELECT, arr, sel );
+#else
+ val = evaluateTermDefault( n, depIndex, children_depIndex );
#endif
- //default term evaluate : evaluate all children, recreate the value
- std::vector< int > children_depIndex;
- val = evaluateTermDefault( n, depIndex, children_depIndex );
- //case split on the type of term
- if( n.getKind()==APPLY_UF ){
- Node op = n.getOperator();
- //Debug("fmf-eval-debug") << "Evaluate term " << n << " (" << gn << ")" << std::endl;
- //if it is a defined UF, then consult the interpretation
- ++d_eval_uf_terms;
- int argDepIndex = 0;
- if( d_model->d_uf_model.find( op )!=d_model->d_uf_model.end() ){
- //make the term model specifically for n
- makeEvalUfModel( n );
- //now, consult the model
- if( d_eval_uf_use_default[n] ){
- val = d_model->d_uf_model[op].d_tree.getValue( d_model, val, argDepIndex );
- }else{
- val = d_eval_uf_model[ n ].getValue( d_model, val, argDepIndex );
- }
+ }else{
+ //default term evaluate : evaluate all children, recreate the value
+ val = evaluateTermDefault( n, depIndex, children_depIndex );
+ }
+ if( !val.isNull() ){
+ bool setVal = false;
+ //custom ways of evaluating terms
+ if( n.getKind()==APPLY_UF ){
+ Node op = n.getOperator();
//Debug("fmf-eval-debug") << "Evaluate term " << n << " (" << gn << ")" << std::endl;
- //d_eval_uf_model[ n ].debugPrint("fmf-eval-debug", d_qe );
- Assert( !val.isNull() );
- }else{
- d_eval_uf_use_default[n] = true;
- argDepIndex = (int)n.getNumChildren();
+ //if it is a defined UF, then consult the interpretation
+ if( d_model->d_uf_model_tree.find( op )!=d_model->d_uf_model_tree.end() ){
+ ++d_eval_uf_terms;
+ int argDepIndex = 0;
+ //make the term model specifically for n
+ makeEvalUfModel( n );
+ //now, consult the model
+ if( d_eval_uf_use_default[n] ){
+ val = d_model->d_uf_model_tree[op].getValue( d_model, val, argDepIndex );
+ }else{
+ val = d_eval_uf_model[ n ].getValue( d_model, val, argDepIndex );
+ }
+ //Debug("fmf-eval-debug") << "Evaluate term " << n << " (" << gn << ")" << std::endl;
+ //d_eval_uf_model[ n ].debugPrint("fmf-eval-debug", d_qe );
+ Assert( !val.isNull() );
+ //recalculate the depIndex
+ depIndex = -1;
+ for( int i=0; i<argDepIndex; i++ ){
+ int index = d_eval_uf_use_default[n] ? i : d_eval_term_index_order[n][i];
+ Debug("fmf-eval-debug") << "Add variables from " << index << "..." << std::endl;
+ if( children_depIndex[index]>depIndex ){
+ depIndex = children_depIndex[index];
+ }
+ }
+ setVal = true;
+ }
+ }else if( n.getKind()==SELECT ){
+ //we are free to interpret this term however we want
}
- //recalculate the depIndex
- depIndex = -1;
- for( int i=0; i<argDepIndex; i++ ){
- int index = d_eval_uf_use_default[n] ? i : d_eval_term_index_order[n][i];
- Debug("fmf-eval-debug") << "Add variables from " << index << "..." << std::endl;
- if( children_depIndex[index]>depIndex ){
- depIndex = children_depIndex[index];
+ //if not set already, rewrite and consult model for interpretation
+ if( !setVal ){
+ val = Rewriter::rewrite( val );
+ if( val.getMetaKind()!=kind::metakind::CONSTANT ){
+ //FIXME: we cannot do this until we trust all theories collectModelInfo!
+ //val = d_model->getInterpretedValue( val );
+ //val = d_model->getRepresentative( val );
}
}
Debug("fmf-eval-debug") << "Evaluate term " << n << " = ";
d_model->printRepresentativeDebug( "fmf-eval-debug", val );
Debug("fmf-eval-debug") << ", depIndex = " << depIndex << std::endl;
- }else if( n.getKind()==SELECT ){
- if( d_model->d_array_model.find( n[0] )!=d_model->d_array_model.end() ){
- //consult the default value for the array DO_THIS
- //val = Rewriter::rewrite( val );
- //val = d_model->d_array_model[ n[0] ];
- val = Rewriter::rewrite( val );
- }else{
- val = Rewriter::rewrite( val );
- }
- }else{
- val = Rewriter::rewrite( val );
}
}
return val;
- }else{
- depIndex = -1;
- return n;
}
}
Node RepSetEvaluator::evaluateTermDefault( Node n, int& depIndex, std::vector< int >& childDepIndex ){
- //first we must evaluate the arguments
- std::vector< Node > children;
- if( n.getMetaKind()==kind::metakind::PARAMETERIZED ){
- children.push_back( n.getOperator() );
- }
depIndex = -1;
- //for each argument, calculate its value, and the variables its value depends upon
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- childDepIndex.push_back( -1 );
- Node nn = evaluateTerm( n[i], childDepIndex[i] );
- if( nn.isNull() ){
- depIndex = d_riter->getNumTerms()-1;
- return nn;
- }else{
- children.push_back( nn );
- if( childDepIndex[i]>depIndex ){
- depIndex = childDepIndex[i];
+ if( n.getNumChildren()==0 ){
+ return n;
+ }else{
+ //first we must evaluate the arguments
+ std::vector< Node > children;
+ if( n.getMetaKind()==kind::metakind::PARAMETERIZED ){
+ children.push_back( n.getOperator() );
+ }
+ //for each argument, calculate its value, and the variables its value depends upon
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ childDepIndex.push_back( -1 );
+ Node nn = evaluateTerm( n[i], childDepIndex[i] );
+ if( nn.isNull() ){
+ depIndex = d_riter->getNumTerms()-1;
+ return nn;
+ }else{
+ children.push_back( nn );
+ if( childDepIndex[i]>depIndex ){
+ depIndex = childDepIndex[i];
+ }
}
}
+ //recreate the value
+ Node val = NodeManager::currentNM()->mkNode( n.getKind(), children );
+ return val;
}
- //recreate the value
- return NodeManager::currentNM()->mkNode( n.getKind(), children );
}
void RepSetEvaluator::clearEvalFailed( int index ){
@@ -443,8 +437,8 @@ void RepSetEvaluator::makeEvalUfModel( Node n ){
makeEvalUfIndexOrder( n );
if( !d_eval_uf_use_default[n] ){
Node op = n.getOperator();
- d_eval_uf_model[n] = uf::UfModelTreeOrdered( op, d_eval_term_index_order[n] );
- d_model->d_uf_model[op].makeModel( d_eval_uf_model[n] );
+ d_eval_uf_model[n] = uf::UfModelTree( op, d_eval_term_index_order[n] );
+ d_model->d_uf_model_gen[op].makeModel( d_model, d_eval_uf_model[n] );
//Debug("fmf-index-order") << "Make model for " << n << " : " << std::endl;
//d_eval_uf_model[n].debugPrint( "fmf-index-order", d_qe, 2 );
}
diff --git a/src/theory/quantifiers/rep_set_iterator.h b/src/theory/quantifiers/rep_set_iterator.h
index 308d09a38..f6312ae5c 100644
--- a/src/theory/quantifiers/rep_set_iterator.h
+++ b/src/theory/quantifiers/rep_set_iterator.h
@@ -85,7 +85,7 @@ private:
private: //for Theory UF:
//map from terms to the models used to calculate their value
std::map< Node, bool > d_eval_uf_use_default;
- std::map< Node, uf::UfModelTreeOrdered > d_eval_uf_model;
+ std::map< Node, uf::UfModelTree > d_eval_uf_model;
void makeEvalUfModel( Node n );
//index ordering to use for each term
std::map< Node, std::vector< int > > d_eval_term_index_order;
@@ -103,13 +103,13 @@ public:
virtual ~RepSetEvaluator(){}
/** evaluate functions */
int evaluate( Node n, int& depIndex );
- int evaluateEquality( Node n1, Node n2, int& depIndex );
Node evaluateTerm( Node n, int& depIndex );
public:
//statistics
int d_eval_formulas;
- int d_eval_eqs;
int d_eval_uf_terms;
+ int d_eval_lits;
+ int d_eval_lits_unknown;
};
diff --git a/src/theory/quantifiers/term_database.cpp b/src/theory/quantifiers/term_database.cpp
index 55715353d..945c82bf9 100644
--- a/src/theory/quantifiers/term_database.cpp
+++ b/src/theory/quantifiers/term_database.cpp
@@ -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];
}
diff --git a/src/theory/quantifiers/term_database.h b/src/theory/quantifiers/term_database.h
index 5004a82dc..1ebba49b5 100644
--- a/src/theory/quantifiers/term_database.h
+++ b/src/theory/quantifiers/term_database.h
@@ -68,6 +68,9 @@ public:
void setMatchingActive( bool a ) { d_matching_active = a; }
/** get active */
bool getMatchingActive() { return d_matching_active; }
+private:
+ /** for efficient e-matching */
+ void addTermEfficient( Node n, std::set< Node >& added);
public:
/** parent structure (for efficient E-matching):
n -> op -> index -> L
diff --git a/src/theory/quantifiers_engine.cpp b/src/theory/quantifiers_engine.cpp
index 448224b81..471bc9ac1 100644
--- a/src/theory/quantifiers_engine.cpp
+++ b/src/theory/quantifiers_engine.cpp
@@ -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
diff --git a/src/theory/quantifiers_engine.h b/src/theory/quantifiers_engine.h
index 157c0ac53..2ae620e3d 100644
--- a/src/theory/quantifiers_engine.h
+++ b/src/theory/quantifiers_engine.h
@@ -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
index 000000000..a2e895c7f
--- /dev/null
+++ b/src/theory/rr_candidate_generator.cpp
@@ -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/uf/theory_uf_candidate_generator.h b/src/theory/rr_candidate_generator.h
index a06f04f99..30f6c067d 100644
--- a/src/theory/uf/theory_uf_candidate_generator.h
+++ b/src/theory/rr_candidate_generator.h
@@ -1,8 +1,8 @@
/********************* */
-/*! \file theory_uf_candidate_generator.h
+/*! \file rr_candidate_generator.h
** \verbatim
** Original author: ajreynol
- ** Major contributors: none
+ ** 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)
@@ -11,7 +11,7 @@
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
- ** \brief Theory uf candidate generator
+ ** \brief rr candidate generator
**/
#include "cvc4_private.h"
@@ -21,7 +21,6 @@
#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;
@@ -102,7 +101,7 @@ public:
} /* namespace rrinst */
} /* namespace eq */
-namespace uf {
+namespace uf{
namespace rrinst {
typedef CVC4::theory::rrinst::CandidateGenerator CandidateGenerator;
@@ -164,96 +163,46 @@ public:
};
} /* namespace rrinst */
+} /* namespace uf */
-namespace inst{
-typedef CVC4::theory::inst::CandidateGenerator CandidateGenerator;
+class GenericCandidateGeneratorClasses: public rrinst::CandidateGenerator{
-//Old CandidateGenerator
+ /** The candidate generators */
+ rrinst::CandidateGenerator* d_can_gen[theory::THEORY_LAST];
+ /** The current theory which candidategenerator is used */
+ TheoryId d_can_gen_id;
-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(){}
+ GenericCandidateGeneratorClasses(QuantifiersEngine * qe);
+ ~GenericCandidateGeneratorClasses();
void resetInstantiationRound();
- void reset( Node eqc );
- Node getNextCandidate();
+ void reset(TNode eqc);
+ TNode getNextCandidate();
+ void lookForNextTheory();
};
-//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 GenericCandidateGeneratorClass: public rrinst::CandidateGenerator{
-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();
-};
+ /** 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;
-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(){}
-
+ GenericCandidateGeneratorClass(QuantifiersEngine * qe);
+ ~GenericCandidateGeneratorClass();
void resetInstantiationRound();
- void reset( Node eqc );
- Node getNextCandidate();
-};
+ void reset(TNode eqc);
+ TNode getNextCandidate();
+ void lookForNextTheory();
+};
-}/* CVC4::theory::uf::inst namespace */
-}/* CVC4::theory::uf namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/rr_inst_match.cpp b/src/theory/rr_inst_match.cpp
index 3ba0c8d32..287f7475a 100644
--- a/src/theory/rr_inst_match.cpp
+++ b/src/theory/rr_inst_match.cpp
@@ -15,16 +15,16 @@
**/
#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;
diff --git a/src/theory/rr_inst_match_impl.h b/src/theory/rr_inst_match_impl.h
index 04a15d41f..28bc8c7eb 100644
--- a/src/theory/rr_inst_match_impl.h
+++ b/src/theory/rr_inst_match_impl.h
@@ -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 {
diff --git a/src/theory/rr_trigger.cpp b/src/theory/rr_trigger.cpp
index 579608b59..52e7efcc2 100644
--- a/src/theory/rr_trigger.cpp
+++ b/src/theory/rr_trigger.cpp
@@ -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;
diff --git a/src/theory/theory.h b/src/theory/theory.h
index 0cf7a8774..24551637b 100644
--- a/src/theory/theory.h
+++ b/src/theory/theory.h
@@ -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
diff --git a/src/theory/theory_engine.cpp b/src/theory/theory_engine.cpp
index 872924385..1fb7305d4 100644
--- a/src/theory/theory_engine.cpp
+++ b/src/theory/theory_engine.cpp
@@ -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 ?
diff --git a/src/theory/trigger.cpp b/src/theory/trigger.cpp
index 14ba88ba1..92573d464 100644
--- a/src/theory/trigger.cpp
+++ b/src/theory/trigger.cpp
@@ -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 ) ){
diff --git a/src/theory/uf/Makefile.am b/src/theory/uf/Makefile.am
index b8446761c..61330bbde 100644
--- a/src/theory/uf/Makefile.am
+++ b/src/theory/uf/Makefile.am
@@ -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
index 80151d1e1..000000000
--- a/src/theory/uf/theory_uf_candidate_generator.cpp
+++ /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_instantiator.cpp b/src/theory/uf/theory_uf_instantiator.cpp
index 257bed0a2..48092b340 100644
--- a/src/theory/uf/theory_uf_instantiator.cpp
+++ b/src/theory/uf/theory_uf_instantiator.cpp
@@ -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();
diff --git a/src/theory/uf/theory_uf_instantiator.h b/src/theory/uf/theory_uf_instantiator.h
index 3a2a5cc0e..d15c0103b 100644
--- a/src/theory/uf/theory_uf_instantiator.h
+++ b/src/theory/uf/theory_uf_instantiator.h
@@ -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 */
}
diff --git a/src/theory/uf/theory_uf_model.cpp b/src/theory/uf/theory_uf_model.cpp
index a85dea997..f68ab1429 100644
--- a/src/theory/uf/theory_uf_model.cpp
+++ b/src/theory/uf/theory_uf_model.cpp
@@ -34,12 +34,12 @@ using namespace CVC4::theory;
using namespace CVC4::theory::uf;
//clear
-void UfModelTree::clear(){
+void UfModelTreeNode::clear(){
d_data.clear();
d_value = Node::null();
}
-bool UfModelTree::hasConcreteArgumentDefinition(){
+bool UfModelTreeNode::hasConcreteArgumentDefinition(){
if( d_data.size()>1 ){
return true;
}else if( d_data.empty() ){
@@ -51,16 +51,16 @@ bool UfModelTree::hasConcreteArgumentDefinition(){
}
//set value function
-void UfModelTree::setValue( TheoryModel* m, Node n, Node v, std::vector< int >& indexOrder, bool ground, int argIndex ){
+void UfModelTreeNode::setValue( TheoryModel* m, Node n, Node v, std::vector< int >& indexOrder, bool ground, int argIndex ){
if( d_data.empty() ){
d_value = v;
}else if( !d_value.isNull() && d_value!=v ){
d_value = Node::null();
}
- if( argIndex<(int)n.getNumChildren() ){
+ if( argIndex<(int)indexOrder.size() ){
//take r = null when argument is the model basis
Node r;
- if( ground || !n[ indexOrder[argIndex] ].getAttribute(ModelBasisAttribute()) ){
+ if( ground || ( !n.isNull() && !n[ indexOrder[argIndex] ].getAttribute(ModelBasisAttribute()) ) ){
r = m->getRepresentative( n[ indexOrder[argIndex] ] );
}
d_data[ r ].setValue( m, n, v, indexOrder, ground, argIndex+1 );
@@ -68,7 +68,7 @@ void UfModelTree::setValue( TheoryModel* m, Node n, Node v, std::vector< int >&
}
//get value function
-Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int& depIndex, int argIndex ){
+Node UfModelTreeNode::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int& depIndex, int argIndex ){
if( !d_value.isNull() && isTotal( n.getOperator(), argIndex ) ){
//Notice() << "Constant, return " << d_value << ", depIndex = " << argIndex << std::endl;
depIndex = argIndex;
@@ -82,7 +82,7 @@ Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrd
if( i==0 ){
r = m->getRepresentative( n[ indexOrder[argIndex] ] );
}
- std::map< Node, UfModelTree >::iterator it = d_data.find( r );
+ std::map< Node, UfModelTreeNode >::iterator it = d_data.find( r );
if( it!=d_data.end() ){
val = it->second.getValue( m, n, indexOrder, childDepIndex[i], argIndex+1 );
if( !val.isNull() ){
@@ -101,7 +101,7 @@ Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrd
}
}
-Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, std::vector< int >& depIndex, int argIndex ){
+Node UfModelTreeNode::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, std::vector< int >& depIndex, int argIndex ){
if( argIndex==(int)indexOrder.size() ){
return d_value;
}else{
@@ -113,7 +113,7 @@ Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrd
if( i==0 ){
r = m->getRepresentative( n[ indexOrder[argIndex] ] );
}
- std::map< Node, UfModelTree >::iterator it = d_data.find( r );
+ std::map< Node, UfModelTreeNode >::iterator it = d_data.find( r );
if( it!=d_data.end() ){
val = it->second.getValue( m, n, indexOrder, depIndex, argIndex+1 );
//we have found a value
@@ -136,11 +136,11 @@ Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrd
}
}
-Node UfModelTree::getFunctionValue(){
+Node UfModelTreeNode::getFunctionValue(){
if( !d_data.empty() ){
Node defaultValue;
std::vector< Node > caseValues;
- for( std::map< Node, UfModelTree >::iterator it = d_data.begin(); it != d_data.end(); ++it ){
+ for( std::map< Node, UfModelTreeNode >::iterator it = d_data.begin(); it != d_data.end(); ++it ){
if( it->first.isNull() ){
defaultValue = it->second.getFunctionValue();
}else{
@@ -166,12 +166,12 @@ Node UfModelTree::getFunctionValue(){
}
//simplify function
-void UfModelTree::simplify( Node op, Node defaultVal, int argIndex ){
+void UfModelTreeNode::simplify( Node op, Node defaultVal, int argIndex ){
if( argIndex<(int)op.getType().getNumChildren()-1 ){
std::vector< Node > eraseData;
//first process the default argument
Node r;
- std::map< Node, UfModelTree >::iterator it = d_data.find( r );
+ std::map< Node, UfModelTreeNode >::iterator it = d_data.find( r );
if( it!=d_data.end() ){
if( !defaultVal.isNull() && it->second.d_value==defaultVal ){
eraseData.push_back( r );
@@ -188,7 +188,7 @@ void UfModelTree::simplify( Node op, Node defaultVal, int argIndex ){
}
}
//now see if any children can be removed, and simplify the ones that cannot
- for( std::map< Node, UfModelTree >::iterator it = d_data.begin(); it != d_data.end(); ++it ){
+ for( std::map< Node, UfModelTreeNode >::iterator it = d_data.begin(); it != d_data.end(); ++it ){
if( !it->first.isNull() ){
if( !defaultVal.isNull() && it->second.d_value==defaultVal ){
eraseData.push_back( it->first );
@@ -207,12 +207,12 @@ void UfModelTree::simplify( Node op, Node defaultVal, int argIndex ){
}
//is total function
-bool UfModelTree::isTotal( Node op, int argIndex ){
+bool UfModelTreeNode::isTotal( Node op, int argIndex ){
if( argIndex==(int)(op.getType().getNumChildren()-1) ){
return !d_value.isNull();
}else{
Node r;
- std::map< Node, UfModelTree >::iterator it = d_data.find( r );
+ std::map< Node, UfModelTreeNode >::iterator it = d_data.find( r );
if( it!=d_data.end() ){
return it->second.isTotal( op, argIndex+1 );
}else{
@@ -221,7 +221,7 @@ bool UfModelTree::isTotal( Node op, int argIndex ){
}
}
-Node UfModelTree::getConstantValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int argIndex ){
+Node UfModelTreeNode::getConstantValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int argIndex ){
return d_value;
}
@@ -231,9 +231,9 @@ void indent( std::ostream& out, int ind ){
}
}
-void UfModelTree::debugPrint( std::ostream& out, TheoryModel* m, std::vector< int >& indexOrder, int ind, int arg ){
+void UfModelTreeNode::debugPrint( std::ostream& out, TheoryModel* m, std::vector< int >& indexOrder, int ind, int arg ){
if( !d_data.empty() ){
- for( std::map< Node, UfModelTree >::iterator it = d_data.begin(); it != d_data.end(); ++it ){
+ for( std::map< Node, UfModelTreeNode >::iterator it = d_data.begin(); it != d_data.end(); ++it ){
if( !it->first.isNull() ){
indent( out, ind );
out << "if x_" << indexOrder[arg] << " == " << it->first << std::endl;
@@ -247,54 +247,36 @@ void UfModelTree::debugPrint( std::ostream& out, TheoryModel* m, std::vector< in
indent( out, ind );
out << "return ";
m->printRepresentative( out, d_value );
- //out << " { ";
- //for( int i=0; i<(int)d_explicit.size(); i++ ){
- // out << d_explicit[i] << " ";
- //}
- //out << "}";
out << std::endl;
}
}
-UfModel::UfModel( Node op, quantifiers::FirstOrderModel* m ) : d_model( m ), d_op( op ),
-d_model_constructed( false ){
- d_tree = UfModelTreeOrdered( op );
- TypeNode tn = d_op.getType();
- tn = tn[(int)tn.getNumChildren()-1];
- Assert( tn==NodeManager::currentNM()->booleanType() || tn.isDatatype() || uf::StrongSolverTheoryUf::isRelevantType( tn ) );
- //look at ground assertions
- for( size_t i=0; i<d_model->getTermDatabase()->d_op_map[ d_op ].size(); i++ ){
- Node n = d_model->getTermDatabase()->d_op_map[ d_op ][i];
- d_model->getTermDatabase()->computeModelBasisArgAttribute( n );
- if( !n.getAttribute(NoMatchAttribute()) || n.getAttribute(ModelBasisArgAttribute())==1 ){
- Node r = d_model->getRepresentative( n );
- d_ground_asserts_reps.push_back( r );
- d_ground_asserts.push_back( n );
- }
- }
- //determine if it is constant
- if( !d_ground_asserts.empty() ){
- bool isConstant = true;
- for( int i=1; i<(int)d_ground_asserts.size(); i++ ){
- if( d_ground_asserts_reps[0]!=d_ground_asserts_reps[i] ){
- isConstant = false;
- break;
+
+Node UfModelTree::toIte2( Node fm_node, std::vector< Node >& args, int index, Node defaultNode ){
+ if( fm_node.getKind()==FUNCTION_MODEL ){
+ if( fm_node[0].getKind()==FUNCTION_CASE_SPLIT ){
+ Node retNode;
+ Node childDefaultNode = defaultNode;
+ //get new default
+ if( fm_node.getNumChildren()==2 ){
+ childDefaultNode = toIte2( fm_node[1], args, index+1, defaultNode );
}
+ retNode = childDefaultNode;
+ for( int i=(int)fm_node[0].getNumChildren()-1; i>=0; i-- ){
+ Node childNode = toIte2( fm_node[0][1], args, index+1, childDefaultNode );
+ retNode = NodeManager::currentNM()->mkNode( ITE, args[index].eqNode( fm_node[0][0] ), childNode, retNode );
+ }
+ return retNode;
+ }else{
+ return toIte2( fm_node[0], args, index+1, defaultNode );
}
- if( isConstant ){
- //set constant value
- Node t = d_model->getTermDatabase()->getModelBasisOpTerm( d_op );
- Node r = d_ground_asserts_reps[0];
- setValue( t, r, false );
- setModel();
- Debug("fmf-model-cons") << "Function " << d_op << " is the constant function ";
- d_model->printRepresentativeDebug( "fmf-model-cons", r );
- Debug("fmf-model-cons") << std::endl;
- }
+ }else{
+ return fm_node;
}
}
-Node UfModel::getIntersection( Node n1, Node n2, bool& isGround ){
+
+Node UfModelTreeGenerator::getIntersection( TheoryModel* m, Node n1, Node n2, bool& isGround ){
//Notice() << "Get intersection " << n1 << " " << n2 << std::endl;
isGround = true;
std::vector< Node > children;
@@ -309,7 +291,7 @@ Node UfModel::getIntersection( Node n1, Node n2, bool& isGround ){
children.push_back( n2[i] );
}else if( n2[i].getAttribute(ModelBasisAttribute()) ){
children.push_back( n1[i] );
- }else if( d_model->areEqual( n1[i], n2[i] ) ){
+ }else if( m->areEqual( n1[i], n2[i] ) ){
children.push_back( n1[i] );
}else{
return Node::null();
@@ -318,7 +300,7 @@ Node UfModel::getIntersection( Node n1, Node n2, bool& isGround ){
return NodeManager::currentNM()->mkNode( APPLY_UF, children );
}
-void UfModel::setValue( Node n, Node v, bool ground, bool isReq ){
+void UfModelTreeGenerator::setValue( TheoryModel* m, Node n, Node v, bool ground, bool isReq ){
Assert( !n.isNull() );
Assert( !v.isNull() );
d_set_values[ isReq ? 1 : 0 ][ ground ? 1 : 0 ][n] = v;
@@ -332,13 +314,13 @@ void UfModel::setValue( Node n, Node v, bool ground, bool isReq ){
// is also defined.
//for example, if we have that f( e, a ) = ..., and f( b, e ) = ...,
// then we must define f( b, a ).
- Node ni = getIntersection( n, d_defaults[i], isGround );
+ Node ni = getIntersection( m, n, d_defaults[i], isGround );
if( !ni.isNull() ){
//if the intersection exists, and is not already defined
if( d_set_values[0][ isGround ? 1 : 0 ].find( ni )==d_set_values[0][ isGround ? 1 : 0 ].end() &&
d_set_values[1][ isGround ? 1 : 0 ].find( ni )==d_set_values[1][ isGround ? 1 : 0 ].end() ){
//use the current value
- setValue( ni, v, isGround, false );
+ setValue( m, ni, v, isGround, false );
}
}
}
@@ -350,36 +332,21 @@ void UfModel::setValue( Node n, Node v, bool ground, bool isReq ){
}
}
-Node UfModel::getValue( Node n, int& depIndex ){
- return d_tree.getValue( d_model, n, depIndex );
-}
-
-Node UfModel::getValue( Node n, std::vector< int >& depIndex ){
- return d_tree.getValue( d_model, n, depIndex );
-}
-
-Node UfModel::getConstantValue( Node n ){
- if( d_model_constructed ){
- return d_tree.getConstantValue( d_model, n );
- }else{
- return Node::null();
+void UfModelTreeGenerator::makeModel( TheoryModel* m, UfModelTree& tree ){
+ for( int j=0; j<2; j++ ){
+ for( int k=0; k<2; k++ ){
+ for( std::map< Node, Node >::iterator it = d_set_values[j][k].begin(); it != d_set_values[j][k].end(); ++it ){
+ tree.setValue( m, it->first, it->second, k==1 );
+ }
+ }
}
-}
-
-Node UfModel::getFunctionValue(){
- if( d_func_value.isNull() && d_model_constructed ){
- d_func_value = d_tree.getFunctionValue();
+ if( !d_default_value.isNull() ){
+ tree.setDefaultValue( m, d_default_value );
}
- return d_func_value;
-}
-
-bool UfModel::isConstant(){
- Node gn = d_model->getTermDatabase()->getModelBasisOpTerm( d_op );
- Node n = getConstantValue( gn );
- return !n.isNull();
+ tree.simplify();
}
-bool UfModel::optUsePartialDefaults(){
+bool UfModelTreeGenerator::optUsePartialDefaults(){
#ifdef USE_PARTIAL_DEFAULT_VALUES
return true;
#else
@@ -387,114 +354,14 @@ bool UfModel::optUsePartialDefaults(){
#endif
}
-void UfModel::setModel(){
- makeModel( d_tree );
- d_model_constructed = true;
- d_func_value = Node::null();
-
- //for debugging, make sure model satisfies all ground assertions
- for( size_t i=0; i<d_ground_asserts.size(); i++ ){
- int depIndex;
- Node n = d_tree.getValue( d_model, d_ground_asserts[i], depIndex );
- if( n!=d_ground_asserts_reps[i] ){
- Debug("fmf-bad") << "Bad model : " << d_ground_asserts[i] << " := ";
- d_model->printRepresentativeDebug("fmf-bad", n );
- Debug("fmf-bad") << " != ";
- d_model->printRepresentativeDebug("fmf-bad", d_ground_asserts_reps[i] );
- Debug("fmf-bad") << std::endl;
- }
- }
-}
-
-void UfModel::clearModel(){
+void UfModelTreeGenerator::clear(){
+ d_default_value = Node::null();
for( int j=0; j<2; j++ ){
for( int k=0; k<2; k++ ){
d_set_values[j][k].clear();
}
}
- d_tree.clear();
- d_model_constructed = false;
-}
-
-void UfModel::makeModel( UfModelTreeOrdered& tree ){
- for( int j=0; j<2; j++ ){
- for( int k=0; k<2; k++ ){
- for( std::map< Node, Node >::iterator it = d_set_values[j][k].begin(); it != d_set_values[j][k].end(); ++it ){
- tree.setValue( d_model, it->first, it->second, k==1 );
- }
- }
- }
- tree.simplify();
-}
-
-void UfModel::toStream(std::ostream& out){
- //out << "Function " << d_op << std::endl;
- //out << " Type: " << d_op.getType() << std::endl;
- //out << " Ground asserts:" << std::endl;
- //for( int i=0; i<(int)d_ground_asserts.size(); i++ ){
- // out << " " << d_ground_asserts[i] << " = ";
- // d_model->printRepresentative( out, d_ground_asserts[i] );
- // out << std::endl;
- //}
- //out << " Model:" << std::endl;
-
- TypeNode t = d_op.getType();
- out << d_op << "( ";
- for( int i=0; i<(int)(t.getNumChildren()-1); i++ ){
- out << "x_" << i << " : " << t[i];
- if( i<(int)(t.getNumChildren()-2) ){
- out << ", ";
- }
- }
- out << " ) : " << t[(int)t.getNumChildren()-1] << std::endl;
- if( d_tree.isEmpty() ){
- out << " [undefined]" << std::endl;
- }else{
- d_tree.debugPrint( out, d_model, 3 );
- out << std::endl;
- }
- //out << " Phase reqs:" << std::endl; //for( int i=0; i<2; i++ ){
- // for( std::map< Node, std::vector< Node > >::iterator it = d_reqs[i].begin(); it != d_reqs[i].end(); ++it ){
- // out << " " << it->first << std::endl;
- // for( int j=0; j<(int)it->second.size(); j++ ){
- // out << " " << it->second[j] << " -> " << (i==1) << std::endl;
- // }
- // }
- //}
- //out << std::endl;
- //for( int i=0; i<2; i++ ){
- // for( std::map< Node, std::map< Node, std::vector< Node > > >::iterator it = d_eq_reqs[i].begin(); it != d_eq_reqs[i].end(); ++it ){
- // out << " " << "For " << it->first << ":" << std::endl;
- // for( std::map< Node, std::vector< Node > >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
- // for( int j=0; j<(int)it2->second.size(); j++ ){
- // out << " " << it2->first << ( i==1 ? "==" : "!=" ) << it2->second[j] << std::endl;
- // }
- // }
- // }
- //}
-}
-
-Node UfModel::toIte2( Node fm_node, std::vector< Node >& args, int index, Node defaultNode ){
- if( fm_node.getKind()==FUNCTION_MODEL ){
- if( fm_node[0].getKind()==FUNCTION_CASE_SPLIT ){
- Node retNode;
- Node childDefaultNode = defaultNode;
- //get new default
- if( fm_node.getNumChildren()==2 ){
- childDefaultNode = toIte2( fm_node[1], args, index+1, defaultNode );
- }
- retNode = childDefaultNode;
- for( int i=(int)fm_node[0].getNumChildren()-1; i>=0; i-- ){
- Node childNode = toIte2( fm_node[0][1], args, index+1, childDefaultNode );
- retNode = NodeManager::currentNM()->mkNode( ITE, args[index].eqNode( fm_node[0][0] ), childNode, retNode );
- }
- return retNode;
- }else{
- return toIte2( fm_node[0], args, index+1, defaultNode );
- }
- }else{
- return fm_node;
- }
+ d_defaults.clear();
}
diff --git a/src/theory/uf/theory_uf_model.h b/src/theory/uf/theory_uf_model.h
index 406c7ff3c..47b149867 100644
--- a/src/theory/uf/theory_uf_model.h
+++ b/src/theory/uf/theory_uf_model.h
@@ -23,19 +23,14 @@
namespace CVC4 {
namespace theory {
-
-namespace quantifiers{
- class FirstOrderModel;
-}
-
namespace uf {
-class UfModelTree
+class UfModelTreeNode
{
public:
- UfModelTree(){}
+ UfModelTreeNode(){}
/** the data */
- std::map< Node, UfModelTree > d_data;
+ std::map< Node, UfModelTreeNode > d_data;
/** the value of this tree node (if all paths lead to same value) */
Node d_value;
/** has concrete argument defintion */
@@ -45,150 +40,137 @@ public:
bool isEmpty() { return d_data.empty() && d_value.isNull(); }
//clear
void clear();
- /** setValue function
- *
- * For each argument of n with ModelBasisAttribute() set to true will be considered default arguments if ground=false
- *
- */
+ /** setValue function */
void setValue( TheoryModel* m, Node n, Node v, std::vector< int >& indexOrder, bool ground, int argIndex );
- /** getValue function
- *
- * returns $val, the value of ground term n
- * Say n is f( t_0...t_n )
- * depIndex is the index for which every term of the form f( t_0 ... t_depIndex, *,... * ) is equal to $val
- * for example, if g( x_0, x_1, x_2 ) := lambda x_0 x_1 x_2. if( x_1==a ) b else c,
- * then g( a, a, a ) would return b with depIndex = 1
- * If ground = true, we are asking whether the term n is constant (assumes that all non-model basis arguments are ground)
- *
- */
+ /** getValue function */
Node getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int& depIndex, int argIndex );
Node getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, std::vector< int >& depIndex, int argIndex );
- ///** getConstant Value function
- // *
- // * given term n, where n may contain model basis arguments
- // * if n is constant for its entire domain, then this function returns the value of its domain
- // * otherwise, it returns null
- // * for example, if f( x_0, x_1 ) := if( x_0 = a ) b else if( x_1 = a ) a else b,
- // * then f( a, e ) would return b, while f( e, a ) would return null
- // *
- // */
+ /** getConstant Value function */
Node getConstantValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int argIndex );
/** getFunctionValue */
Node getFunctionValue();
/** simplify function */
void simplify( Node op, Node defaultVal, int argIndex );
- // is total ?
+ /** is total ? */
bool isTotal( Node op, int argIndex );
public:
void debugPrint( std::ostream& out, TheoryModel* m, std::vector< int >& indexOrder, int ind = 0, int arg = 0 );
};
-class UfModelTreeOrdered
+class UfModelTree
{
private:
+ //the op this model is for
Node d_op;
+ //the order we will treat the arguments
std::vector< int > d_index_order;
- UfModelTree d_tree;
+ //the data
+ UfModelTreeNode d_tree;
public:
- UfModelTreeOrdered(){}
- UfModelTreeOrdered( Node op ) : d_op( op ){
+ //constructors
+ UfModelTree(){}
+ UfModelTree( Node op ) : d_op( op ){
TypeNode tn = d_op.getType();
for( int i=0; i<(int)(tn.getNumChildren()-1); i++ ){
d_index_order.push_back( i );
}
}
- UfModelTreeOrdered( Node op, std::vector< int >& indexOrder ) : d_op( op ){
+ UfModelTree( Node op, std::vector< int >& indexOrder ) : d_op( op ){
d_index_order.insert( d_index_order.end(), indexOrder.begin(), indexOrder.end() );
}
- bool isEmpty() { return d_tree.isEmpty(); }
+ /** clear/reset the function */
void clear() { d_tree.clear(); }
+ /** setValue function
+ *
+ * For each argument of n with ModelBasisAttribute() set to true will be considered default arguments if ground=false
+ *
+ */
void setValue( TheoryModel* m, Node n, Node v, bool ground = true ){
d_tree.setValue( m, n, v, d_index_order, ground, 0 );
}
+ /** setDefaultValue function */
+ void setDefaultValue( TheoryModel* m, Node v ){
+ d_tree.setValue( m, Node::null(), v, d_index_order, false, 0 );
+ }
+ /** getValue function
+ *
+ * returns val, the value of ground term n
+ * Say n is f( t_0...t_n )
+ * depIndex is the index for which every term of the form f( t_0 ... t_depIndex, *,... * ) is equal to val
+ * for example, if g( x_0, x_1, x_2 ) := lambda x_0 x_1 x_2. if( x_1==a ) b else c,
+ * then g( a, a, a ) would return b with depIndex = 1
+ *
+ */
Node getValue( TheoryModel* m, Node n, int& depIndex ){
return d_tree.getValue( m, n, d_index_order, depIndex, 0 );
}
+ /** -> implementation incomplete */
Node getValue( TheoryModel* m, Node n, std::vector< int >& depIndex ){
return d_tree.getValue( m, n, d_index_order, depIndex, 0 );
}
+ /** getConstantValue function
+ *
+ * given term n, where n may contain "all value" arguments, aka model basis arguments
+ * if n is null, then every argument of n is considered "all value"
+ * if n is constant for the entire domain specified by n, then this function returns the value of its domain
+ * otherwise, it returns null
+ * for example, say the term e represents "all values"
+ * if f( x_0, x_1 ) := if( x_0 = a ) b else if( x_1 = a ) a else b,
+ * then f( a, e ) would return b, while f( e, a ) would return null
+ * -> implementation incomplete
+ */
Node getConstantValue( TheoryModel* m, Node n ) {
return d_tree.getConstantValue( m, n, d_index_order, 0 );
}
+ /** getFunctionValue
+ * Returns a compact representation of this function, of kind FUNCTION_MODEL.
+ * See documentation in theory/uf/kinds
+ */
Node getFunctionValue(){
return d_tree.getFunctionValue();
}
+ /** simplify the tree */
void simplify() { d_tree.simplify( d_op, Node::null(), 0 ); }
+ /** is this tree total? */
bool isTotal() { return d_tree.isTotal( d_op, 0 ); }
+ /** is this function constant? */
+ bool isConstant( TheoryModel* m ) { return !getConstantValue( m, Node::null() ).isNull(); }
+ /** is this tree empty? */
+ bool isEmpty() { return d_tree.isEmpty(); }
public:
void debugPrint( std::ostream& out, TheoryModel* m, int ind = 0 ){
d_tree.debugPrint( out, m, d_index_order, ind );
}
+private:
+ //helper for to ITE function.
+ static Node toIte2( Node fm_node, std::vector< Node >& args, int index, Node defaultNode );
+public:
+ /** to ITE function for function model nodes */
+ static Node toIte( Node fm_node, std::vector< Node >& args ) { return toIte2( fm_node, args, 0, Node::null() ); }
};
-class UfModel
+class UfModelTreeGenerator
{
private:
- quantifiers::FirstOrderModel* d_model;
- //the operator this model is for
- Node d_op;
- //is model constructed
- bool d_model_constructed;
//store for set values
+ Node d_default_value;
std::map< Node, Node > d_set_values[2][2];
-private:
// defaults
std::vector< Node > d_defaults;
- Node getIntersection( Node n1, Node n2, bool& isGround );
+ Node getIntersection( TheoryModel* m, Node n1, Node n2, bool& isGround );
public:
- UfModel(){}
- UfModel( Node op, quantifiers::FirstOrderModel* m );
- ~UfModel(){}
- //ground terms for this operator
- std::vector< Node > d_ground_asserts;
- //the representatives they are equal to
- std::vector< Node > d_ground_asserts_reps;
- //data structure that stores the model
- UfModelTreeOrdered d_tree;
- //node equivalent of this model
- Node d_func_value;
-public:
- /** get operator */
- Node getOperator() { return d_op; }
- /** debug print */
- void toStream( std::ostream& out );
+ UfModelTreeGenerator(){}
+ ~UfModelTreeGenerator(){}
+ /** set default value */
+ void setDefaultValue( Node v ) { d_default_value = v; }
/** set value */
- void setValue( Node n, Node v, bool ground = true, bool isReq = true );
- /** get value, return arguments that the value depends on */
- Node getValue( Node n, int& depIndex );
- Node getValue( Node n, std::vector< int >& depIndex );
- /** get constant value */
- Node getConstantValue( Node n );
- /** get function value for this function */
- Node getFunctionValue();
- /** is model constructed */
- bool isModelConstructed() { return d_model_constructed; }
- /** is empty */
- bool isEmpty() { return d_ground_asserts.empty(); }
- /** is constant */
- bool isConstant();
+ void setValue( TheoryModel* m, Node n, Node v, bool ground = true, bool isReq = true );
+ /** make model */
+ void makeModel( TheoryModel* m, UfModelTree& tree );
/** uses partial default values */
bool optUsePartialDefaults();
-public:
- /** set model */
- void setModel();
- /** clear model */
- void clearModel();
- /** make model */
- void makeModel( UfModelTreeOrdered& tree );
-public:
- /** set value preference */
- void setValuePreference( Node f, Node n, bool isPro );
-private:
- //helper for to ITE function.
- static Node toIte2( Node fm_node, std::vector< Node >& args, int index, Node defaultNode );
-public:
- /** to ITE function for function model nodes */
- static Node toIte( Node fm_node, std::vector< Node >& args ) { return toIte2( fm_node, args, 0, Node::null() ); }
+ /** reset */
+ void clear();
};
//this class stores temporary information useful to model engine for constructing model
@@ -197,6 +179,7 @@ class UfModelPreferenceData
public:
UfModelPreferenceData() : d_reconsiderModel( false ){}
virtual ~UfModelPreferenceData(){}
+ Node d_const_val;
// preferences for default values
std::vector< Node > d_values;
std::map< Node, std::vector< Node > > d_value_pro_con[2];
diff --git a/src/theory/uf/theory_uf_strong_solver.cpp b/src/theory/uf/theory_uf_strong_solver.cpp
index e5cb7e4f8..895a7d056 100644
--- a/src/theory/uf/theory_uf_strong_solver.cpp
+++ b/src/theory/uf/theory_uf_strong_solver.cpp
@@ -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;
}
}
diff --git a/src/theory/uf/theory_uf_strong_solver.h b/src/theory/uf/theory_uf_strong_solver.h
index bd4c4cb22..479fea05f 100644
--- a/src/theory/uf/theory_uf_strong_solver.h
+++ b/src/theory/uf/theory_uf_strong_solver.h
@@ -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 */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback