summaryrefslogtreecommitdiff
path: root/src/theory
diff options
context:
space:
mode:
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>2012-07-12 18:30:15 +0000
committerAndrew Reynolds <andrew.j.reynolds@gmail.com>2012-07-12 18:30:15 +0000
commit65798541fa437278cde0c759ab70fd9fa4fe9638 (patch)
tree27341327b8159e58a5ce6371bede6129bf67beb3 /src/theory
parent78d8b3ce56a1fd243acb54d2aaaf6d716e3b9788 (diff)
merged fmf-devel branch, includes support for SMT2 command get-value and (extended) SMT command get-model. added collectModelInfo and removed getValue from theory interface. merge also includes major updates to finite model finding module (from CASC), added fmf options, some updates to strong solver and quantifiers engine interface. The test recursion_breaker_black currently fails for me on production builds, Morgan is planning to look into this.
Diffstat (limited to 'src/theory')
-rw-r--r--src/theory/Makefile.am4
-rw-r--r--src/theory/arith/theory_arith.cpp83
-rw-r--r--src/theory/arith/theory_arith.h2
-rw-r--r--src/theory/arith/theory_arith_instantiator.cpp21
-rw-r--r--src/theory/arith/theory_arith_instantiator.h6
-rw-r--r--src/theory/arrays/theory_arrays.cpp30
-rw-r--r--src/theory/arrays/theory_arrays.h8
-rw-r--r--src/theory/arrays/theory_arrays_instantiator.cpp31
-rw-r--r--src/theory/arrays/theory_arrays_instantiator.h8
-rw-r--r--src/theory/booleans/theory_bool.cpp100
-rw-r--r--src/theory/booleans/theory_bool.h3
-rw-r--r--src/theory/builtin/theory_builtin.cpp33
-rw-r--r--src/theory/builtin/theory_builtin.h2
-rw-r--r--src/theory/bv/theory_bv.cpp54
-rw-r--r--src/theory/bv/theory_bv.h10
-rw-r--r--src/theory/datatypes/theory_datatypes.cpp80
-rw-r--r--src/theory/datatypes/theory_datatypes.h10
-rw-r--r--src/theory/datatypes/theory_datatypes_instantiator.cpp26
-rw-r--r--src/theory/datatypes/theory_datatypes_instantiator.h10
-rw-r--r--src/theory/example/theory_uf_tim.h5
-rw-r--r--src/theory/inst_match.cpp167
-rw-r--r--src/theory/inst_match.h35
-rw-r--r--src/theory/instantiator_default.cpp4
-rw-r--r--src/theory/instantiator_default.h2
-rw-r--r--src/theory/model.cpp436
-rw-r--r--src/theory/model.h165
-rw-r--r--src/theory/quantifiers/Makefile.am10
-rw-r--r--src/theory/quantifiers/first_order_model.cpp146
-rw-r--r--src/theory/quantifiers/first_order_model.h82
-rw-r--r--src/theory/quantifiers/instantiation_engine.cpp156
-rw-r--r--src/theory/quantifiers/instantiation_engine.h7
-rw-r--r--src/theory/quantifiers/model_engine.cpp1667
-rw-r--r--src/theory/quantifiers/model_engine.h366
-rw-r--r--src/theory/quantifiers/relevant_domain.cpp173
-rw-r--r--src/theory/quantifiers/relevant_domain.h54
-rw-r--r--src/theory/quantifiers/rep_set_iterator.cpp523
-rw-r--r--src/theory/quantifiers/rep_set_iterator.h120
-rw-r--r--src/theory/quantifiers/term_database.cpp324
-rw-r--r--src/theory/quantifiers/term_database.h151
-rw-r--r--src/theory/quantifiers/theory_quantifiers.cpp27
-rw-r--r--src/theory/quantifiers/theory_quantifiers.h3
-rw-r--r--src/theory/quantifiers/theory_quantifiers_instantiator.cpp2
-rw-r--r--src/theory/quantifiers/theory_quantifiers_instantiator.h2
-rw-r--r--src/theory/quantifiers_engine.cpp454
-rw-r--r--src/theory/quantifiers_engine.h194
-rw-r--r--src/theory/rewriterules/theory_rewriterules.cpp19
-rw-r--r--src/theory/rewriterules/theory_rewriterules.h3
-rw-r--r--src/theory/rewriterules/theory_rewriterules_rules.cpp4
-rw-r--r--src/theory/shared_terms_database.h20
-rw-r--r--src/theory/theory.cpp64
-rw-r--r--src/theory/theory.h64
-rw-r--r--src/theory/theory_engine.cpp149
-rw-r--r--src/theory/theory_engine.h49
-rw-r--r--src/theory/trigger.cpp4
-rw-r--r--src/theory/trigger.h2
-rw-r--r--src/theory/uf/Makefile.am4
-rw-r--r--src/theory/uf/inst_strategy.cpp51
-rw-r--r--src/theory/uf/inst_strategy.h20
-rw-r--r--src/theory/uf/kinds44
-rw-r--r--src/theory/uf/theory_uf.cpp5
-rw-r--r--src/theory/uf/theory_uf.h6
-rw-r--r--src/theory/uf/theory_uf_candidate_generator.cpp21
-rw-r--r--src/theory/uf/theory_uf_instantiator.cpp24
-rw-r--r--src/theory/uf/theory_uf_instantiator.h10
-rw-r--r--src/theory/uf/theory_uf_model.cpp554
-rw-r--r--src/theory/uf/theory_uf_model.h216
-rw-r--r--src/theory/uf/theory_uf_strong_solver.cpp427
-rw-r--r--src/theory/uf/theory_uf_strong_solver.h59
-rw-r--r--src/theory/uf/theory_uf_type_rules.h64
-rw-r--r--src/theory/valuation.cpp5
-rw-r--r--src/theory/valuation.h2
71 files changed, 4832 insertions, 2854 deletions
diff --git a/src/theory/Makefile.am b/src/theory/Makefile.am
index 84af80035..bca96f7d7 100644
--- a/src/theory/Makefile.am
+++ b/src/theory/Makefile.am
@@ -43,7 +43,9 @@ libtheory_la_SOURCES = \
inst_match_impl.h \
inst_match.cpp \
trigger.h \
- trigger.cpp
+ trigger.cpp \
+ model.h \
+ model.cpp
nodist_libtheory_la_SOURCES = \
rewriter_tables.h \
diff --git a/src/theory/arith/theory_arith.cpp b/src/theory/arith/theory_arith.cpp
index 390ac280b..c68e9cf54 100644
--- a/src/theory/arith/theory_arith.cpp
+++ b/src/theory/arith/theory_arith.cpp
@@ -40,6 +40,7 @@
#include "theory/arith/constraint.h"
#include "theory/arith/theory_arith.h"
#include "theory/arith/normal_form.h"
+#include "theory/model.h"
#include <stdint.h>
@@ -1464,12 +1465,12 @@ void TheoryArith::check(Effort effortLevel){
d_qflraStatus = Result::UNSAT;
if(previous == Result::SAT){
++d_statistics.d_revertsOnConflicts;
- Debug("arith::bt") << "clearing here " << " " << newFacts << " " << previous << " " << d_qflraStatus << endl;
+ Debug("arith::bt") << "clearing here " << " " << newFacts << " " << previous << " " << d_qflraStatus << endl;
revertOutOfConflict();
d_simplex.clearQueue();
}else{
++d_statistics.d_commitsOnConflicts;
- Debug("arith::bt") << "committing here " << " " << newFacts << " " << previous << " " << d_qflraStatus << endl;
+ Debug("arith::bt") << "committing here " << " " << newFacts << " " << previous << " " << d_qflraStatus << endl;
d_partialModel.commitAssignmentChanges();
revertOutOfConflict();
}
@@ -1492,7 +1493,7 @@ void TheoryArith::check(Effort effortLevel){
++d_statistics.d_nontrivialSatChecks;
}
- Debug("arith::bt") << "committing sap inConflit" << " " << newFacts << " " << previous << " " << d_qflraStatus << endl;
+ Debug("arith::bt") << "committing sap inConflit" << " " << newFacts << " " << previous << " " << d_qflraStatus << endl;
d_partialModel.commitAssignmentChanges();
d_unknownsInARow = 0;
if(Debug.isOn("arith::consistency")){
@@ -1503,7 +1504,7 @@ void TheoryArith::check(Effort effortLevel){
++d_unknownsInARow;
++(d_statistics.d_unknownChecks);
Assert(!fullEffort(effortLevel));
- Debug("arith::bt") << "committing unknown" << " " << newFacts << " " << previous << " " << d_qflraStatus << endl;
+ Debug("arith::bt") << "committing unknown" << " " << newFacts << " " << previous << " " << d_qflraStatus << endl;
d_partialModel.commitAssignmentChanges();
d_statistics.d_maxUnknownsInARow.maxAssign(d_unknownsInARow);
break;
@@ -1922,80 +1923,8 @@ DeltaRational TheoryArith::getDeltaValue(TNode n) {
}
}
-Node TheoryArith::getValue(TNode n) {
- NodeManager* nodeManager = NodeManager::currentNM();
+void TheoryArith::collectModelInfo( TheoryModel* m ){
- Assert(d_qflraStatus == Result::SAT);
-
- switch(n.getKind()) {
- case kind::VARIABLE: {
- ArithVar var = d_arithvarNodeMap.asArithVar(n);
-
- DeltaRational drat = d_partialModel.getAssignment(var);
- const Rational& delta = d_partialModel.getDelta();
- Debug("getValue") << n << " " << drat << " " << delta << endl;
- return nodeManager->
- mkConst( drat.getNoninfinitesimalPart() +
- drat.getInfinitesimalPart() * delta );
- }
-
- case kind::EQUAL: // 2 args
- return nodeManager->
- mkConst( d_valuation.getValue(n[0]) == d_valuation.getValue(n[1]) );
-
- case kind::PLUS: { // 2+ args
- Rational value(0);
- for(TNode::iterator i = n.begin(),
- iend = n.end();
- i != iend;
- ++i) {
- value += d_valuation.getValue(*i).getConst<Rational>();
- }
- return nodeManager->mkConst(value);
- }
-
- case kind::MULT: { // 2+ args
- Rational value(1);
- for(TNode::iterator i = n.begin(),
- iend = n.end();
- i != iend;
- ++i) {
- value *= d_valuation.getValue(*i).getConst<Rational>();
- }
- return nodeManager->mkConst(value);
- }
-
- case kind::MINUS: // 2 args
- // should have been rewritten
- Unreachable();
-
- case kind::UMINUS: // 1 arg
- // should have been rewritten
- Unreachable();
-
- case kind::DIVISION: // 2 args
- return nodeManager->mkConst( d_valuation.getValue(n[0]).getConst<Rational>() /
- d_valuation.getValue(n[1]).getConst<Rational>() );
-
- case kind::LT: // 2 args
- return nodeManager->mkConst( d_valuation.getValue(n[0]).getConst<Rational>() <
- d_valuation.getValue(n[1]).getConst<Rational>() );
-
- case kind::LEQ: // 2 args
- return nodeManager->mkConst( d_valuation.getValue(n[0]).getConst<Rational>() <=
- d_valuation.getValue(n[1]).getConst<Rational>() );
-
- case kind::GT: // 2 args
- return nodeManager->mkConst( d_valuation.getValue(n[0]).getConst<Rational>() >
- d_valuation.getValue(n[1]).getConst<Rational>() );
-
- case kind::GEQ: // 2 args
- return nodeManager->mkConst( d_valuation.getValue(n[0]).getConst<Rational>() >=
- d_valuation.getValue(n[1]).getConst<Rational>() );
-
- default:
- Unhandled(n.getKind());
- }
}
bool TheoryArith::safeToReset() const {
diff --git a/src/theory/arith/theory_arith.h b/src/theory/arith/theory_arith.h
index fd2925bf6..35fcca406 100644
--- a/src/theory/arith/theory_arith.h
+++ b/src/theory/arith/theory_arith.h
@@ -323,7 +323,7 @@ public:
void propagate(Effort e);
Node explain(TNode n);
- Node getValue(TNode n);
+ void collectModelInfo( TheoryModel* m );
void shutdown(){ }
diff --git a/src/theory/arith/theory_arith_instantiator.cpp b/src/theory/arith/theory_arith_instantiator.cpp
index f1b870c52..c4cb2f493 100644
--- a/src/theory/arith/theory_arith_instantiator.cpp
+++ b/src/theory/arith/theory_arith_instantiator.cpp
@@ -17,6 +17,7 @@
#include "theory/arith/theory_arith_instantiator.h"
#include "theory/arith/theory_arith.h"
#include "theory/theory_engine.h"
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
@@ -40,7 +41,7 @@ void InstStrategySimplex::processResetInstantiationRound( Theory::Effort effort
d_counter++;
}
-int InstStrategySimplex::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategySimplex::process( Node f, Theory::Effort effort, int e ){
if( e<2 ){
return STATUS_UNFINISHED;
}else if( e==2 ){
@@ -99,7 +100,7 @@ int InstStrategySimplex::process( Node f, Theory::Effort effort, int e, int inst
//
//}
//
-//int InstStrategySimplexUfMatch::process( Node f, int effort, int instLimit ){
+//int InstStrategySimplexUfMatch::process( Node f, int effort ){
// if( effort<2 ){
// return STATUS_UNFINISHED;
// }else if( effort==2 ){
@@ -120,7 +121,7 @@ int InstStrategySimplex::process( Node f, Theory::Effort effort, int e, int inst
// while( d_tableaux_ce_term_trigger[x]->getNextMatch() && !addedLemma ){
// InstMatch* m = d_tableaux_ce_term_trigger[x]->getCurrent();
// if( m->isComplete( f ) ){
-// if( d_quantEngine->addInstantiation( f, m, true ) ){
+// if( d_quantEngine->addInstantiation( f, m ) ){
// ++(d_th->d_statistics.d_instantiations_match_pure);
// ++(d_th->d_statistics.d_instantiations);
// addedLemma = true;
@@ -133,8 +134,8 @@ int InstStrategySimplex::process( Node f, Theory::Effort effort, int e, int inst
// //Debug("quant-arith") << std::endl;
// std::vector< Node > vars;
// std::vector< Node > matches;
-// for( int i=0; i<d_quantEngine->getNumInstantiationConstants( f ); i++ ){
-// Node ic = d_quantEngine->getInstantiationConstant( f, i );
+// for( int i=0; i<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
+// Node ic = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i );
// if( m->d_map[ ic ]!=Node::null() ){
// vars.push_back( ic );
// matches.push_back( m->d_map[ ic ] );
@@ -162,7 +163,7 @@ int InstStrategySimplex::process( Node f, Theory::Effort effort, int e, int inst
// ++(d_th->d_statistics.d_instantiations_match_var);
// }
// }else{
-// if( d_quantEngine->addInstantiation( f, m, true ) ){
+// if( d_quantEngine->addInstantiation( f, m ) ){
// addedLemma = true;
// ++(d_th->d_statistics.d_instantiations_match_no_var);
// ++(d_th->d_statistics.d_instantiations);
@@ -242,7 +243,7 @@ void InstantiatorTheoryArith::processResetInstantiationRound( Theory::Effort eff
}
}
-int InstantiatorTheoryArith::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstantiatorTheoryArith::process( Node f, Theory::Effort effort, int e ){
Debug("quant-arith") << "Arith: Try to solve (" << effort << ") for " << f << "... " << std::endl;
return InstStrategy::STATUS_UNKNOWN;
}
@@ -316,11 +317,11 @@ void InstantiatorTheoryArith::debugPrint( const char* c ){
Node f = d_quantEngine->getQuantifier( q );
Debug(c) << f << std::endl;
Debug(c) << " Inst constants: ";
- for( int i=0; i<(int)d_quantEngine->getNumInstantiationConstants( f ); i++ ){
+ for( int i=0; i<(int)d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
if( i>0 ){
Debug( c ) << ", ";
}
- Debug( c ) << d_quantEngine->getInstantiationConstant( f, i );
+ Debug( c ) << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i );
}
Debug(c) << std::endl;
Debug(c) << " Instantiation rows: ";
@@ -377,7 +378,7 @@ bool InstantiatorTheoryArith::doInstantiation2( Node f, Node term, ArithVar x, I
//use as instantiation value for var
m.d_map[ var ] = instVal;
Debug("quant-arith") << "Add instantiation " << m << std::endl;
- return d_quantEngine->addInstantiation( f, m, true );
+ return d_quantEngine->addInstantiation( f, m );
}
Node InstantiatorTheoryArith::getTableauxValue( Node n, bool minus_delta ){
diff --git a/src/theory/arith/theory_arith_instantiator.h b/src/theory/arith/theory_arith_instantiator.h
index 3880a49a7..406478a2a 100644
--- a/src/theory/arith/theory_arith_instantiator.h
+++ b/src/theory/arith/theory_arith_instantiator.h
@@ -41,7 +41,7 @@ private:
Node d_negOne;
/** process functions */
void processResetInstantiationRound( Theory::Effort effort );
- int process( Node f, Theory::Effort effort, int e, int instLimit );
+ int process( Node f, Theory::Effort effort, int e );
public:
InstStrategySimplex( InstantiatorTheoryArith* th, QuantifiersEngine* ie );
~InstStrategySimplex(){}
@@ -56,7 +56,7 @@ public:
// /** trigger for instantiation rows */
// std::map< ArithVar, Trigger* > d_tableaux_ce_term_trigger;
//public:
-// InstStrategySimplexUfMatch( InstantiatorTheoryArith* th, QuantifiersEngine* ie ) :
+// InstStrategySimplexUfMatch( InstantiatorTheoryArith* th, QuantifiersEngine* ie ) :
// InstStrategy( ie ), d_th( th ){}
// ~InstStrategySimplexUfMatch(){}
// void resetInstantiationRound();
@@ -102,7 +102,7 @@ private:
/** reset instantiation */
void processResetInstantiationRound( Theory::Effort effort );
/** process at effort */
- int process( Node f, Theory::Effort effort, int e, int instLimit );
+ int process( Node f, Theory::Effort effort, int e );
/** add term to row */
void addTermToRow( ArithVar x, Node n, Node& f, NodeBuilder<>& t );
/** get delta for node */
diff --git a/src/theory/arrays/theory_arrays.cpp b/src/theory/arrays/theory_arrays.cpp
index 460289439..5add52d1f 100644
--- a/src/theory/arrays/theory_arrays.cpp
+++ b/src/theory/arrays/theory_arrays.cpp
@@ -24,6 +24,7 @@
#include "theory/rewriter.h"
#include "expr/command.h"
#include "theory/arrays/theory_arrays_instantiator.h"
+#include "theory/model.h"
using namespace std;
@@ -57,7 +58,7 @@ TheoryArrays::TheoryArrays(context::Context* c, context::UserContext* u, OutputC
d_checkTimer("theory::arrays::checkTime"),
d_ppEqualityEngine(u, "theory::arrays::TheoryArraysPP"),
d_ppFacts(u),
- // d_ppCache(u),
+ // d_ppCache(u),
d_literalsToPropagate(c),
d_literalsToPropagateIndex(c, 0),
d_isPreRegistered(c),
@@ -211,7 +212,7 @@ Node TheoryArrays::ppRewrite(TNode term) {
for (j = leftWrites - 1; j > i; --j) {
index_j = write_j[1];
if (!ppDisequal(index_i, index_j)) {
- Node hyp2(index_i.getType() == nm->booleanType()?
+ Node hyp2(index_i.getType() == nm->booleanType()?
index_i.iffNode(index_j) : index_i.eqNode(index_j));
hyp << hyp2.notNode();
}
@@ -623,27 +624,10 @@ void TheoryArrays::computeCareGraph()
// MODEL GENERATION
/////////////////////////////////////////////////////////////////////////////
-
-Node TheoryArrays::getValue(TNode n)
-{
- // TODO: Implement this
- NodeManager* nodeManager = NodeManager::currentNM();
-
- switch(n.getKind()) {
-
- case kind::VARIABLE:
- Unhandled(kind::VARIABLE);
-
- case kind::EQUAL: // 2 args
- return nodeManager->
- mkConst( d_valuation.getValue(n[0]) == d_valuation.getValue(n[1]) );
-
- default:
- Unhandled(n.getKind());
- }
+void TheoryArrays::collectModelInfo( TheoryModel* m ){
+ m->assertEqualityEngine( &d_equalityEngine );
}
-
/////////////////////////////////////////////////////////////////////////////
// NOTIFICATIONS
/////////////////////////////////////////////////////////////////////////////
@@ -663,7 +647,7 @@ void TheoryArrays::presolve()
void TheoryArrays::check(Effort e) {
TimerStat::CodeTimer codeTimer(d_checkTimer);
- while (!done() && !d_conflict)
+ while (!done() && !d_conflict)
{
// Get all the assertions
Assertion assertion = get();
@@ -1306,7 +1290,7 @@ void TheoryArrays::dischargeLemmas()
d_equalityEngine.assertEquality(eq2, true, d_true);
continue;
}
-
+
Node lem = nm->mkNode(kind::OR, eq2_r, eq1_r);
Trace("arrays-lem")<<"Arrays::addRowLemma adding "<<lem<<"\n";
diff --git a/src/theory/arrays/theory_arrays.h b/src/theory/arrays/theory_arrays.h
index 25797dda3..6787f8ad8 100644
--- a/src/theory/arrays/theory_arrays.h
+++ b/src/theory/arrays/theory_arrays.h
@@ -219,7 +219,7 @@ class TheoryArrays : public Theory {
private:
public:
- Node getValue(TNode n);
+ void collectModelInfo( TheoryModel* m );
/////////////////////////////////////////////////////////////////////////////
// NOTIFICATIONS
@@ -346,6 +346,12 @@ class TheoryArrays : public Theory {
void queueRowLemma(RowLemmaType lem);
void dischargeLemmas();
+ public:
+
+ eq::EqualityEngine* getEqualityEngine() {
+ return &d_equalityEngine;
+ }
+
};/* class TheoryArrays */
}/* CVC4::theory::arrays namespace */
diff --git a/src/theory/arrays/theory_arrays_instantiator.cpp b/src/theory/arrays/theory_arrays_instantiator.cpp
index 334d70eea..2e446c57f 100644
--- a/src/theory/arrays/theory_arrays_instantiator.cpp
+++ b/src/theory/arrays/theory_arrays_instantiator.cpp
@@ -51,6 +51,35 @@ void InstantiatorTheoryArrays::processResetInstantiationRound( Theory::Effort ef
}
-int InstantiatorTheoryArrays::process( Node f, Theory::Effort effort, int e, int limitInst ){
+int InstantiatorTheoryArrays::process( Node f, Theory::Effort effort, int e ){
return InstStrategy::STATUS_SAT;
}
+
+bool InstantiatorTheoryArrays::hasTerm( Node a ){
+ return ((TheoryArrays*)d_th)->getEqualityEngine()->hasTerm( a );
+}
+
+bool InstantiatorTheoryArrays::areEqual( Node a, Node b ){
+ if( hasTerm( a ) && hasTerm( b ) ){
+ return ((TheoryArrays*)d_th)->getEqualityEngine()->areEqual( a, b );
+ }else{
+ return a==b;
+ }
+}
+
+bool InstantiatorTheoryArrays::areDisequal( Node a, Node b ){
+ if( hasTerm( a ) && hasTerm( b ) ){
+ return ((TheoryArrays*)d_th)->getEqualityEngine()->areDisequal( a, b, false );
+ }else{
+ return false;
+ }
+}
+
+Node InstantiatorTheoryArrays::getRepresentative( Node a ){
+ if( hasTerm( a ) ){
+ return ((TheoryArrays*)d_th)->getEqualityEngine()->getRepresentative( a );
+ }else{
+ return a;
+ }
+}
+
diff --git a/src/theory/arrays/theory_arrays_instantiator.h b/src/theory/arrays/theory_arrays_instantiator.h
index 6a7c9c3ed..ade43fdb0 100644
--- a/src/theory/arrays/theory_arrays_instantiator.h
+++ b/src/theory/arrays/theory_arrays_instantiator.h
@@ -32,7 +32,7 @@ protected:
/** reset instantiation round */
void processResetInstantiationRound( Theory::Effort effort );
/** process quantifier */
- int process( Node f, Theory::Effort effort, int e, int limitInst = 0 );
+ int process( Node f, Theory::Effort effort, int e );
public:
InstantiatorTheoryArrays(context::Context* c, QuantifiersEngine* ie, Theory* th);
~InstantiatorTheoryArrays() {}
@@ -42,6 +42,12 @@ public:
void assertNode( Node assertion );
/** identify */
std::string identify() const { return std::string("InstantiatorTheoryArrays"); }
+public:
+ /** general queries about equality */
+ bool hasTerm( Node a );
+ bool areEqual( Node a, Node b );
+ bool areDisequal( Node a, Node b );
+ Node getRepresentative( Node a );
};/* class Instantiatior */
}
diff --git a/src/theory/booleans/theory_bool.cpp b/src/theory/booleans/theory_bool.cpp
index 520adc228..f096987db 100644
--- a/src/theory/booleans/theory_bool.cpp
+++ b/src/theory/booleans/theory_bool.cpp
@@ -32,106 +32,8 @@ namespace CVC4 {
namespace theory {
namespace booleans {
-Node TheoryBool::getValue(TNode n) {
- NodeManager* nodeManager = NodeManager::currentNM();
+void TheoryBool::collectModelInfo( TheoryModel* m ){
- switch(n.getKind()) {
- case kind::VARIABLE:
- // case for Boolean vars is implemented in TheoryEngine (since it
- // appeals to the PropEngine to get the value)
- Unreachable();
-
- case kind::EQUAL: // 2 args
- // should be handled by IFF
- Unreachable();
-
- case kind::NOT: { // 1 arg
- Node v = d_valuation.getValue(n[0]);
- return v.isNull() ? Node::null() : nodeManager->mkConst(! v.getConst<bool>());
- }
-
- case kind::AND: { // 2+ args
- bool foundNull = false;
- for(TNode::iterator i = n.begin(),
- iend = n.end();
- i != iend;
- ++i) {
- Node v = d_valuation.getValue(*i);
- if(v.isNull()) {
- foundNull = true;
- } else if(! v.getConst<bool>()) {
- return nodeManager->mkConst(false);
- }
- }
- return foundNull ? Node::null() : nodeManager->mkConst(true);
- }
-
- case kind::IFF: { // 2 args
- Node v0 = d_valuation.getValue(n[0]);
- Node v1 = d_valuation.getValue(n[1]);
- if(v0.isNull() || v1.isNull()) {
- return Node::null();
- }
- return nodeManager->mkConst( v0.getConst<bool>() == v1.getConst<bool>() );
- }
-
- case kind::IMPLIES: { // 2 args
- Node v0 = d_valuation.getValue(n[0]);
- Node v1 = d_valuation.getValue(n[1]);
- if(v0.isNull() && v1.isNull()) {
- return Node::null();
- }
- bool value = false;
- if(! v0.isNull()) {
- value = value || (! v0.getConst<bool>());
- }
- if(! v1.isNull()) {
- value = value || v1.getConst<bool>();
- }
- return nodeManager->mkConst(value);
- }
-
- case kind::OR: { // 2+ args
- bool foundNull = false;
- for(TNode::iterator i = n.begin(),
- iend = n.end();
- i != iend;
- ++i) {
- Node v = d_valuation.getValue(*i);
- if(v.isNull()) {
- foundNull = true;
- } else if(v.getConst<bool>()) {
- return nodeManager->mkConst(true);
- }
- }
- return foundNull ? Node::null() : nodeManager->mkConst(false);
- }
-
- case kind::XOR: { // 2 args
- Node v0 = d_valuation.getValue(n[0]);
- Node v1 = d_valuation.getValue(n[1]);
- if(v0.isNull() || v1.isNull()) {
- return Node::null();
- }
- return nodeManager->mkConst( v0.getConst<bool>() != v1.getConst<bool>() );
- }
-
- case kind::ITE: { // 3 args
- // all ITEs should be gone except (bool,bool,bool) ones
- Assert( n[1].getType() == nodeManager->booleanType() &&
- n[2].getType() == nodeManager->booleanType() );
- Node v0 = d_valuation.getValue(n[0]);
- Node v1 = d_valuation.getValue(n[1]);
- Node v2 = d_valuation.getValue(n[2]);
- if(v0.isNull()) {
- return v1 == v2 ? v1 : Node::null();
- }
- return nodeManager->mkConst( v0.getConst<bool>() ? v1.getConst<bool>() : v2.getConst<bool>() );
- }
-
- default:
- Unhandled(n.getKind());
- }
}
Theory::PPAssertStatus TheoryBool::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
diff --git a/src/theory/booleans/theory_bool.h b/src/theory/booleans/theory_bool.h
index 40783a6ce..827b0ff57 100644
--- a/src/theory/booleans/theory_bool.h
+++ b/src/theory/booleans/theory_bool.h
@@ -23,6 +23,7 @@
#include "theory/theory.h"
#include "context/context.h"
+#include "theory/model.h"
namespace CVC4 {
namespace theory {
@@ -34,7 +35,7 @@ public:
Theory(THEORY_BOOL, c, u, out, valuation, logicInfo, qe) {
}
- Node getValue(TNode n);
+ void collectModelInfo( TheoryModel* m );
PPAssertStatus ppAssert(TNode in, SubstitutionMap& outSubstitutions);
diff --git a/src/theory/builtin/theory_builtin.cpp b/src/theory/builtin/theory_builtin.cpp
index e955539d5..fa176243c 100644
--- a/src/theory/builtin/theory_builtin.cpp
+++ b/src/theory/builtin/theory_builtin.cpp
@@ -19,6 +19,7 @@
#include "theory/builtin/theory_builtin.h"
#include "theory/valuation.h"
#include "expr/kind.h"
+#include "theory/model.h"
using namespace std;
@@ -26,38 +27,8 @@ namespace CVC4 {
namespace theory {
namespace builtin {
-Node TheoryBuiltin::getValue(TNode n) {
- switch(n.getKind()) {
+void TheoryBuiltin::collectModelInfo( TheoryModel* m ){
- case kind::VARIABLE:
- // no variables that the builtin theory is responsible for
- Unreachable();
-
- case kind::EQUAL: { // 2 args
- // has to be an EQUAL over tuples, since all others should be
- // handled elsewhere
- Assert(n[0].getKind() == kind::TUPLE &&
- n[1].getKind() == kind::TUPLE);
- return NodeManager::currentNM()->
- mkConst( getValue(n[0]) == getValue(n[1]) );
- }
-
- case kind::TUPLE: { // 2+ args
- NodeBuilder<> nb(kind::TUPLE);
- for(TNode::iterator i = n.begin(),
- iend = n.end();
- i != iend;
- ++i) {
- nb << d_valuation.getValue(*i);
- }
- return Node(nb);
- }
-
- default:
- // all other "builtins" should have been rewritten away or handled
- // by the valuation, or handled elsewhere.
- Unhandled(n.getKind());
- }
}
}/* CVC4::theory::builtin namespace */
diff --git a/src/theory/builtin/theory_builtin.h b/src/theory/builtin/theory_builtin.h
index a13c69d9d..51bd7c756 100644
--- a/src/theory/builtin/theory_builtin.h
+++ b/src/theory/builtin/theory_builtin.h
@@ -31,7 +31,7 @@ class TheoryBuiltin : public Theory {
public:
TheoryBuiltin(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo, QuantifiersEngine* qe) :
Theory(THEORY_BUILTIN, c, u, out, valuation, logicInfo, qe) {}
- Node getValue(TNode n);
+ void collectModelInfo( TheoryModel* m );
std::string identify() const { return std::string("TheoryBuiltin"); }
};/* class TheoryBuiltin */
diff --git a/src/theory/bv/theory_bv.cpp b/src/theory/bv/theory_bv.cpp
index 273b406e6..da2dd77f6 100644
--- a/src/theory/bv/theory_bv.cpp
+++ b/src/theory/bv/theory_bv.cpp
@@ -57,13 +57,13 @@ TheoryBV::Statistics::Statistics():
{
StatisticsRegistry::registerStat(&d_avgConflictSize);
StatisticsRegistry::registerStat(&d_solveSubstitutions);
- StatisticsRegistry::registerStat(&d_solveTimer);
+ StatisticsRegistry::registerStat(&d_solveTimer);
}
TheoryBV::Statistics::~Statistics() {
StatisticsRegistry::unregisterStat(&d_avgConflictSize);
StatisticsRegistry::unregisterStat(&d_solveSubstitutions);
- StatisticsRegistry::unregisterStat(&d_solveTimer);
+ StatisticsRegistry::unregisterStat(&d_solveTimer);
}
void TheoryBV::preRegisterTerm(TNode node) {
@@ -75,7 +75,7 @@ void TheoryBV::preRegisterTerm(TNode node) {
}
d_bitblastSolver.preRegister(node);
- d_equalitySolver.preRegister(node);
+ d_equalitySolver.preRegister(node);
}
void TheoryBV::sendConflict() {
@@ -94,54 +94,40 @@ void TheoryBV::check(Effort e)
{
BVDebug("bitvector") << "TheoryBV::check(" << e << ")" << std::endl;
- // if we are already in conflict just return the conflict
+ // if we are already in conflict just return the conflict
if (inConflict()) {
sendConflict();
return;
}
-
+
// getting the new assertions
- std::vector<TNode> new_assertions;
+ std::vector<TNode> new_assertions;
while (!done()) {
Assertion assertion = get();
TNode fact = assertion.assertion;
new_assertions.push_back(fact);
- BVDebug("bitvector-assertions") << "TheoryBV::check assertion " << fact << "\n";
+ BVDebug("bitvector-assertions") << "TheoryBV::check assertion " << fact << "\n";
}
if (!inConflict()) {
// sending assertions to the equality solver first
d_equalitySolver.addAssertions(new_assertions, e);
}
-
+
if (!inConflict()) {
// sending assertions to the bitblast solver
d_bitblastSolver.addAssertions(new_assertions, e);
}
-
+
if (inConflict()) {
sendConflict();
}
}
+void TheoryBV::collectModelInfo( TheoryModel* m ){
-Node TheoryBV::getValue(TNode n) {
- //NodeManager* nodeManager = NodeManager::currentNM();
-
- switch(n.getKind()) {
-
- case kind::VARIABLE:
- Unhandled(kind::VARIABLE);
-
- case kind::EQUAL: // 2 args
- Unhandled(kind::VARIABLE);
-
- default:
- Unhandled(n.getKind());
- }
}
-
void TheoryBV::propagate(Effort e) {
BVDebug("bitvector") << indent() << "TheoryBV::propagate()" << std::endl;
@@ -166,14 +152,14 @@ void TheoryBV::propagate(Effort e) {
Theory::PPAssertStatus TheoryBV::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
switch(in.getKind()) {
case kind::EQUAL:
-
+
if (in[0].getMetaKind() == kind::metakind::VARIABLE && !in[1].hasSubterm(in[0])) {
- ++(d_statistics.d_solveSubstitutions);
+ ++(d_statistics.d_solveSubstitutions);
outSubstitutions.addSubstitution(in[0], in[1]);
return PP_ASSERT_STATUS_SOLVED;
}
if (in[1].getMetaKind() == kind::metakind::VARIABLE && !in[0].hasSubterm(in[1])) {
- ++(d_statistics.d_solveSubstitutions);
+ ++(d_statistics.d_solveSubstitutions);
outSubstitutions.addSubstitution(in[1], in[0]);
return PP_ASSERT_STATUS_SOLVED;
}
@@ -243,14 +229,14 @@ bool TheoryBV::storePropagation(TNode literal, SubTheory subtheory)
void TheoryBV::explain(TNode literal, std::vector<TNode>& assumptions) {
- // Ask the appropriate subtheory for the explanation
+ // Ask the appropriate subtheory for the explanation
if (propagatedBy(literal, SUB_EQUALITY)) {
BVDebug("bitvector::explain") << "TheoryBV::explain(" << literal << "): EQUALITY" << std::endl;
- d_equalitySolver.explain(literal, assumptions);
+ d_equalitySolver.explain(literal, assumptions);
} else {
Assert(propagatedBy(literal, SUB_BITBLAST));
- BVDebug("bitvector::explain") << "TheoryBV::explain(" << literal << ") : BITBLASTER" << std::endl;
- d_bitblastSolver.explain(literal, assumptions);
+ BVDebug("bitvector::explain") << "TheoryBV::explain(" << literal << ") : BITBLASTER" << std::endl;
+ d_bitblastSolver.explain(literal, assumptions);
}
}
@@ -263,7 +249,7 @@ Node TheoryBV::explain(TNode node) {
explain(node, assumptions);
// this means that it is something true at level 0
if (assumptions.size() == 0) {
- return utils::mkTrue();
+ return utils::mkTrue();
}
// return the explanation
Node explanation = mkAnd(assumptions);
@@ -274,9 +260,9 @@ Node TheoryBV::explain(TNode node) {
void TheoryBV::addSharedTerm(TNode t) {
Debug("bitvector::sharing") << indent() << "TheoryBV::addSharedTerm(" << t << ")" << std::endl;
- d_sharedTermsSet.insert(t);
+ d_sharedTermsSet.insert(t);
if (!Options::current()->bitvectorEagerBitblast && d_useEqualityEngine) {
- d_equalitySolver.addSharedTerm(t);
+ d_equalitySolver.addSharedTerm(t);
}
}
diff --git a/src/theory/bv/theory_bv.h b/src/theory/bv/theory_bv.h
index 761c11e3d..611927b2b 100644
--- a/src/theory/bv/theory_bv.h
+++ b/src/theory/bv/theory_bv.h
@@ -57,10 +57,10 @@ public:
void check(Effort e);
void propagate(Effort e);
-
+
Node explain(TNode n);
- Node getValue(TNode n);
+ void collectModelInfo( TheoryModel* m );
std::string identify() const { return std::string("TheoryBV"); }
@@ -124,7 +124,7 @@ private:
}
void setConflict(Node conflict = Node::null()) {
- d_conflict = true;
+ d_conflict = true;
d_conflictNode = conflict;
}
@@ -136,8 +136,8 @@ private:
friend class Bitblaster;
friend class BitblastSolver;
- friend class EqualitySolver;
-
+ friend class EqualitySolver;
+
};/* class TheoryBV */
}/* CVC4::theory::bv namespace */
diff --git a/src/theory/datatypes/theory_datatypes.cpp b/src/theory/datatypes/theory_datatypes.cpp
index f9ef49c6b..cb0f75c12 100644
--- a/src/theory/datatypes/theory_datatypes.cpp
+++ b/src/theory/datatypes/theory_datatypes.cpp
@@ -23,6 +23,7 @@
#include "util/datatype.h"
#include "util/Assert.h"
#include "theory/datatypes/theory_datatypes_instantiator.h"
+#include "theory/model.h"
#include <map>
@@ -94,6 +95,9 @@ void TheoryDatatypes::notifyCongruent(TNode lhs, TNode rhs) {
void TheoryDatatypes::preRegisterTerm(TNode n) {
Debug("datatypes-prereg") << "TheoryDatatypes::preRegisterTerm() " << n << endl;
+ if( n.getType().isDatatype() ){
+ d_preRegTerms.push_back( n );
+ }
}
@@ -616,16 +620,11 @@ void TheoryDatatypes::updateSelectors( Node a ) {
}
}
-Node TheoryDatatypes::getValue(TNode n) {
- NodeManager* nodeManager = NodeManager::currentNM();
- switch(n.getKind()) {
- case kind::VARIABLE:
- Unhandled(kind::VARIABLE);
- case kind::EQUAL: // 2 args
- return nodeManager->
- mkConst( d_valuation.getValue(n[0]) == d_valuation.getValue(n[1]) );
- default:
- Unhandled(n.getKind());
+void TheoryDatatypes::collectModelInfo( TheoryModel* m ){
+ //temporary
+ for( int i=0; i<(int)d_preRegTerms.size(); i++ ){
+ Node n = find( d_preRegTerms[i] );
+ m->assertEquality( n, d_preRegTerms[i], true );
}
}
@@ -1054,3 +1053,64 @@ bool TheoryDatatypes::searchForCycle( Node n, Node on,
}
return false;
}
+
+bool TheoryDatatypes::hasTerm( Node a ){
+ return false;
+}
+
+bool TheoryDatatypes::areEqual( Node a, Node b ){
+ Node ar = find( a );
+ Node br = find( b );
+ if( ar==br ){
+ return true;
+ }else if( ar.getKind()==APPLY_CONSTRUCTOR && br.getKind()==APPLY_CONSTRUCTOR &&
+ ar.getOperator()==br.getOperator() ){
+ //for( int i=0; i<(int)ar.getNumChildren(); i++ ){
+ // if( !areEqual( ar[0], br[0] ) ){
+ // return false;
+ // }
+ //}
+ //return true;
+ return false;
+ }else{
+ return false;
+ }
+}
+
+bool TheoryDatatypes::areDisequal( Node a, Node b ){
+ Node ar = find( a );
+ Node br = find( b );
+ if( ar==br ){
+ return false;
+ }else if( ar.getKind()==APPLY_CONSTRUCTOR && br.getKind()==APPLY_CONSTRUCTOR &&
+ ar.getOperator()!=br.getOperator() ){
+ return true;
+ }else{
+ EqLists::iterator deq_ia = d_disequalities.find( ar );
+ EqLists::iterator deq_ib = d_disequalities.find( br );
+ if( deq_ia!=d_disequalities.end() && deq_ib!=d_disequalities.end() ){
+ EqList* deq;
+ if( (*deq_ib).second->size()<(*deq_ia).second->size() ){
+ deq = (*deq_ib).second;
+ }else{
+ deq = (*deq_ia).second;
+ }
+ for(EqList::const_iterator i = deq->begin(); i != deq->end(); i++) {
+ TNode deqn = (*i);
+ TNode sp = find(deqn[0]);
+ TNode tp = find(deqn[1]);
+ if( sp==a && tp==b ){
+ return true;
+ }else if( sp==b && tp==a ){
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
+
+Node TheoryDatatypes::getRepresentative( Node a ){
+ return find( a );
+}
+
diff --git a/src/theory/datatypes/theory_datatypes.h b/src/theory/datatypes/theory_datatypes.h
index 5a4135a3b..783c0ebc7 100644
--- a/src/theory/datatypes/theory_datatypes.h
+++ b/src/theory/datatypes/theory_datatypes.h
@@ -142,6 +142,8 @@ private:
*/
CongruenceClosureExplainer<CongruenceChannel, CONGRUENCE_OPERATORS_2 (kind::APPLY_CONSTRUCTOR, kind::APPLY_SELECTOR)> d_cce;
+ //temporary
+ std::vector< Node > d_preRegTerms;
public:
TheoryDatatypes(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo, QuantifiersEngine* qe);
~TheoryDatatypes();
@@ -150,7 +152,7 @@ public:
void addSharedTerm(TNode t);
void check(Effort e);
- Node getValue(TNode n);
+ void collectModelInfo( TheoryModel* m );
void shutdown() { }
std::string identify() const { return std::string("TheoryDatatypes"); }
@@ -180,6 +182,12 @@ private:
bool searchForCycle( Node n, Node on,
std::map< Node, bool >& visited,
NodeBuilder<>& explanation );
+public:
+ //equality queries
+ bool hasTerm( Node a );
+ bool areEqual( Node a, Node b );
+ bool areDisequal( Node a, Node b );
+ Node getRepresentative( Node a );
};/* class TheoryDatatypes */
inline bool TheoryDatatypes::hasConflict() {
diff --git a/src/theory/datatypes/theory_datatypes_instantiator.cpp b/src/theory/datatypes/theory_datatypes_instantiator.cpp
index 6a32466e4..9495e4d48 100644
--- a/src/theory/datatypes/theory_datatypes_instantiator.cpp
+++ b/src/theory/datatypes/theory_datatypes_instantiator.cpp
@@ -17,6 +17,7 @@
#include "theory/datatypes/theory_datatypes_instantiator.h"
#include "theory/datatypes/theory_datatypes.h"
#include "theory/theory_engine.h"
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
@@ -47,15 +48,15 @@ void InstantiatorTheoryDatatypes::processResetInstantiationRound( Theory::Effort
}
-int InstantiatorTheoryDatatypes::process( Node f, Theory::Effort effort, int e, int limitInst ){
+int InstantiatorTheoryDatatypes::process( Node f, Theory::Effort effort, int e ){
Debug("quant-datatypes") << "Datatypes: Try to solve (" << e << ") for " << f << "... " << std::endl;
if( Options::current()->cbqi ){
if( e<2 ){
return InstStrategy::STATUS_UNFINISHED;
}else if( e==2 ){
InstMatch m;
- for( int j = 0; j<(int)d_quantEngine->getNumInstantiationConstants( f ); j++ ){
- Node i = d_quantEngine->getInstantiationConstant( f, j );
+ for( int j = 0; j<(int)d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); j++ ){
+ Node i = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );
if( i.getType().isDatatype() ){
Node n = getValueFor( i );
Debug("quant-datatypes-debug") << "Value for " << i << " is " << n << std::endl;
@@ -142,10 +143,6 @@ Node InstantiatorTheoryDatatypes::getValueFor( Node n ){
}
}
-Node InstantiatorTheoryDatatypes::getRepresentative( Node n ){
- return ((TheoryDatatypes*)d_th)->find( n );
-}
-
InstantiatorTheoryDatatypes::Statistics::Statistics():
d_instantiations("InstantiatorTheoryDatatypes::Instantiations_Total", 0)
{
@@ -156,3 +153,18 @@ InstantiatorTheoryDatatypes::Statistics::~Statistics(){
StatisticsRegistry::unregisterStat(&d_instantiations);
}
+bool InstantiatorTheoryDatatypes::hasTerm( Node a ){
+ return ((TheoryDatatypes*)d_th)->hasTerm( a );
+}
+
+bool InstantiatorTheoryDatatypes::areEqual( Node a, Node b ){
+ return ((TheoryDatatypes*)d_th)->areEqual( a, b );
+}
+
+bool InstantiatorTheoryDatatypes::areDisequal( Node a, Node b ){
+ return ((TheoryDatatypes*)d_th)->areDisequal( a, b );
+}
+
+Node InstantiatorTheoryDatatypes::getRepresentative( Node a ){
+ return ((TheoryDatatypes*)d_th)->getRepresentative( a );
+}
diff --git a/src/theory/datatypes/theory_datatypes_instantiator.h b/src/theory/datatypes/theory_datatypes_instantiator.h
index ab5703757..a080465af 100644
--- a/src/theory/datatypes/theory_datatypes_instantiator.h
+++ b/src/theory/datatypes/theory_datatypes_instantiator.h
@@ -42,11 +42,9 @@ private:
/** reset instantiation */
void processResetInstantiationRound( Theory::Effort effort );
/** process at effort */
- int process( Node f, Theory::Effort effort, int e, int limitInst );
+ int process( Node f, Theory::Effort effort, int e );
/** get value for */
Node getValueFor( Node n );
- /** get representative */
- Node getRepresentative( Node n );
class Statistics {
public:
@@ -55,6 +53,12 @@ private:
~Statistics();
};
Statistics d_statistics;
+public:
+ /** general queries about equality */
+ bool hasTerm( Node a );
+ bool areEqual( Node a, Node b );
+ bool areDisequal( Node a, Node b );
+ Node getRepresentative( Node a );
};/* class InstantiatiorTheoryDatatypes */
}
diff --git a/src/theory/example/theory_uf_tim.h b/src/theory/example/theory_uf_tim.h
index 41e58349a..5a6732bc4 100644
--- a/src/theory/example/theory_uf_tim.h
+++ b/src/theory/example/theory_uf_tim.h
@@ -143,12 +143,11 @@ public:
void explain(TNode n) {}
/**
- * Get a theory value.
+ * Get model
*
- * Overloads Node getValue(TNode n); from theory.h.
* See theory/theory.h for more information about this method.
*/
- Node getValue(TNode n) {
+ void collectModelInfo( TheoryModel* m ){
Unimplemented("TheoryUFTim doesn't support model generation");
}
diff --git a/src/theory/inst_match.cpp b/src/theory/inst_match.cpp
index 32d6c958b..abcf5aa7f 100644
--- a/src/theory/inst_match.cpp
+++ b/src/theory/inst_match.cpp
@@ -20,6 +20,10 @@
#include "theory/uf/theory_uf_instantiator.h"
#include "theory/uf/theory_uf_candidate_generator.h"
#include "theory/uf/equality_engine.h"
+#include "theory/quantifiers/model_engine.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/first_order_model.h"
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
@@ -29,7 +33,8 @@ using namespace CVC4::theory;
bool CandidateGenerator::isLegalCandidate( Node n ){
- return !n.getAttribute(NoMatchAttribute()) && ( !Options::current()->cbqi || !n.hasAttribute(InstConstantAttribute()) );
+ return ( !n.getAttribute(NoMatchAttribute()) && ( !Options::current()->cbqi || !n.hasAttribute(InstConstantAttribute()) ) ) ||
+ ( Options::current()->finiteModelFind && n.hasAttribute(ModelBasisArgAttribute()) && n.getAttribute(ModelBasisArgAttribute())==1 );
}
void CandidateGeneratorQueue::addCandidate( Node n ) {
@@ -115,9 +120,9 @@ void InstMatch::debugPrint( const char* c ){
}
void InstMatch::makeComplete( Node f, QuantifiersEngine* qe ){
- for( int i=0; i<(int)qe->d_inst_constants[f].size(); i++ ){
- if( d_map.find( qe->d_inst_constants[f][i] )==d_map.end() ){
- d_map[ qe->d_inst_constants[f][i] ] = qe->getFreeVariableForInstConstant( qe->d_inst_constants[f][i] );
+ for( int i=0; i<(int)qe->getTermDatabase()->d_inst_constants[f].size(); i++ ){
+ if( d_map.find( qe->getTermDatabase()->d_inst_constants[f][i] )==d_map.end() ){
+ d_map[ qe->getTermDatabase()->d_inst_constants[f][i] ] = qe->getTermDatabase()->getFreeVariableForInstConstant( qe->getTermDatabase()->d_inst_constants[f][i] );
}
}
}
@@ -127,7 +132,7 @@ void InstMatch::makeInternal( QuantifiersEngine* qe ){
if( Options::current()->cbqi && it->second.hasAttribute(InstConstantAttribute()) ){
d_map[ it->first ] = qe->getEqualityQuery()->getInternalRepresentative( it->second );
if( Options::current()->cbqi && it->second.hasAttribute(InstConstantAttribute()) ){
- d_map[ it->first ] = qe->getFreeVariableForInstConstant( it->first );
+ d_map[ it->first ] = qe->getTermDatabase()->getFreeVariableForInstConstant( it->first );
}
}
}
@@ -137,7 +142,7 @@ void InstMatch::makeRepresentative( QuantifiersEngine* qe ){
for( std::map< Node, Node >::iterator it = d_map.begin(); it != d_map.end(); ++it ){
d_map[ it->first ] = qe->getEqualityQuery()->getInternalRepresentative( it->second );
if( Options::current()->cbqi && it->second.hasAttribute(InstConstantAttribute()) ){
- d_map[ it->first ] = qe->getFreeVariableForInstConstant( it->first );
+ d_map[ it->first ] = qe->getTermDatabase()->getFreeVariableForInstConstant( it->first );
}
}
}
@@ -154,7 +159,7 @@ void InstMatch::computeTermVec( QuantifiersEngine* qe, const std::vector< Node >
if( it!=d_map.end() && !it->second.isNull() ){
match.push_back( it->second );
}else{
- match.push_back( qe->getFreeVariableForInstConstant( vars[i] ) );
+ match.push_back( qe->getTermDatabase()->getFreeVariableForInstConstant( vars[i] ) );
}
}
}
@@ -169,7 +174,7 @@ void InstMatch::computeTermVec( const std::vector< Node >& vars, std::vector< No
void InstMatchTrie::addInstMatch2( QuantifiersEngine* qe, Node f, InstMatch& m, int index, ImtIndexOrder* imtio ){
if( long(index)<long(f[0].getNumChildren()) && ( !imtio || long(index)<long(imtio->d_order.size()) ) ){
int i_index = imtio ? imtio->d_order[index] : index;
- Node n = m.d_map[ qe->getInstantiationConstant( f, i_index ) ];
+ Node n = m.d_map[ qe->getTermDatabase()->getInstantiationConstant( f, i_index ) ];
d_data[n].addInstMatch2( qe, f, m, index+1, imtio );
}
}
@@ -180,7 +185,7 @@ bool InstMatchTrie::existsInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m
return true;
}else{
int i_index = imtio ? imtio->d_order[index] : index;
- Node n = m.d_map[ qe->getInstantiationConstant( f, i_index ) ];
+ Node n = m.d_map[ qe->getTermDatabase()->getInstantiationConstant( f, i_index ) ];
std::map< Node, InstMatchTrie >::iterator it = d_data.find( n );
if( it!=d_data.end() ){
if( it->second.existsInstMatch( qe, f, m, modEq, index+1, imtio ) ){
@@ -190,7 +195,7 @@ bool InstMatchTrie::existsInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m
if( modEq ){
//check modulo equality if any other instantiation match exists
if( ((uf::TheoryUF*)qe->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine()->hasTerm( n ) ){
- eq::EqClassIterator eqc( qe->getEqualityQuery()->getRepresentative( n ),
+ eq::EqClassIterator eqc( ((uf::TheoryUF*)qe->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine()->getRepresentative( n ),
((uf::TheoryUF*)qe->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine() );
while( !eqc.isFinished() ){
Node en = (*eqc);
@@ -344,7 +349,9 @@ bool InstMatchGenerator::getMatch( Node t, InstMatch& m, QuantifiersEngine* qe )
Debug("matching") << "Matching " << t << " against pattern " << d_match_pattern << " ("
<< m.d_map.size() << ")" << ", " << d_children.size() << std::endl;
Assert( !d_match_pattern.isNull() );
- if( d_matchPolicy==MATCH_GEN_INTERNAL_ARITHMETIC ){
+ if( qe->d_optMatchIgnoreModelBasis && t.getAttribute(ModelBasisAttribute()) ){
+ return true;
+ }else if( d_matchPolicy==MATCH_GEN_INTERNAL_ARITHMETIC ){
return getMatchArithmetic( t, m, qe );
}else if( d_matchPolicy==MATCH_GEN_INTERNAL_ERROR ){
return false;
@@ -421,7 +428,6 @@ bool InstMatchGenerator::getNextMatch2( InstMatch& m, QuantifiersEngine* qe, boo
t = d_cg->getNextCandidate();
//if t not null, try to fit it into match m
if( !t.isNull() && t.getType()==d_match_pattern.getType() ){
- //Assert( t.getType()==d_match_pattern.getType() );
success = getMatch( t, m, qe );
}
}while( !success && !t.isNull() );
@@ -592,16 +598,16 @@ bool InstMatchGenerator::nonunifiable( TNode t0, const std::vector<Node> & vars)
return false;
}
-int InstMatchGenerator::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit, bool addSplits ){
+int InstMatchGenerator::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
//now, try to add instantiation for each match produced
int addedLemmas = 0;
InstMatch m;
while( getNextMatch( m, qe ) ){
//m.makeInternal( d_quantEngine->getEqualityQuery() );
m.add( baseMatch );
- if( qe->addInstantiation( f, m, addSplits ) ){
+ if( qe->addInstantiation( f, m ) ){
addedLemmas++;
- if( instLimit>0 && addedLemmas==instLimit ){
+ if( qe->d_optInstLimitActive && qe->d_optInstLimit<=0 ){
return addedLemmas;
}
}
@@ -706,29 +712,62 @@ void InstMatchGeneratorMulti::reset( Node eqc, QuantifiersEngine* qe ){
}
}
-void InstMatchGeneratorMulti::collectInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
- std::vector< IndexedTrie >& unique_var_tries,
- int trieIndex, int childIndex, int endChildIndex, bool modEq ){
+int InstMatchGeneratorMulti::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
+ int addedLemmas = 0;
+ Debug("smart-multi-trigger") << "Process smart multi trigger" << std::endl;
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ Debug("smart-multi-trigger") << "Calculate matches " << i << std::endl;
+ std::vector< InstMatch > newMatches;
+ InstMatch m;
+ while( d_children[i]->getNextMatch( m, qe ) ){
+ m.makeRepresentative( qe );
+ newMatches.push_back( InstMatch( &m ) );
+ m.clear();
+ }
+ for( int j=0; j<(int)newMatches.size(); j++ ){
+ processNewMatch( qe, newMatches[j], i, addedLemmas );
+ }
+ }
+ return addedLemmas;
+}
+
+void InstMatchGeneratorMulti::processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas ){
+ //see if these produce new matches
+ d_children_trie[fromChildIndex].addInstMatch( qe, d_f, m, true );
+ //possibly only do the following if we know that new matches will be produced?
+ //the issue is that instantiations are filtered in quantifiers engine, and so there is no guarentee that
+ // we can safely skip the following lines, even when we have already produced this match.
+ Debug("smart-multi-trigger") << "Child " << fromChildIndex << " produced match " << m << std::endl;
+ //process new instantiations
+ int childIndex = (fromChildIndex+1)%(int)d_children.size();
+ std::vector< IndexedTrie > unique_var_tries;
+ processNewInstantiations( qe, m, addedLemmas, d_children_trie[childIndex].getTrie(),
+ unique_var_tries, 0, childIndex, fromChildIndex, true );
+}
+
+void InstMatchGeneratorMulti::processNewInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
+ std::vector< IndexedTrie >& unique_var_tries,
+ int trieIndex, int childIndex, int endChildIndex, bool modEq ){
if( childIndex==endChildIndex ){
//now, process unique variables
- collectInstantiations2( qe, m, addedLemmas, unique_var_tries, 0 );
+ processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, 0 );
}else if( trieIndex<(int)d_children_trie[childIndex].getOrdering()->d_order.size() ){
int curr_index = d_children_trie[childIndex].getOrdering()->d_order[trieIndex];
- Node curr_ic = qe->getInstantiationConstant( d_f, curr_index );
+ Node curr_ic = qe->getTermDatabase()->getInstantiationConstant( d_f, curr_index );
if( m.d_map.find( curr_ic )==m.d_map.end() ){
//if( d_var_to_node[ curr_index ].size()==1 ){ //FIXME
// //unique variable(s), defer calculation
// unique_var_tries.push_back( IndexedTrie( std::pair< int, int >( childIndex, trieIndex ), tr ) );
// int newChildIndex = (childIndex+1)%(int)d_children.size();
- // collectInstantiations( qe, m, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
- // 0, newChildIndex, endChildIndex, modEq );
+ // processNewInstantiations( qe, m, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
+ // 0, newChildIndex, endChildIndex, modEq );
//}else{
//shared and non-set variable, add to InstMatch
for( std::map< Node, InstMatchTrie >::iterator it = tr->d_data.begin(); it != tr->d_data.end(); ++it ){
InstMatch mn( &m );
mn.d_map[ curr_ic ] = it->first;
- collectInstantiations( qe, mn, addedLemmas, &(it->second), unique_var_tries,
- trieIndex+1, childIndex, endChildIndex, modEq );
+ processNewInstantiations( qe, mn, addedLemmas, &(it->second), unique_var_tries,
+ trieIndex+1, childIndex, endChildIndex, modEq );
}
//}
}else{
@@ -736,8 +775,8 @@ void InstMatchGeneratorMulti::collectInstantiations( QuantifiersEngine* qe, Inst
Node n = m.d_map[ curr_ic ];
std::map< Node, InstMatchTrie >::iterator it = tr->d_data.find( n );
if( it!=tr->d_data.end() ){
- collectInstantiations( qe, m, addedLemmas, &(it->second), unique_var_tries,
- trieIndex+1, childIndex, endChildIndex, modEq );
+ processNewInstantiations( qe, m, addedLemmas, &(it->second), unique_var_tries,
+ trieIndex+1, childIndex, endChildIndex, modEq );
}
if( modEq ){
//check modulo equality for other possible instantiations
@@ -749,8 +788,8 @@ void InstMatchGeneratorMulti::collectInstantiations( QuantifiersEngine* qe, Inst
if( en!=n ){
std::map< Node, InstMatchTrie >::iterator itc = tr->d_data.find( en );
if( itc!=tr->d_data.end() ){
- collectInstantiations( qe, m, addedLemmas, &(itc->second), unique_var_tries,
- trieIndex+1, childIndex, endChildIndex, modEq );
+ processNewInstantiations( qe, m, addedLemmas, &(itc->second), unique_var_tries,
+ trieIndex+1, childIndex, endChildIndex, modEq );
}
}
++eqc;
@@ -760,14 +799,14 @@ void InstMatchGeneratorMulti::collectInstantiations( QuantifiersEngine* qe, Inst
}
}else{
int newChildIndex = (childIndex+1)%(int)d_children.size();
- collectInstantiations( qe, m, addedLemmas, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
- 0, newChildIndex, endChildIndex, modEq );
+ processNewInstantiations( qe, m, addedLemmas, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
+ 0, newChildIndex, endChildIndex, modEq );
}
}
-void InstMatchGeneratorMulti::collectInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
- std::vector< IndexedTrie >& unique_var_tries,
- int uvtIndex, InstMatchTrie* tr, int trieIndex ){
+void InstMatchGeneratorMulti::processNewInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
+ std::vector< IndexedTrie >& unique_var_tries,
+ int uvtIndex, InstMatchTrie* tr, int trieIndex ){
if( uvtIndex<(int)unique_var_tries.size() ){
int childIndex = unique_var_tries[uvtIndex].first.first;
if( !tr ){
@@ -776,58 +815,25 @@ void InstMatchGeneratorMulti::collectInstantiations2( QuantifiersEngine* qe, Ins
}
if( trieIndex<(int)d_children_trie[childIndex].getOrdering()->d_order.size() ){
int curr_index = d_children_trie[childIndex].getOrdering()->d_order[trieIndex];
- Node curr_ic = qe->getInstantiationConstant( d_f, curr_index );
+ Node curr_ic = qe->getTermDatabase()->getInstantiationConstant( d_f, curr_index );
//unique non-set variable, add to InstMatch
for( std::map< Node, InstMatchTrie >::iterator it = tr->d_data.begin(); it != tr->d_data.end(); ++it ){
InstMatch mn( &m );
mn.d_map[ curr_ic ] = it->first;
- collectInstantiations2( qe, mn, addedLemmas, unique_var_tries, uvtIndex, &(it->second), trieIndex+1 );
+ processNewInstantiations2( qe, mn, addedLemmas, unique_var_tries, uvtIndex, &(it->second), trieIndex+1 );
}
}else{
- collectInstantiations2( qe, m, addedLemmas, unique_var_tries, uvtIndex+1 );
+ processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, uvtIndex+1 );
}
}else{
//m is an instantiation
- if( qe->addInstantiation( d_f, m, true ) ){
+ if( qe->addInstantiation( d_f, m ) ){
addedLemmas++;
Debug("smart-multi-trigger") << "-> Produced instantiation " << m << std::endl;
}
}
}
-int InstMatchGeneratorMulti::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit, bool addSplits ){
- int addedLemmas = 0;
- Debug("smart-multi-trigger") << "Process smart multi trigger" << std::endl;
- for( int i=0; i<(int)d_children.size(); i++ ){
- Debug("smart-multi-trigger") << "Calculate matches " << i << std::endl;
- std::vector< InstMatch > newMatches;
- InstMatch m;
- while( d_children[i]->getNextMatch( m, qe ) ){
- m.makeRepresentative( qe );
- newMatches.push_back( InstMatch( &m ) );
- m.clear();
- }
- for( int j=0; j<(int)newMatches.size(); j++ ){
- processNewMatch( qe, newMatches[j], i, addedLemmas );
- }
- }
- return addedLemmas;
-}
-
-void InstMatchGeneratorMulti::processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas ){
- //see if these produce new matches
- d_children_trie[fromChildIndex].addInstMatch( qe, d_f, m, true );
- //possibly only do the following if we know that new matches will be produced?
- //the issue is that instantiations are filtered in quantifiers engine, and so there is no guarentee that
- // we can safely skip the following lines, even when we have already produced this match.
- Debug("smart-multi-trigger") << "Child " << fromChildIndex << " produced match " << m << std::endl;
- //collect new instantiations
- int childIndex = (fromChildIndex+1)%(int)d_children.size();
- std::vector< IndexedTrie > unique_var_tries;
- collectInstantiations( qe, m, addedLemmas,
- d_children_trie[childIndex].getTrie(), unique_var_tries, 0, childIndex, fromChildIndex, true );
-}
-
int InstMatchGeneratorMulti::addTerm( Node f, Node t, QuantifiersEngine* qe ){
Assert( Options::current()->eagerInstQuant );
int addedLemmas = 0;
@@ -843,47 +849,44 @@ int InstMatchGeneratorMulti::addTerm( Node f, Node t, QuantifiersEngine* qe ){
return addedLemmas;
}
-int InstMatchGeneratorSimple::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit, bool addSplits ){
+int InstMatchGeneratorSimple::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
InstMatch m;
m.add( baseMatch );
int addedLemmas = 0;
if( d_match_pattern.getType()==NodeManager::currentNM()->booleanType() ){
for( int i=0; i<2; i++ ){
- addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_pred_map_trie[i][ d_match_pattern.getOperator() ]),
- instLimit, addSplits );
+ addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_pred_map_trie[i][ d_match_pattern.getOperator() ]) );
}
}else{
- addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_func_map_trie[ d_match_pattern.getOperator() ]),
- instLimit, addSplits );
+ addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_func_map_trie[ d_match_pattern.getOperator() ]) );
}
return addedLemmas;
}
-void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex,
- TermArgTrie* tat, int instLimit, bool addSplits ){
+void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex, quantifiers::TermArgTrie* tat ){
if( argIndex==(int)d_match_pattern.getNumChildren() ){
//m is an instantiation
- if( qe->addInstantiation( d_f, m, addSplits ) ){
+ if( qe->addInstantiation( d_f, m ) ){
addedLemmas++;
Debug("simple-multi-trigger") << "-> Produced instantiation " << m << std::endl;
}
}else{
if( d_match_pattern[argIndex].getKind()==INST_CONSTANT ){
Node ic = d_match_pattern[argIndex];
- for( std::map< Node, TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
+ for( std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
Node t = it->first;
if( m.d_map[ ic ].isNull() || m.d_map[ ic ]==t ){
Node prev = m.d_map[ ic ];
m.d_map[ ic ] = t;
- addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second), instLimit, addSplits );
+ addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
m.d_map[ ic ] = prev;
}
}
}else{
Node r = qe->getEqualityQuery()->getRepresentative( d_match_pattern[argIndex] );
- std::map< Node, TermArgTrie >::iterator it = tat->d_data.find( r );
+ std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.find( r );
if( it!=tat->d_data.end() ){
- addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second), instLimit, addSplits );
+ addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
}
}
}
diff --git a/src/theory/inst_match.h b/src/theory/inst_match.h
index dcb9190a1..7cc5b2249 100644
--- a/src/theory/inst_match.h
+++ b/src/theory/inst_match.h
@@ -281,7 +281,7 @@ public:
given Node can't match the pattern */
virtual bool nonunifiable( TNode t, const std::vector<Node> & vars) = 0;
/** add instantiations directly */
- virtual int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit = 0, bool addSplits = false ) = 0;
+ virtual int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ) = 0;
/** add ground term t, called when t is added to term db */
virtual int addTerm( Node f, Node t, QuantifiersEngine* qe ) = 0;
};/* class IMGenerator */
@@ -350,7 +350,7 @@ public:
given Node can't match the pattern */
bool nonunifiable( TNode t, const std::vector<Node> & vars);
/** add instantiations */
- int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit = 0, bool addSplits = false );
+ int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
/** add ground term t */
int addTerm( Node f, Node t, QuantifiersEngine* qe );
};/* class InstMatchGenerator */
@@ -358,18 +358,18 @@ public:
/** smart multi-trigger implementation */
class InstMatchGeneratorMulti : public IMGenerator {
private:
- void processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas );
-private:
/** indexed trie */
typedef std::pair< std::pair< int, int >, InstMatchTrie* > IndexedTrie;
- /** collect instantiations */
- void collectInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
- std::vector< IndexedTrie >& unique_var_tries,
- int trieIndex, int childIndex, int endChildIndex, bool modEq );
- /** collect instantiations 2 */
- void collectInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
- std::vector< IndexedTrie >& unique_var_tries,
- int uvtIndex, InstMatchTrie* tr = NULL, int trieIndex = 0 );
+ /** process new match */
+ void processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas );
+ /** process new instantiations */
+ void processNewInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
+ std::vector< IndexedTrie >& unique_var_tries,
+ int trieIndex, int childIndex, int endChildIndex, bool modEq );
+ /** process new instantiations 2 */
+ void processNewInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
+ std::vector< IndexedTrie >& unique_var_tries,
+ int uvtIndex, InstMatchTrie* tr = NULL, int trieIndex = 0 );
private:
/** var contains (variable indices) for each pattern node */
std::map< Node, std::vector< int > > d_var_contains;
@@ -400,12 +400,14 @@ public:
given Node can't match the pattern */
bool nonunifiable( TNode t, const std::vector<Node> & vars) { return true; }
/** add instantiations */
- int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit = 0, bool addSplits = false );
+ int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
/** add ground term t */
int addTerm( Node f, Node t, QuantifiersEngine* qe );
};/* class InstMatchGeneratorMulti */
-class TermArgTrie;
+namespace quantifiers{
+ class TermArgTrie;
+}
/** smart (single)-trigger implementation */
class InstMatchGeneratorSimple : public IMGenerator {
@@ -415,8 +417,7 @@ private:
/** match term */
Node d_match_pattern;
/** add instantiations */
- void addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas,
- int argIndex, TermArgTrie* tat, int instLimit, bool addSplits );
+ void addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex, quantifiers::TermArgTrie* tat );
public:
/** constructors */
InstMatchGeneratorSimple( Node f, Node pat ) : d_f( f ), d_match_pattern( pat ){}
@@ -432,7 +433,7 @@ public:
given Node can't match the pattern */
bool nonunifiable( TNode t, const std::vector<Node> & vars) { return true; }
/** add instantiations */
- int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit = 0, bool addSplits = false );
+ int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
/** add ground term t, possibly add instantiations */
int addTerm( Node f, Node t, QuantifiersEngine* qe );
};/* class InstMatchGeneratorSimple */
diff --git a/src/theory/instantiator_default.cpp b/src/theory/instantiator_default.cpp
index 4d6ea2fdb..a1766ce3c 100644
--- a/src/theory/instantiator_default.cpp
+++ b/src/theory/instantiator_default.cpp
@@ -33,7 +33,8 @@ void InstantiatorDefault::assertNode( Node assertion ){
void InstantiatorDefault::processResetInstantiationRound( Theory::Effort effort ){
}
-int InstantiatorDefault::process( Node f, Theory::Effort effort, int e, int limitInst ){
+int InstantiatorDefault::process( Node f, Theory::Effort effort, int e ){
+ /*
if( e < 4 ){
return InstStrategy::STATUS_UNFINISHED;
}else if( e == 4 ){
@@ -50,5 +51,6 @@ int InstantiatorDefault::process( Node f, Theory::Effort effort, int e, int limi
}
d_quantEngine->addInstantiation( f, m );
}
+ */
return InstStrategy::STATUS_UNKNOWN;
}
diff --git a/src/theory/instantiator_default.h b/src/theory/instantiator_default.h
index 8e0e47231..967a0c1ca 100644
--- a/src/theory/instantiator_default.h
+++ b/src/theory/instantiator_default.h
@@ -32,7 +32,7 @@ protected:
/** reset instantiation round */
void processResetInstantiationRound(Theory::Effort effort);
/** process quantifier */
- int process(Node f, Theory::Effort effort, int e, int limitInst = 0);
+ int process( Node f, Theory::Effort effort, int e );
public:
InstantiatorDefault(context::Context* c, QuantifiersEngine* ie, Theory* th);
~InstantiatorDefault() { }
diff --git a/src/theory/model.cpp b/src/theory/model.cpp
new file mode 100644
index 000000000..03bba185c
--- /dev/null
+++ b/src/theory/model.cpp
@@ -0,0 +1,436 @@
+/********************* */
+/*! \file 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 model class
+ **/
+
+#include "theory/model.h"
+#include "theory/quantifiers_engine.h"
+#include "theory/theory_engine.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+
+void RepSet::clear(){
+ d_type_reps.clear();
+ d_tmap.clear();
+}
+
+void RepSet::add( Node n ){
+ TypeNode t = n.getType();
+ d_tmap[ n ] = (int)d_type_reps[t].size();
+ d_type_reps[t].push_back( n );
+}
+
+void RepSet::set( TypeNode t, std::vector< Node >& reps ){
+ for( size_t i=0; i<reps.size(); i++ ){
+ d_tmap[ reps[i] ] = i;
+ }
+ d_type_reps[t].insert( d_type_reps[t].begin(), reps.begin(), reps.end() );
+}
+
+void RepSet::toStream(std::ostream& out){
+#if 0
+ for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){
+ out << it->first << " : " << std::endl;
+ for( int i=0; i<(int)it->second.size(); i++ ){
+ out << " " << i << ": " << it->second[i] << std::endl;
+ }
+ }
+#else
+ for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){
+ if( !it->first.isFunction() && !it->first.isPredicate() ){
+ out << "(" << it->first << " " << it->second.size();
+ out << " (";
+ for( int i=0; i<(int)it->second.size(); i++ ){
+ if( i>0 ){ out << " "; }
+ out << it->second[i];
+ }
+ out << ")";
+ out << ")" << std::endl;
+ }
+ }
+#endif
+}
+
+TheoryModel::TheoryModel( context::Context* c, std::string name ) :
+d_equalityEngine( c, name ){
+ d_true = NodeManager::currentNM()->mkConst( true );
+ d_false = NodeManager::currentNM()->mkConst( false );
+}
+
+void TheoryModel::addDefineFunction( Node n ){
+ d_define_funcs.push_back( n );
+ d_defines.push_back( 0 );
+}
+
+void TheoryModel::addDefineType( TypeNode tn ){
+ d_define_types.push_back( tn );
+ d_defines.push_back( 1 );
+}
+
+void TheoryModel::toStreamFunction( Node n, std::ostream& out ){
+ out << "(" << n;
+ //out << " : " << n.getType();
+ out << " ";
+ Node value = getValue( n );
+ if( n.getType().isSort() ){
+ int index = d_ra.getIndexFor( value );
+ if( index!=-1 ){
+ out << value.getType() << "_" << index;
+ }else{
+ out << value;
+ }
+ }else{
+ 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();
+ //out << " (";
+ //for( size_t i=0; i<d_ra.d_type_reps[tn].size(); i++ ){
+ // if( i>0 ){ out << " "; }
+ // out << d_ra.d_type_reps[tn][i];
+ //}
+ //out << ")";
+ }
+ }
+ out << ")" << std::endl;
+}
+
+void TheoryModel::toStream( std::ostream& out ){
+ int funcIndex = 0;
+ int typeIndex = 0;
+ for( size_t i=0; i<d_defines.size(); i++ ){
+ if( d_defines[i]==0 ){
+ toStreamFunction( d_define_funcs[funcIndex], out );
+ funcIndex++;
+ }else if( d_defines[i]==1 ){
+ toStreamType( d_define_types[typeIndex], out );
+ typeIndex++;
+ }
+ }
+}
+
+Node TheoryModel::getValue( TNode n ){
+ Debug("model") << "TheoryModel::getValue " << n << std::endl;
+
+ kind::MetaKind metakind = n.getMetaKind();
+
+ //// special case: prop engine handles boolean vars
+ //if(metakind == kind::metakind::VARIABLE && n.getType().isBoolean()) {
+ // Debug("model") << "-> Propositional variable." << std::endl;
+ // return d_te->getPropEngine()->getValue( n );
+ //}
+
+ // special case: value of a constant == itself
+ if(metakind == kind::metakind::CONSTANT) {
+ Debug("model") << "-> Constant." << std::endl;
+ return n;
+ }
+
+ // see if the value is explicitly set in the model
+ if( d_equalityEngine.hasTerm( n ) ){
+ Debug("model") << "-> Defined term." << std::endl;
+ return getRepresentative( n );
+ }else{
+ Node nn;
+ if( n.getNumChildren()>0 ){
+ std::vector< Node > children;
+ if( metakind == kind::metakind::PARAMETERIZED ){
+ Debug("model-debug") << "get operator: " << n.getOperator() << std::endl;
+ children.push_back( n.getOperator() );
+ }
+ //evaluate the children
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ Node val = getValue( n[i] );
+ Debug("model-debug") << i << " : " << n[i] << " -> " << val << std::endl;
+ Assert( !val.isNull() );
+ children.push_back( val );
+ }
+ Debug("model-debug") << "Done eval children" << std::endl;
+ nn = NodeManager::currentNM()->mkNode( n.getKind(), children );
+ }else{
+ nn = n;
+ }
+ //interpretation is the rewritten form
+ nn = Rewriter::rewrite( nn );
+
+ // special case: value of a constant == itself
+ if(metakind == kind::metakind::CONSTANT) {
+ Debug("model") << "-> Theory-interpreted term." << std::endl;
+ return nn;
+ }else if( d_equalityEngine.hasTerm( nn ) ){
+ Debug("model") << "-> Theory-interpreted (defined) term." << std::endl;
+ return getRepresentative( nn );
+ }else{
+ Debug("model") << "-> Model-interpreted term." << std::endl;
+ //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() ){
+ //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];
+ }
+ }
+ }
+ return Node::null();
+}
+
+//FIXME: use the theory enumerator to generate constants here
+Node TheoryModel::getNewDomainValue( TypeNode tn, bool mkConst ){
+ if( tn==NodeManager::currentNM()->booleanType() ){
+ if( d_ra.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{
+ return Node::null();
+ }
+ }else if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){
+ 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() &&
+ !d_equalityEngine.hasTerm( r ) ){
+ return r;
+ }
+ val++;
+ }while( true );
+ }else{
+ //otherwise must make a variable FIXME: how to make constants for other sorts?
+ //return NodeManager::currentNM()->mkVar( tn );
+ return Node::null();
+ }
+}
+
+/** assert equality */
+void TheoryModel::assertEquality( Node a, Node b, bool polarity ){
+ d_equalityEngine.assertEquality( a.eqNode(b), polarity, Node::null() );
+}
+
+/** assert predicate */
+void TheoryModel::assertPredicate( Node a, bool polarity ){
+ if( a.getKind()==EQUAL ){
+ d_equalityEngine.assertEquality( a, polarity, Node::null() );
+ }else{
+ d_equalityEngine.assertPredicate( a, polarity, Node::null() );
+ }
+}
+
+/** assert equality engine */
+void TheoryModel::assertEqualityEngine( eq::EqualityEngine* ee ){
+ eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );
+ while( !eqcs_i.isFinished() ){
+ Node eqc = (*eqcs_i);
+ bool predicate = false;
+ bool predPolarity = false;
+ if( eqc.getType()==NodeManager::currentNM()->booleanType() ){
+ predicate = true;
+ predPolarity = ee->areEqual( eqc, d_true );
+ //FIXME: do we guarentee that all boolean equivalence classes contain either d_true or d_false?
+ }
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, ee );
+ while( !eqc_i.isFinished() ){
+ if( predicate ){
+ assertPredicate( *eqc_i, predPolarity );
+ }else{
+ assertEquality( *eqc_i, eqc, true );
+ }
+ ++eqc_i;
+ }
+ ++eqcs_i;
+ }
+}
+
+bool TheoryModel::hasTerm( Node a ){
+ return d_equalityEngine.hasTerm( a );
+}
+
+Node TheoryModel::getRepresentative( Node a ){
+ if( d_equalityEngine.hasTerm( a ) ){
+ return d_reps[ d_equalityEngine.getRepresentative( a ) ];
+ }else{
+ return a;
+ }
+}
+
+bool TheoryModel::areEqual( Node a, Node b ){
+ if( a==b ){
+ return true;
+ }else if( d_equalityEngine.hasTerm( a ) && d_equalityEngine.hasTerm( b ) ){
+ return d_equalityEngine.areEqual( a, b );
+ }else{
+ return false;
+ }
+}
+
+bool TheoryModel::areDisequal( Node a, Node b ){
+ if( d_equalityEngine.hasTerm( a ) && d_equalityEngine.hasTerm( b ) ){
+ return d_equalityEngine.areDisequal( a, b, false );
+ }else{
+ return false;
+ }
+}
+
+//for debugging
+void TheoryModel::printRepresentativeDebug( const char* c, Node r ){
+ if( r.isNull() ){
+ Debug( c ) << "null";
+ }else if( r.getType()==NodeManager::currentNM()->booleanType() ){
+ if( areEqual( r, d_true ) ){
+ Debug( c ) << "true";
+ }else{
+ Debug( c ) << "false";
+ }
+ }else{
+ Debug( c ) << getRepresentative( r );
+ }
+}
+
+void TheoryModel::printRepresentative( std::ostream& out, Node r ){
+ Assert( !r.isNull() );
+ if( r.isNull() ){
+ out << "null";
+ }else if( r.getType()==NodeManager::currentNM()->booleanType() ){
+ if( areEqual( r, d_true ) ){
+ out << "true";
+ }else{
+ out << "false";
+ }
+ }else{
+ out << getRepresentative( r );
+ }
+}
+
+DefaultModel::DefaultModel( context::Context* c, std::string name ) : TheoryModel( c, name ){
+
+}
+
+Node DefaultModel::getInterpretedValue( TNode n ){
+ Assert( !d_equalityEngine.hasTerm( n ) );
+ TypeNode type = n.getType();
+ if( type.isFunction() || type.isPredicate() ){
+ //DO_THIS?
+ return n;
+ }else{
+ //first, try to choose an existing term as value
+ std::vector< Node > v_emp;
+ Node n2 = getDomainValue( type, v_emp );
+ if( !n2.isNull() ){
+ return n2;
+ }else{
+ //otherwise, choose new valuse
+ n2 = getNewDomainValue( type, true );
+ if( !n2.isNull() ){
+ return n2;
+ }else{
+ return n;
+ }
+ }
+ }
+}
+
+TheoryEngineModelBuilder::TheoryEngineModelBuilder( TheoryEngine* te ) : d_te( te ){
+
+}
+
+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;
+ //collect model info from the theory engine
+ d_te->collectModelInfo( tm );
+ Debug( "model-builder" ) << "TheoryEngineModelBuilder: Build representatives..." << std::endl;
+ //populate term database, store representatives
+ eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &tm->d_equalityEngine );
+ while( !eqcs_i.isFinished() ){
+ Node eqc = (*eqcs_i);
+ //add terms to model
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &tm->d_equalityEngine );
+ while( !eqc_i.isFinished() ){
+ tm->addTerm( *eqc_i );
+ ++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 );
+ }
+ ++eqcs_i;
+ }
+ //do model-builder specific initialization
+ // this should include choosing representatives for equivalence classes that have not yet been
+ // assigned representatives
+ 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;
+ }
+ ++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, true );
+ if( !rep.isNull() ){
+ tm->assertEquality( n, rep, true );
+ }else{
+ rep = n;
+ }
+ tm->d_reps[ n ] = rep;
+ tm->d_ra.add( rep );
+ }
+ ++eqcs_i;
+ }
+}
diff --git a/src/theory/model.h b/src/theory/model.h
new file mode 100644
index 000000000..4d6035ae5
--- /dev/null
+++ b/src/theory/model.h
@@ -0,0 +1,165 @@
+/********************* */
+/*! \file 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 class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY_MODEL_H
+#define __CVC4__THEORY_MODEL_H
+
+#include "util/model.h"
+#include "theory/uf/equality_engine.h"
+
+namespace CVC4 {
+namespace theory {
+
+class QuantifiersEngine;
+
+/** this class stores a representative set */
+class RepSet {
+public:
+ RepSet(){}
+ ~RepSet(){}
+ std::map< TypeNode, std::vector< Node > > d_type_reps;
+ std::map< Node, int > d_tmap;
+ /** clear the set */
+ void clear();
+ /** has type */
+ bool hasType( TypeNode tn ) { return d_type_reps.find( tn )!=d_type_reps.end(); }
+ /** add representative for type */
+ void add( Node n );
+ /** set the representatives for type */
+ void set( TypeNode t, std::vector< Node >& reps );
+ /** returns index in d_type_reps for node n */
+ int getIndexFor( Node n ) { return d_tmap.find( n )!=d_tmap.end() ? d_tmap[n] : -1; }
+ /** debug print */
+ void toStream(std::ostream& out);
+};
+
+//representative domain
+typedef std::vector< int > RepDomain;
+
+class TheoryEngineModelBuilder;
+
+/** Theory Model class
+ * For Model m, should call m.initialize() before using
+ */
+class TheoryModel : public Model
+{
+ friend class TheoryEngineModelBuilder;
+protected:
+ /** add term */
+ virtual void addTerm( Node n ) {}
+private:
+ /** definitions */
+ std::vector< Node > d_define_funcs;
+ std::vector< TypeNode > d_define_types;
+ std::vector< int > d_defines;
+protected:
+ /** to stream functions */
+ virtual void toStreamFunction( Node n, std::ostream& out );
+ virtual void toStreamType( TypeNode tn, std::ostream& out );
+public:
+ TheoryModel( context::Context* c, std::string name );
+ virtual ~TheoryModel(){}
+ /** equality engine containing all known equalities/disequalities */
+ 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
+ Node d_true;
+ Node d_false;
+public:
+ /** add defined function */
+ void addDefineFunction( Node n );
+ /** add defined type */
+ 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 */
+ Node getDomainValue( TypeNode tn, std::vector< Node >& exclude );
+ /** get new domain value */
+ Node getNewDomainValue( TypeNode tn, bool mkConst = false );
+public:
+ /** assert equality */
+ void assertEquality( Node a, Node b, bool polarity );
+ /** assert predicate */
+ void assertPredicate( Node a, bool polarity );
+ /** assert equality engine */
+ void assertEqualityEngine( eq::EqualityEngine* ee );
+public:
+ //queries about equality
+ bool hasTerm( Node a );
+ Node getRepresentative( Node a );
+ bool areEqual( Node a, Node b );
+ bool areDisequal( Node a, Node b );
+public:
+ /** print representative function */
+ void printRepresentativeDebug( const char* c, Node r );
+ void printRepresentative( std::ostream& out, Node r );
+ /** to stream function */
+ void toStream( std::ostream& out );
+};
+
+//default model class: extends model arbitrarily
+class DefaultModel : public TheoryModel
+{
+public:
+ DefaultModel( context::Context* c, std::string name );
+ virtual ~DefaultModel(){}
+public:
+ 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(); }
+};
+
+
+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 );
+public:
+ TheoryEngineModelBuilder( TheoryEngine* te );
+ virtual ~TheoryEngineModelBuilder(){}
+ /**
+ * Build model function.
+ */
+ void buildModel( Model* m );
+};
+
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/theory/quantifiers/Makefile.am b/src/theory/quantifiers/Makefile.am
index de74e44f8..ae5b99c06 100644
--- a/src/theory/quantifiers/Makefile.am
+++ b/src/theory/quantifiers/Makefile.am
@@ -16,6 +16,14 @@ libquantifiers_la_SOURCES = \
instantiation_engine.h \
instantiation_engine.cpp \
model_engine.h \
- model_engine.cpp
+ model_engine.cpp \
+ relevant_domain.h \
+ relevant_domain.cpp \
+ rep_set_iterator.h \
+ rep_set_iterator.cpp \
+ term_database.h \
+ term_database.cpp \
+ first_order_model.h \
+ first_order_model.cpp
EXTRA_DIST = kinds \ No newline at end of file
diff --git a/src/theory/quantifiers/first_order_model.cpp b/src/theory/quantifiers/first_order_model.cpp
new file mode 100644
index 000000000..71a48b33d
--- /dev/null
+++ b/src/theory/quantifiers/first_order_model.cpp
@@ -0,0 +1,146 @@
+/********************* */
+/*! \file first_order_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 model engine model class
+ **/
+
+#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"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+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 ),
+d_term_db( qe->getTermDatabase() ), d_forall_asserts( c ){
+
+}
+
+void FirstOrderModel::initialize(){
+ //rebuild models
+ d_uf_model.clear();
+ d_array_model.clear();
+ //for each quantifier, collect all operators we care about
+ for( int i=0; i<getNumAssertedQuantifiers(); i++ ){
+ Node f = getAssertedQuantifier( i );
+ //initialize model for term
+ initializeModelForTerm( f[1] );
+ }
+
+ 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 ) ){
+ Message() << "Cardinality( " << it->first << " )" << " = " << it->second.size() << std::endl;
+ }
+ }
+ }
+}
+
+void FirstOrderModel::initializeModelForTerm( Node n ){
+ if( n.getKind()==APPLY_UF ){
+ Node op = n.getOperator();
+ if( d_uf_model.find( op )==d_uf_model.end() ){
+ TypeNode tn = op.getType();
+ tn = tn[ (int)tn.getNumChildren()-1 ];
+ if( tn==NodeManager::currentNM()->booleanType() || uf::StrongSolverTheoryUf::isRelevantType( tn ) ){
+ d_uf_model[ op ] = uf::UfModel( op, this );
+ }
+ }
+ }
+ if( n.getKind()!=STORE && n.getType().isArray() ){
+ d_array_model[n] = Node::null();
+ }
+ 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 );
+ }
+}
+
+void FirstOrderModel::toStreamType( TypeNode tn, std::ostream& out ){
+ DefaultModel::toStreamType( tn, out );
+}
+
+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();
+ }else{
+ return n;
+ }
+ }else if( n.getKind()==APPLY_UF ){
+ int depIndex;
+ return d_uf_model[ n.getOperator() ].getValue( n, depIndex );
+ }
+ return DefaultModel::getInterpretedValue( n );
+}
+
+TermDb* FirstOrderModel::getTermDatabase(){
+ return d_term_db;
+}
+
+
+void FirstOrderModel::toStream(std::ostream& out){
+ DefaultModel::toStream( out );
+#if 0
+ out << "---Current Model---" << std::endl;
+ out << "Representatives: " << std::endl;
+ d_ra.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 );
+ //print everything not related to UF in equality engine
+ eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &d_equalityEngine );
+ while( !eqcs_i.isFinished() ){
+ Node eqc = (*eqcs_i);
+ Node rep = getRepresentative( eqc );
+ TypeNode type = rep.getType();
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &d_equalityEngine );
+ while( !eqc_i.isFinished() ){
+ //do not print things that have interpretations in model
+ if( (*eqc_i).getMetaKind()!=kind::metakind::CONSTANT && !hasInterpretedValue( *eqc_i ) ){
+ out << "(" << (*eqc_i) << " " << rep << ")" << std::endl;
+ }
+ ++eqc_i;
+ }
+ ++eqcs_i;
+ }
+ //print functions
+ 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;
+ }
+#endif
+} \ No newline at end of file
diff --git a/src/theory/quantifiers/first_order_model.h b/src/theory/quantifiers/first_order_model.h
new file mode 100644
index 000000000..832acbee3
--- /dev/null
+++ b/src/theory/quantifiers/first_order_model.h
@@ -0,0 +1,82 @@
+/********************* */
+/*! \file first_order_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 extended classes
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__FIRST_ORDER_MODEL_H
+#define __CVC4__FIRST_ORDER_MODEL_H
+
+#include "theory/model.h"
+#include "theory/uf/theory_uf_model.h"
+
+namespace CVC4 {
+namespace theory {
+
+struct ModelBasisAttributeId {};
+typedef expr::Attribute<ModelBasisAttributeId, bool> ModelBasisAttribute;
+//for APPLY_UF terms, 1 : term has direct child with model basis attribute,
+// 0 : term has no direct child with model basis attribute.
+struct ModelBasisArgAttributeId {};
+typedef expr::Attribute<ModelBasisArgAttributeId, uint64_t> ModelBasisArgAttribute;
+
+class QuantifiersEngine;
+
+namespace quantifiers{
+
+class TermDb;
+
+class FirstOrderModel : public DefaultModel
+{
+private:
+ //pointer to term database
+ TermDb* d_term_db;
+ //for initialize model
+ void initializeModelForTerm( Node n );
+ /** to stream functions */
+ void toStreamFunction( Node n, std::ostream& out );
+ void toStreamType( TypeNode tn, std::ostream& out );
+public: //for Theory UF:
+ //models for each UF operator
+ std::map< Node, uf::UfModel > d_uf_model;
+public: //for Theory Arrays:
+ //default value for each non-store array
+ std::map< Node, Node > d_array_model;
+public: //for Theory Quantifiers:
+ /** list of quantifiers asserted in the current context */
+ context::CDList<Node> d_forall_asserts;
+ /** get number of asserted quantifiers */
+ int getNumAssertedQuantifiers() { return (int)d_forall_asserts.size(); }
+ /** get asserted quantifier */
+ Node getAssertedQuantifier( int i ) { return d_forall_asserts[i]; }
+public:
+ FirstOrderModel( QuantifiersEngine* qe, context::Context* c, std::string name );
+ virtual ~FirstOrderModel(){}
+ // initialize the model
+ void initialize();
+ /** get interpreted value */
+ Node getInterpretedValue( TNode n );
+public:
+ /** get term database */
+ TermDb* getTermDatabase();
+ /** to stream function */
+ void toStream( std::ostream& out );
+};
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/instantiation_engine.cpp b/src/theory/quantifiers/instantiation_engine.cpp
index c1476acb8..fae54c151 100644
--- a/src/theory/quantifiers/instantiation_engine.cpp
+++ b/src/theory/quantifiers/instantiation_engine.cpp
@@ -18,6 +18,8 @@
#include "theory/theory_engine.h"
#include "theory/uf/theory_uf_instantiator.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/first_order_model.h"
using namespace std;
using namespace CVC4;
@@ -26,15 +28,9 @@ using namespace CVC4::context;
using namespace CVC4::theory;
using namespace CVC4::theory::quantifiers;
-//#define IE_PRINT_PROCESS_TIMES
+InstantiationEngine::InstantiationEngine( QuantifiersEngine* qe, bool setIncomplete ) :
+QuantifiersModule( qe ), d_setIncomplete( setIncomplete ){
-InstantiationEngine::InstantiationEngine( TheoryQuantifiers* th ) :
-d_th( th ){
-
-}
-
-QuantifiersEngine* InstantiationEngine::getQuantifiersEngine(){
- return d_th->getQuantifiersEngine();
}
bool InstantiationEngine::hasAddedCbqiLemma( Node f ) {
@@ -46,25 +42,25 @@ void InstantiationEngine::addCbqiLemma( Node f ){
//code for counterexample-based quantifier instantiation
Debug("cbqi") << "Do cbqi for " << f << std::endl;
//make the counterexample body
- //Node ceBody = f[1].substitute( getQuantifiersEngine()->d_vars[f].begin(), getQuantifiersEngine()->d_vars[f].end(),
- // getQuantifiersEngine()->d_inst_constants[f].begin(),
- // getQuantifiersEngine()->d_inst_constants[f].end() );
+ //Node ceBody = f[1].substitute( d_quantEngine->d_vars[f].begin(), d_quantEngine->d_vars[f].end(),
+ // d_quantEngine->d_inst_constants[f].begin(),
+ // d_quantEngine->d_inst_constants[f].end() );
//get the counterexample literal
- Node ceBody = getQuantifiersEngine()->getCounterexampleBody( f );
- Node ceLit = d_th->getValuation().ensureLiteral( ceBody.notNode() );
+ Node ceBody = d_quantEngine->getTermDatabase()->getCounterexampleBody( f );
+ Node ceLit = d_quantEngine->getValuation().ensureLiteral( ceBody.notNode() );
d_ce_lit[ f ] = ceLit;
- getQuantifiersEngine()->setInstantiationConstantAttr( ceLit, f );
+ d_quantEngine->getTermDatabase()->setInstantiationConstantAttr( ceLit, f );
// set attributes, mark all literals in the body of n as dependent on cel
//registerLiterals( ceLit, f );
//require any decision on cel to be phase=true
- d_th->getOutputChannel().requirePhase( ceLit, true );
+ d_quantEngine->getOutputChannel().requirePhase( ceLit, true );
Debug("cbqi-debug") << "Require phase " << ceLit << " = true." << std::endl;
//add counterexample lemma
NodeBuilder<> nb(kind::OR);
nb << f << ceLit;
Node lem = nb;
Debug("cbqi-debug") << "Counterexample lemma : " << lem << std::endl;
- d_th->getOutputChannel().lemma( lem );
+ d_quantEngine->getOutputChannel().lemma( lem );
}
bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
@@ -72,8 +68,8 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
if( Options::current()->cbqi ){
//check if any cbqi lemma has not been added yet
bool addedLemma = false;
- for( int i=0; i<(int)getQuantifiersEngine()->getNumAssertedQuantifiers(); i++ ){
- Node f = getQuantifiersEngine()->getAssertedQuantifier( i );
+ for( int i=0; i<(int)d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
if( doCbqi( f ) && !hasAddedCbqiLemma( f ) ){
//add cbqi lemma
addCbqiLemma( f );
@@ -87,14 +83,9 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
//if not, proceed to instantiation round
Debug("inst-engine") << "IE: Instantiation Round." << std::endl;
Debug("inst-engine-ctrl") << "IE: Instantiation Round." << std::endl;
- //reset instantiators
+ //reset the quantifiers engine
Debug("inst-engine-ctrl") << "Reset IE" << std::endl;
- for( int i=0; i<theory::THEORY_LAST; i++ ){
- if( getQuantifiersEngine()->getInstantiator( i ) ){
- getQuantifiersEngine()->getInstantiator( i )->resetInstantiationRound( effort );
- }
- }
- getQuantifiersEngine()->getTermDatabase()->reset( effort );
+ d_quantEngine->resetInstantiationRound( effort );
//iterate over an internal effort level e
int e = 0;
int eLimit = effort==Theory::EFFORT_LAST_CALL ? 10 : 2;
@@ -104,20 +95,19 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
Debug("inst-engine") << "IE: Prepare instantiation (" << e << ")." << std::endl;
d_inst_round_status = InstStrategy::STATUS_SAT;
//instantiate each quantifier
- for( int q=0; q<getQuantifiersEngine()->getNumAssertedQuantifiers(); q++ ){
- Node f = getQuantifiersEngine()->getAssertedQuantifier( q );
+ for( int q=0; q<d_quantEngine->getModel()->getNumAssertedQuantifiers(); q++ ){
+ Node f = d_quantEngine->getModel()->getAssertedQuantifier( q );
Debug("inst-engine-debug") << "IE: Instantiate " << f << "..." << std::endl;
//if this quantifier is active
- if( getQuantifiersEngine()->getActive( f ) ){
- //int e_use = getQuantifiersEngine()->getRelevance( f )==-1 ? e - 1 : e;
+ if( d_quantEngine->getActive( f ) ){
+ //int e_use = d_quantEngine->getRelevance( f )==-1 ? e - 1 : e;
int e_use = e;
if( e_use>=0 ){
//use each theory instantiator to instantiate f
for( int i=0; i<theory::THEORY_LAST; i++ ){
- if( getQuantifiersEngine()->getInstantiator( i ) ){
- Debug("inst-engine-debug") << "Do " << getQuantifiersEngine()->getInstantiator( i )->identify() << " " << e_use << std::endl;
- int limitInst = 0;
- int quantStatus = getQuantifiersEngine()->getInstantiator( i )->doInstantiation( f, effort, e_use, limitInst );
+ if( d_quantEngine->getInstantiator( i ) ){
+ Debug("inst-engine-debug") << "Do " << d_quantEngine->getInstantiator( i )->identify() << " " << e_use << std::endl;
+ int quantStatus = d_quantEngine->getInstantiator( i )->doInstantiation( f, effort, e_use );
Debug("inst-engine-debug") << " -> status is " << quantStatus << std::endl;
InstStrategy::updateStatus( d_inst_round_status, quantStatus );
}
@@ -126,31 +116,31 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
}
}
//do not consider another level if already added lemma at this level
- if( getQuantifiersEngine()->hasAddedLemma() ){
+ if( d_quantEngine->hasAddedLemma() ){
d_inst_round_status = InstStrategy::STATUS_UNKNOWN;
}
e++;
}
Debug("inst-engine") << "All instantiators finished, # added lemmas = ";
- Debug("inst-engine") << (int)getQuantifiersEngine()->d_lemmas_waiting.size() << std::endl;
+ Debug("inst-engine") << (int)d_quantEngine->d_lemmas_waiting.size() << std::endl;
//Notice() << "All instantiators finished, # added lemmas = " << (int)d_lemmas_waiting.size() << std::endl;
- if( !getQuantifiersEngine()->hasAddedLemma() ){
+ if( !d_quantEngine->hasAddedLemma() ){
Debug("inst-engine-stuck") << "No instantiations produced at this state: " << std::endl;
for( int i=0; i<theory::THEORY_LAST; i++ ){
- if( getQuantifiersEngine()->getInstantiator( i ) ){
- getQuantifiersEngine()->getInstantiator( i )->debugPrint("inst-engine-stuck");
+ if( d_quantEngine->getInstantiator( i ) ){
+ d_quantEngine->getInstantiator( i )->debugPrint("inst-engine-stuck");
Debug("inst-engine-stuck") << std::endl;
}
}
Debug("inst-engine-ctrl") << "---Fail." << std::endl;
return false;
}else{
- Debug("inst-engine-ctrl") << "---Done. " << (int)getQuantifiersEngine()->d_lemmas_waiting.size() << std::endl;
-#ifdef IE_PRINT_PROCESS_TIMES
- Notice() << "lemmas = " << (int)getQuantifiersEngine()->d_lemmas_waiting.size() << std::endl;
-#endif
+ Debug("inst-engine-ctrl") << "---Done. " << (int)d_quantEngine->d_lemmas_waiting.size() << std::endl;
+ if( Options::current()->printInstEngine ){
+ Message() << "Added lemmas = " << (int)d_quantEngine->d_lemmas_waiting.size() << std::endl;
+ }
//flush lemmas to output channel
- getQuantifiersEngine()->flushLemmas( &d_th->getOutputChannel() );
+ d_quantEngine->flushLemmas( &d_quantEngine->getOutputChannel() );
return true;
}
}
@@ -174,42 +164,43 @@ void InstantiationEngine::check( Theory::Effort e ){
}
if( performCheck ){
Debug("inst-engine") << "IE: Check " << e << " " << ierCounter << std::endl;
-#ifdef IE_PRINT_PROCESS_TIMES
- double clSet = double(clock())/double(CLOCKS_PER_SEC);
- Notice() << "Run instantiation round " << e << " " << ierCounter << std::endl;
-#endif
+ double clSet = 0;
+ if( Options::current()->printInstEngine ){
+ clSet = double(clock())/double(CLOCKS_PER_SEC);
+ Message() << "---Instantiation Engine Round, effort = " << e << "---" << std::endl;
+ }
bool quantActive = false;
//for each quantifier currently asserted,
// such that the counterexample literal is not in positive in d_counterexample_asserts
// for( BoolMap::iterator i = d_forall_asserts.begin(); i != d_forall_asserts.end(); i++ ) {
// if( (*i).second ) {
- Debug("quantifiers") << "quantifiers: check: asserted quantifiers size"
- << getQuantifiersEngine()->getNumAssertedQuantifiers() << std::endl;
- for( int i=0; i<(int)getQuantifiersEngine()->getNumAssertedQuantifiers(); i++ ){
- Node n = getQuantifiersEngine()->getAssertedQuantifier( i );
+ Debug("quantifiers") << "quantifiers: check: asserted quantifiers size"
+ << d_quantEngine->getModel()->getNumAssertedQuantifiers() << std::endl;
+ for( int i=0; i<(int)d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node n = d_quantEngine->getModel()->getAssertedQuantifier( i );
if( Options::current()->cbqi && hasAddedCbqiLemma( n ) ){
Node cel = d_ce_lit[ n ];
bool active, value;
bool ceValue = false;
- if( d_th->getValuation().hasSatValue( cel, value ) ){
+ if( d_quantEngine->getValuation().hasSatValue( cel, value ) ){
active = value;
ceValue = true;
}else{
active = true;
}
- getQuantifiersEngine()->setActive( n, active );
+ d_quantEngine->setActive( n, active );
if( active ){
Debug("quantifiers") << " Active : " << n;
quantActive = true;
}else{
Debug("quantifiers") << " NOT active : " << n;
- if( d_th->getValuation().isDecision( cel ) ){
+ if( d_quantEngine->getValuation().isDecision( cel ) ){
Debug("quant-req-phase") << "Bad decision : " << cel << std::endl;
}
//note that the counterexample literal must not be a decision
- Assert( !d_th->getValuation().isDecision( cel ) );
+ Assert( !d_quantEngine->getValuation().isDecision( cel ) );
}
- if( d_th->getValuation().hasSatValue( n, value ) ){
+ if( d_quantEngine->getValuation().hasSatValue( n, value ) ){
Debug("quantifiers") << ", value = " << value;
}
if( ceValue ){
@@ -217,18 +208,18 @@ void InstantiationEngine::check( Theory::Effort e ){
}
Debug("quantifiers") << std::endl;
}else{
- getQuantifiersEngine()->setActive( n, true );
+ d_quantEngine->setActive( n, true );
quantActive = true;
Debug("quantifiers") << " Active : " << n << ", no ce assigned." << std::endl;
}
Debug("quantifiers-relevance") << "Quantifier : " << n << std::endl;
- Debug("quantifiers-relevance") << " Relevance : " << getQuantifiersEngine()->getRelevance( n ) << std::endl;
- Debug("quantifiers") << " Relevance : " << getQuantifiersEngine()->getRelevance( n ) << std::endl;
+ Debug("quantifiers-relevance") << " Relevance : " << d_quantEngine->getRelevance( n ) << std::endl;
+ Debug("quantifiers") << " Relevance : " << d_quantEngine->getRelevance( n ) << std::endl;
}
//}
if( quantActive ){
bool addedLemmas = doInstantiationRound( e );
- //Debug("quantifiers-dec") << "Do instantiation, level = " << d_th->getValuation().getDecisionLevel() << std::endl;
+ //Debug("quantifiers-dec") << "Do instantiation, level = " << d_quantEngine->getValuation().getDecisionLevel() << std::endl;
//for( int i=1; i<=(int)d_valuation.getDecisionLevel(); i++ ){
// Debug("quantifiers-dec") << " " << d_valuation.getDecision( i ) << std::endl;
//}
@@ -237,9 +228,12 @@ void InstantiationEngine::check( Theory::Effort e ){
if( d_inst_round_status==InstStrategy::STATUS_SAT ){
Debug("inst-engine") << "No instantiation given, returning SAT..." << std::endl;
debugSat( SAT_INST_STRATEGY );
- }else{
+ }else if( d_setIncomplete ){
Debug("inst-engine") << "No instantiation given, returning unknown..." << std::endl;
- d_th->getOutputChannel().setIncomplete();
+ d_quantEngine->getOutputChannel().setIncomplete();
+ }else{
+ Assert( Options::current()->finiteModelFind );
+ Debug("inst-engine") << "No instantiation given, defer to another engine..." << std::endl;
}
}
}
@@ -250,30 +244,30 @@ void InstantiationEngine::check( Theory::Effort e ){
}
}
}
-#ifdef IE_PRINT_PROCESS_TIMES
- double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
- Notice() << "Done Run instantiation round " << (clSet2-clSet) << std::endl;
-#endif
+ if( Options::current()->printInstEngine ){
+ double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
+ Message() << "Finished instantiation engine, time = " << (clSet2-clSet) << std::endl;
+ }
}
}
void InstantiationEngine::registerQuantifier( Node f ){
//Notice() << "do cbqi " << f << " ? " << std::endl;
- Node ceBody = getQuantifiersEngine()->getCounterexampleBody( f );
+ Node ceBody = d_quantEngine->getTermDatabase()->getCounterexampleBody( f );
if( !doCbqi( f ) ){
- getQuantifiersEngine()->addTermToDatabase( ceBody, true );
+ d_quantEngine->addTermToDatabase( ceBody, true );
//need to tell which instantiators will be responsible
//by default, just chose the UF instantiator
- getQuantifiersEngine()->getInstantiator( theory::THEORY_UF )->setHasConstraintsFrom( f );
+ d_quantEngine->getInstantiator( theory::THEORY_UF )->setHasConstraintsFrom( f );
}
//take into account user patterns
if( f.getNumChildren()==3 ){
- Node subsPat = getQuantifiersEngine()->getSubstitutedNode( f[2], f );
+ Node subsPat = d_quantEngine->getTermDatabase()->getSubstitutedNode( f[2], f );
//add patterns
for( int i=0; i<(int)subsPat.getNumChildren(); i++ ){
//Notice() << "Add pattern " << subsPat[i] << " for " << f << std::endl;
- ((uf::InstantiatorTheoryUf*)getQuantifiersEngine()->getInstantiator( theory::THEORY_UF ))->addUserPattern( f, subsPat[i] );
+ ((uf::InstantiatorTheoryUf*)d_quantEngine->getInstantiator( theory::THEORY_UF ))->addUserPattern( f, subsPat[i] );
}
}
}
@@ -337,11 +331,11 @@ bool InstantiationEngine::doCbqi( Node f ){
// registerLiterals( n[i], f );
// }
// if( !d_ce_lit[ f ].isNull() ){
-// if( getQuantifiersEngine()->d_te->getPropEngine()->isSatLiteral( n ) && n.getKind()!=NOT ){
+// if( d_quantEngine->d_te->getPropEngine()->isSatLiteral( n ) && n.getKind()!=NOT ){
// if( n!=d_ce_lit[ f ] && n.notNode()!=d_ce_lit[ f ] ){
// Debug("quant-dep-dec") << "Make " << n << " dependent on ";
// Debug("quant-dep-dec") << d_ce_lit[ f ] << std::endl;
-// d_th->getOutputChannel().dependentDecision( d_ce_lit[ f ], n );
+// d_quantEngine->getOutputChannel().dependentDecision( d_ce_lit[ f ], n );
// }
// }
// }
@@ -351,19 +345,19 @@ bool InstantiationEngine::doCbqi( Node f ){
void InstantiationEngine::debugSat( int reason ){
if( reason==SAT_CBQI ){
//Debug("quantifiers-sat") << "Decisions:" << std::endl;
- //for( int i=1; i<=(int)d_th->getValuation().getDecisionLevel(); i++ ){
- // Debug("quantifiers-sat") << " " << i << ": " << d_th->getValuation().getDecision( i ) << std::endl;
+ //for( int i=1; i<=(int)d_quantEngine->getValuation().getDecisionLevel(); i++ ){
+ // Debug("quantifiers-sat") << " " << i << ": " << d_quantEngine->getValuation().getDecision( i ) << std::endl;
//}
//for( BoolMap::iterator i = d_forall_asserts.begin(); i != d_forall_asserts.end(); i++ ) {
// if( (*i).second ) {
- for( int i=0; i<(int)getQuantifiersEngine()->getNumAssertedQuantifiers(); i++ ){
- Node f = getQuantifiersEngine()->getAssertedQuantifier( i );
+ for( int i=0; i<(int)d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
Node cel = d_ce_lit[ f ];
Assert( !cel.isNull() );
bool value;
- if( d_th->getValuation().hasSatValue( cel, value ) ){
+ if( d_quantEngine->getValuation().hasSatValue( cel, value ) ){
if( !value ){
- AlwaysAssert(! d_th->getValuation().isDecision( cel ),
+ AlwaysAssert(! d_quantEngine->getValuation().isDecision( cel ),
"bad decision on counterexample literal");
}
}
@@ -386,9 +380,9 @@ void InstantiationEngine::propagate( Theory::Effort level ){
//propagate as decision all counterexample literals that are not asserted
for( std::map< Node, Node >::iterator it = d_ce_lit.begin(); it != d_ce_lit.end(); ++it ){
bool value;
- if( !d_th->getValuation().hasSatValue( it->second, value ) ){
+ if( !d_quantEngine->getValuation().hasSatValue( it->second, value ) ){
//if not already set, propagate as decision
- d_th->getOutputChannel().propagateAsDecision( it->second );
+ d_quantEngine->getOutputChannel().propagateAsDecision( it->second );
Debug("cbqi-prop-as-dec") << "CBQI: propagate as decision " << it->second << std::endl;
}
}
diff --git a/src/theory/quantifiers/instantiation_engine.h b/src/theory/quantifiers/instantiation_engine.h
index c6aaed18a..13de210ab 100644
--- a/src/theory/quantifiers/instantiation_engine.h
+++ b/src/theory/quantifiers/instantiation_engine.h
@@ -29,14 +29,13 @@ namespace quantifiers {
class InstantiationEngine : public QuantifiersModule
{
private:
- TheoryQuantifiers* d_th;
- QuantifiersEngine* getQuantifiersEngine();
-private:
typedef context::CDHashMap< Node, bool, NodeHashFunction > BoolMap;
/** status of instantiation round (one of InstStrategy::STATUS_*) */
int d_inst_round_status;
/** map from universal quantifiers to their counterexample literals */
std::map< Node, Node > d_ce_lit;
+ /** whether the instantiation engine should set incomplete if it cannot answer SAT */
+ bool d_setIncomplete;
private:
bool hasAddedCbqiLemma( Node f );
void addCbqiLemma( Node f );
@@ -59,7 +58,7 @@ private:
/** debug sat */
void debugSat( int reason );
public:
- InstantiationEngine( TheoryQuantifiers* th );
+ InstantiationEngine( QuantifiersEngine* qe, bool setIncomplete = true );
~InstantiationEngine(){}
void check( Theory::Effort e );
diff --git a/src/theory/quantifiers/model_engine.cpp b/src/theory/quantifiers/model_engine.cpp
index a72b103d1..ad259f864 100644
--- a/src/theory/quantifiers/model_engine.cpp
+++ b/src/theory/quantifiers/model_engine.cpp
@@ -15,19 +15,23 @@
**/
#include "theory/quantifiers/model_engine.h"
+#include "theory/quantifiers/rep_set_iterator.h"
#include "theory/theory_engine.h"
#include "theory/uf/equality_engine.h"
#include "theory/uf/theory_uf.h"
#include "theory/uf/theory_uf_strong_solver.h"
#include "theory/uf/theory_uf_instantiator.h"
+#include "theory/quantifiers/first_order_model.h"
+#include "theory/quantifiers/term_database.h"
-//#define ME_PRINT_PROCESS_TIMES
+//#define ME_PRINT_WARNINGS
//#define DISABLE_EVAL_SKIP_MULTIPLE
-#define RECONSIDER_FUNC_DEFAULT_VALUE
+
#define RECONSIDER_FUNC_CONSTANT
-#define USE_INDEX_ORDERING
-//#define ONE_INST_PER_QUANT_PER_ROUND
+#define EVAL_FAIL_SKIP_MULTIPLE
+//#define ONE_QUANT_PER_ROUND_INST_GEN
+//#define ONE_QUANT_PER_ROUND
using namespace std;
using namespace CVC4;
@@ -36,570 +40,417 @@ using namespace CVC4::context;
using namespace CVC4::theory;
using namespace CVC4::theory::quantifiers;
-void printRepresentative( const char* c, QuantifiersEngine* qe, Node r ){
- if( r.getType()==NodeManager::currentNM()->booleanType() ){
- if( qe->getEqualityQuery()->areEqual( r, NodeManager::currentNM()->mkConst( true ) ) ){
- Debug( c ) << "true";
- }else{
- Debug( c ) << "false";
- }
- }else{
- Debug( c ) << qe->getEqualityQuery()->getRepresentative( r );
- }
-}
-
-RepAlphabet::RepAlphabet( RepAlphabet& ra, QuantifiersEngine* qe ){
- //translate to current representatives
- for( std::map< TypeNode, std::vector< Node > >::iterator it = ra.d_type_reps.begin(); it != ra.d_type_reps.end(); ++it ){
- std::vector< Node > reps;
- for( int i=0; i<(int)it->second.size(); i++ ){
- //reps.push_back( ie->getEqualityQuery()->getRepresentative( it->second[i] ) );
- reps.push_back( it->second[i] );
- }
- set( it->first, reps );
- }
-}
-
-void RepAlphabet::set( TypeNode t, std::vector< Node >& reps ){
- d_type_reps[t].insert( d_type_reps[t].begin(), reps.begin(), reps.end() );
- for( int i=0; i<(int)reps.size(); i++ ){
- d_tmap[ reps[i] ] = i;
- }
-}
-
-void RepAlphabet::debugPrint( const char* c, QuantifiersEngine* qe ){
- for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){
- Debug( c ) << it->first << " : " << std::endl;
- for( int i=0; i<(int)it->second.size(); i++ ){
- Debug( c ) << " " << i << ": " << it->second[i] << std::endl;
- Debug( c ) << " eq_class( " << it->second[i] << " ) : ";
- ((uf::InstantiatorTheoryUf*)qe->getInstantiator( THEORY_UF ))->outputEqClass( c, it->second[i] );
- Debug( c ) << std::endl;
- }
- }
-}
-
-RepAlphabetIterator::RepAlphabetIterator( QuantifiersEngine* qe, Node f, ModelEngine* model ){
- for( size_t i=0; i<f[0].getNumChildren(); i++ ){
- d_index_order.push_back( i );
- }
- initialize( qe, f, model );
-}
-
-RepAlphabetIterator::RepAlphabetIterator( QuantifiersEngine* qe, Node f, ModelEngine* model, std::vector< int >& indexOrder ){
- d_index_order.insert( d_index_order.begin(), indexOrder.begin(), indexOrder.end() );
- initialize( qe, f, model );
-}
-
-void RepAlphabetIterator::initialize( QuantifiersEngine* qe, Node f, ModelEngine* model ){
- d_f = f;
- d_model = model;
- //store instantiation constants
- for( size_t i=0; i<f[0].getNumChildren(); i++ ){
- d_ic.push_back( qe->getInstantiationConstant( d_f, i ) );
- d_index.push_back( 0 );
- }
- //make the d_var_order mapping
- for( size_t i=0; i<d_index_order.size(); i++ ){
- d_var_order[d_index_order[i]] = i;
- }
- //for testing
- d_inst_tried = 0;
- d_inst_tests = 0;
-}
-
-void RepAlphabetIterator::increment2( QuantifiersEngine* qe, int counter ){
- Assert( !isFinished() );
- //increment d_index
- while( counter>=0 && d_index[counter]==(int)(d_model->getReps()->d_type_reps[d_f[0][d_index_order[counter]].getType()].size()-1) ){
- counter--;
- }
- if( counter==-1 ){
- d_index.clear();
- }else{
- for( int i=(int)d_index.size()-1; i>counter; i-- ){
- d_index[i] = 0;
- d_model->clearEvalFailed( i );
- }
- d_index[counter]++;
- d_model->clearEvalFailed( counter );
- }
-}
-
-void RepAlphabetIterator::increment( QuantifiersEngine* qe ){
- if( !isFinished() ){
- increment2( qe, (int)d_index.size()-1 );
- }
-}
+ModelEngineBuilder::ModelEngineBuilder( QuantifiersEngine* qe ) :
+TheoryEngineModelBuilder( qe->getTheoryEngine() ),
+d_qe( qe ){
-bool RepAlphabetIterator::isFinished(){
- return d_index.empty();
}
-void RepAlphabetIterator::getMatch( QuantifiersEngine* ie, InstMatch& m ){
- for( int i=0; i<(int)d_index.size(); i++ ){
- m.d_map[ ie->getInstantiationConstant( d_f, i ) ] = getTerm( i );
- }
+Node ModelEngineBuilder::chooseRepresentative( TheoryModel* tm, Node eqc ){
+ return eqc;
}
-Node RepAlphabetIterator::getTerm( int i ){
- TypeNode tn = d_f[0][d_index_order[i]].getType();
- Assert( d_model->getReps()->d_type_reps.find( tn )!=d_model->getReps()->d_type_reps.end() );
- return d_model->getReps()->d_type_reps[tn][d_index[d_index_order[i]]];
-}
-
-void RepAlphabetIterator::calculateTerms( QuantifiersEngine* qe ){
- d_terms.clear();
- for( int i=0; i<qe->getNumInstantiationConstants( d_f ); i++ ){
- d_terms.push_back( getTerm( i ) );
- }
-}
-
-void RepAlphabetIterator::debugPrint( const char* c ){
- for( int i=0; i<(int)d_index.size(); i++ ){
- Debug( c ) << i << ": " << d_index[i] << ", (" << getTerm( i ) << " / " << d_ic[ i ] << std::endl;
- }
-}
-
-void RepAlphabetIterator::debugPrintSmall( const char* c ){
- Debug( c ) << "RI: ";
- for( int i=0; i<(int)d_index.size(); i++ ){
- Debug( c ) << d_index[i] << ": " << getTerm( i ) << " ";
- }
- Debug( c ) << std::endl;
-}
-
-//set value function
-void UfModelTree::setValue( QuantifiersEngine* qe, Node n, Node v, std::vector< int >& indexOrder, bool ground, int argIndex ){
- if( d_data.empty() ){
- d_value = v;
- }else if( !d_value.isNull() && d_value!=v ){
- d_value = Node::null();
- }
- if( argIndex<(int)n.getNumChildren() ){
- //take r = null when argument is the model basis
- Node r;
- if( ground || !n[ indexOrder[argIndex] ].getAttribute(ModelBasisAttribute()) ){
- r = qe->getEqualityQuery()->getRepresentative( n[ indexOrder[argIndex] ] );
- }
- d_data[ r ].setValue( qe, n, v, indexOrder, ground, argIndex+1 );
- }
-}
-
-//get value function
-Node UfModelTree::getValue( QuantifiersEngine* qe, Node n, std::vector< int >& indexOrder, int& depIndex, int argIndex ){
- if( !d_value.isNull() && isTotal( n.getOperator(), argIndex ) ){
- //Notice() << "Constant, return " << d_value << ", depIndex = " << argIndex << std::endl;
- depIndex = argIndex;
- return d_value;
- }else{
- Node val;
- int childDepIndex[2] = { argIndex, argIndex };
- for( int i=0; i<2; i++ ){
- //first check the argument, then check default
- Node r;
- if( i==0 ){
- r = qe->getEqualityQuery()->getRepresentative( n[ indexOrder[argIndex] ] );
+void ModelEngineBuilder::processBuildModel( TheoryModel* m ) {
+ d_addedLemmas = 0;
+ //only construct first order model if optUseModel() is true
+ if( optUseModel() ){
+ FirstOrderModel* fm = (FirstOrderModel*)m;
+ //initialize model
+ fm->initialize();
+ //analyze the quantifiers
+ Debug("fmf-model-debug") << "Analyzing quantifiers..." << std::endl;
+ analyzeQuantifiers( fm );
+ //if applicable, find exceptions
+ if( optInstGen() ){
+ //now, see if we know that any exceptions via InstGen exist
+ Debug("fmf-model-debug") << "Perform InstGen techniques for quantifiers..." << std::endl;
+ for( int i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
+ Node f = fm->getAssertedQuantifier( i );
+ if( d_quant_sat.find( f )==d_quant_sat.end() ){
+ d_addedLemmas += doInstGen( fm, f );
+ if( optOneQuantPerRoundInstGen() && d_addedLemmas>0 ){
+ break;
+ }
+ }
}
- std::map< Node, UfModelTree >::iterator it = d_data.find( r );
- if( it!=d_data.end() ){
- val = it->second.getValue( qe, n, indexOrder, childDepIndex[i], argIndex+1 );
- if( !val.isNull() ){
- break;
+ if( Options::current()->printModelEngine ){
+ if( d_addedLemmas>0 ){
+ Message() << "InstGen, added lemmas = " << d_addedLemmas << std::endl;
+ }else{
+ Message() << "No InstGen lemmas..." << std::endl;
}
- }else{
- //argument is not a defined argument: thus, it depends on this argument
- childDepIndex[i] = argIndex+1;
}
+ Debug("fmf-model-debug") << "---> Added lemmas = " << d_addedLemmas << std::endl;
+ }
+ if( d_addedLemmas==0 ){
+ //if no immediate exceptions, build the model
+ // this model will be an approximation that will need to be tested via exhaustive instantiation
+ Debug("fmf-model-debug") << "Building model..." << std::endl;
+ finishBuildModel( fm );
}
- //update depIndex
- depIndex = childDepIndex[0]>childDepIndex[1] ? childDepIndex[0] : childDepIndex[1];
- //Notice() << "Return " << val << ", depIndex = " << depIndex;
- //Notice() << " ( " << childDepIndex[0] << ", " << childDepIndex[1] << " )" << std::endl;
- return val;
}
}
-//simplify function
-void UfModelTree::simplify( Node op, Node defaultVal, int argIndex ){
- if( argIndex<(int)op.getType().getNumChildren()-1 ){
- std::vector< Node > eraseData;
- //first process the default argument
- Node r;
- std::map< Node, UfModelTree >::iterator it = d_data.find( r );
- if( it!=d_data.end() ){
- if( !defaultVal.isNull() && it->second.d_value==defaultVal ){
- eraseData.push_back( r );
- }else{
- it->second.simplify( op, defaultVal, argIndex+1 );
- if( !it->second.d_value.isNull() && it->second.isTotal( op, argIndex+1 ) ){
- defaultVal = it->second.d_value;
+void ModelEngineBuilder::analyzeQuantifiers( FirstOrderModel* fm ){
+ d_quant_selection_lits.clear();
+ d_quant_sat.clear();
+ d_uf_prefs.clear();
+ int quantSatInit = 0;
+ int nquantSatInit = 0;
+ //analyze the preferences of each quantifier
+ for( int i=0; i<(int)fm->getNumAssertedQuantifiers(); i++ ){
+ Node f = fm->getAssertedQuantifier( i );
+ Debug("fmf-model-prefs") << "Analyze quantifier " << f << std::endl;
+ std::vector< Node > pro_con[2];
+ std::vector< Node > constantSatOps;
+ bool constantSatReconsider;
+ //for each asserted quantifier f,
+ // - determine which literals form model basis for each quantifier
+ // - check which function/predicates have good and bad definitions according to f
+ for( std::map< Node, bool >::iterator it = d_qe->d_phase_reqs[f].begin();
+ it != d_qe->d_phase_reqs[f].end(); ++it ){
+ Node n = it->first;
+ Node gn = d_qe->getTermDatabase()->getModelBasis( n );
+ Debug("fmf-model-req") << " Req: " << n << " -> " << it->second << std::endl;
+ //calculate preference
+ int pref = 0;
+ bool value;
+ if( d_qe->getValuation().hasSatValue( gn, value ) ){
+ if( value!=it->second ){
+ //store this literal as a model basis literal
+ // this literal will force a default values in model that (modulo exceptions) shows
+ // that f is satisfied by the model
+ d_quant_selection_lits[f].push_back( value ? n : n.notNode() );
+ pref = 1;
}else{
- defaultVal = Node::null();
+ pref = -1;
}
}
- }
- //now see if any children can be removed, and simplify the ones that cannot
- for( std::map< Node, UfModelTree >::iterator it = d_data.begin(); it != d_data.end(); ++it ){
- if( !it->first.isNull() ){
- if( !defaultVal.isNull() && it->second.d_value==defaultVal ){
- eraseData.push_back( it->first );
+ if( pref!=0 ){
+ //Store preferences for UF
+ bool isConst = !n.hasAttribute(InstConstantAttribute());
+ std::vector< Node > uf_terms;
+ if( gn.getKind()==APPLY_UF ){
+ uf_terms.push_back( gn );
+ isConst = fm->d_uf_model[gn.getOperator()].isConstant();
+ }else if( gn.getKind()==EQUAL ){
+ isConst = true;
+ for( int j=0; j<2; j++ ){
+ if( n[j].hasAttribute(InstConstantAttribute()) ){
+ if( n[j].getKind()==APPLY_UF ){
+ Node op = gn[j].getOperator();
+ if( fm->d_uf_model.find( op )!=fm->d_uf_model.end() ){
+ uf_terms.push_back( gn[j] );
+ isConst = isConst && fm->d_uf_model[op].isConstant();
+ }else{
+ isConst = false;
+ }
+ }else{
+ isConst = false;
+ }
+ }
+ }
+ }
+ Debug("fmf-model-prefs") << " It is " << ( pref==1 ? "pro" : "con" );
+ Debug("fmf-model-prefs") << " the definition of " << n << std::endl;
+ if( pref==1 && isConst ){
+ d_quant_sat[f] = true;
+ //instead, just note to the model for each uf term that f is pro its definition
+ constantSatReconsider = false;
+ constantSatOps.clear();
+ for( int j=0; j<(int)uf_terms.size(); j++ ){
+ Node op = uf_terms[j].getOperator();
+ constantSatOps.push_back( op );
+ if( d_uf_prefs[op].d_reconsiderModel ){
+ constantSatReconsider = true;
+ }
+ }
+ if( !constantSatReconsider ){
+ break;
+ }
}else{
- it->second.simplify( op, defaultVal, argIndex+1 );
+ int pcIndex = pref==1 ? 0 : 1;
+ for( int j=0; j<(int)uf_terms.size(); j++ ){
+ pro_con[pcIndex].push_back( uf_terms[j] );
+ }
}
}
}
- for( int i=0; i<(int)eraseData.size(); i++ ){
- d_data.erase( eraseData[i] );
- }
- }
-}
-
-//is total function
-bool UfModelTree::isTotal( Node op, int argIndex ){
- if( argIndex==(int)(op.getType().getNumChildren()-1) ){
- return !d_value.isNull();
- }else{
- Node r;
- std::map< Node, UfModelTree >::iterator it = d_data.find( r );
- if( it!=d_data.end() ){
- return it->second.isTotal( op, argIndex+1 );
+ if( d_quant_sat.find( f )!=d_quant_sat.end() ){
+ Debug("fmf-model-prefs") << " * Constant SAT due to definition of ops: ";
+ for( int i=0; i<(int)constantSatOps.size(); i++ ){
+ Debug("fmf-model-prefs") << constantSatOps[i] << " ";
+ d_uf_prefs[constantSatOps[i]].d_reconsiderModel = false;
+ }
+ Debug("fmf-model-prefs") << std::endl;
+ quantSatInit++;
+ d_statistics.d_pre_sat_quant += quantSatInit;
}else{
- return false;
- }
- }
-}
-
-Node UfModelTree::getConstantValue( QuantifiersEngine* qe, Node n, std::vector< int >& indexOrder, int argIndex ){
- return d_value;
-}
-
-void indent( const char* c, int ind ){
- for( int i=0; i<ind; i++ ){
- Debug( c ) << " ";
- }
-}
-
-void UfModelTree::debugPrint( const char* c, QuantifiersEngine* qe, std::vector< int >& indexOrder, int ind, int arg ){
- if( !d_data.empty() ){
- for( std::map< Node, UfModelTree >::iterator it = d_data.begin(); it != d_data.end(); ++it ){
- if( !it->first.isNull() ){
- indent( c, ind );
- Debug( c ) << "if x_" << indexOrder[arg] << " == " << it->first << std::endl;
- it->second.debugPrint( c, qe, indexOrder, ind+2, arg+1 );
+ nquantSatInit++;
+ d_statistics.d_pre_nsat_quant += quantSatInit;
+ //note quantifier's value preferences to models
+ for( int k=0; k<2; k++ ){
+ for( int j=0; j<(int)pro_con[k].size(); j++ ){
+ Node op = pro_con[k][j].getOperator();
+ Node r = fm->getRepresentative( pro_con[k][j] );
+ d_uf_prefs[op].setValuePreference( f, pro_con[k][j], r, k==0 );
+ }
}
}
- if( d_data.find( Node::null() )!=d_data.end() ){
- d_data[ Node::null() ].debugPrint( c, qe, indexOrder, ind, arg+1 );
- }
- }else{
- indent( c, ind );
- Debug( c ) << "return ";
- printRepresentative( c, qe, d_value );
- //Debug( c ) << " { ";
- //for( int i=0; i<(int)d_explicit.size(); i++ ){
- // Debug( c ) << d_explicit[i] << " ";
- //}
- //Debug( c ) << "}";
- Debug( c ) << std::endl;
}
+ Debug("fmf-model-prefs") << "Pre-Model Completion: Quantifiers SAT: " << quantSatInit << " / " << (quantSatInit+nquantSatInit) << std::endl;
}
-UfModel::UfModel( Node op, ModelEngine* me ) : d_op( op ), d_me( me ),
- d_model_constructed( false ), d_reconsider_model( false ){
-
- d_tree = UfModelTreeOrdered( op ); TypeNode tn = d_op.getType(); tn = tn[(int)tn.getNumChildren()-1]; Assert( tn==NodeManager::currentNM()->booleanType() || uf::StrongSolverTheoryUf::isRelevantType( tn ) ); //look at ground assertions
- for( int i=0; i<(int)d_me->getQuantifiersEngine()->getTermDatabase()->d_op_map[ d_op ].size(); i++ ){
- Node n = d_me->getQuantifiersEngine()->getTermDatabase()->d_op_map[ d_op ][i];
- bool add = true;
- if( n.getAttribute(NoMatchAttribute()) ){
- add = false;
- //determine if it has model basis attribute
- for( int j=0; j<(int)n.getNumChildren(); j++ ){
- if( n[j].getAttribute(ModelBasisAttribute()) ){
- add = true;
- break;
+int ModelEngineBuilder::doInstGen( FirstOrderModel* fm, Node f ){
+ //we wish to add all known exceptions to our model basis literal(s)
+ // this will help to refine our current model.
+ //This step is advantageous over exhaustive instantiation, since we are adding instantiations that involve model basis terms,
+ // effectively acting as partial instantiations instead of pointwise instantiations.
+ int addedLemmas = 0;
+ for( int i=0; i<(int)d_quant_selection_lits[f].size(); i++ ){
+ bool phase = d_quant_selection_lits[f][i].getKind()!=NOT;
+ Node lit = d_quant_selection_lits[f][i].getKind()==NOT ? d_quant_selection_lits[f][i][0] : d_quant_selection_lits[f][i];
+ Assert( lit.hasAttribute(InstConstantAttribute()) );
+ std::vector< Node > tr_terms;
+ if( lit.getKind()==APPLY_UF ){
+ //only match predicates that are contrary to this one, use literal matching
+ Node eq = NodeManager::currentNM()->mkNode( IFF, lit, !phase ? fm->d_true : fm->d_false );
+ fm->getTermDatabase()->setInstantiationConstantAttr( eq, f );
+ tr_terms.push_back( eq );
+ }else if( lit.getKind()==EQUAL ){
+ //collect trigger terms
+ for( int j=0; j<2; j++ ){
+ if( lit[j].hasAttribute(InstConstantAttribute()) ){
+ if( lit[j].getKind()==APPLY_UF ){
+ tr_terms.push_back( lit[j] );
+ }else{
+ tr_terms.clear();
+ break;
+ }
}
}
- }
- if( add ){
- d_ground_asserts.push_back( n );
- Node r = d_me->getQuantifiersEngine()->getEqualityQuery()->getRepresentative( n );
- d_ground_asserts_reps.push_back( r );
- }
- }
- //determine if it is constant
- if( !d_ground_asserts.empty() ){
- bool isConstant = true;
- for( int i=1; i<(int)d_ground_asserts.size(); i++ ){
- if( d_ground_asserts_reps[0]!=d_ground_asserts_reps[i] ){
- isConstant = false;
- break;
+ if( tr_terms.size()==1 && !phase ){
+ //equality between a function and a ground term, use literal matching
+ tr_terms.clear();
+ tr_terms.push_back( lit );
}
}
- if( isConstant ){
- //set constant value
- Node t = d_me->getModelBasisApplyUfTerm( d_op );
- Node r = d_ground_asserts_reps[0];
- setValue( t, r, false );
- setModel();
- d_reconsider_model = true;
- Debug("fmf-model-cons") << "Function " << d_op << " is the constant function ";
- printRepresentative( "fmf-model-cons", d_me->getQuantifiersEngine(), r );
- Debug("fmf-model-cons") << std::endl;
+ //if applicable, try to add exceptions here
+ if( !tr_terms.empty() ){
+ //make a trigger for these terms, add instantiations
+ Trigger* tr = Trigger::mkTrigger( d_qe, f, tr_terms );
+ //Notice() << "Trigger = " << (*tr) << std::endl;
+ tr->resetInstantiationRound();
+ tr->reset( Node::null() );
+ //d_qe->d_optInstMakeRepresentative = false;
+ //d_qe->d_optMatchIgnoreModelBasis = true;
+ addedLemmas += tr->addInstantiations( d_quant_basis_match[f] );
}
}
+ return addedLemmas;
}
-void UfModel::setValue( Node n, Node v, bool ground ){
- d_set_values[ ground ? 1 : 0 ][n] = v;
-}
-
-void UfModel::setModel(){
- makeModel( d_me->getQuantifiersEngine(), d_tree );
- d_model_constructed = true;
-}
-
-void UfModel::clearModel(){
- for( int k=0; k<2; k++ ){
- d_set_values[k].clear();
+void ModelEngineBuilder::finishBuildModel( FirstOrderModel* fm ){
+ //build model for UF
+ for( std::map< Node, uf::UfModel >::iterator it = fm->d_uf_model.begin(); it != fm->d_uf_model.end(); ++it ){
+ finishBuildModelUf( fm, it->second );
}
- d_tree.clear();
- d_model_constructed = false;
-}
-
-Node UfModel::getConstantValue( QuantifiersEngine* qe, Node n ){
- if( d_model_constructed ){
- return d_tree.getConstantValue( qe, n );
- }else{
- return Node::null();
+ //build model for arrays
+ for( std::map< Node, Node >::iterator it = fm->d_array_model.begin(); it != fm->d_array_model.end(); ++it ){
+ //consult the model basis select term
+ // i.e. the default value for array A is the value of select( A, e ), where e is the model basis term
+ TypeNode tn = it->first.getType();
+ Node selModelBasis = NodeManager::currentNM()->mkNode( SELECT, it->first, fm->getTermDatabase()->getModelBasisTerm( tn[0] ) );
+ it->second = fm->getRepresentative( selModelBasis );
}
+ Debug("fmf-model-debug") << "Done building models." << std::endl;
}
-bool UfModel::isConstant(){
- Node gn = d_me->getModelBasisApplyUfTerm( d_op );
- Node n = getConstantValue( d_me->getQuantifiersEngine(), gn );
- return !n.isNull();
-}
-
-void UfModel::buildModel(){
+void ModelEngineBuilder::finishBuildModelUf( FirstOrderModel* fm, uf::UfModel& model ){
+ Node op = model.getOperator();
#ifdef RECONSIDER_FUNC_CONSTANT
- if( d_model_constructed ){
- if( d_reconsider_model ){
+ if( model.isModelConstructed() && model.isConstant() ){
+ if( d_uf_prefs[op].d_reconsiderModel ){
//if we are allowed to reconsider default value, then see if the default value can be improved
- Node t = d_me->getModelBasisApplyUfTerm( d_op );
- Node v = d_set_values[0][t];
- if( d_value_pro_con[1][v].size()>d_value_pro_con[0][v].size() ){
- Debug("fmf-model-cons-debug") << "Consider changing the default value for " << d_op << std::endl;
- clearModel();
+ Node t = d_qe->getTermDatabase()->getModelBasisOpTerm( op );
+ Node v = model.getConstantValue( t );
+ if( d_uf_prefs[op].d_value_pro_con[0][v].empty() ){
+ Debug("fmf-model-cons-debug") << "Consider changing the default value for " << op << std::endl;
+ model.clearModel();
}
}
}
#endif
- //now, construct models for each uninterpretted function/predicate
- if( !d_model_constructed ){
- Debug("fmf-model-cons") << "Construct model for " << d_op << "..." << std::endl;
- //now, set the values in the model
- for( int i=0; i<(int)d_ground_asserts.size(); i++ ){
- Node n = d_ground_asserts[i];
- Node v = d_ground_asserts_reps[i];
+ if( !model.isModelConstructed() ){
+ //construct the model for the uninterpretted function/predicate
+ bool setDefaultVal = true;
+ Node defaultTerm = d_qe->getTermDatabase()->getModelBasisOpTerm( op );
+ Debug("fmf-model-cons") << "Construct model for " << op << "..." << std::endl;
+ //set the values in the model
+ for( size_t i=0; i<model.d_ground_asserts.size(); i++ ){
+ Node n = model.d_ground_asserts[i];
+ Node v = model.d_ground_asserts_reps[i];
//if this assertion did not help the model, just consider it ground
//set n = v in the model tree
Debug("fmf-model-cons") << " Set " << n << " = ";
- printRepresentative( "fmf-model-cons", d_me->getQuantifiersEngine(), v );
+ fm->printRepresentativeDebug( "fmf-model-cons", v );
Debug("fmf-model-cons") << std::endl;
//set it as ground value
- setValue( n, v );
- }
- //set the default value
- //chose defaultVal based on heuristic (the best proportion of "pro" responses)
- Node defaultVal;
- double maxScore = -1;
- for( int i=0; i<(int)d_values.size(); i++ ){
- Node v = d_values[i];
- double score = ( 1.0 + (double)d_value_pro_con[0][v].size() )/( 1.0 + (double)d_value_pro_con[1][v].size() );
- Debug("fmf-model-cons") << " - score( ";
- printRepresentative( "fmf-model-cons", d_me->getQuantifiersEngine(), v );
- Debug("fmf-model-cons") << " ) = " << score << std::endl;
- if( score>maxScore ){
- defaultVal = v;
- maxScore = score;
- }
- }
-#ifdef RECONSIDER_FUNC_DEFAULT_VALUE
- if( maxScore<1.0 ){
- //consider finding another value, if possible
- Debug("fmf-model-cons-debug") << "Poor choice for default value, score = " << maxScore << std::endl;
- TypeNode tn = d_op.getType();
- Node newDefaultVal = d_me->getArbitraryElement( tn[(int)tn.getNumChildren()-1], d_values );
- if( !newDefaultVal.isNull() ){
- defaultVal = newDefaultVal;
- Debug("fmf-model-cons-debug") << "-> Change default value to ";
- printRepresentative( "fmf-model-cons-debug", d_me->getQuantifiersEngine(), defaultVal );
- Debug("fmf-model-cons-debug") << std::endl;
+ model.setValue( n, v );
+ if( model.optUsePartialDefaults() ){
+ //also set as default value if necessary
+ //if( n.getAttribute(ModelBasisArgAttribute())==1 && !d_term_pro_con[0][n].empty() ){
+ if( n.hasAttribute(ModelBasisArgAttribute()) && n.getAttribute(ModelBasisArgAttribute())==1 ){
+ model.setValue( n, v, false );
+ if( n==defaultTerm ){
+ //incidentally already set, we will not need to find a default value
+ setDefaultVal = false;
+ }
+ }
}else{
- Debug("fmf-model-cons-debug") << "-> Could not find arbitrary element of type " << tn[(int)tn.getNumChildren()-1] << std::endl;
- Debug("fmf-model-cons-debug") << " Excluding: ";
- for( int i=0; i<(int)d_values.size(); i++ ){
- Debug("fmf-model-cons-debug") << d_values[i] << " ";
+ if( n==defaultTerm ){
+ model.setValue( n, v, false );
+ //incidentally already set, we will not need to find a default value
+ setDefaultVal = false;
}
- Debug("fmf-model-cons-debug") << std::endl;
}
}
-#endif
- Assert( !defaultVal.isNull() );
- //get the default term (this term must be defined non-ground in model)
- Node defaultTerm = d_me->getModelBasisApplyUfTerm( d_op );
- Debug("fmf-model-cons") << " Choose ";
- printRepresentative("fmf-model-cons", d_me->getQuantifiersEngine(), defaultVal );
- Debug("fmf-model-cons") << " as default value (" << defaultTerm << ")" << std::endl;
- Debug("fmf-model-cons") << " # quantifiers pro = " << d_value_pro_con[0][defaultVal].size() << std::endl;
- Debug("fmf-model-cons") << " # quantifiers con = " << d_value_pro_con[1][defaultVal].size() << std::endl;
- setValue( defaultTerm, defaultVal, false );
+ //set the overall default value if not set already (is this necessary??)
+ if( setDefaultVal ){
+ Debug("fmf-model-cons") << " Choose default value..." << std::endl;
+ //chose defaultVal based on heuristic, currently the best ratio of "pro" responses
+ Node defaultVal = d_uf_prefs[op].getBestDefaultValue( defaultTerm, fm );
+ Assert( !defaultVal.isNull() );
+ model.setValue( defaultTerm, defaultVal, false );
+ }
Debug("fmf-model-cons") << " Making model...";
- setModel();
- Debug("fmf-model-cons") << " Finished constructing model for " << d_op << "." << std::endl;
+ model.setModel();
+ Debug("fmf-model-cons") << " Finished constructing model for " << op << "." << std::endl;
}
}
-void UfModel::setValuePreference( Node f, Node n, bool isPro ){
- Node v = d_me->getQuantifiersEngine()->getEqualityQuery()->getRepresentative( n );
- //Notice() << "Set value preference " << n << " = " << v << " " << isPro << std::endl;
- if( std::find( d_values.begin(), d_values.end(), v )==d_values.end() ){
- d_values.push_back( v );
- }
- int index = isPro ? 0 : 1;
- if( std::find( d_value_pro_con[index][v].begin(), d_value_pro_con[index][v].end(), f )==d_value_pro_con[index][v].end() ){
- d_value_pro_con[index][v].push_back( f );
- }
+bool ModelEngineBuilder::optUseModel() {
+ return Options::current()->fmfModelBasedInst;
}
-void UfModel::makeModel( QuantifiersEngine* qe, UfModelTreeOrdered& tree ){
- for( int k=0; k<2; k++ ){
- for( std::map< Node, Node >::iterator it = d_set_values[k].begin(); it != d_set_values[k].end(); ++it ){
- tree.setValue( qe, it->first, it->second, k==1 );
- }
- }
- tree.simplify();
+bool ModelEngineBuilder::optInstGen(){
+ return Options::current()->fmfInstGen;
+}
+
+bool ModelEngineBuilder::optOneQuantPerRoundInstGen(){
+#ifdef ONE_QUANT_PER_ROUND_INST_GEN
+ return true;
+#else
+ return false;
+#endif
}
-void UfModel::debugPrint( const char* c ){
- //Debug( c ) << "Function " << d_op << std::endl;
- //Debug( c ) << " Type: " << d_op.getType() << std::endl;
- //Debug( c ) << " Ground asserts:" << std::endl;
- //for( int i=0; i<(int)d_ground_asserts.size(); i++ ){
- // Debug( c ) << " " << d_ground_asserts[i] << " = ";
- // printRepresentative( c, d_me->getQuantifiersEngine(), d_ground_asserts[i] );
- // Debug( c ) << std::endl;
- //}
- //Debug( c ) << " Model:" << std::endl;
+ModelEngineBuilder::Statistics::Statistics():
+ d_pre_sat_quant("ModelEngineBuilder::Status_quant_pre_sat", 0),
+ d_pre_nsat_quant("ModelEngineBuilder::Status_quant_pre_non_sat", 0)
+{
+ StatisticsRegistry::registerStat(&d_pre_sat_quant);
+ StatisticsRegistry::registerStat(&d_pre_nsat_quant);
+}
- TypeNode t = d_op.getType();
- Debug( c ) << d_op << "( ";
- for( int i=0; i<(int)(t.getNumChildren()-1); i++ ){
- Debug( c ) << "x_" << i << " : " << t[i];
- if( i<(int)(t.getNumChildren()-2) ){
- Debug( c ) << ", ";
- }
- }
- Debug( c ) << " ) : " << t[(int)t.getNumChildren()-1] << std::endl;
- if( d_tree.isEmpty() ){
- Debug( c ) << " [undefined]" << std::endl;
- }else{
- d_tree.debugPrint( c, d_me->getQuantifiersEngine(), 3 );
- Debug( c ) << std::endl;
- }
- //Debug( c ) << " Phase reqs:" << std::endl; //for( int i=0; i<2; i++ ){
- // for( std::map< Node, std::vector< Node > >::iterator it = d_reqs[i].begin(); it != d_reqs[i].end(); ++it ){
- // Debug( c ) << " " << it->first << std::endl;
- // for( int j=0; j<(int)it->second.size(); j++ ){
- // Debug( c ) << " " << it->second[j] << " -> " << (i==1) << std::endl;
- // }
- // }
- //}
- //Debug( c ) << std::endl;
- //for( int i=0; i<2; i++ ){
- // for( std::map< Node, std::map< Node, std::vector< Node > > >::iterator it = d_eq_reqs[i].begin(); it != d_eq_reqs[i].end(); ++it ){
- // Debug( c ) << " " << "For " << it->first << ":" << std::endl;
- // for( std::map< Node, std::vector< Node > >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
- // for( int j=0; j<(int)it2->second.size(); j++ ){
- // Debug( c ) << " " << it2->first << ( i==1 ? "==" : "!=" ) << it2->second[j] << std::endl;
- // }
- // }
- // }
- //}
+ModelEngineBuilder::Statistics::~Statistics(){
+ StatisticsRegistry::unregisterStat(&d_pre_sat_quant);
+ StatisticsRegistry::unregisterStat(&d_pre_nsat_quant);
}
//Model Engine constructor
-ModelEngine::ModelEngine( TheoryQuantifiers* th ){
- d_th = th;
- d_quantEngine = th->getQuantifiersEngine();
- d_ss = ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->getTheory( THEORY_UF ))->getStrongSolver();
+ModelEngine::ModelEngine( QuantifiersEngine* qe ) :
+QuantifiersModule( qe ),
+d_builder( qe ),
+d_rel_domain( qe->getModel() ){
+
}
void ModelEngine::check( Theory::Effort e ){
- if( e==Theory::EFFORT_LAST_CALL ){
- bool quantsInit = true;
+ if( e==Theory::EFFORT_LAST_CALL && !d_quantEngine->hasAddedLemma() ){
//first, check if we can minimize the model further
- if( !d_ss->minimize() ){
+ if( !((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->getTheory( THEORY_UF ))->getStrongSolver()->minimize() ){
return;
}
- if( useModel() ){
- //now, check if any quantifiers are un-initialized
- for( int i=0; i<d_quantEngine->getNumAssertedQuantifiers(); i++ ){
- Node f = d_quantEngine->getAssertedQuantifier( i );
- if( !initializeQuantifier( f ) ){
- quantsInit = false;
- }
+ //the following will attempt to build a model and test that it satisfies all asserted universal quantifiers
+ int addedLemmas = 0;
+ if( d_builder.optUseModel() ){
+ //check if any quantifiers are un-initialized
+ for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
+ addedLemmas += initializeQuantifier( f );
}
}
- if( quantsInit ){
-#ifdef ME_PRINT_PROCESS_TIMES
- Notice() << "---Instantiation Round---" << std::endl;
-#endif
+ if( addedLemmas==0 ){
+ //quantifiers are initialized, we begin an instantiation round
+ double clSet = 0;
+ if( Options::current()->printModelEngine ){
+ clSet = double(clock())/double(CLOCKS_PER_SEC);
+ Message() << "---Model Engine Round---" << std::endl;
+ }
Debug("fmf-model-debug") << "---Begin Instantiation Round---" << std::endl;
++(d_statistics.d_inst_rounds);
- d_quantEngine->getTermDatabase()->reset( e );
- //build the representatives
- Debug("fmf-model-debug") << "Building representatives..." << std::endl;
- buildRepresentatives();
- if( useModel() ){
- //initialize the model
- Debug("fmf-model-debug") << "Initializing model..." << std::endl;
- initializeModel();
- //analyze the quantifiers
- Debug("fmf-model-debug") << "Analyzing quantifiers..." << std::endl;
- analyzeQuantifiers();
- //build the model
- Debug("fmf-model-debug") << "Building model..." << std::endl;
- for( std::map< Node, UfModel >::iterator it = d_uf_model.begin(); it != d_uf_model.end(); ++it ){
- it->second.buildModel();
+ //reset the quantifiers engine
+ d_quantEngine->resetInstantiationRound( e );
+ //initialize the model
+ Debug("fmf-model-debug") << "Build model..." << std::endl;
+ d_builder.buildModel( d_quantEngine->getModel() );
+ d_quantEngine->d_model_set = true;
+ //if builder has lemmas, add and return
+ if( d_builder.d_addedLemmas>0 ){
+ addedLemmas += (int)d_builder.d_addedLemmas;
+ }else{
+ //print debug
+ Debug("fmf-model-complete") << std::endl;
+ debugPrint("fmf-model-complete");
+ //verify we are SAT by trying exhaustive instantiation
+ if( optUseRelevantDomain() ){
+ d_rel_domain.compute();
}
- }
- //print debug
- debugPrint("fmf-model-complete");
- //try exhaustive instantiation
- Debug("fmf-model-debug") << "Do exhaustive instantiation..." << std::endl;
- int addedLemmas = 0;
- for( int i=0; i<d_quantEngine->getNumAssertedQuantifiers(); i++ ){
- Node f = d_quantEngine->getAssertedQuantifier( i );
- if( d_quant_sat.find( f )==d_quant_sat.end() ){
- addedLemmas += instantiateQuantifier( f );
+ d_triedLemmas = 0;
+ d_testLemmas = 0;
+ d_relevantLemmas = 0;
+ d_totalLemmas = 0;
+ Debug("fmf-model-debug") << "Do exhaustive instantiation..." << std::endl;
+ for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
+ if( d_builder.d_quant_sat.find( f )==d_builder.d_quant_sat.end() ){
+ addedLemmas += exhaustiveInstantiate( f, optUseRelevantDomain() );
+ if( optOneQuantPerRound() && addedLemmas>0 ){
+ break;
+ }
+ }
+#ifdef ME_PRINT_WARNINGS
+ if( addedLemmas>10000 ){
+ break;
+ }
+#endif
+ }
+ Debug("fmf-model-debug") << "---> Added lemmas = " << addedLemmas << " / " << d_triedLemmas << " / ";
+ Debug("fmf-model-debug") << d_testLemmas << " / " << d_relevantLemmas << " / " << d_totalLemmas << std::endl;
+ if( Options::current()->printModelEngine ){
+ Message() << "Added Lemmas = " << addedLemmas << " / " << d_triedLemmas << " / ";
+ Message() << d_testLemmas << " / " << d_relevantLemmas << " / " << d_totalLemmas << std::endl;
+ double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
+ Message() << "Finished model engine, time = " << (clSet2-clSet) << std::endl;
+ }
+#ifdef ME_PRINT_WARNINGS
+ if( addedLemmas>10000 ){
+ Debug("fmf-exit") << std::endl;
+ debugPrint("fmf-exit");
+ exit( 0 );
}
- }
-#ifdef ME_PRINT_PROCESS_TIMES
- Notice() << "Added Lemmas = " << addedLemmas << std::endl;
#endif
- if( addedLemmas==0 ){
- //debugPrint("fmf-consistent");
- //for( std::map< Node, UfModel >::iterator it = d_uf_model.begin(); it != d_uf_model.end(); ++it ){
- // it->second.simplify();
- //}
- Debug("fmf-consistent") << std::endl;
- debugPrint("fmf-consistent");
}
}
- d_quantEngine->flushLemmas( &d_th->getOutputChannel() );
+ if( addedLemmas==0 ){
+ //CVC4 will answer SAT
+ Debug("fmf-consistent") << std::endl;
+ debugPrint("fmf-consistent");
+ }else{
+ //otherwise, the search will continue
+ d_quantEngine->flushLemmas( &d_quantEngine->getOutputChannel() );
+ }
}
}
@@ -611,19 +462,31 @@ void ModelEngine::assertNode( Node f ){
}
-bool ModelEngine::useModel() {
- return Options::current()->fmfModelBasedInst;
+bool ModelEngine::optOneInstPerQuantRound(){
+ return Options::current()->fmfOneInstPerRound;
+}
+
+bool ModelEngine::optUseRelevantDomain(){
+ return Options::current()->fmfRelevantDomain;
+}
+
+bool ModelEngine::optOneQuantPerRound(){
+#ifdef ONE_QUANT_PER_ROUND
+ return true;
+#else
+ return false;
+#endif
}
-bool ModelEngine::initializeQuantifier( Node f ){
+int ModelEngine::initializeQuantifier( Node f ){
if( d_quant_init.find( f )==d_quant_init.end() ){
d_quant_init[f] = true;
Debug("inst-fmf-init") << "Initialize " << f << std::endl;
//add the model basis instantiation
// This will help produce the necessary information for model completion.
- // We do this by extending distinguish ground assertions (those
+ // We do this by extending distinguish ground assertions (those
// containing terms with "model basis" attribute) to hold for all cases.
-
+
////first, check if any variables are required to be equal
//for( std::map< Node, bool >::iterator it = d_quantEngine->d_phase_reqs[f].begin();
// it != d_quantEngine->d_phase_reqs[f].end(); ++it ){
@@ -632,747 +495,167 @@ bool ModelEngine::initializeQuantifier( Node f ){
// Notice() << "Unhandled phase req: " << n << std::endl;
// }
//}
-
+ std::vector< Node > ics;
std::vector< Node > terms;
for( int j=0; j<(int)f[0].getNumChildren(); j++ ){
- terms.push_back( getModelBasisTerm( f[0][j].getType() ) );
+ Node ic = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );
+ Node t = d_quantEngine->getTermDatabase()->getModelBasisTerm( ic.getType() );
+ ics.push_back( ic );
+ terms.push_back( t );
+ //calculate the basis match for f
+ d_builder.d_quant_basis_match[f].d_map[ ic ] = t;
}
++(d_statistics.d_num_quants_init);
+ //register model basis body
+ Node n = d_quantEngine->getTermDatabase()->getCounterexampleBody( f );
+ Node gn = n.substitute( ics.begin(), ics.end(), terms.begin(), terms.end() );
+ d_quantEngine->getTermDatabase()->registerModelBasis( n, gn );
+ //add model basis instantiation
if( d_quantEngine->addInstantiation( f, terms ) ){
- return false;
+ return 1;
}else{
- //usually shouldn't happen
+ //shouldn't happen usually, but will occur if x != y is a required literal for f.
//Notice() << "No model basis for " << f << std::endl;
++(d_statistics.d_num_quants_init_fail);
}
}
- return true;
-}
-
-void ModelEngine::buildRepresentatives(){
- d_ra.clear();
- //collect all representatives for all types and store as representative alphabet
- for( int i=0; i<d_ss->getNumCardinalityTypes(); i++ ){
- TypeNode tn = d_ss->getCardinalityType( i );
- std::vector< Node > reps;
- d_ss->getRepresentatives( tn, reps );
- Assert( !reps.empty() );
- //if( (int)reps.size()!=d_ss->getCardinality( tn ) ){
- // Notice() << "InstStrategyFinteModelFind::processResetInstantiationRound: Bad representatives for type." << std::endl;
- // Notice() << " " << tn << " has cardinality " << d_ss->getCardinality( tn );
- // Notice() << " but only " << (int)reps.size() << " were given." << std::endl;
- // Unimplemented( 27 );
- //}
- Debug("fmf-model-debug") << " " << tn << " -> " << reps.size() << std::endl;
- Debug("fmf-model-debug") << " ";
- for( int i=0; i<(int)reps.size(); i++ ){
- Debug("fmf-model-debug") << reps[i] << " ";
- }
- Debug("fmf-model-debug") << std::endl;
- //set them in the alphabet
- d_ra.set( tn, reps );
-#ifdef ME_PRINT_PROCESS_TIMES
- Notice() << tn << " has " << reps.size() << " representatives. " << std::endl;
-#endif
- }
+ return 0;
}
-void ModelEngine::initializeModel(){
- d_uf_model.clear();
- d_quant_sat.clear();
- for( int k=0; k<2; k++ ){
- d_pro_con_quant[k].clear();
- }
-
- ////now analyze quantifiers (temporary)
- //for( int i=0; i<(int)d_quantEngine->getNumAssertedQuantifiers(); i++ ){
- // Node f = d_quantEngine->getAssertedQuantifier( i );
- // Debug("fmf-model-req") << "Phase requirements for " << f << ": " << std::endl;
- // for( std::map< Node, bool >::iterator it = d_quantEngine->d_phase_reqs[f].begin();
- // it != d_quantEngine->d_phase_reqs[f].end(); ++it ){
- // Node n = it->first;
- // Debug("fmf-model-req") << " " << n << " -> " << it->second << std::endl;
- // if( n.getKind()==APPLY_UF ){
- // processPredicate( f, n, it->second );
- // }else if( n.getKind()==EQUAL ){
- // processEquality( f, n, it->second );
- // }
- // }
- //}
- for( int i=0; i<(int)d_quantEngine->getNumAssertedQuantifiers(); i++ ){
- Node f = d_quantEngine->getAssertedQuantifier( i );
- initializeUf( f[1] );
- //register model basis terms
- std::vector< Node > vars;
- std::vector< Node > subs;
- for( int j=0; j<(int)f[0].getNumChildren(); j++ ){
- vars.push_back( d_quantEngine->getInstantiationConstant( f, j ) );
- subs.push_back( getModelBasisTerm( f[0][j].getType() ) );
- }
- Node n = d_quantEngine->getCounterexampleBody( f );
- Node gn = n.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
- registerModelBasis( n, gn );
- }
-}
-
-void ModelEngine::analyzeQuantifiers(){
- int quantSatInit = 0;
- int nquantSatInit = 0;
- //analyze the preferences of each quantifier
- for( int i=0; i<(int)d_quantEngine->getNumAssertedQuantifiers(); i++ ){
- Node f = d_quantEngine->getAssertedQuantifier( i );
- Debug("fmf-model-prefs") << "Analyze quantifier " << f << std::endl;
- std::vector< Node > pro_con[2];
- std::vector< Node > pro_con_patterns[2];
- //check which model basis terms have good and bad definitions according to f
- for( std::map< Node, bool >::iterator it = d_quantEngine->d_phase_reqs[f].begin();
- it != d_quantEngine->d_phase_reqs[f].end(); ++it ){
- Node n = it->first;
- Node gn = d_model_basis[n];
- Debug("fmf-model-req") << " Req: " << n << " -> " << it->second << std::endl;
- int pref = 0;
- bool isConst = true;
- std::vector< Node > uf_terms;
- std::vector< Node > uf_term_patterns;
- if( gn.getKind()==APPLY_UF ){
- if( d_quantEngine->getEqualityQuery()->hasTerm( gn ) ){
- uf_terms.push_back( gn );
- uf_term_patterns.push_back( n );
- bool phase = areEqual( gn, NodeManager::currentNM()->mkConst( true ) );
- pref = phase!=it->second ? 1 : -1;
- }
- }else if( gn.getKind()==EQUAL ){
- bool success = true;
- for( int j=0; j<2; j++ ){
- if( n[j].getKind()==APPLY_UF ){
- Node op = gn[j].getOperator();
- if( d_uf_model.find( op )!=d_uf_model.end() ){
- Assert( gn[j].getKind()==APPLY_UF );
- uf_terms.push_back( gn[j] );
- uf_term_patterns.push_back( n[j] );
- }else{
- //found undefined uf operator
- success = false;
- }
- }else if( n[j].hasAttribute(InstConstantAttribute()) ){
- isConst = false;
- }
- }
- if( success && !uf_terms.empty() ){
- if( (!it->second && areEqual( gn[0], gn[1] )) || (it->second && areDisequal( gn[0], gn[1] )) ){
- pref = 1;
- }else if( (it->second && areEqual( gn[0], gn[1] )) || (!it->second && areDisequal( gn[0], gn[1] )) ){
- pref = -1;
- }
- }
- }
- if( pref!=0 ){
- Debug("fmf-model-prefs") << " It is " << ( pref==1 ? "pro" : "con" );
- Debug("fmf-model-prefs") << " the definition of " << n << std::endl;
- if( pref==1 ){
- if( isConst ){
- for( int j=0; j<(int)uf_terms.size(); j++ ){
- //the only uf that is initialized are those that are constant
- Node op = uf_terms[j].getOperator();
- Assert( d_uf_model.find( op )!=d_uf_model.end() );
- if( !d_uf_model[op].isConstant() ){
- isConst = false;
- break;
- }
- }
- if( isConst ){
- d_quant_sat[f] = true;
- //we only need to consider current term definition(s) for this quantifier to be satisified, ignore the others
- for( int k=0; k<2; k++ ){
- pro_con[k].clear();
- pro_con_patterns[k].clear();
- }
- //instead, just note to the model for each uf term that f is pro its definition
- for( int j=0; j<(int)uf_terms.size(); j++ ){
- Node op = uf_terms[j].getOperator();
- d_uf_model[op].d_reconsider_model = false;
- }
- }
- }
- }
- if( d_quant_sat.find( f )!=d_quant_sat.end() ){
- Debug("fmf-model-prefs") << " * Constant SAT due to definition of " << n << std::endl;
- break;
- }else{
- int pcIndex = pref==1 ? 0 : 1;
- for( int j=0; j<(int)uf_terms.size(); j++ ){
- pro_con[pcIndex].push_back( uf_terms[j] );
- pro_con_patterns[pcIndex].push_back( uf_term_patterns[j] );
- }
- }
- }
- }
- if( d_quant_sat.find( f )!=d_quant_sat.end() ){
- quantSatInit++;
- d_statistics.d_pre_sat_quant += quantSatInit;
- }else{
- nquantSatInit++;
- d_statistics.d_pre_nsat_quant += quantSatInit;
- }
- //add quantifier's preferences to vector
- for( int k=0; k<2; k++ ){
- for( int j=0; j<(int)pro_con[k].size(); j++ ){
- Node op = pro_con[k][j].getOperator();
- d_uf_model[op].setValuePreference( f, pro_con[k][j], k==0 );
- d_pro_con_quant[k][ f ].push_back( pro_con_patterns[k][j] );
- }
- }
- }
- Debug("fmf-model-prefs") << "Pre-Model Completion: Quantifiers SAT: " << quantSatInit << " / " << (quantSatInit+nquantSatInit) << std::endl;
-}
-
-int ModelEngine::instantiateQuantifier( Node f ){
+int ModelEngine::exhaustiveInstantiate( Node f, bool useRelInstDomain ){
+ int tests = 0;
int addedLemmas = 0;
+ int triedLemmas = 0;
Debug("inst-fmf-ei") << "Add matches for " << f << "..." << std::endl;
Debug("inst-fmf-ei") << " Instantiation Constants: ";
for( size_t i=0; i<f[0].getNumChildren(); i++ ){
- Debug("inst-fmf-ei") << d_quantEngine->getInstantiationConstant( f, i ) << " ";
+ Debug("inst-fmf-ei") << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i ) << " ";
}
Debug("inst-fmf-ei") << std::endl;
- for( int k=0; k<2; k++ ){
- Debug("inst-fmf-ei") << " " << ( k==0 ? "Pro" : "Con" ) << " definitions:" << std::endl;
- for( int i=0; i<(int)d_pro_con_quant[k][f].size(); i++ ){
- Debug("inst-fmf-ei") << " " << d_pro_con_quant[k][f][i] << std::endl;
- }
- }
- if( d_pro_con_quant[0][f].empty() ){
- Debug("inst-fmf-ei") << "WARNING: " << f << " has no pros for default literal definitions" << std::endl;
- }
- d_eval_failed_lits.clear();
- d_eval_failed.clear();
- d_eval_term_model.clear();
- //d_eval_term_vals.clear();
- //d_eval_term_fv_deps.clear();
- RepAlphabetIterator riter( d_quantEngine, f, this );
- increment( &riter );
-#ifdef ONE_INST_PER_QUANT_PER_ROUND
- while( !riter.isFinished() && addedLemmas==0 ){
-#else
- while( !riter.isFinished() ){
+ if( d_builder.d_quant_selection_lits[f].empty() ){
+ Debug("inst-fmf-ei") << "WARNING: " << f << " has no model literal definitions (is f clausified?)" << std::endl;
+#ifdef ME_PRINT_WARNINGS
+ Message() << "WARNING: " << f << " has no model literal definitions (is f clausified?)" << std::endl;
#endif
- InstMatch m;
- riter.getMatch( d_quantEngine, m );
- Debug("fmf-model-eval") << "* Add instantiation " << std::endl;
- riter.d_inst_tried++;
- if( d_quantEngine->addInstantiation( f, m ) ){
- addedLemmas++;
- }
- riter.increment( d_quantEngine );
- increment( &riter );
- }
- if( Debug.isOn("inst-fmf-ei") ){
- int totalInst = 1;
- for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
- totalInst = totalInst * (int)getReps()->d_type_reps[ f[0][i].getType() ].size();
- }
- Debug("inst-fmf-ei") << "Finished: " << std::endl;
- Debug("inst-fmf-ei") << " Inst Skipped: " << (totalInst-riter.d_inst_tried) << std::endl;
- Debug("inst-fmf-ei") << " Inst Tried: " << riter.d_inst_tried << std::endl;
- Debug("inst-fmf-ei") << " Inst Added: " << addedLemmas << std::endl;
- Debug("inst-fmf-ei") << " # Tests: " << riter.d_inst_tests << std::endl;
- }
- return addedLemmas;
-}
-
-void ModelEngine::registerModelBasis( Node n, Node gn ){
- if( d_model_basis.find( n )==d_model_basis.end() ){
- d_model_basis[n] = gn;
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- registerModelBasis( n[i], gn[i] );
- }
- }
-}
-
-Node ModelEngine::getArbitraryElement( TypeNode tn, std::vector< Node >& exclude ){
- Node retVal;
- if( tn==NodeManager::currentNM()->booleanType() ){
- if( exclude.empty() ){
- retVal = NodeManager::currentNM()->mkConst( false );
- }else if( exclude.size()==1 ){
- retVal = NodeManager::currentNM()->mkConst( areEqual( exclude[0], NodeManager::currentNM()->mkConst( false ) ) );
- }
- }else if( d_ra.d_type_reps.find( tn )!=d_ra.d_type_reps.end() ){
- for( int i=0; i<(int)d_ra.d_type_reps[tn].size(); i++ ){
- if( std::find( exclude.begin(), exclude.end(), d_ra.d_type_reps[tn][i] )==exclude.end() ){
- retVal = d_ra.d_type_reps[tn][i];
- break;
- }
- }
- }
- if( !retVal.isNull() ){
- return d_quantEngine->getEqualityQuery()->getRepresentative( retVal );
}else{
- return Node::null();
- }
-}
-
-Node ModelEngine::getModelBasisTerm( TypeNode tn, int i ){
- return d_ss->getCardinalityTerm( tn );
-}
-
-Node ModelEngine::getModelBasisApplyUfTerm( Node op ){
- if( d_model_basis_term.find( op )==d_model_basis_term.end() ){
- TypeNode t = op.getType();
- std::vector< Node > children;
- children.push_back( op );
- for( int i=0; i<(int)t.getNumChildren()-1; i++ ){
- children.push_back( getModelBasisTerm( t[i] ) );
- }
- d_model_basis_term[op] = NodeManager::currentNM()->mkNode( APPLY_UF, children );
- }
- return d_model_basis_term[op];
-}
-
-bool ModelEngine::isModelBasisTerm( Node op, Node n ){
- if( n.getOperator()==op ){
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( !n[i].getAttribute(ModelBasisAttribute()) ){
- return false;
- }
- }
- return true;
- }else{
- return false;
- }
-}
-
-void ModelEngine::initializeUf( Node n ){
- std::vector< Node > terms;
- collectUfTerms( n, terms );
- for( int i=0; i<(int)terms.size(); i++ ){
- initializeUfModel( terms[i].getOperator() );
- }
-}
-
-void ModelEngine::collectUfTerms( Node n, std::vector< Node >& terms ){
- if( n.getKind()==APPLY_UF ){
- terms.push_back( n );
- }
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- collectUfTerms( n[i], terms );
- }
-}
-
-void ModelEngine::initializeUfModel( Node op ){
- if( d_uf_model.find( op )==d_uf_model.end() ){
- TypeNode tn = op.getType();
- tn = tn[ (int)tn.getNumChildren()-1 ];
- if( tn==NodeManager::currentNM()->booleanType() || uf::StrongSolverTheoryUf::isRelevantType( tn ) ){
- d_uf_model[ op ] = UfModel( op, this );
- }
- }
-}
-
-void ModelEngine::makeEvalTermModel( Node n ){
- if( d_eval_term_model.find( n )==d_eval_term_model.end() ){
- makeEvalTermIndexOrder( n );
- if( !d_eval_term_use_default_model[n] ){
- Node op = n.getOperator();
- d_eval_term_model[n] = UfModelTreeOrdered( op, d_eval_term_index_order[n] );
- d_uf_model[op].makeModel( d_quantEngine, d_eval_term_model[n] );
- Debug("fmf-model-index-order") << "Make model for " << n << " : " << std::endl;
- d_eval_term_model[n].debugPrint( "fmf-model-index-order", d_quantEngine, 2 );
- }
- }
-}
-
-struct sortGetMaxVariableNum {
- std::map< Node, int > d_max_var_num;
- int computeMaxVariableNum( Node n ){
- if( n.getKind()==INST_CONSTANT ){
- return n.getAttribute(InstVarNumAttribute());
- }else if( n.hasAttribute(InstConstantAttribute()) ){
- int maxVal = -1;
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- int val = getMaxVariableNum( n[i] );
- if( val>maxVal ){
- maxVal = val;
- }
- }
- return maxVal;
- }else{
- return -1;
- }
- }
- int getMaxVariableNum( Node n ){
- std::map< Node, int >::iterator it = d_max_var_num.find( n );
- if( it==d_max_var_num.end() ){
- int num = computeMaxVariableNum( n );
- d_max_var_num[n] = num;
- return num;
- }else{
- return it->second;
- }
- }
- bool operator() (Node i,Node j) { return (getMaxVariableNum(i)<getMaxVariableNum(j));}
-};
-
-void ModelEngine::makeEvalTermIndexOrder( Node n ){
- if( d_eval_term_index_order.find( n )==d_eval_term_index_order.end() ){
- //sort arguments in order of least significant vs. most significant variable in default ordering
- std::map< Node, std::vector< int > > argIndex;
- std::vector< Node > args;
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( argIndex.find( n[i] )==argIndex.end() ){
- args.push_back( n[i] );
- }
- argIndex[n[i]].push_back( i );
- }
- sortGetMaxVariableNum sgmvn;
- std::sort( args.begin(), args.end(), sgmvn );
- for( int i=0; i<(int)args.size(); i++ ){
- for( int j=0; j<(int)argIndex[ args[i] ].size(); j++ ){
- d_eval_term_index_order[n].push_back( argIndex[ args[i] ][j] );
- }
- }
- bool useDefault = true;
- for( int i=0; i<(int)d_eval_term_index_order[n].size(); i++ ){
- if( i!=d_eval_term_index_order[n][i] ){
- useDefault = false;
- break;
- }
- }
- d_eval_term_use_default_model[n] = useDefault;
- Debug("fmf-model-index-order") << "Will consider the following index ordering for " << n << " : ";
- for( int i=0; i<(int)d_eval_term_index_order[n].size(); i++ ){
- Debug("fmf-model-index-order") << d_eval_term_index_order[n][i] << " ";
- }
- Debug("fmf-model-index-order") << std::endl;
- }
-}
-
-//void ModelEngine::processPredicate( Node f, Node p, bool phase ){
-// Node op = p.getOperator();
-// initializeUfModel( op );
-// d_uf_model[ op ].addRequirement( f, p, phase );
-//}
-//
-//void ModelEngine::processEquality( Node f, Node eq, bool phase ){
-// for( int i=0; i<2; i++ ){
-// int j = i==0 ? 1 : 0;
-// if( eq[i].getKind()==APPLY_UF && eq[i].hasAttribute(InstConstantAttribute()) ){
-// Node op = eq[i].getOperator();
-// initializeUfModel( op );
-// d_uf_model[ op ].addEqRequirement( f, eq[i], eq[j], phase );
-// }
-// }
-//}
-
-void ModelEngine::increment( RepAlphabetIterator* rai ){
- if( useModel() ){
- bool success;
- do{
- success = true;
- if( !rai->isFinished() ){
- //see if instantiation is already true in current model
- Debug("fmf-model-eval") << "Evaulating ";
- rai->debugPrintSmall("fmf-model-eval");
- //calculate represenative terms we are currently considering
- rai->calculateTerms( d_quantEngine );
- rai->d_inst_tests++;
- //if eVal is not (int)rai->d_index.size(), then the instantiation is already true in the model,
- // and eVal is the highest index in rai which we can safely iterate
- int depIndex;
- if( evaluate( rai, d_quantEngine->getCounterexampleBody( rai->d_f ), depIndex )==1 ){
- Debug("fmf-model-eval") << " Returned success with depIndex = " << depIndex << std::endl;
- //Notice() << "Returned eVal = " << eVal << "/" << rai->d_index.size() << std::endl;
- if( depIndex<(int)rai->d_index.size() ){
-#ifdef DISABLE_EVAL_SKIP_MULTIPLE
- depIndex = (int)rai->d_index.size()-1;
-#endif
- rai->increment2( d_quantEngine, depIndex );
- success = false;
+ Debug("inst-fmf-ei") << " Model literal definitions:" << std::endl;
+ for( size_t i=0; i<d_builder.d_quant_selection_lits[f].size(); i++ ){
+ Debug("inst-fmf-ei") << " " << d_builder.d_quant_selection_lits[f][i] << std::endl;
+ }
+ }
+ RepSetIterator riter( f, d_quantEngine->getModel() );
+ //set the domain for the iterator (the sufficient set of instantiations to try)
+ if( useRelInstDomain ){
+ riter.setDomain( d_rel_domain.d_quant_inst_domain[f] );
+ }
+ RepSetEvaluator reval( d_quantEngine->getModel(), &riter );
+ while( !riter.isFinished() && ( addedLemmas==0 || !optOneInstPerQuantRound() ) ){
+ d_testLemmas++;
+ if( d_builder.optUseModel() ){
+ //see if instantiation is already true in current model
+ Debug("fmf-model-eval") << "Evaluating ";
+ riter.debugPrintSmall("fmf-model-eval");
+ Debug("fmf-model-eval") << "Done calculating terms." << std::endl;
+ tests++;
+ //if evaluate(...)==1, then the instantiation is already true in the model
+ // depIndex is the index of the least significant variable that this evaluation relies upon
+ int depIndex = riter.getNumTerms()-1;
+ int eval = reval.evaluate( d_quantEngine->getTermDatabase()->getCounterexampleBody( f ), depIndex );
+ if( eval==1 ){
+ Debug("fmf-model-eval") << " Returned success with depIndex = " << depIndex << std::endl;
+ riter.increment2( depIndex );
+ }else{
+ Debug("fmf-model-eval") << " Returned " << (eval==-1 ? "failure" : "unknown") << ", depIndex = " << depIndex << std::endl;
+ InstMatch m;
+ riter.getMatch( d_quantEngine, m );
+ Debug("fmf-model-eval") << "* Add instantiation " << m << std::endl;
+ triedLemmas++;
+ d_triedLemmas++;
+ if( d_quantEngine->addInstantiation( f, m ) ){
+ addedLemmas++;
+#ifdef EVAL_FAIL_SKIP_MULTIPLE
+ if( eval==-1 ){
+ riter.increment2( depIndex );
+ }else{
+ riter.increment();
}
+#else
+ riter.increment();
+#endif
}else{
- Debug("fmf-model-eval") << " Returned failure." << std::endl;
- }
- }
- }while( !success );
- }
-}
-
-//if evaluate( rai, n, phaseReq ) = eVal,
-// if eVal = rai->d_index.size()
-// then the formula n instantiated with rai cannot be proven to be equal to phaseReq
-// otherwise,
-// each n{rai->d_index[0]/x_0...rai->d_index[eVal]/x_eVal, */x_(eVal+1) ... */x_n } is equal to phaseReq in the current model
-int ModelEngine::evaluate( RepAlphabetIterator* rai, Node n, int& depIndex ){
- ++(d_statistics.d_eval_formulas);
- //Debug("fmf-model-eval-debug") << "Evaluate " << n << " " << phaseReq << std::endl;
- if( n.getKind()==NOT ){
- int val = evaluate( rai, n[0], depIndex );
- return val==1 ? -1 : ( val==-1 ? 1 : 0 );
- }else if( n.getKind()==OR || n.getKind()==AND || n.getKind()==IMPLIES ){
- int baseVal = n.getKind()==AND ? 1 : -1;
- int eVal = baseVal;
- int posDepIndex = (int)rai->d_index.size();
- int negDepIndex = -1;
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- //evaluate subterm
- int childDepIndex;
- Node nn = ( i==0 && n.getKind()==IMPLIES ) ? n[i].notNode() : n[i];
- int eValT = evaluate( rai, nn, childDepIndex );
- if( eValT==baseVal ){
- if( eVal==baseVal ){
- if( childDepIndex>negDepIndex ){
- negDepIndex = childDepIndex;
- }
- }
- }else if( eValT==-baseVal ){
- eVal = -baseVal;
- if( childDepIndex<posDepIndex ){
- posDepIndex = childDepIndex;
- if( posDepIndex==-1 ){
- break;
- }
- }
- }else if( eValT==0 ){
- if( eVal==baseVal ){
- eVal = 0;
+ Debug("ajr-temp") << "* Failed Add instantiation " << m << std::endl;
+ riter.increment();
}
}
- }
- if( eVal!=0 ){
- depIndex = eVal==-baseVal ? posDepIndex : negDepIndex;
- return eVal;
- }else{
- return 0;
- }
- }else if( n.getKind()==IFF || n.getKind()==XOR ){
- int depIndex1;
- int eVal = evaluate( rai, n[0], depIndex1 );
- if( eVal!=0 ){
- int depIndex2;
- int eVal2 = evaluate( rai, n.getKind()==XOR ? n[1].notNode() : n[1], depIndex2 );
- if( eVal2!=0 ){
- depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
- return eVal==eVal2 ? 1 : -1;
- }
- }
- return 0;
- }else if( n.getKind()==ITE ){
- int depIndex1;
- int eVal = evaluate( rai, n[0], depIndex1 );
- if( eVal==0 ){
- //DO_THIS: evaluate children to see if they are the same value?
- return 0;
}else{
- int depIndex2;
- int eValT = evaluate( rai, n[eVal==1 ? 1 : 2], depIndex2 );
- depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
- return eValT;
- }
- }else if( n.getKind()==FORALL ){
- return 0;
- }else{
- ////if we know we will fail again, immediately return
- //if( d_eval_failed.find( n )!=d_eval_failed.end() ){
- // if( d_eval_failed[n] ){
- // return -1;
- // }
- //}
- //Debug("fmf-model-eval-debug") << "Evaluate literal " << n << std::endl;
- //this should be a literal
- Node gn = n.substitute( rai->d_ic.begin(), rai->d_ic.end(), rai->d_terms.begin(), rai->d_terms.end() );
- //Debug("fmf-model-eval-debug") << " Ground version = " << gn << std::endl;
- int retVal = 0;
- std::vector< Node > fv_deps;
- if( n.getKind()==APPLY_UF ){
- //case for boolean predicates
- Node val = evaluateTerm( n, gn, fv_deps );
- if( d_quantEngine->getEqualityQuery()->hasTerm( val ) ){
- if( areEqual( val, NodeManager::currentNM()->mkConst( true ) ) ){
- retVal = 1;
- }else{
- retVal = -1;
- }
- }
- }else if( n.getKind()==EQUAL ){
- //case for equality
- retVal = evaluateEquality( n[0], n[1], gn[0], gn[1], fv_deps );
- }
- if( retVal!=0 ){
- int maxIndex = -1;
- for( int i=0; i<(int)fv_deps.size(); i++ ){
- int index = rai->d_var_order[ fv_deps[i].getAttribute(InstVarNumAttribute()) ];
- if( index>maxIndex ){
- maxIndex = index;
- if( index==(int)rai->d_index.size()-1 ){
- break;
- }
- }
+ InstMatch m;
+ riter.getMatch( d_quantEngine, m );
+ Debug("fmf-model-eval") << "* Add instantiation " << std::endl;
+ triedLemmas++;
+ d_triedLemmas++;
+ if( d_quantEngine->addInstantiation( f, m ) ){
+ addedLemmas++;
}
- Debug("fmf-model-eval-debug") << "Evaluate literal: return " << retVal << ", depends = " << maxIndex << std::endl;
- depIndex = maxIndex;
+ riter.increment();
}
- return retVal;
- }
-}
-
-int ModelEngine::evaluateEquality( Node n1, Node n2, Node gn1, Node gn2, std::vector< Node >& fv_deps ){
- ++(d_statistics.d_eval_eqs);
- Debug("fmf-model-eval-debug") << "Evaluate equality: " << std::endl;
- Debug("fmf-model-eval-debug") << " " << n1 << " = " << n2 << std::endl;
- Debug("fmf-model-eval-debug") << " " << gn1 << " = " << gn2 << std::endl;
- Node val1 = evaluateTerm( n1, gn1, fv_deps );
- Node val2 = evaluateTerm( n2, gn2, fv_deps );
- Debug("fmf-model-eval-debug") << " Values : ";
- printRepresentative( "fmf-model-eval-debug", d_quantEngine, val1 );
- Debug("fmf-model-eval-debug") << " = ";
- printRepresentative( "fmf-model-eval-debug", d_quantEngine, val2 );
- Debug("fmf-model-eval-debug") << std::endl;
- int retVal = 0;
- if( areEqual( val1, val2 ) ){
- retVal = 1;
- }else if( areDisequal( val1, val2 ) ){
- retVal = -1;
- }
- if( retVal!=0 ){
- Debug("fmf-model-eval-debug") << " ---> Success, value = " << (retVal==1) << std::endl;
- }else{
- Debug("fmf-model-eval-debug") << " ---> Failed" << std::endl;
- }
- Debug("fmf-model-eval-debug") << " Value depends on variables: ";
- for( int i=0; i<(int)fv_deps.size(); i++ ){
- Debug("fmf-model-eval-debug") << fv_deps[i] << " ";
}
- Debug("fmf-model-eval-debug") << std::endl;
- return retVal;
-}
-
-Node ModelEngine::evaluateTerm( Node n, Node gn, std::vector< Node >& fv_deps ){
- if( n.hasAttribute(InstConstantAttribute()) ){
- if( n.getKind()==INST_CONSTANT ){
- fv_deps.push_back( n );
- return gn;
- //}else if( d_eval_term_fv_deps.find( n )!=d_eval_term_fv_deps.end() &&
- // d_eval_term_fv_deps[n].find( gn )!=d_eval_term_fv_deps[n].end() ){
- // fv_deps.insert( fv_deps.end(), d_eval_term_fv_deps[n][gn].begin(), d_eval_term_fv_deps[n][gn].end() );
- // return d_eval_term_vals[gn];
- }else{
- //Debug("fmf-model-eval-debug") << "Evaluate term " << n << " (" << gn << ")" << std::endl;
- //first we must evaluate the arguments
- Node val = gn;
- if( n.getKind()==APPLY_UF ){
- Node op = gn.getOperator();
- //if it is a defined UF, then consult the interpretation
- Node gnn = gn;
- ++(d_statistics.d_eval_uf_terms);
- int depIndex = 0;
- //first we must evaluate the arguments
- bool childrenChanged = false;
- std::vector< Node > children;
- children.push_back( op );
- std::map< int, std::vector< Node > > children_var_deps;
- //for each argument, calculate its value, and the variables its value depends upon
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- Node nn = evaluateTerm( n[i], gn[i], children_var_deps[i] );
- children.push_back( nn );
- childrenChanged = childrenChanged || nn!=gn[i];
- }
- //remake gn if changed
- if( childrenChanged ){
- gnn = NodeManager::currentNM()->mkNode( APPLY_UF, children );
- }
- if( d_uf_model.find( op )!=d_uf_model.end() ){
-#ifdef USE_INDEX_ORDERING
- //make the term model specifically for n
- makeEvalTermModel( n );
- //now, consult the model
- if( d_eval_term_use_default_model[n] ){
- val = d_uf_model[op].d_tree.getValue( d_quantEngine, gnn, depIndex );
- }else{
- val = d_eval_term_model[ n ].getValue( d_quantEngine, gnn, depIndex );
- }
- //Debug("fmf-model-eval-debug") << "Evaluate term " << n << " (" << gn << ", " << gnn << ")" << std::endl;
- //d_eval_term_model[ n ].debugPrint("fmf-model-eval-debug", d_quantEngine );
- Assert( !val.isNull() );
-#else
- //now, consult the model
- val = d_uf_model[op].d_tree.getValue( d_quantEngine, gnn, depIndex );
-#endif
- }else{
- d_eval_term_use_default_model[n] = true;
- val = gnn;
- depIndex = (int)n.getNumChildren();
- }
- Debug("fmf-model-eval-debug") << "Evaluate term " << n << " = " << gn << " = " << gnn << " = ";
- printRepresentative( "fmf-model-eval-debug", d_quantEngine, val );
- Debug("fmf-model-eval-debug") << ", depIndex = " << depIndex << std::endl;
- if( !val.isNull() ){
-#ifdef USE_INDEX_ORDERING
- for( int i=0; i<depIndex; i++ ){
- int index = d_eval_term_use_default_model[n] ? i : d_eval_term_index_order[n][i];
- Debug("fmf-model-eval-debug") << "Add variables from " << index << "..." << std::endl;
- fv_deps.insert( fv_deps.end(), children_var_deps[index].begin(),
- children_var_deps[index].end() );
- }
-#else
- //calculate the free variables that the value depends on : take those in children_var_deps[0...depIndex-1]
- for( std::map< int, std::vector< Node > >::iterator it = children_var_deps.begin(); it != children_var_deps.end(); ++it ){
- if( it->first<depIndex ){
- fv_deps.insert( fv_deps.end(), it->second.begin(), it->second.end() );
- }
- }
-#endif
- }
- ////cache the result
- //d_eval_term_vals[gn] = val;
- //d_eval_term_fv_deps[n][gn].insert( d_eval_term_fv_deps[n][gn].end(), fv_deps.begin(), fv_deps.end() );
+ d_statistics.d_eval_formulas += reval.d_eval_formulas;
+ d_statistics.d_eval_eqs += reval.d_eval_eqs;
+ d_statistics.d_eval_uf_terms += reval.d_eval_uf_terms;
+ int totalInst = 1;
+ int relevantInst = 1;
+ for( size_t i=0; i<f[0].getNumChildren(); i++ ){
+ totalInst = totalInst * (int)d_quantEngine->getModel()->d_ra.d_type_reps[ f[0][i].getType() ].size();
+ relevantInst = relevantInst * (int)riter.d_domain[i].size();
+ }
+ d_totalLemmas += totalInst;
+ d_relevantLemmas += relevantInst;
+ Debug("inst-fmf-ei") << "Finished: " << std::endl;
+ Debug("inst-fmf-ei") << " Inst Total: " << totalInst << std::endl;
+ Debug("inst-fmf-ei") << " Inst Relevant: " << relevantInst << std::endl;
+ Debug("inst-fmf-ei") << " Inst Tried: " << triedLemmas << std::endl;
+ Debug("inst-fmf-ei") << " Inst Added: " << addedLemmas << std::endl;
+ Debug("inst-fmf-ei") << " # Tests: " << tests << std::endl;
+///-----------
+#ifdef ME_PRINT_WARNINGS
+ if( addedLemmas>1000 ){
+ Notice() << "WARNING: many instantiations produced for " << f << ": " << std::endl;
+ Notice() << " Inst Total: " << totalInst << std::endl;
+ Notice() << " Inst Relevant: " << totalRelevant << std::endl;
+ Notice() << " Inst Tried: " << triedLemmas << std::endl;
+ Notice() << " Inst Added: " << addedLemmas << std::endl;
+ Notice() << " # Tests: " << tests << std::endl;
+ Notice() << std::endl;
+ if( !d_builder.d_quant_selection_lits[f].empty() ){
+ Notice() << " Model literal definitions:" << std::endl;
+ for( size_t i=0; i<d_builder.d_quant_selection_lits[f].size(); i++ ){
+ Notice() << " " << d_builder.d_quant_selection_lits[f][i] << std::endl;
}
- return val;
+ Notice() << std::endl;
}
- }else{
- return n;
- }
-}
-
-void ModelEngine::clearEvalFailed( int index ){
- for( int i=0; i<(int)d_eval_failed_lits[index].size(); i++ ){
- d_eval_failed[ d_eval_failed_lits[index][i] ] = false;
}
- d_eval_failed_lits[index].clear();
-}
-
-bool ModelEngine::areEqual( Node a, Node b ){
- return d_quantEngine->getEqualityQuery()->areEqual( a, b );
-}
-
-bool ModelEngine::areDisequal( Node a, Node b ){
- return d_quantEngine->getEqualityQuery()->areDisequal( a, b );
+#endif
+///-----------
+ return addedLemmas;
}
void ModelEngine::debugPrint( const char* c ){
- Debug( c ) << "---Current Model---" << std::endl;
- Debug( c ) << "Representatives: " << std::endl;
- d_ra.debugPrint( c, d_quantEngine );
Debug( c ) << "Quantifiers: " << std::endl;
- for( int i=0; i<(int)d_quantEngine->getNumAssertedQuantifiers(); i++ ){
- Node f = d_quantEngine->getAssertedQuantifier( i );
+ for( int i=0; i<(int)d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
Debug( c ) << " ";
- if( d_quant_sat.find( f )!=d_quant_sat.end() ){
+ if( d_builder.d_quant_sat.find( f )!=d_builder.d_quant_sat.end() ){
Debug( c ) << "*SAT* ";
}else{
Debug( c ) << " ";
}
Debug( c ) << f << std::endl;
}
- Debug( c ) << "Functions: " << std::endl;
- for( std::map< Node, UfModel >::iterator it = d_uf_model.begin(); it != d_uf_model.end(); ++it ){
- it->second.debugPrint( c );
- Debug( c ) << std::endl;
- }
+ //d_quantEngine->getModel()->debugPrint( c );
}
ModelEngine::Statistics::Statistics():
d_inst_rounds("ModelEngine::Inst_Rounds", 0),
- d_pre_sat_quant("ModelEngine::Status_quant_pre_sat", 0),
- d_pre_nsat_quant("ModelEngine::Status_quant_pre_non_sat", 0),
d_eval_formulas("ModelEngine::Eval_Formulas", 0 ),
d_eval_eqs("ModelEngine::Eval_Equalities", 0 ),
d_eval_uf_terms("ModelEngine::Eval_Uf_Terms", 0 ),
@@ -1380,8 +663,6 @@ ModelEngine::Statistics::Statistics():
d_num_quants_init_fail("ModelEngine::Num_Quants_No_Basis", 0 )
{
StatisticsRegistry::registerStat(&d_inst_rounds);
- StatisticsRegistry::registerStat(&d_pre_sat_quant);
- StatisticsRegistry::registerStat(&d_pre_nsat_quant);
StatisticsRegistry::registerStat(&d_eval_formulas);
StatisticsRegistry::registerStat(&d_eval_eqs);
StatisticsRegistry::registerStat(&d_eval_uf_terms);
@@ -1391,11 +672,11 @@ ModelEngine::Statistics::Statistics():
ModelEngine::Statistics::~Statistics(){
StatisticsRegistry::unregisterStat(&d_inst_rounds);
- StatisticsRegistry::unregisterStat(&d_pre_sat_quant);
- StatisticsRegistry::unregisterStat(&d_pre_nsat_quant);
StatisticsRegistry::unregisterStat(&d_eval_formulas);
StatisticsRegistry::unregisterStat(&d_eval_eqs);
StatisticsRegistry::unregisterStat(&d_eval_uf_terms);
StatisticsRegistry::unregisterStat(&d_num_quants_init);
StatisticsRegistry::unregisterStat(&d_num_quants_init_fail);
}
+
+
diff --git a/src/theory/quantifiers/model_engine.h b/src/theory/quantifiers/model_engine.h
index cf6691918..b01139826 100644
--- a/src/theory/quantifiers/model_engine.h
+++ b/src/theory/quantifiers/model_engine.h
@@ -11,7 +11,7 @@
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
- ** \brief Instantiation Engine classes
+ ** \brief Model Engine classes
**/
#include "cvc4_private.h"
@@ -21,6 +21,9 @@
#include "theory/quantifiers_engine.h"
#include "theory/quantifiers/theory_quantifiers.h"
+#include "theory/model.h"
+#include "theory/uf/theory_uf_model.h"
+#include "theory/quantifiers/relevant_domain.h"
namespace CVC4 {
namespace theory {
@@ -31,312 +34,87 @@ namespace uf{
namespace quantifiers {
-/** this class stores a representative alphabet */
-class RepAlphabet {
-public:
- RepAlphabet(){}
- RepAlphabet( RepAlphabet& ra, QuantifiersEngine* qe );
- ~RepAlphabet(){}
- std::map< TypeNode, std::vector< Node > > d_type_reps;
- std::map< Node, int > d_tmap;
- /** clear the alphabet */
- void clear(){
- d_type_reps.clear();
- d_tmap.clear();
- }
- /** set the representatives for type */
- void set( TypeNode t, std::vector< Node >& reps );
- /** returns index in d_type_reps for node n */
- int getIndexFor( Node n ) { return d_tmap.find( n )!=d_tmap.end() ? d_tmap[n] : -1; }
- /** debug print */
- void debugPrint( const char* c, QuantifiersEngine* qe );
-};
-
-class ModelEngine;
-
-/** this class iterates over a RepAlphabet */
-class RepAlphabetIterator {
-private:
- void initialize( QuantifiersEngine* qe, Node f, ModelEngine* model );
-public:
- RepAlphabetIterator( QuantifiersEngine* qe, Node f, ModelEngine* model );
- RepAlphabetIterator( QuantifiersEngine* qe, Node f, ModelEngine* model, std::vector< int >& indexOrder );
- ~RepAlphabetIterator(){}
- //pointer to quantifier
- Node d_f;
- //pointer to model
- ModelEngine* d_model;
- //index we are considering
- std::vector< int > d_index;
- //ordering for variables we are indexing over
- // for example, given reps = { a, b } and quantifier forall( x, y, z ) P( x, y, z ) with d_index_order = { 2, 0, 1 },
- // then we consider instantiations in this order:
- // a/x a/y a/z
- // a/x b/y a/z
- // b/x a/y a/z
- // b/x b/y a/z
- // ...
- std::vector< int > d_index_order;
- //variables to index they are considered at
- // for example, if d_index_order = { 2, 0, 1 }
- // then d_var_order = { 0 -> 1, 1 -> 2, 2 -> 0 }
- std::map< int, int > d_var_order;
- //the instantiation constants of d_f
- std::vector< Node > d_ic;
- //the current terms we are considering
- std::vector< Node > d_terms;
-public:
- /** increment the iterator */
- void increment2( QuantifiersEngine* qe, int counter );
- void increment( QuantifiersEngine* qe );
- /** is the iterator finished? */
- bool isFinished();
- /** produce the match that this iterator represents */
- void getMatch( QuantifiersEngine* qe, InstMatch& m );
- /** get the i_th term we are considering */
- Node getTerm( int i );
- /** get the number of terms we are considering */
- int getNumTerms() { return d_f[0].getNumChildren(); }
- /** refresh d_term to be current with d_index */
- void calculateTerms( QuantifiersEngine* qe );
- /** debug print */
- void debugPrint( const char* c );
- void debugPrintSmall( const char* c );
- //for debugging
- int d_inst_tried;
- int d_inst_tests;
-};
-
-
-class UfModelTree
-{
-public:
- UfModelTree(){}
- /** the data */
- std::map< Node, UfModelTree > d_data;
- /** the value of this tree node (if all paths lead to same value) */
- Node d_value;
-public:
- //is this model tree empty?
- bool isEmpty() { return d_data.empty(); }
- //clear
- void clear(){
- d_data.clear();
- d_value = Node::null();
- }
- /** setValue function
- *
- * For each argument of n with ModelBasisAttribute() set to true will be considered default arguments if ground=false
- *
- */
- void setValue( QuantifiersEngine* qe, Node n, Node v, std::vector< int >& indexOrder, bool ground, int argIndex );
- /** getValue function
- *
- * returns $val, the value of ground term n
- * Say n is f( t_0...t_n )
- * depIndex is the index for which every term of the form f( t_0 ... t_depIndex, *,... * ) is equal to $val
- * for example, if g( x_0, x_1, x_2 ) := lambda x_0 x_1 x_2. if( x_1==a ) b else c,
- * then g( a, a, a ) would return b with depIndex = 1
- * If ground = true, we are asking whether the term n is constant (assumes that all non-model basis arguments are ground)
- *
- */
- Node getValue( QuantifiersEngine* qe, Node n, std::vector< int >& indexOrder, int& depIndex, int argIndex );
- ///** getConstant Value function
- // *
- // * given term n, where n may contain model basis arguments
- // * if n is constant for its entire domain, then this function returns the value of its domain
- // * otherwise, it returns null
- // * for example, if f( x_0, x_1 ) := if( x_0 = a ) b else if( x_1 = a ) a else b,
- // * then f( a, e ) would return b, while f( e, a ) would return null
- // *
- // */
- Node getConstantValue( QuantifiersEngine* qe, Node n, std::vector< int >& indexOrder, int argIndex );
- /** simplify function */
- void simplify( Node op, Node defaultVal, int argIndex );
- // is total ?
- bool isTotal( Node op, int argIndex );
-public:
- void debugPrint( const char* c, QuantifiersEngine* qe, std::vector< int >& indexOrder, int ind = 0, int arg = 0 );
-};
-class UfModelTreeOrdered
+//the model builder
+class ModelEngineBuilder : public TheoryEngineModelBuilder
{
-private:
- Node d_op;
- std::vector< int > d_index_order;
- UfModelTree d_tree;
-public:
- UfModelTreeOrdered(){}
- UfModelTreeOrdered( Node op ) : d_op( op ){
- TypeNode tn = d_op.getType();
- for( int i=0; i<(int)(tn.getNumChildren()-1); i++ ){
- d_index_order.push_back( i );
- }
- }
- UfModelTreeOrdered( Node op, std::vector< int >& indexOrder ) : d_op( op ){
- d_index_order.insert( d_index_order.end(), indexOrder.begin(), indexOrder.end() );
- }
- bool isEmpty() { return d_tree.isEmpty(); }
- void clear() { d_tree.clear(); }
- void setValue( QuantifiersEngine* qe, Node n, Node v, bool ground = true ){
- d_tree.setValue( qe, n, v, d_index_order, ground, 0 );
- }
- Node getValue( QuantifiersEngine* qe, Node n, int& depIndex ){
- return d_tree.getValue( qe, n, d_index_order, depIndex, 0 );
- }
- Node getConstantValue( QuantifiersEngine* qe, Node n ) {
- return d_tree.getConstantValue( qe, n, d_index_order, 0 );
- }
- void simplify() { d_tree.simplify( d_op, Node::null(), 0 ); }
- bool isTotal() { return d_tree.isTotal( d_op, 0 ); }
-public:
- void debugPrint( const char* c, QuantifiersEngine* qe, int ind = 0 ){
- d_tree.debugPrint( c, qe, d_index_order, ind );
- }
-};
-
-class UfModel
-{
-//public:
- //std::map< Node, std::vector< Node > > d_reqs[2];
- //std::map< Node, std::map< Node, std::vector< Node > > > d_eq_reqs[2];
- ///** add requirement */
- //void addRequirement( Node f, Node p, bool phase ) { d_reqs[ phase ? 1 : 0 ][ f ].push_back( p ); }
- ///** add equality requirement */
- //void addEqRequirement( Node f, Node t, Node te, bool phase ) { d_eq_reqs[ phase ? 1 : 0 ][ f ][ t ].push_back( te ); }
-private:
- Node d_op;
- ModelEngine* d_me;
- std::vector< Node > d_ground_asserts;
- std::vector< Node > d_ground_asserts_reps;
- bool d_model_constructed;
- //store for set values
- std::map< Node, Node > d_set_values[2];
- // preferences for default values
- std::vector< Node > d_values;
- std::map< Node, std::vector< Node > > d_value_pro_con[2];
- /** set value */
- void setValue( Node n, Node v, bool ground = true );
- /** set model */
- void setModel();
- /** clear model */
- void clearModel();
-public:
- UfModel(){}
- UfModel( Node op, ModelEngine* qe );
- ~UfModel(){}
- //data structure that stores the model
- UfModelTreeOrdered d_tree;
- //quantifiers that are satisfied because of the constant definition of d_op
- bool d_reconsider_model;
-public:
- /** debug print */
- void debugPrint( const char* c );
- /** get constant value */
- Node getConstantValue( QuantifiersEngine* qe, Node n );
- /** is empty */
- bool isEmpty() { return d_ground_asserts.empty(); }
- /** is constant */
- bool isConstant();
-public:
- /** build model */
- void buildModel();
- /** make model */
- void makeModel( QuantifiersEngine* qe, UfModelTreeOrdered& tree );
-public:
- /** set value preference */
- void setValuePreference( Node f, Node n, bool isPro );
+protected:
+ //quantifiers engine
+ QuantifiersEngine* d_qe;
+ //map from operators to model preference data
+ std::map< Node, uf::UfModelPreferenceData > d_uf_prefs;
+ /** choose representative */
+ Node chooseRepresentative( TheoryModel* tm, Node eqc );
+ /** use constants for representatives */
+ void processBuildModel( TheoryModel* m );
+ //analyze quantifiers
+ void analyzeQuantifiers( FirstOrderModel* fm );
+ //build model
+ void finishBuildModel( FirstOrderModel* fm );
+ //theory-specific build models
+ void finishBuildModelUf( FirstOrderModel* fm, uf::UfModel& model );
+ //do InstGen techniques for quantifier, return number of lemmas produced
+ int doInstGen( FirstOrderModel* fm, Node f );
+public:
+ ModelEngineBuilder( QuantifiersEngine* qe );
+ virtual ~ModelEngineBuilder(){}
+public:
+ /** number of lemmas generated while building model */
+ int d_addedLemmas;
+ //map from quantifiers to if are constant SAT
+ std::map< Node, bool > d_quant_sat;
+ //map from quantifiers to the instantiation literals that their model is dependent upon
+ std::map< Node, std::vector< Node > > d_quant_selection_lits;
+public:
+ //map from quantifiers to model basis match
+ std::map< Node, InstMatch > d_quant_basis_match;
+ //options
+ bool optUseModel();
+ bool optInstGen();
+ bool optOneQuantPerRoundInstGen();
+ /** statistics class */
+ class Statistics {
+ public:
+ IntStat d_pre_sat_quant;
+ IntStat d_pre_nsat_quant;
+ Statistics();
+ ~Statistics();
+ };
+ Statistics d_statistics;
};
-
-
-
class ModelEngine : public QuantifiersModule
{
- friend class UfModel;
- friend class RepAlphabetIterator;
+ friend class uf::UfModel;
+ friend class RepSetIterator;
private:
- TheoryQuantifiers* d_th;
- QuantifiersEngine* d_quantEngine;
- uf::StrongSolverTheoryUf* d_ss;
+ /** builder class */
+ ModelEngineBuilder d_builder;
+private: //data maintained globally:
//which quantifiers have been initialized
std::map< Node, bool > d_quant_init;
- //map from ops to model basis terms
- std::map< Node, Node > d_model_basis_term;
- //map from instantiation terms to their model basis equivalent
- std::map< Node, Node > d_model_basis;
- //the model we are working with
- RepAlphabet d_ra;
- std::map< Node, UfModel > d_uf_model;
- ////map from model basis terms to quantifiers that are pro/con their definition
- //std::map< Node, std::vector< Node > > d_quant_pro_con[2];
- //map from quantifiers to model basis terms that are pro the definition of
- std::map< Node, std::vector< Node > > d_pro_con_quant[2];
- //map from quantifiers to if are constant SAT
- std::map< Node, bool > d_quant_sat;
+private: //analysis of current model:
+ //relevant domain
+ RelevantDomain d_rel_domain;
private:
- int evaluate( RepAlphabetIterator* rai, Node n, int& depIndex );
- int evaluateEquality( Node n1, Node n2, Node gn1, Node gn2, std::vector< Node >& fv_deps );
- Node evaluateTerm( Node n, Node gn, std::vector< Node >& fv_deps );
- //temporary storing which literals have failed
- void clearEvalFailed( int index );
- std::map< Node, bool > d_eval_failed;
- std::map< int, std::vector< Node > > d_eval_failed_lits;
- ////temporary storing for values/free variable dependencies
- //std::map< Node, Node > d_eval_term_vals;
- //std::map< Node, std::map< Node, std::vector< Node > > > d_eval_term_fv_deps;
+ //options
+ bool optOneInstPerQuantRound();
+ bool optUseRelevantDomain();
+ bool optOneQuantPerRound();
private:
- //map from terms to the models used to calculate their value
- std::map< Node, UfModelTreeOrdered > d_eval_term_model;
- std::map< Node, bool > d_eval_term_use_default_model;
- void makeEvalTermModel( Node n );
- //index ordering to use for each term
- std::map< Node, std::vector< int > > d_eval_term_index_order;
- int getMaxVariableNum( int n );
- void makeEvalTermIndexOrder( Node n );
-public:
- void increment( RepAlphabetIterator* rai );
+ //initialize quantifiers, return number of lemmas produced
+ int initializeQuantifier( Node f );
+ //exhaustively instantiate quantifier (possibly using mbqi), return number of lemmas produced
+ int exhaustiveInstantiate( Node f, bool useRelInstDomain = false );
private:
- //queries about equality
- bool areEqual( Node a, Node b );
- bool areDisequal( Node a, Node b );
-private:
- bool useModel();
-private:
- //initialize quantifiers, return false if lemma needed to be added
- bool initializeQuantifier( Node f );
- //build representatives
- void buildRepresentatives();
- //initialize model
- void initializeModel();
- //analyze quantifiers
- void analyzeQuantifiers();
- //instantiate quantifier, return number of lemmas produced
- int instantiateQuantifier( Node f );
-private:
- //register instantiation terms with their corresponding model basis terms
- void registerModelBasis( Node n, Node gn );
- //for building UF model
- void initializeUf( Node n );
- void collectUfTerms( Node n, std::vector< Node >& terms );
- void initializeUfModel( Node op );
- //void processPredicate( Node f, Node p, bool phase );
- //void processEquality( Node f, Node eq, bool phase );
+ //temporary statistics
+ int d_triedLemmas;
+ int d_testLemmas;
+ int d_totalLemmas;
+ int d_relevantLemmas;
public:
- ModelEngine( TheoryQuantifiers* th );
+ ModelEngine( QuantifiersEngine* qe );
~ModelEngine(){}
- //get quantifiers engine
- QuantifiersEngine* getQuantifiersEngine() { return d_quantEngine; }
- //get representatives
- RepAlphabet* getReps() { return &d_ra; }
- //get arbitrary element
- Node getArbitraryElement( TypeNode tn, std::vector< Node >& exclude );
- //get model basis term
- Node getModelBasisTerm( TypeNode tn, int i = 0 );
- //get model basis term for op
- Node getModelBasisApplyUfTerm( Node op );
- //is model basis term for op
- bool isModelBasisTerm( Node op, Node n );
public:
void check( Theory::Effort e );
void registerQuantifier( Node f );
@@ -349,8 +127,6 @@ public:
class Statistics {
public:
IntStat d_inst_rounds;
- IntStat d_pre_sat_quant;
- IntStat d_pre_nsat_quant;
IntStat d_eval_formulas;
IntStat d_eval_eqs;
IntStat d_eval_uf_terms;
diff --git a/src/theory/quantifiers/relevant_domain.cpp b/src/theory/quantifiers/relevant_domain.cpp
new file mode 100644
index 000000000..e7ae1d1c7
--- /dev/null
+++ b/src/theory/quantifiers/relevant_domain.cpp
@@ -0,0 +1,173 @@
+/********************* */
+/*! \file relevant_domain.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 relevant domain class
+ **/
+
+#include "theory/quantifiers_engine.h"
+#include "theory/quantifiers/relevant_domain.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/first_order_model.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+
+RelevantDomain::RelevantDomain( FirstOrderModel* m ) : d_model( m ){
+
+}
+
+void RelevantDomain::compute(){
+ d_quant_inst_domain.clear();
+ for( int i=0; i<(int)d_model->getNumAssertedQuantifiers(); i++ ){
+ Node f = d_model->getAssertedQuantifier( i );
+ 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 ){
+ 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];
+ //add arguments to domain
+ for( int j=0; j<(int)n.getNumChildren(); j++ ){
+ if( d_model->d_ra.hasType( n[j].getType() ) ){
+ Node ra = d_model->getRepresentative( n[j] );
+ int raIndex = d_model->d_ra.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 );
+ }
+ }
+ }
+ //add to range
+ Node r = it->second.d_ground_asserts_reps[i];
+ int raIndex = d_model->d_ra.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 );
+ }
+ }
+ }
+ //find fixed point for relevant domain computation
+ bool success;
+ do{
+ success = true;
+ for( int i=0; i<(int)d_model->getNumAssertedQuantifiers(); i++ ){
+ Node f = d_model->getAssertedQuantifier( i );
+ //compute the domain of relevant instantiations (rule 3 of complete instantiation, essentially uf fragment)
+ if( computeRelevantInstantiationDomain( d_model->getTermDatabase()->getCounterexampleBody( f ), Node::null(), -1, d_quant_inst_domain[f] ) ){
+ success = false;
+ }
+ //extend the possible domain for functions (rule 2 of complete instantiation, essentially uf fragment)
+ RepDomain range;
+ if( extendFunctionDomains( d_model->getTermDatabase()->getCounterexampleBody( f ), range ) ){
+ success = false;
+ }
+ }
+ }while( !success );
+}
+
+bool RelevantDomain::computeRelevantInstantiationDomain( Node n, Node parent, int arg, std::vector< RepDomain >& rd ){
+ bool domainChanged = false;
+ if( n.getKind()==INST_CONSTANT ){
+ bool domainSet = false;
+ int vi = n.getAttribute(InstVarNumAttribute());
+ Assert( !parent.isNull() );
+ if( parent.getKind()==APPLY_UF ){
+ //if the child of APPLY_UF term f( ... ), only consider the active domain of f at given argument
+ Node op = parent.getOperator();
+ if( d_active_domain.find( op )!=d_active_domain.end() ){
+ for( size_t i=0; i<d_active_domain[op][arg].size(); i++ ){
+ int d = d_active_domain[op][arg][i];
+ if( std::find( rd[vi].begin(), rd[vi].end(), d )==rd[vi].end() ){
+ rd[vi].push_back( d );
+ domainChanged = true;
+ }
+ }
+ domainSet = true;
+ }
+ }
+ 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() ){
+ rd[vi].clear();
+ for( size_t i=0; i<d_model->d_ra.d_type_reps[tn].size(); i++ ){
+ rd[vi].push_back( i );
+ domainChanged = true;
+ }
+ }
+ }else{
+ //infinite domain?
+ }
+ }
+ }else{
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( computeRelevantInstantiationDomain( n[i], n, i, rd ) ){
+ domainChanged = true;
+ }
+ }
+ }
+ return domainChanged;
+}
+
+bool RelevantDomain::extendFunctionDomains( Node n, RepDomain& range ){
+ if( n.getKind()==INST_CONSTANT ){
+ Node f = n.getAttribute(InstConstantAttribute());
+ int var = n.getAttribute(InstVarNumAttribute());
+ range.insert( range.begin(), d_quant_inst_domain[f][var].begin(), d_quant_inst_domain[f][var].end() );
+ return false;
+ }else{
+ Node op;
+ if( n.getKind()==APPLY_UF ){
+ op = n.getOperator();
+ }
+ bool domainChanged = false;
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ RepDomain childRange;
+ if( extendFunctionDomains( n[i], childRange ) ){
+ domainChanged = true;
+ }
+ if( n.getKind()==APPLY_UF ){
+ if( d_active_domain.find( op )!=d_active_domain.end() ){
+ for( int j=0; j<(int)childRange.size(); j++ ){
+ int v = childRange[j];
+ if( std::find( d_active_domain[op][i].begin(), d_active_domain[op][i].end(), v )==d_active_domain[op][i].end() ){
+ d_active_domain[op][i].push_back( v );
+ domainChanged = true;
+ }
+ }
+ }else{
+ //do this?
+ }
+ }
+ }
+ //get the range
+ if( n.hasAttribute(InstConstantAttribute()) ){
+ if( n.getKind()==APPLY_UF && d_active_range.find( op )!=d_active_range.end() ){
+ range.insert( range.end(), d_active_range[op].begin(), d_active_range[op].end() );
+ }else{
+ //infinite range?
+ }
+ }else{
+ Node r = d_model->getRepresentative( n );
+ range.push_back( d_model->d_ra.getIndexFor( r ) );
+ }
+ return domainChanged;
+ }
+} \ No newline at end of file
diff --git a/src/theory/quantifiers/relevant_domain.h b/src/theory/quantifiers/relevant_domain.h
new file mode 100644
index 000000000..362a39d6a
--- /dev/null
+++ b/src/theory/quantifiers/relevant_domain.h
@@ -0,0 +1,54 @@
+/********************* */
+/*! \file relevant_domain.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 relevant domain class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__RELEVANT_DOMAIN_H
+#define __CVC4__RELEVANT_DOMAIN_H
+
+#include "theory/quantifiers/first_order_model.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+class RelevantDomain
+{
+private:
+ FirstOrderModel* d_model;
+
+ //the domain of the arguments for each operator
+ std::map< Node, std::map< int, RepDomain > > d_active_domain;
+ //the range for each operator
+ std::map< Node, RepDomain > d_active_range;
+ //for computing relevant instantiation domain, return true if changed
+ bool computeRelevantInstantiationDomain( Node n, Node parent, int arg, std::vector< RepDomain >& rd );
+ //for computing extended
+ bool extendFunctionDomains( Node n, RepDomain& range );
+public:
+ RelevantDomain( FirstOrderModel* m );
+ virtual ~RelevantDomain(){}
+ //compute the relevant domain
+ void compute();
+ //relevant instantiation domain for each quantifier
+ std::map< Node, std::vector< RepDomain > > d_quant_inst_domain;
+};
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/rep_set_iterator.cpp b/src/theory/quantifiers/rep_set_iterator.cpp
new file mode 100644
index 000000000..02041480f
--- /dev/null
+++ b/src/theory/quantifiers/rep_set_iterator.cpp
@@ -0,0 +1,523 @@
+/********************* */
+/*! \file rep_set_iterator.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 relevant domain class
+ **/
+
+#include "theory/quantifiers/rep_set_iterator.h"
+#include "theory/quantifiers/model_engine.h"
+#include "theory/quantifiers/term_database.h"
+
+#define USE_INDEX_ORDERING
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+
+RepSetIterator::RepSetIterator( Node f, FirstOrderModel* model ) : d_f( f ), d_model( model ){
+ //store instantiation constants
+ for( size_t i=0; i<f[0].getNumChildren(); i++ ){
+ d_index.push_back( 0 );
+ }
+ for( size_t i=0; i<f[0].getNumChildren(); i++ ){
+ //store default index order
+ d_index_order.push_back( i );
+ 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 );
+ }
+ }
+}
+
+void RepSetIterator::setIndexOrder( std::vector< int >& indexOrder ){
+ d_index_order.clear();
+ d_index_order.insert( d_index_order.begin(), indexOrder.begin(), indexOrder.end() );
+ //make the d_var_order mapping
+ for( int i=0; i<(int)d_index_order.size(); i++ ){
+ d_var_order[d_index_order[i]] = i;
+ }
+}
+
+void RepSetIterator::setDomain( std::vector< RepDomain >& domain ){
+ d_domain.clear();
+ d_domain.insert( d_domain.begin(), domain.begin(), domain.end() );
+ //we are done if a domain is empty
+ for( int i=0; i<(int)d_domain.size(); i++ ){
+ if( d_domain[i].empty() ){
+ d_index.clear();
+ }
+ }
+}
+
+void RepSetIterator::increment2( int counter ){
+ Assert( !isFinished() );
+#ifdef DISABLE_EVAL_SKIP_MULTIPLE
+ counter = (int)d_index.size()-1;
+#endif
+ //increment d_index
+ while( counter>=0 && d_index[counter]==(int)(d_domain[counter].size()-1) ){
+ counter--;
+ }
+ if( counter==-1 ){
+ d_index.clear();
+ }else{
+ for( int i=(int)d_index.size()-1; i>counter; i-- ){
+ d_index[i] = 0;
+ //d_model->clearEvalFailed( i );
+ }
+ d_index[counter]++;
+ //d_model->clearEvalFailed( counter );
+ }
+}
+
+void RepSetIterator::increment(){
+ if( !isFinished() ){
+ increment2( (int)d_index.size()-1 );
+ }
+}
+
+bool RepSetIterator::isFinished(){
+ return d_index.empty();
+}
+
+void RepSetIterator::getMatch( QuantifiersEngine* qe, InstMatch& m ){
+ for( int i=0; i<(int)d_index.size(); i++ ){
+ m.d_map[ qe->getTermDatabase()->getInstantiationConstant( d_f, d_index_order[i] ) ] = getTerm( i );
+ }
+}
+
+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() );
+ int index = d_index_order[i];
+ return d_model->d_ra.d_type_reps[tn][d_domain[index][d_index[index]]];
+}
+
+void RepSetIterator::debugPrint( const char* c ){
+ for( int i=0; i<(int)d_index.size(); i++ ){
+ Debug( c ) << i << " : " << d_index[i] << " : " << getTerm( i ) << std::endl;
+ }
+}
+
+void RepSetIterator::debugPrintSmall( const char* c ){
+ Debug( c ) << "RI: ";
+ for( int i=0; i<(int)d_index.size(); i++ ){
+ Debug( c ) << d_index[i] << ": " << getTerm( i ) << " ";
+ }
+ Debug( c ) << std::endl;
+}
+
+RepSetEvaluator::RepSetEvaluator( FirstOrderModel* m, RepSetIterator* ri ) : d_model( m ), d_riter( ri ){
+
+}
+
+//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
+int RepSetEvaluator::evaluate( Node n, int& depIndex ){
+ ++d_eval_formulas;
+ //Debug("fmf-eval-debug") << "Evaluate " << n << " " << phaseReq << std::endl;
+ //Notice() << "Eval " << n << std::endl;
+ if( n.getKind()==NOT ){
+ int val = evaluate( n[0], depIndex );
+ return val==1 ? -1 : ( val==-1 ? 1 : 0 );
+ }else if( n.getKind()==OR || n.getKind()==AND || n.getKind()==IMPLIES ){
+ int baseVal = n.getKind()==AND ? 1 : -1;
+ int eVal = baseVal;
+ int posDepIndex = d_riter->getNumTerms();
+ int negDepIndex = -1;
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ //evaluate subterm
+ int childDepIndex;
+ Node nn = ( i==0 && n.getKind()==IMPLIES ) ? n[i].notNode() : n[i];
+ int eValT = evaluate( nn, childDepIndex );
+ if( eValT==baseVal ){
+ if( eVal==baseVal ){
+ if( childDepIndex>negDepIndex ){
+ negDepIndex = childDepIndex;
+ }
+ }
+ }else if( eValT==-baseVal ){
+ eVal = -baseVal;
+ if( childDepIndex<posDepIndex ){
+ posDepIndex = childDepIndex;
+ if( posDepIndex==-1 ){
+ break;
+ }
+ }
+ }else if( eValT==0 ){
+ if( eVal==baseVal ){
+ eVal = 0;
+ }
+ }
+ }
+ if( eVal!=0 ){
+ depIndex = eVal==-baseVal ? posDepIndex : negDepIndex;
+ return eVal;
+ }else{
+ return 0;
+ }
+ }else if( n.getKind()==IFF || n.getKind()==XOR ){
+ int depIndex1;
+ int eVal = evaluate( n[0], depIndex1 );
+ if( eVal!=0 ){
+ int depIndex2;
+ int eVal2 = evaluate( n.getKind()==XOR ? n[1].notNode() : n[1], depIndex2 );
+ if( eVal2!=0 ){
+ depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
+ return eVal==eVal2 ? 1 : -1;
+ }
+ }
+ return 0;
+ }else if( n.getKind()==ITE ){
+ int depIndex1, depIndex2;
+ int eVal = evaluate( n[0], depIndex1 );
+ if( eVal==0 ){
+ //evaluate children to see if they are the same value
+ int eval1 = evaluate( n[1], depIndex1 );
+ if( eval1!=0 ){
+ int eval2 = evaluate( n[1], depIndex2 );
+ if( eval1==eval2 ){
+ depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
+ return eval1;
+ }
+ }
+ }else{
+ int eValT = evaluate( n[eVal==1 ? 1 : 2], depIndex2 );
+ depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
+ return eValT;
+ }
+ return 0;
+ }else if( n.getKind()==FORALL ){
+ return 0;
+ }else{
+ ////if we know we will fail again, immediately return
+ //if( d_eval_failed.find( n )!=d_eval_failed.end() ){
+ // if( d_eval_failed[n] ){
+ // return -1;
+ // }
+ //}
+ //Debug("fmf-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;
+ }
+ }
+ }
+ if( retVal!=0 ){
+ Debug("fmf-eval-debug") << "Evaluate literal: return " << retVal << ", depends = " << depIndex << std::endl;
+ }else{
+ Debug("fmf-eval-amb") << "Neither true nor false : " << n << std::endl;
+ //std::cout << "Neither true nor false : " << n << 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()) ){
+ Node val;
+ depIndex = d_riter->getNumTerms()-1;
+ //check the type of n
+ if( n.getKind()==INST_CONSTANT ){
+ int v = n.getAttribute(InstVarNumAttribute());
+ depIndex = d_riter->d_var_order[ v ];
+ val = d_riter->getTerm( v );
+ }else if( n.getKind()==ITE ){
+ int depIndex1, depIndex2;
+ int eval = evaluate( n[0], depIndex1 );
+ if( eval==0 ){
+ //evaluate children to see if they are the same
+ Node val1 = evaluateTerm( n[ 1 ], depIndex1 );
+ Node val2 = evaluateTerm( n[ 1 ], depIndex1 );
+ if( val1==val2 ){
+ val = val1;
+ depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
+ }else{
+ return Node::null();
+ }
+ }else{
+ val = evaluateTerm( n[ eval==1 ? 1 : 2 ], depIndex2 );
+ depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
+ }
+ }else{
+#if 0
+ //for select, pre-process read over writes
+ if( n.getKind()==SELECT ){
+ Node selIndex = evaluateTerm( n[1], depIndex );
+ if( selIndex.isNull() ){
+ depIndex = d_riter->getNumTerms()-1;
+ return Node::null();
+ }
+ Node arr = n[0];
+ int eval = 1;
+ while( arr.getKind()==STORE && eval!=0 ){
+ int tempIndex;
+ eval = evaluateEquality( selIndex, arr[1], tempIndex );
+ depIndex = tempIndex > depIndex ? tempIndex : depIndex;
+ if( eval==1 ){
+ val = evaluateTerm( arr[2], tempIndex );
+ depIndex = tempIndex > depIndex ? tempIndex : depIndex;
+ return val;
+ }else if( eval==-1 ){
+ arr = arr[0];
+ }
+ }
+ n = NodeManager::currentNM()->mkNode( SELECT, arr, selIndex );
+ }
+#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 );
+ }
+ //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();
+ }
+ //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];
+ }
+ }
+ 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];
+ }
+ }
+ }
+ //recreate the value
+ return NodeManager::currentNM()->mkNode( n.getKind(), children );
+}
+
+void RepSetEvaluator::clearEvalFailed( int index ){
+ for( int i=0; i<(int)d_eval_failed_lits[index].size(); i++ ){
+ d_eval_failed[ d_eval_failed_lits[index][i] ] = false;
+ }
+ d_eval_failed_lits[index].clear();
+}
+
+void RepSetEvaluator::makeEvalUfModel( Node n ){
+ if( d_eval_uf_model.find( n )==d_eval_uf_model.end() ){
+ 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] );
+ //Debug("fmf-index-order") << "Make model for " << n << " : " << std::endl;
+ //d_eval_uf_model[n].debugPrint( "fmf-index-order", d_qe, 2 );
+ }
+ }
+}
+
+struct sortGetMaxVariableNum {
+ std::map< Node, int > d_max_var_num;
+ int computeMaxVariableNum( Node n ){
+ if( n.getKind()==INST_CONSTANT ){
+ return n.getAttribute(InstVarNumAttribute());
+ }else if( n.hasAttribute(InstConstantAttribute()) ){
+ int maxVal = -1;
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ int val = getMaxVariableNum( n[i] );
+ if( val>maxVal ){
+ maxVal = val;
+ }
+ }
+ return maxVal;
+ }else{
+ return -1;
+ }
+ }
+ int getMaxVariableNum( Node n ){
+ std::map< Node, int >::iterator it = d_max_var_num.find( n );
+ if( it==d_max_var_num.end() ){
+ int num = computeMaxVariableNum( n );
+ d_max_var_num[n] = num;
+ return num;
+ }else{
+ return it->second;
+ }
+ }
+ bool operator() (Node i,Node j) { return (getMaxVariableNum(i)<getMaxVariableNum(j));}
+};
+
+void RepSetEvaluator::makeEvalUfIndexOrder( Node n ){
+ if( d_eval_term_index_order.find( n )==d_eval_term_index_order.end() ){
+#ifdef USE_INDEX_ORDERING
+ //sort arguments in order of least significant vs. most significant variable in default ordering
+ std::map< Node, std::vector< int > > argIndex;
+ std::vector< Node > args;
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( argIndex.find( n[i] )==argIndex.end() ){
+ args.push_back( n[i] );
+ }
+ argIndex[n[i]].push_back( i );
+ }
+ sortGetMaxVariableNum sgmvn;
+ std::sort( args.begin(), args.end(), sgmvn );
+ for( int i=0; i<(int)args.size(); i++ ){
+ for( int j=0; j<(int)argIndex[ args[i] ].size(); j++ ){
+ d_eval_term_index_order[n].push_back( argIndex[ args[i] ][j] );
+ }
+ }
+ bool useDefault = true;
+ for( int i=0; i<(int)d_eval_term_index_order[n].size(); i++ ){
+ if( i!=d_eval_term_index_order[n][i] ){
+ useDefault = false;
+ break;
+ }
+ }
+ d_eval_uf_use_default[n] = useDefault;
+ Debug("fmf-index-order") << "Will consider the following index ordering for " << n << " : ";
+ for( int i=0; i<(int)d_eval_term_index_order[n].size(); i++ ){
+ Debug("fmf-index-order") << d_eval_term_index_order[n][i] << " ";
+ }
+ Debug("fmf-index-order") << std::endl;
+#else
+ d_eval_uf_use_default[n] = true;
+#endif
+ }
+}
+
+
diff --git a/src/theory/quantifiers/rep_set_iterator.h b/src/theory/quantifiers/rep_set_iterator.h
new file mode 100644
index 000000000..308d09a38
--- /dev/null
+++ b/src/theory/quantifiers/rep_set_iterator.h
@@ -0,0 +1,120 @@
+/********************* */
+/*! \file rep_set_iterator.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 rep_set_iterator class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__REP_SET_ITERATOR_H
+#define __CVC4__REP_SET_ITERATOR_H
+
+#include "theory/quantifiers_engine.h"
+#include "theory/quantifiers/first_order_model.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+/** this class iterates over a RepSet */
+class RepSetIterator {
+public:
+ RepSetIterator( Node f, FirstOrderModel* model );
+ ~RepSetIterator(){}
+ //pointer to quantifier
+ Node d_f;
+ //pointer to model
+ FirstOrderModel* d_model;
+ //index we are considering
+ std::vector< int > d_index;
+ //domain we are considering
+ std::vector< RepDomain > d_domain;
+ //ordering for variables we are indexing over
+ // for example, given reps = { a, b } and quantifier forall( x, y, z ) P( x, y, z ) with d_index_order = { 2, 0, 1 },
+ // then we consider instantiations in this order:
+ // a/x a/y a/z
+ // a/x b/y a/z
+ // b/x a/y a/z
+ // b/x b/y a/z
+ // ...
+ std::vector< int > d_index_order;
+ //variables to index they are considered at
+ // for example, if d_index_order = { 2, 0, 1 }
+ // then d_var_order = { 0 -> 1, 1 -> 2, 2 -> 0 }
+ std::map< int, int > d_var_order;
+ //the instantiation constants of d_f
+ std::vector< Node > d_ic;
+ //the current terms we are considering
+ std::vector< Node > d_terms;
+public:
+ /** set index order */
+ void setIndexOrder( std::vector< int >& indexOrder );
+ /** set domain */
+ void setDomain( std::vector< RepDomain >& domain );
+ /** increment the iterator */
+ void increment2( int counter );
+ void increment();
+ /** is the iterator finished? */
+ bool isFinished();
+ /** produce the match that this iterator represents */
+ void getMatch( QuantifiersEngine* qe, InstMatch& m );
+ /** get the i_th term we are considering */
+ Node getTerm( int i );
+ /** get the number of terms we are considering */
+ int getNumTerms() { return d_f[0].getNumChildren(); }
+ /** debug print */
+ void debugPrint( const char* c );
+ void debugPrintSmall( const char* c );
+};
+
+class RepSetEvaluator
+{
+private:
+ FirstOrderModel* d_model;
+ RepSetIterator* d_riter;
+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;
+ void makeEvalUfModel( Node n );
+ //index ordering to use for each term
+ std::map< Node, std::vector< int > > d_eval_term_index_order;
+ int getMaxVariableNum( int n );
+ void makeEvalUfIndexOrder( Node n );
+private:
+ //default evaluate term function
+ Node evaluateTermDefault( Node n, int& depIndex, std::vector< int >& childDepIndex );
+ //temporary storing which literals have failed
+ void clearEvalFailed( int index );
+ std::map< Node, bool > d_eval_failed;
+ std::map< int, std::vector< Node > > d_eval_failed_lits;
+public:
+ RepSetEvaluator( FirstOrderModel* m, RepSetIterator* ri );
+ 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;
+};
+
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/term_database.cpp b/src/theory/quantifiers/term_database.cpp
new file mode 100644
index 000000000..55ea693ef
--- /dev/null
+++ b/src/theory/quantifiers/term_database.cpp
@@ -0,0 +1,324 @@
+/********************* */
+/*! \file term_database.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 term databse class
+ **/
+
+ #include "theory/quantifiers/term_database.h"
+ #include "theory/quantifiers_engine.h"
+ #include "theory/uf/theory_uf_instantiator.h"
+ #include "theory/theory_engine.h"
+ #include "theory/quantifiers/first_order_model.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+
+ bool TermArgTrie::addTerm2( QuantifiersEngine* qe, Node n, int argIndex ){
+ if( argIndex<(int)n.getNumChildren() ){
+ Node r = qe->getEqualityQuery()->getRepresentative( n[ argIndex ] );
+ std::map< Node, TermArgTrie >::iterator it = d_data.find( r );
+ if( it==d_data.end() ){
+ d_data[r].addTerm2( qe, n, argIndex+1 );
+ return true;
+ }else{
+ return it->second.addTerm2( qe, n, argIndex+1 );
+ }
+ }else{
+ //store n in d_data (this should be interpretted as the "data" and not as a reference to a child)
+ d_data[n].d_data.clear();
+ return false;
+ }
+ }
+
+ void TermDb::addTerm( Node n, std::vector< Node >& added, bool withinQuant ){
+ //don't add terms in quantifier bodies
+ if( !withinQuant || Options::current()->registerQuantBodyTerms ){
+ if( d_processed.find( n )==d_processed.end() ){
+ d_processed[n] = true;
+ //if this is an atomic trigger, consider adding it
+ if( Trigger::isAtomicTrigger( n ) ){
+ if( !n.hasAttribute(InstConstantAttribute()) ){
+ Debug("term-db") << "register trigger term " << n << std::endl;
+ //Notice() << "register trigger term " << n << std::endl;
+ Node op = n.getOperator();
+ d_op_map[op].push_back( n );
+ d_type_map[ n.getType() ].push_back( n );
+ added.push_back( n );
+
+ uf::InstantiatorTheoryUf* d_ith = (uf::InstantiatorTheoryUf*)d_quantEngine->getInstantiator( THEORY_UF );
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ addTerm( n[i], added, withinQuant );
+ if( Options::current()->efficientEMatching ){
+ if( d_parents[n[i]][op].empty() ){
+ //must add parent to equivalence class info
+ Node nir = d_ith->getRepresentative( n[i] );
+ uf::EqClassInfo* eci_nir = d_ith->getEquivalenceClassInfo( nir );
+ if( eci_nir ){
+ eci_nir->d_pfuns[ op ] = true;
+ }
+ }
+ //add to parent structure
+ if( std::find( d_parents[n[i]][op][i].begin(), d_parents[n[i]][op][i].end(), n )==d_parents[n[i]][op][i].end() ){
+ d_parents[n[i]][op][i].push_back( n );
+ }
+ }
+ }
+ if( Options::current()->efficientEMatching ){
+ //new term, add n to candidate generators
+ for( int i=0; i<(int)d_ith->d_cand_gens[op].size(); i++ ){
+ d_ith->d_cand_gens[op][i]->addCandidate( n );
+ }
+ }
+ if( Options::current()->eagerInstQuant ){
+ if( !n.hasAttribute(InstLevelAttribute()) && n.getAttribute(InstLevelAttribute())==0 ){
+ int addedLemmas = 0;
+ for( int i=0; i<(int)d_ith->d_op_triggers[op].size(); i++ ){
+ addedLemmas += d_ith->d_op_triggers[op][i]->addTerm( n );
+ }
+ //Message() << "Terms, added lemmas: " << addedLemmas << std::endl;
+ d_quantEngine->flushLemmas( &d_quantEngine->getTheoryEngine()->getTheory( THEORY_QUANTIFIERS )->getOutputChannel() );
+ }
+ }
+ }
+ }
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ addTerm( n[i], added, withinQuant );
+ }
+ }
+ }
+ }
+
+ void TermDb::reset( Theory::Effort effort ){
+ int nonCongruentCount = 0;
+ int congruentCount = 0;
+ int alreadyCongruentCount = 0;
+ //rebuild d_func/pred_map_trie for each operation, this will calculate all congruent terms
+ for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){
+ if( !it->second.empty() ){
+ if( it->second[0].getType()==NodeManager::currentNM()->booleanType() ){
+ d_pred_map_trie[ 0 ][ it->first ].d_data.clear();
+ d_pred_map_trie[ 1 ][ it->first ].d_data.clear();
+ }else{
+ d_func_map_trie[ it->first ].d_data.clear();
+ for( int i=0; i<(int)it->second.size(); i++ ){
+ Node n = it->second[i];
+ if( !n.getAttribute(NoMatchAttribute()) ){
+ if( !d_func_map_trie[ it->first ].addTerm( d_quantEngine, n ) ){
+ NoMatchAttribute nma;
+ n.setAttribute(nma,true);
+ congruentCount++;
+ }else{
+ nonCongruentCount++;
+ }
+ }else{
+ congruentCount++;
+ alreadyCongruentCount++;
+ }
+ }
+ }
+ }
+ }
+ for( int i=0; i<2; i++ ){
+ Node n = NodeManager::currentNM()->mkConst( i==1 );
+ eq::EqClassIterator eqc( d_quantEngine->getEqualityQuery()->getRepresentative( n ),
+ ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine() );
+ while( !eqc.isFinished() ){
+ Node en = (*eqc);
+ if( en.getKind()==APPLY_UF && !en.hasAttribute(InstConstantAttribute()) ){
+ if( !en.getAttribute(NoMatchAttribute()) ){
+ Node op = en.getOperator();
+ if( !d_pred_map_trie[i][op].addTerm( d_quantEngine, en ) ){
+ NoMatchAttribute nma;
+ en.setAttribute(nma,true);
+ congruentCount++;
+ }else{
+ nonCongruentCount++;
+ }
+ }else{
+ alreadyCongruentCount++;
+ }
+ }
+ ++eqc;
+ }
+ }
+ Debug("term-db-cong") << "TermDb: Reset" << std::endl;
+ Debug("term-db-cong") << "Congruent/Non-Congruent = ";
+ Debug("term-db-cong") << congruentCount << "(" << alreadyCongruentCount << ") / " << nonCongruentCount << std::endl;
+}
+
+void TermDb::registerModelBasis( Node n, Node gn ){
+ if( d_model_basis.find( n )==d_model_basis.end() ){
+ d_model_basis[n] = gn;
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ registerModelBasis( n[i], gn[i] );
+ }
+ }
+}
+
+Node 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 );
+ ModelBasisAttribute mba;
+ d_model_basis_term[tn].setAttribute(mba,true);
+ }
+ return d_model_basis_term[tn];
+}
+
+Node TermDb::getModelBasisOpTerm( Node op ){
+ if( d_model_basis_op_term.find( op )==d_model_basis_op_term.end() ){
+ TypeNode t = op.getType();
+ std::vector< Node > children;
+ children.push_back( op );
+ for( size_t i=0; i<t.getNumChildren()-1; i++ ){
+ children.push_back( getModelBasisTerm( t[i] ) );
+ }
+ d_model_basis_op_term[op] = NodeManager::currentNM()->mkNode( APPLY_UF, children );
+ }
+ return d_model_basis_op_term[op];
+}
+
+void TermDb::computeModelBasisArgAttribute( Node n ){
+ if( !n.hasAttribute(ModelBasisArgAttribute()) ){
+ uint64_t val = 0;
+ //determine if it has model basis attribute
+ for( int j=0; j<(int)n.getNumChildren(); j++ ){
+ if( n[j].getAttribute(ModelBasisAttribute()) ){
+ val = 1;
+ break;
+ }
+ }
+ ModelBasisArgAttribute mbaa;
+ n.setAttribute( mbaa, val );
+ }
+}
+
+void TermDb::makeInstantiationConstantsFor( Node f ){
+ if( d_inst_constants.find( f )==d_inst_constants.end() ){
+ Debug("quantifiers-engine") << "Instantiation constants for " << f << " : " << std::endl;
+ for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
+ d_vars[f].push_back( f[0][i] );
+ //make instantiation constants
+ Node ic = NodeManager::currentNM()->mkInstConstant( f[0][i].getType() );
+ d_inst_constants_map[ic] = f;
+ d_inst_constants[ f ].push_back( ic );
+ Debug("quantifiers-engine") << " " << ic << std::endl;
+ //set the var number attribute
+ InstVarNumAttribute ivna;
+ ic.setAttribute(ivna,i);
+ }
+ }
+}
+
+void TermDb::setInstantiationLevelAttr( Node n, uint64_t level ){
+ if( !n.hasAttribute(InstLevelAttribute()) ){
+ InstLevelAttribute ila;
+ n.setAttribute(ila,level);
+ }
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ setInstantiationLevelAttr( n[i], level );
+ }
+}
+
+
+void TermDb::setInstantiationConstantAttr( Node n, Node f ){
+ if( !n.hasAttribute(InstConstantAttribute()) ){
+ bool setAttr = false;
+ if( n.getKind()==INST_CONSTANT ){
+ setAttr = true;
+ }else{
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ setInstantiationConstantAttr( n[i], f );
+ if( n[i].hasAttribute(InstConstantAttribute()) ){
+ setAttr = true;
+ }
+ }
+ }
+ if( setAttr ){
+ InstConstantAttribute ica;
+ n.setAttribute(ica,f);
+ //also set the no-match attribute
+ NoMatchAttribute nma;
+ n.setAttribute(nma,true);
+ }
+ }
+}
+
+
+Node TermDb::getCounterexampleBody( Node f ){
+ std::map< Node, Node >::iterator it = d_counterexample_body.find( f );
+ if( it==d_counterexample_body.end() ){
+ makeInstantiationConstantsFor( f );
+ Node n = getSubstitutedNode( f[1], f );
+ d_counterexample_body[ f ] = n;
+ return n;
+ }else{
+ return it->second;
+ }
+}
+
+Node TermDb::getSkolemizedBody( Node f ){
+ Assert( f.getKind()==FORALL );
+ if( d_skolem_body.find( f )==d_skolem_body.end() ){
+ std::vector< Node > vars;
+ for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
+ Node skv = NodeManager::currentNM()->mkSkolem( f[0][i].getType() );
+ d_skolem_constants[ f ].push_back( skv );
+ vars.push_back( f[0][i] );
+ }
+ d_skolem_body[ f ] = f[ 1 ].substitute( vars.begin(), vars.end(),
+ d_skolem_constants[ f ].begin(), d_skolem_constants[ f ].end() );
+ if( f.hasAttribute(InstLevelAttribute()) ){
+ setInstantiationLevelAttr( d_skolem_body[ f ], f.getAttribute(InstLevelAttribute()) );
+ }
+ }
+ return d_skolem_body[ f ];
+}
+
+
+Node TermDb::getSubstitutedNode( Node n, Node f ){
+ return convertNodeToPattern(n,f,d_vars[f],d_inst_constants[ f ]);
+}
+
+Node TermDb::convertNodeToPattern( Node n, Node f, const std::vector<Node> & vars,
+ const std::vector<Node> & inst_constants){
+ Node n2 = n.substitute( vars.begin(), vars.end(),
+ inst_constants.begin(),
+ inst_constants.end() );
+ setInstantiationConstantAttr( n2, f );
+ return n2;
+}
+
+Node TermDb::getFreeVariableForInstConstant( Node n ){
+ TypeNode tn = n.getType();
+ if( d_free_vars.find( tn )==d_free_vars.end() ){
+ //if integer or real, make zero
+ if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){
+ Rational z(0);
+ d_free_vars[tn] = NodeManager::currentNM()->mkConst( z );
+ }else{
+ if( d_type_map[ tn ].empty() ){
+ d_free_vars[tn] = NodeManager::currentNM()->mkVar( tn );
+ }else{
+ d_free_vars[tn] = d_type_map[ tn ][ 0 ];
+ }
+ }
+ }
+ return d_free_vars[tn];
+} \ No newline at end of file
diff --git a/src/theory/quantifiers/term_database.h b/src/theory/quantifiers/term_database.h
new file mode 100644
index 000000000..5bf3d7900
--- /dev/null
+++ b/src/theory/quantifiers/term_database.h
@@ -0,0 +1,151 @@
+/**********************/
+/*! \file term_database.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 term database class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__QUANTIFIERS_TERM_DATABASE_H
+#define __CVC4__QUANTIFIERS_TERM_DATABASE_H
+
+#include "theory/theory.h"
+
+#include <map>
+
+namespace CVC4 {
+namespace theory {
+
+class QuantifiersEngine;
+
+namespace quantifiers {
+
+class TermArgTrie {
+private:
+ bool addTerm2( QuantifiersEngine* qe, Node n, int argIndex );
+public:
+ /** the data */
+ std::map< Node, TermArgTrie > d_data;
+public:
+ bool addTerm( QuantifiersEngine* qe, Node n ) { return addTerm2( qe, n, 0 ); }
+};/* class TermArgTrie */
+
+class TermDb {
+ friend class ::CVC4::theory::QuantifiersEngine;
+private:
+ /** reference to the quantifiers engine */
+ QuantifiersEngine* d_quantEngine;
+ /** calculated no match terms */
+ bool d_matching_active;
+ /** terms processed */
+ std::map< Node, bool > d_processed;
+public:
+ TermDb( QuantifiersEngine* qe ) : d_quantEngine( qe ), d_matching_active( true ){}
+ ~TermDb(){}
+ /** map from APPLY_UF operators to ground terms for that operator */
+ std::map< Node, std::vector< Node > > d_op_map;
+ /** map from APPLY_UF functions to trie */
+ std::map< Node, TermArgTrie > d_func_map_trie;
+ /** map from APPLY_UF predicates to trie */
+ std::map< Node, TermArgTrie > d_pred_map_trie[2];
+ /** map from type nodes to terms of that type */
+ std::map< TypeNode, std::vector< Node > > d_type_map;
+ /** add a term to the database */
+ void addTerm( Node n, std::vector< Node >& added, bool withinQuant = false );
+ /** reset (calculate which terms are active) */
+ void reset( Theory::Effort effort );
+ /** set active */
+ void setMatchingActive( bool a ) { d_matching_active = a; }
+ /** get active */
+ bool getMatchingActive() { return d_matching_active; }
+public:
+ /** parent structure (for efficient E-matching):
+ n -> op -> index -> L
+ map from node "n" to a list of nodes "L", where each node n' in L
+ has operator "op", and n'["index"] = n.
+ for example, d_parents[n][f][1] = { f( t1, n ), f( t2, n ), ... }
+ */
+ std::map< Node, std::map< Node, std::map< int, std::vector< Node > > > > d_parents;
+private:
+ //map from types to model basis terms
+ std::map< TypeNode, Node > d_model_basis_term;
+ //map from ops to model basis terms
+ std::map< Node, Node > d_model_basis_op_term;
+ //map from instantiation terms to their model basis equivalent
+ std::map< Node, Node > d_model_basis;
+public:
+ //get model basis term
+ Node getModelBasisTerm( TypeNode tn, int i = 0 );
+ //get model basis term for op
+ Node getModelBasisOpTerm( Node op );
+ // compute model basis arg
+ void computeModelBasisArgAttribute( Node n );
+ //register instantiation terms with their corresponding model basis terms
+ void registerModelBasis( Node n, Node gn );
+ //get model basis
+ Node getModelBasis( Node n ) { return d_model_basis[n]; }
+private:
+ /** map from universal quantifiers to the list of variables */
+ std::map< Node, std::vector< Node > > d_vars;
+ /** map from universal quantifiers to the list of skolem constants */
+ std::map< Node, std::vector< Node > > d_skolem_constants;
+ /** map from universal quantifiers to their skolemized body */
+ std::map< Node, Node > d_skolem_body;
+ /** instantiation constants to universal quantifiers */
+ std::map< Node, Node > d_inst_constants_map;
+ /** map from universal quantifiers to their counterexample body */
+ std::map< Node, Node > d_counterexample_body;
+ /** free variable for instantiation constant type */
+ std::map< TypeNode, Node > d_free_vars;
+private:
+ /** make instantiation constants for */
+ void makeInstantiationConstantsFor( Node f );
+public:
+ /** map from universal quantifiers to the list of instantiation constants */
+ std::map< Node, std::vector< Node > > d_inst_constants;
+ /** set instantiation level attr */
+ void setInstantiationLevelAttr( Node n, uint64_t level );
+ /** set instantiation constant attr */
+ void setInstantiationConstantAttr( Node n, Node f );
+ /** get the i^th instantiation constant of f */
+ Node getInstantiationConstant( Node f, int i ) { return d_inst_constants[f][i]; }
+ /** get number of instantiation constants for f */
+ int getNumInstantiationConstants( Node f ) { return (int)d_inst_constants[f].size(); }
+ /** get the ce body f[e/x] */
+ Node getCounterexampleBody( Node f );
+ /** get the skolemized body f[e/x] */
+ Node getSkolemizedBody( Node f );
+ /** returns node n with bound vars of f replaced by instantiation constants of f
+ node n : is the futur pattern
+ node f : is the quantifier containing which bind the variable
+ return a pattern where the variable are replaced by variable for
+ instantiation.
+ */
+ Node getSubstitutedNode( Node n, Node f );
+ /** same as before but node f is just linked to the new pattern by the
+ applied attribute
+ vars the bind variable
+ nvars the same variable but with an attribute
+ */
+ Node convertNodeToPattern( Node n, Node f,
+ const std::vector<Node> & vars,
+ const std::vector<Node> & nvars);
+ /** get free variable for instantiation constant */
+ Node getFreeVariableForInstConstant( Node n );
+};/* class TermDb */
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/theory_quantifiers.cpp b/src/theory/quantifiers/theory_quantifiers.cpp
index ead47e4b0..27310e21b 100644
--- a/src/theory/quantifiers/theory_quantifiers.cpp
+++ b/src/theory/quantifiers/theory_quantifiers.cpp
@@ -27,11 +27,7 @@
#include <map>
#include <time.h>
#include "theory/quantifiers/theory_quantifiers_instantiator.h"
-
-#define USE_FLIP_DECISION
-
-//static bool clockSet = false;
-//double initClock;
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
@@ -45,11 +41,6 @@ TheoryQuantifiers::TheoryQuantifiers(Context* c, context::UserContext* u, Output
d_numRestarts(0){
d_numInstantiations = 0;
d_baseDecLevel = -1;
- if( Options::current()->finiteModelFind ){
- qe->addModule( new ModelEngine( this ) );
- }else{
- qe->addModule( new InstantiationEngine( this ) );
- }
}
@@ -65,10 +56,10 @@ void TheoryQuantifiers::addSharedTerm(TNode t) {
void TheoryQuantifiers::notifyEq(TNode lhs, TNode rhs) {
Debug("quantifiers-other") << "TheoryQuantifiers::notifyEq(): "
<< lhs << " = " << rhs << endl;
-
+
}
-void TheoryQuantifiers::preRegisterTerm(TNode n) {
+void TheoryQuantifiers::preRegisterTerm(TNode n) {
Debug("quantifiers-prereg") << "TheoryQuantifiers::preRegisterTerm() " << n << endl;
if( n.getKind()==FORALL && !n.hasAttribute(InstConstantAttribute()) ){
getQuantifiersEngine()->registerQuantifier( n );
@@ -97,6 +88,10 @@ Node TheoryQuantifiers::getValue(TNode n) {
}
}
+void TheoryQuantifiers::collectModelInfo( TheoryModel* m ){
+
+}
+
void TheoryQuantifiers::check(Effort e) {
CodeTimer codeTimer(d_theoryTime);
@@ -119,7 +114,7 @@ void TheoryQuantifiers::check(Effort e) {
break;
}
}
- break;
+ break;
default:
Unhandled(assertion.getKind());
break;
@@ -147,7 +142,7 @@ void TheoryQuantifiers::assertExistential( Node n ){
Assert( n.getKind()== NOT && n[0].getKind()==FORALL );
if( !n[0].hasAttribute(InstConstantAttribute()) ){
if( d_skolemized.find( n )==d_skolemized.end() ){
- Node body = getQuantifiersEngine()->getSkolemizedBody( n[0] );
+ Node body = getQuantifiersEngine()->getTermDatabase()->getSkolemizedBody( n[0] );
NodeBuilder<> nb(kind::OR);
nb << n[0] << body.notNode();
Node lem = nb;
@@ -159,9 +154,6 @@ void TheoryQuantifiers::assertExistential( Node n ){
}
bool TheoryQuantifiers::flipDecision(){
-#ifndef USE_FLIP_DECISION
- return false;
-#else
//Debug("quantifiers-flip") << "No instantiation given, flip decision, level = " << d_valuation.getDecisionLevel() << std::endl;
//for( int i=1; i<=(int)d_valuation.getDecisionLevel(); i++ ){
// Debug("quantifiers-flip") << " " << d_valuation.getDecision( i ) << std::endl;
@@ -179,7 +171,6 @@ bool TheoryQuantifiers::flipDecision(){
return restart();
}
return true;
-#endif
}
bool TheoryQuantifiers::restart(){
diff --git a/src/theory/quantifiers/theory_quantifiers.h b/src/theory/quantifiers/theory_quantifiers.h
index 05c3b9695..517786400 100644
--- a/src/theory/quantifiers/theory_quantifiers.h
+++ b/src/theory/quantifiers/theory_quantifiers.h
@@ -34,6 +34,8 @@ namespace theory {
namespace quantifiers {
class TheoryEngine;
+class ModelEngine;
+class InstantiationEngine;
class TheoryQuantifiers : public Theory {
private:
@@ -59,6 +61,7 @@ public:
void check(Effort e);
void propagate(Effort level);
Node getValue(TNode n);
+ void collectModelInfo( TheoryModel* m );
void shutdown() { }
std::string identify() const { return std::string("TheoryQuantifiers"); }
bool flipDecision();
diff --git a/src/theory/quantifiers/theory_quantifiers_instantiator.cpp b/src/theory/quantifiers/theory_quantifiers_instantiator.cpp
index a5b6cc3bc..84b6c65c7 100644
--- a/src/theory/quantifiers/theory_quantifiers_instantiator.cpp
+++ b/src/theory/quantifiers/theory_quantifiers_instantiator.cpp
@@ -48,7 +48,7 @@ void InstantiatorTheoryQuantifiers::processResetInstantiationRound( Theory::Effo
}
-int InstantiatorTheoryQuantifiers::process( Node f, Theory::Effort effort, int e, int limitInst ){
+int InstantiatorTheoryQuantifiers::process( Node f, Theory::Effort effort, int e ){
Debug("quant-quant") << "Quant: Try to solve (" << e << ") for " << f << "... " << std::endl;
if( e<5 ){
return InstStrategy::STATUS_UNFINISHED;
diff --git a/src/theory/quantifiers/theory_quantifiers_instantiator.h b/src/theory/quantifiers/theory_quantifiers_instantiator.h
index 39e34c319..bf17495a1 100644
--- a/src/theory/quantifiers/theory_quantifiers_instantiator.h
+++ b/src/theory/quantifiers/theory_quantifiers_instantiator.h
@@ -42,7 +42,7 @@ private:
/** reset instantiation */
void processResetInstantiationRound( Theory::Effort effort );
/** process at effort */
- int process( Node f, Theory::Effort effort, int e, int limitInst );
+ int process( Node f, Theory::Effort effort, int e );
class Statistics {
public:
diff --git a/src/theory/quantifiers_engine.cpp b/src/theory/quantifiers_engine.cpp
index e8a17eadd..e4e3df9be 100644
--- a/src/theory/quantifiers_engine.cpp
+++ b/src/theory/quantifiers_engine.cpp
@@ -19,7 +19,13 @@
#include "theory/uf/theory_uf_instantiator.h"
#include "theory/uf/theory_uf_strong_solver.h"
#include "theory/uf/equality_engine.h"
+#include "theory/arrays/theory_arrays.h"
+#include "theory/datatypes/theory_datatypes.h"
#include "theory/quantifiers/quantifiers_rewriter.h"
+#include "theory/quantifiers/model_engine.h"
+#include "theory/quantifiers/instantiation_engine.h"
+#include "theory/quantifiers/first_order_model.h"
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
@@ -36,11 +42,12 @@ void InstStrategy::resetInstantiationRound( Theory::Effort effort ){
d_no_instantiate_temp.insert( d_no_instantiate_temp.begin(), d_no_instantiate.begin(), d_no_instantiate.end() );
processResetInstantiationRound( effort );
}
+
/** do instantiation round method */
-int InstStrategy::doInstantiation( Node f, Theory::Effort effort, int e, int limitInst ){
+int InstStrategy::doInstantiation( Node f, Theory::Effort effort, int e ){
if( shouldInstantiate( f ) ){
int origLemmas = d_quantEngine->getNumLemmasWaiting();
- int retVal = process( f, effort, e, limitInst );
+ int retVal = process( f, effort, e );
if( d_quantEngine->getNumLemmasWaiting()!=origLemmas ){
for( int i=0; i<(int)d_priority_over.size(); i++ ){
d_priority_over[i]->d_no_instantiate_temp.push_back( f );
@@ -52,156 +59,61 @@ int InstStrategy::doInstantiation( Node f, Theory::Effort effort, int e, int lim
}
}
-bool TermArgTrie::addTerm2( QuantifiersEngine* qe, Node n, int argIndex ){
- if( argIndex<(int)n.getNumChildren() ){
- Node r = qe->getEqualityQuery()->getRepresentative( n[ argIndex ] );
- std::map< Node, TermArgTrie >::iterator it = d_data.find( r );
- if( it==d_data.end() ){
- d_data[r].addTerm2( qe, n, argIndex+1 );
- return true;
- }else{
- return it->second.addTerm2( qe, n, argIndex+1 );
- }
+QuantifiersEngine::QuantifiersEngine(context::Context* c, TheoryEngine* te):
+d_te( te ),
+d_active( c ){
+ d_eq_query = new EqualityQueryQuantifiersEngine( this );
+ d_term_db = new quantifiers::TermDb( this );
+ d_hasAddedLemma = false;
+
+ //the model object
+ d_model = new quantifiers::FirstOrderModel( this, c, "FirstOrderModel" );
+
+ //add quantifiers modules
+ if( !Options::current()->finiteModelFind || Options::current()->fmfInstEngine ){
+ //the instantiation must set incomplete flag unless finite model finding is turned on
+ d_inst_engine = new quantifiers::InstantiationEngine( this, !Options::current()->finiteModelFind );
+ d_modules.push_back( d_inst_engine );
}else{
- //store n in d_data (this should be interpretted as the "data" and not as a reference to a child)
- d_data[n].d_data.clear();
- return false;
+ d_inst_engine = NULL;
}
-}
-
-void TermDb::addTerm( Node n, std::vector< Node >& added, bool withinQuant ){
- //don't add terms in quantifier bodies
- if( !withinQuant || Options::current()->registerQuantBodyTerms ){
- if( d_processed.find( n )==d_processed.end() ){
- d_processed[n] = true;
- //if this is an atomic trigger, consider adding it
- if( Trigger::isAtomicTrigger( n ) ){
- if( !n.hasAttribute(InstConstantAttribute()) ){
- Debug("term-db") << "register trigger term " << n << std::endl;
- //Notice() << "register trigger term " << n << std::endl;
- Node op = n.getOperator();
- d_op_map[op].push_back( n );
- d_type_map[ n.getType() ].push_back( n );
- added.push_back( n );
-
- uf::InstantiatorTheoryUf* d_ith = (uf::InstantiatorTheoryUf*)d_quantEngine->getInstantiator( THEORY_UF );
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- addTerm( n[i], added, withinQuant );
- if( Options::current()->efficientEMatching ){
- if( d_parents[n[i]][op].empty() ){
- //must add parent to equivalence class info
- Node nir = d_ith->getRepresentative( n[i] );
- uf::EqClassInfo* eci_nir = d_ith->getEquivalenceClassInfo( nir );
- if( eci_nir ){
- eci_nir->d_pfuns[ op ] = true;
- }
- }
- //add to parent structure
- if( std::find( d_parents[n[i]][op][i].begin(), d_parents[n[i]][op][i].end(), n )==d_parents[n[i]][op][i].end() ){
- d_parents[n[i]][op][i].push_back( n );
- }
- }
- }
- if( Options::current()->efficientEMatching ){
- //new term, add n to candidate generators
- for( int i=0; i<(int)d_ith->d_cand_gens[op].size(); i++ ){
- d_ith->d_cand_gens[op][i]->addCandidate( n );
- }
- }
- if( Options::current()->eagerInstQuant ){
- if( !n.hasAttribute(InstLevelAttribute()) && n.getAttribute(InstLevelAttribute())==0 ){
- int addedLemmas = 0;
- for( int i=0; i<(int)d_ith->d_op_triggers[op].size(); i++ ){
- addedLemmas += d_ith->d_op_triggers[op][i]->addTerm( n );
- }
- //Message() << "Terms, added lemmas: " << addedLemmas << std::endl;
- d_quantEngine->flushLemmas( &d_quantEngine->getTheoryEngine()->getTheory( THEORY_QUANTIFIERS )->getOutputChannel() );
- }
- }
- }
- }
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- addTerm( n[i], added, withinQuant );
- }
- }
+ if( Options::current()->finiteModelFind ){
+ d_model_engine = new quantifiers::ModelEngine( this );
+ d_modules.push_back( d_model_engine );
+ }else{
+ d_model_engine = NULL;
}
-}
-void TermDb::reset( Theory::Effort effort ){
- int nonCongruentCount = 0;
- int congruentCount = 0;
- int alreadyCongruentCount = 0;
- //rebuild d_func/pred_map_trie for each operation, this will calculate all congruent terms
- for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){
- if( !it->second.empty() ){
- if( it->second[0].getType()==NodeManager::currentNM()->booleanType() ){
- d_pred_map_trie[ 0 ][ it->first ].d_data.clear();
- d_pred_map_trie[ 1 ][ it->first ].d_data.clear();
- }else{
- d_func_map_trie[ it->first ].d_data.clear();
- for( int i=0; i<(int)it->second.size(); i++ ){
- Node n = it->second[i];
- if( !n.getAttribute(NoMatchAttribute()) ){
- if( !d_func_map_trie[ it->first ].addTerm( d_quantEngine, n ) ){
- NoMatchAttribute nma;
- n.setAttribute(nma,true);
- congruentCount++;
- }else{
- nonCongruentCount++;
- }
- }else{
- congruentCount++;
- alreadyCongruentCount++;
- }
- }
- }
- }
- }
- for( int i=0; i<2; i++ ){
- Node n = NodeManager::currentNM()->mkConst( i==1 );
- eq::EqClassIterator eqc( d_quantEngine->getEqualityQuery()->getRepresentative( n ),
- ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine() );
- while( !eqc.isFinished() ){
- Node en = (*eqc);
- if( en.getKind()==APPLY_UF && !en.hasAttribute(InstConstantAttribute()) ){
- if( !en.getAttribute(NoMatchAttribute()) ){
- Node op = en.getOperator();
- if( !d_pred_map_trie[i][op].addTerm( d_quantEngine, en ) ){
- NoMatchAttribute nma;
- en.setAttribute(nma,true);
- congruentCount++;
- }else{
- nonCongruentCount++;
- }
- }else{
- alreadyCongruentCount++;
- }
- }
- ++eqc;
- }
- }
- Debug("term-db-cong") << "TermDb: Reset" << std::endl;
- Debug("term-db-cong") << "Congruent/Non-Congruent = ";
- Debug("term-db-cong") << congruentCount << "(" << alreadyCongruentCount << ") / " << nonCongruentCount << std::endl;
+ //options
+ d_optInstCheckDuplicate = true;
+ d_optInstMakeRepresentative = true;
+ d_optInstAddSplits = false;
+ d_optMatchIgnoreModelBasis = false;
+ d_optInstLimitActive = false;
+ d_optInstLimit = 0;
}
+Instantiator* QuantifiersEngine::getInstantiator( int id ){
+ return d_te->getTheory( id )->getInstantiator();
+}
-
-QuantifiersEngine::QuantifiersEngine(context::Context* c, TheoryEngine* te):
-d_te( te ),
-d_forall_asserts( c ),
-d_active( c ){
- d_eq_query = NULL;
- d_term_db = new TermDb( this );
+context::Context* QuantifiersEngine::getSatContext(){
+ return d_te->getTheory( THEORY_QUANTIFIERS )->getSatContext();
}
-Instantiator* QuantifiersEngine::getInstantiator( int id ){
- return d_te->getTheory( id )->getInstantiator();
+OutputChannel& QuantifiersEngine::getOutputChannel(){
+ return d_te->getTheory( THEORY_QUANTIFIERS )->getOutputChannel();
+}
+/** get default valuation for the quantifiers engine */
+Valuation& QuantifiersEngine::getValuation(){
+ return d_te->getTheory( THEORY_QUANTIFIERS )->getValuation();
}
void QuantifiersEngine::check( Theory::Effort e ){
CodeTimer codeTimer(d_time);
+ d_hasAddedLemma = false;
+ d_model_set = false;
if( e==Theory::EFFORT_LAST_CALL ){
++(d_statistics.d_instantiation_rounds_lc);
}else if( e==Theory::EFFORT_FULL ){
@@ -210,9 +122,11 @@ void QuantifiersEngine::check( Theory::Effort e ){
for( int i=0; i<(int)d_modules.size(); i++ ){
d_modules[i]->check( e );
}
- //if( e==Theory::EFFORT_FULL ){
- // Notice() << "Done instantiation Round" << std::endl;
- //}
+ //build the model if not done so already
+ // this happens if no quantifiers are currently asserted and no model-building module is enabled
+ if( Options::current()->produceModels && e==Theory::EFFORT_LAST_CALL && !d_hasAddedLemma && !d_model_set ){
+ d_te->getModelBuilder()->buildModel( d_model );
+ }
}
std::vector<Node> QuantifiersEngine::createInstVariable( std::vector<Node> & vars ){
@@ -227,25 +141,9 @@ std::vector<Node> QuantifiersEngine::createInstVariable( std::vector<Node> & var
return inst_constant;
}
-void QuantifiersEngine::makeInstantiationConstantsFor( Node f ){
- if( d_inst_constants.find( f )==d_inst_constants.end() ){
- Debug("quantifiers-engine") << "Instantiation constants for " << f << " : " << std::endl;
- for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
- d_vars[f].push_back( f[0][i] );
- //make instantiation constants
- Node ic = NodeManager::currentNM()->mkInstConstant( f[0][i].getType() );
- d_inst_constants_map[ic] = f;
- d_inst_constants[ f ].push_back( ic );
- Debug("quantifiers-engine") << " " << ic << std::endl;
- //set the var number attribute
- InstVarNumAttribute ivna;
- ic.setAttribute(ivna,i);
- }
- }
-}
-
void QuantifiersEngine::registerQuantifier( Node f ){
if( std::find( d_quants.begin(), d_quants.end(), f )==d_quants.end() ){
+ d_quants.push_back( f );
std::vector< Node > quants;
#ifdef REWRITE_ASSERTED_QUANTIFIERS
//do assertion-time rewriting of quantifier
@@ -277,9 +175,9 @@ void QuantifiersEngine::registerQuantifier( Node f ){
++(d_statistics.d_num_quant);
Assert( quants[q].getKind()==FORALL );
//register quantifier
- d_quants.push_back( quants[q] );
+ d_r_quants.push_back( quants[q] );
//make instantiation constants for quants[q]
- makeInstantiationConstantsFor( quants[q] );
+ d_term_db->makeInstantiationConstantsFor( quants[q] );
//compute symbols in quants[q]
std::vector< Node > syms;
computeSymbols( quants[q][1], syms );
@@ -302,7 +200,7 @@ void QuantifiersEngine::registerQuantifier( Node f ){
for( int i=0; i<(int)d_modules.size(); i++ ){
d_modules[i]->registerQuantifier( quants[q] );
}
- Node ceBody = getCounterexampleBody( quants[q] );
+ Node ceBody = d_term_db->getCounterexampleBody( quants[q] );
generatePhaseReqs( quants[q], ceBody );
//also register it with the strong solver
if( Options::current()->finiteModelFind ){
@@ -315,14 +213,14 @@ void QuantifiersEngine::registerQuantifier( Node f ){
void QuantifiersEngine::registerPattern( std::vector<Node> & pattern) {
for(std::vector<Node>::iterator p = pattern.begin(); p != pattern.end(); ++p){
std::vector< Node > added;
- d_term_db->addTerm(*p,added);
+ getTermDatabase()->addTerm(*p,added);
}
}
void QuantifiersEngine::assertNode( Node f ){
Assert( f.getKind()==FORALL );
for( int j=0; j<(int)d_quant_rewritten[f].size(); j++ ){
- d_forall_asserts.push_back( d_quant_rewritten[f][j] );
+ d_model->d_forall_asserts.push_back( d_quant_rewritten[f][j] );
for( int i=0; i<(int)d_modules.size(); i++ ){
d_modules[i]->assertNode( d_quant_rewritten[f][j] );
}
@@ -337,20 +235,26 @@ void QuantifiersEngine::propagate( Theory::Effort level ){
}
}
+void QuantifiersEngine::resetInstantiationRound( Theory::Effort level ){
+ for( int i=0; i<theory::THEORY_LAST; i++ ){
+ if( getInstantiator( i ) ){
+ getInstantiator( i )->resetInstantiationRound( level );
+ }
+ }
+ getTermDatabase()->reset( level );
+}
+
void QuantifiersEngine::addTermToDatabase( Node n, bool withinQuant ){
- if( d_term_db ){
- std::vector< Node > added;
- d_term_db->addTerm( n, added, withinQuant );
+ std::vector< Node > added;
+ getTermDatabase()->addTerm( n, added, withinQuant );
#ifdef COMPUTE_RELEVANCE
- for( int i=0; i<(int)added.size(); i++ ){
- if( !withinQuant ){
- setRelevance( added[i].getOperator(), 0 );
- }
+ for( int i=0; i<(int)added.size(); i++ ){
+ if( !withinQuant ){
+ setRelevance( added[i].getOperator(), 0 );
}
-#endif
- }else{
- Notice() << "Warning: no term database for quantifier engine." << std::endl;
}
+#endif
+
}
bool QuantifiersEngine::addLemma( Node lem ){
@@ -377,8 +281,8 @@ bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& terms )
//}
Assert( f.getKind()==FORALL );
Assert( !f.hasAttribute(InstConstantAttribute()) );
- Assert( d_vars[f].size()==terms.size() && d_vars[f].size()==f[0].getNumChildren() );
- Node body = f[ 1 ].substitute( d_vars[f].begin(), d_vars[f].end(),
+ Assert( d_term_db->d_vars[f].size()==terms.size() && d_term_db->d_vars[f].size()==f[0].getNumChildren() );
+ Node body = f[ 1 ].substitute( d_term_db->d_vars[f].begin(), d_term_db->d_vars[f].end(),
terms.begin(), terms.end() );
NodeBuilder<> nb(kind::OR);
nb << d_rewritten_quant[f].notNode() << body;
@@ -411,11 +315,11 @@ bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& terms )
maxInstLevel = terms[i].getAttribute(InstLevelAttribute());
}
}else{
- setInstantiationLevelAttr( terms[i], 0 );
+ d_term_db->setInstantiationLevelAttr( terms[i], 0 );
}
}
}
- setInstantiationLevelAttr( body, maxInstLevel+1 );
+ d_term_db->setInstantiationLevelAttr( body, maxInstLevel+1 );
++(d_statistics.d_instantiations);
d_statistics.d_total_inst_var += (int)terms.size();
d_statistics.d_max_instantiation_level.maxAssign( maxInstLevel+1 );
@@ -426,7 +330,7 @@ bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& terms )
}
}
-bool QuantifiersEngine::addInstantiation( Node f, InstMatch& m, bool addSplits ){
+bool QuantifiersEngine::addInstantiation( Node f, InstMatch& m ){
m.makeComplete( f, this );
m.makeRepresentative( this );
Debug("quant-duplicate") << "After make rep: " << m << std::endl;
@@ -437,7 +341,7 @@ bool QuantifiersEngine::addInstantiation( Node f, InstMatch& m, bool addSplits )
}
Debug("quant-duplicate") << " -> Does not exist." << std::endl;
std::vector< Node > match;
- m.computeTermVec( d_inst_constants[f], match );
+ m.computeTermVec( d_term_db->d_inst_constants[f], match );
//old....
//m.makeRepresentative( d_eq_query );
@@ -494,40 +398,16 @@ bool QuantifiersEngine::addSplitEquality( Node n1, Node n2, bool reqPhase, bool
}
void QuantifiersEngine::flushLemmas( OutputChannel* out ){
- for( int i=0; i<(int)d_lemmas_waiting.size(); i++ ){
- out->lemma( d_lemmas_waiting[i] );
- }
- d_lemmas_waiting.clear();
-}
-
-Node QuantifiersEngine::getCounterexampleBody( Node f ){
- std::map< Node, Node >::iterator it = d_counterexample_body.find( f );
- if( it==d_counterexample_body.end() ){
- makeInstantiationConstantsFor( f );
- Node n = getSubstitutedNode( f[1], f );
- d_counterexample_body[ f ] = n;
- return n;
- }else{
- return it->second;
- }
-}
-
-Node QuantifiersEngine::getSkolemizedBody( Node f ){
- Assert( f.getKind()==FORALL );
- if( d_skolem_body.find( f )==d_skolem_body.end() ){
- std::vector< Node > vars;
- for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
- Node skv = NodeManager::currentNM()->mkSkolem( f[0][i].getType() );
- d_skolem_constants[ f ].push_back( skv );
- vars.push_back( f[0][i] );
- }
- d_skolem_body[ f ] = f[ 1 ].substitute( vars.begin(), vars.end(),
- d_skolem_constants[ f ].begin(), d_skolem_constants[ f ].end() );
- if( f.hasAttribute(InstLevelAttribute()) ){
- setInstantiationLevelAttr( d_skolem_body[ f ], f.getAttribute(InstLevelAttribute()) );
+ if( !d_lemmas_waiting.empty() ){
+ //take default output channel if none is provided
+ d_hasAddedLemma = true;
+ for( int i=0; i<(int)d_lemmas_waiting.size(); i++ ){
+ if( out ){
+ out->lemma( d_lemmas_waiting[i] );
+ }
}
+ d_lemmas_waiting.clear();
}
- return d_skolem_body[ f ];
}
void QuantifiersEngine::getPhaseReqTerms( Node f, std::vector< Node >& nodes ){
@@ -553,7 +433,7 @@ void QuantifiersEngine::getPhaseReqTerms( Node f, std::vector< Node >& nodes ){
}
Debug("literal-matching") << " Make " << prev << " -> " << nodes[i] << std::endl;
Assert( prev.hasAttribute(InstConstantAttribute()) );
- setInstantiationConstantAttr( nodes[i], prev.getAttribute(InstConstantAttribute()) );
+ d_term_db->setInstantiationConstantAttr( nodes[i], prev.getAttribute(InstConstantAttribute()) );
++(d_statistics.d_lit_phase_req);
}else{
++(d_statistics.d_lit_phase_nreq);
@@ -634,54 +514,6 @@ void QuantifiersEngine::generatePhaseReqs( Node f, Node n ){
}
-Node QuantifiersEngine::getSubstitutedNode( Node n, Node f ){
- return convertNodeToPattern(n,f,d_vars[f],d_inst_constants[ f ]);
-}
-
-Node QuantifiersEngine::convertNodeToPattern( Node n, Node f, const std::vector<Node> & vars,
- const std::vector<Node> & inst_constants){
- Node n2 = n.substitute( vars.begin(), vars.end(),
- inst_constants.begin(),
- inst_constants.end() );
- setInstantiationConstantAttr( n2, f );
- return n2;
-}
-
-
-void QuantifiersEngine::setInstantiationLevelAttr( Node n, uint64_t level ){
- if( !n.hasAttribute(InstLevelAttribute()) ){
- InstLevelAttribute ila;
- n.setAttribute(ila,level);
- }
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- setInstantiationLevelAttr( n[i], level );
- }
-}
-
-
-void QuantifiersEngine::setInstantiationConstantAttr( Node n, Node f ){
- if( !n.hasAttribute(InstConstantAttribute()) ){
- bool setAttr = false;
- if( n.getKind()==INST_CONSTANT ){
- setAttr = true;
- }else{
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- setInstantiationConstantAttr( n[i], f );
- if( n[i].hasAttribute(InstConstantAttribute()) ){
- setAttr = true;
- }
- }
- }
- if( setAttr ){
- InstConstantAttribute ica;
- n.setAttribute(ica,f);
- //also set the no-match attribute
- NoMatchAttribute nma;
- n.setAttribute(nma,true);
- }
- }
-}
-
QuantifiersEngine::Statistics::Statistics():
d_num_quant("QuantifiersEngine::Num_Quantifiers", 0),
d_instantiation_rounds("QuantifiersEngine::Rounds_Instantiation_Full", 0),
@@ -737,24 +569,6 @@ QuantifiersEngine::Statistics::~Statistics(){
StatisticsRegistry::unregisterStat(&d_multi_trigger_instantiations);
}
-Node QuantifiersEngine::getFreeVariableForInstConstant( Node n ){
- TypeNode tn = n.getType();
- if( d_free_vars.find( tn )==d_free_vars.end() ){
- //if integer or real, make zero
- if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){
- Rational z(0);
- d_free_vars[tn] = NodeManager::currentNM()->mkConst( z );
- }else{
- if( d_term_db->d_type_map[ tn ].empty() ){
- d_free_vars[tn] = NodeManager::currentNM()->mkVar( tn );
- }else{
- d_free_vars[tn] =d_term_db->d_type_map[ tn ][ 0 ];
- }
- }
- }
- return d_free_vars[tn];
-}
-
/** compute symbols */
void QuantifiersEngine::computeSymbols( Node n, std::vector< Node >& syms ){
if( n.getKind()==APPLY_UF ){
@@ -786,3 +600,87 @@ void QuantifiersEngine::setRelevance( Node s, int r ){
}
}
}
+
+
+
+bool EqualityQueryQuantifiersEngine::hasTerm( Node a ){
+ eq::EqualityEngine* ee = d_qe->getTheoryEngine()->getSharedTermsDatabase()->getEqualityEngine();
+ if( ee->hasTerm( a ) ){
+ return true;
+ }
+ for( int i=0; i<theory::THEORY_LAST; i++ ){
+ if( d_qe->getInstantiator( i ) ){
+ if( d_qe->getInstantiator( i )->hasTerm( a ) ){
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+Node EqualityQueryQuantifiersEngine::getRepresentative( Node a ){
+ eq::EqualityEngine* ee = d_qe->getTheoryEngine()->getSharedTermsDatabase()->getEqualityEngine();
+ if( ee->hasTerm( a ) ){
+ return ee->getRepresentative( a );
+ }
+ for( int i=0; i<theory::THEORY_LAST; i++ ){
+ if( d_qe->getInstantiator( i ) ){
+ if( d_qe->getInstantiator( i )->hasTerm( a ) ){
+ return d_qe->getInstantiator( i )->getRepresentative( a );
+ }
+ }
+ }
+ return a;
+}
+
+bool EqualityQueryQuantifiersEngine::areEqual( Node a, Node b ){
+ if( a==b ){
+ return true;
+ }else{
+ eq::EqualityEngine* ee = d_qe->getTheoryEngine()->getSharedTermsDatabase()->getEqualityEngine();
+ if( ee->hasTerm( a ) && ee->hasTerm( b ) ){
+ if( ee->areEqual( a, b ) ){
+ return true;
+ }
+ }
+ for( int i=0; i<theory::THEORY_LAST; i++ ){
+ if( d_qe->getInstantiator( i ) ){
+ if( d_qe->getInstantiator( i )->areEqual( a, b ) ){
+ return true;
+ }
+ }
+ }
+ //std::cout << "Equal = " << eq_sh << " " << eq_uf << " " << eq_a << " " << eq_dt << std::endl;
+ return false;
+ }
+}
+
+bool EqualityQueryQuantifiersEngine::areDisequal( Node a, Node b ){
+ eq::EqualityEngine* ee = d_qe->getTheoryEngine()->getSharedTermsDatabase()->getEqualityEngine();
+ if( ee->hasTerm( a ) && ee->hasTerm( b ) ){
+ if( ee->areDisequal( a, b, false ) ){
+ return true;
+ }
+ }
+ for( int i=0; i<theory::THEORY_LAST; i++ ){
+ if( d_qe->getInstantiator( i ) ){
+ if( d_qe->getInstantiator( i )->areDisequal( a, b ) ){
+ return true;
+ }
+ }
+ }
+ return false;
+ //std::cout << "Disequal = " << deq_sh << " " << deq_uf << " " << deq_a << " " << deq_dt << std::endl;
+}
+
+Node EqualityQueryQuantifiersEngine::getInternalRepresentative( Node a ){
+ //for( int i=0; i<theory::THEORY_LAST; i++ ){
+ // if( d_qe->getInstantiator( i ) ){
+ // if( d_qe->getInstantiator( i )->hasTerm( a ) ){
+ // return d_qe->getInstantiator( i )->getInternalRepresentative( a );
+ // }
+ // }
+ //}
+ //return a;
+ return d_qe->getInstantiator( THEORY_UF )->getInternalRepresentative( a );
+}
diff --git a/src/theory/quantifiers_engine.h b/src/theory/quantifiers_engine.h
index d0c5fb00b..5477214b0 100644
--- a/src/theory/quantifiers_engine.h
+++ b/src/theory/quantifiers_engine.h
@@ -66,7 +66,7 @@ protected:
/** reset instantiation */
virtual void processResetInstantiationRound( Theory::Effort effort ) = 0;
/** process method */
- virtual int process( Node f, Theory::Effort effort, int e, int limitInst = 0 ) = 0;
+ virtual int process( Node f, Theory::Effort effort, int e ) = 0;
public:
InstStrategy( QuantifiersEngine* ie ) : d_quantEngine( ie ){}
virtual ~InstStrategy(){}
@@ -74,7 +74,7 @@ public:
/** reset instantiation */
void resetInstantiationRound( Theory::Effort effort );
/** do instantiation round method */
- int doInstantiation( Node f, Theory::Effort effort, int e, int limitInst = 0 );
+ int doInstantiation( Node f, Theory::Effort effort, int e );
/** update status */
static void updateStatus( int& currStatus, int addStatus ){
if( addStatus==STATUS_UNFINISHED ){
@@ -99,9 +99,13 @@ public:
};/* class InstStrategy */
class QuantifiersModule {
+protected:
+ QuantifiersEngine* d_quantEngine;
public:
- QuantifiersModule(){}
+ QuantifiersModule( QuantifiersEngine* qe ) : d_quantEngine( qe ){}
~QuantifiersModule(){}
+ //get quantifiers engine
+ QuantifiersEngine* getQuantifiersEngine() { return d_quantEngine; }
/* Call during check registerQuantifier has already been called */
virtual void check( Theory::Effort e ) = 0;
/* Called for new quantifiers */
@@ -111,59 +115,17 @@ public:
virtual Node explain(TNode n) = 0;
};/* class QuantifiersModule */
-class TermArgTrie {
-private:
- bool addTerm2( QuantifiersEngine* qe, Node n, int argIndex );
-public:
- /** the data */
- std::map< Node, TermArgTrie > d_data;
-public:
- bool addTerm( QuantifiersEngine* qe, Node n ) { return addTerm2( qe, n, 0 ); }
-};/* class TermArgTrie */
-
-class TermDb {
-private:
- /** reference to the quantifiers engine */
- QuantifiersEngine* d_quantEngine;
- /** calculated no match terms */
- bool d_matching_active;
- /** terms processed */
- std::map< Node, bool > d_processed;
-public:
- TermDb( QuantifiersEngine* qe ) : d_quantEngine( qe ), d_matching_active( true ){}
- ~TermDb(){}
- /** map from APPLY_UF operators to ground terms for that operator */
- std::map< Node, std::vector< Node > > d_op_map;
- /** map from APPLY_UF functions to trie */
- std::map< Node, TermArgTrie > d_func_map_trie;
- /** map from APPLY_UF predicates to trie */
- std::map< Node, TermArgTrie > d_pred_map_trie[2];
- /** map from type nodes to terms of that type */
- std::map< TypeNode, std::vector< Node > > d_type_map;
- /** add a term to the database */
- void addTerm( Node n, std::vector< Node >& added, bool withinQuant = false );
- /** reset (calculate which terms are active) */
- void reset( Theory::Effort effort );
- /** set active */
- void setMatchingActive( bool a ) { d_matching_active = a; }
- /** get active */
- bool getMatchingActive() { return d_matching_active; }
-public:
- /** parent structure (for efficient E-matching):
- n -> op -> index -> L
- map from node "n" to a list of nodes "L", where each node n' in L
- has operator "op", and n'["index"] = n.
- for example, d_parents[n][f][1] = { f( t1, n ), f( t2, n ), ... }
- */
- std::map< Node, std::map< Node, std::map< int, std::vector< Node > > > > d_parents;
-};/* class TermDb */
-
namespace quantifiers {
class InstantiationEngine;
+ class ModelEngine;
+ class TermDb;
+ class FirstOrderModel;
}/* CVC4::theory::quantifiers */
+
class QuantifiersEngine {
friend class quantifiers::InstantiationEngine;
+ friend class quantifiers::ModelEngine;
friend class InstMatch;
private:
typedef context::CDHashMap< Node, bool, NodeHashFunction > BoolMap;
@@ -171,41 +133,35 @@ private:
TheoryEngine* d_te;
/** vector of modules for quantifiers */
std::vector< QuantifiersModule* > d_modules;
+ /** instantiation engine */
+ quantifiers::InstantiationEngine* d_inst_engine;
+ /** model engine */
+ quantifiers::ModelEngine* d_model_engine;
/** equality query class */
EqualityQuery* d_eq_query;
- /** list of all quantifiers */
+ /** list of all quantifiers (pre-rewrite) */
std::vector< Node > d_quants;
- /** list of quantifiers asserted in the current context */
- context::CDList<Node> d_forall_asserts;
- /** map from universal quantifiers to the list of variables */
- std::map< Node, std::vector< Node > > d_vars;
- /** map from universal quantifiers to the list of skolem constants */
- std::map< Node, std::vector< Node > > d_skolem_constants;
- /** map from universal quantifiers to their skolemized body */
- std::map< Node, Node > d_skolem_body;
- /** map from universal quantifiers to their bound body */
- std::map< Node, Node > d_bound_body;
- /** instantiation constants to universal quantifiers */
- std::map< Node, Node > d_inst_constants_map;
- /** map from universal quantifiers to their counterexample body */
- std::map< Node, Node > d_counterexample_body;
- /** map from universal quantifiers to the list of instantiation constants */
- std::map< Node, std::vector< Node > > d_inst_constants;
+ /** list of all quantifiers (post-rewrite) */
+ std::vector< Node > d_r_quants;
/** map from quantifiers to whether they are active */
BoolMap d_active;
/** lemmas produced */
std::map< Node, bool > d_lemmas_produced;
/** lemmas waiting */
std::vector< Node > d_lemmas_waiting;
+ /** has added lemma this round */
+ bool d_hasAddedLemma;
/** inst matches produced for each quantifier */
std::map< Node, InstMatchTrie > d_inst_match_trie;
- /** free variable for instantiation constant type */
- std::map< TypeNode, Node > d_free_vars;
/** owner of quantifiers */
std::map< Node, Theory* > d_owner;
/** term database */
- TermDb* d_term_db;
+ quantifiers::TermDb* d_term_db;
+ /** extended model object */
+ quantifiers::FirstOrderModel* d_model;
+ /** has the model been set? */
+ bool d_model_set;
/** universal quantifiers that have been rewritten */
std::map< Node, std::vector< Node > > d_quant_rewritten;
/** map from rewritten universal quantifiers to the quantifier they are the consequence of */
@@ -223,12 +179,6 @@ private:
private:
/** helper functions compute phase requirements */
static void computePhaseReqs2( Node n, bool polarity, std::map< Node, int >& phaseReqs );
- /** set instantiation level attr */
- void setInstantiationLevelAttr( Node n, uint64_t level );
- /** set instantiation constant attr */
- void setInstantiationConstantAttr( Node n, Node f );
- /** make instantiation constants for */
- void makeInstantiationConstantsFor( Node f );
KEEP_STATISTIC(TimerStat, d_time, "theory::QuantifiersEngine::time");
@@ -241,11 +191,17 @@ public:
TheoryEngine* getTheoryEngine() { return d_te; }
/** get equality query object */
EqualityQuery* getEqualityQuery() { return d_eq_query; }
- /** set equality query object */
- void setEqualityQuery( EqualityQuery* eq ) { d_eq_query = eq; }
+ /** get instantiation engine */
+ quantifiers::InstantiationEngine* getInstantiationEngine() { return d_inst_engine; }
+ /** get model engine */
+ quantifiers::ModelEngine* getModelEngine() { return d_model_engine; }
+ /** get default sat context for quantifiers engine */
+ context::Context* getSatContext();
+ /** get default output channel for the quantifiers engine */
+ OutputChannel& getOutputChannel();
+ /** get default valuation for the quantifiers engine */
+ Valuation& getValuation();
public:
- /** add module */
- void addModule( QuantifiersModule* qm ) { d_modules.push_back( qm ); }
/** check at level */
void check( Theory::Effort e );
/** register (non-rewritten) quantifier */
@@ -256,19 +212,24 @@ public:
void assertNode( Node f );
/** propagate */
void propagate( Theory::Effort level );
+ /** reset instantiation round */
+ void resetInstantiationRound( Theory::Effort level );
+
+ //create inst variable
+ std::vector<Node> createInstVariable( std::vector<Node> & vars );
public:
/** add lemma lem */
bool addLemma( Node lem );
/** instantiate f with arguments terms */
bool addInstantiation( Node f, std::vector< Node >& terms );
/** do instantiation specified by m */
- bool addInstantiation( Node f, InstMatch& m, bool addSplits = false );
+ bool addInstantiation( Node f, InstMatch& m );
/** split on node n */
bool addSplit( Node n, bool reqPhase = false, bool reqPhasePol = true );
/** add split equality */
bool addSplitEquality( Node n1, Node n2, bool reqPhase = false, bool reqPhasePol = true );
/** has added lemma */
- bool hasAddedLemma() { return !d_lemmas_waiting.empty(); }
+ bool hasAddedLemma() { return !d_lemmas_waiting.empty() || d_hasAddedLemma; }
/** flush lemmas */
void flushLemmas( OutputChannel* out );
/** get number of waiting lemmas */
@@ -278,24 +239,6 @@ public:
int getNumQuantifiers() { return (int)d_quants.size(); }
/** get quantifier */
Node getQuantifier( int i ) { return d_quants[i]; }
- /** get number of asserted quantifiers */
- int getNumAssertedQuantifiers() { return (int)d_forall_asserts.size(); }
- /** get asserted quantifier */
- Node getAssertedQuantifier( int i ) { return d_forall_asserts[i]; }
- /** get instantiation constants */
- void getInstantiationConstantsFor( Node f, std::vector< Node >& ics ) {
- ics.insert( ics.begin(), d_inst_constants[f].begin(), d_inst_constants[f].end() );
- }
- /** get the i^th instantiation constant of f */
- Node getInstantiationConstant( Node f, int i ) { return d_inst_constants[f][i]; }
- /** get number of instantiation constants for f */
- int getNumInstantiationConstants( Node f ) { return (int)d_inst_constants[f].size(); }
- std::vector<Node> createInstVariable( std::vector<Node> & vars );
-public:
- /** get the ce body f[e/x] */
- Node getCounterexampleBody( Node f );
- /** get the skolemized body f[e/x] */
- Node getSkolemizedBody( Node f );
/** set active */
void setActive( Node n, bool val ) { d_active[n] = val; }
/** get active */
@@ -317,26 +260,6 @@ public:
/** compute phase requirements */
void generatePhaseReqs( Node f, Node n );
public:
- /** returns node n with bound vars of f replaced by instantiation constants of f
- node n : is the futur pattern
- node f : is the quantifier containing which bind the variable
- return a pattern where the variable are replaced by variable for
- instantiation.
- */
- Node getSubstitutedNode( Node n, Node f );
- /** same as before but node f is just linked to the new pattern by the
- applied attribute
- vars the bind variable
- nvars the same variable but with an attribute
- */
- Node convertNodeToPattern( Node n, Node f,
- const std::vector<Node> & vars,
- const std::vector<Node> & nvars);
- /** get free variable for instantiation constant */
- Node getFreeVariableForInstConstant( Node n );
- /** get bound variable for variable */
- Node getBoundVariableForVariable( Node n );
-public:
/** has owner */
bool hasOwner( Node f ) { return d_owner.find( f )!=d_owner.end(); }
/** get owner */
@@ -344,8 +267,10 @@ public:
/** set owner */
void setOwner( Node f, Theory* t ) { d_owner[f] = t; }
public:
+ /** get model */
+ quantifiers::FirstOrderModel* getModel() { return d_model; }
/** get term database */
- TermDb* getTermDatabase() { return d_term_db; }
+ quantifiers::TermDb* getTermDatabase() { return d_term_db; }
/** add term to database */
void addTermToDatabase( Node n, bool withinQuant = false );
private:
@@ -380,8 +305,35 @@ public:
~Statistics();
};/* class QuantifiersEngine::Statistics */
Statistics d_statistics;
+public:
+ /** options */
+ bool d_optInstCheckDuplicate;
+ bool d_optInstMakeRepresentative;
+ bool d_optInstAddSplits;
+ bool d_optMatchIgnoreModelBasis;
+ bool d_optInstLimitActive;
+ int d_optInstLimit;
};/* class QuantifiersEngine */
+
+
+/** equality query object using theory engine */
+class EqualityQueryQuantifiersEngine : public EqualityQuery
+{
+private:
+ /** pointer to theory engine */
+ QuantifiersEngine* d_qe;
+public:
+ EqualityQueryQuantifiersEngine( QuantifiersEngine* qe ) : d_qe( qe ){}
+ ~EqualityQueryQuantifiersEngine(){}
+ /** general queries about equality */
+ bool hasTerm( Node a );
+ Node getRepresentative( Node a );
+ bool areEqual( Node a, Node b );
+ bool areDisequal( Node a, Node b );
+ Node getInternalRepresentative( Node a );
+}; /* EqualityQueryQuantifiersEngine */
+
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/rewriterules/theory_rewriterules.cpp b/src/theory/rewriterules/theory_rewriterules.cpp
index 0d7f5005a..265026b39 100644
--- a/src/theory/rewriterules/theory_rewriterules.cpp
+++ b/src/theory/rewriterules/theory_rewriterules.cpp
@@ -317,13 +317,14 @@ Answer TheoryRewriteRules::addWatchIfDontKnow(Node g0, const RuleInst* ri,
const size_t gid){
/** TODO: Should use the representative of g, but should I keep the
mapping for myself? */
- /* If it false in one model (current valuation) it's false for all */
- if (useCurrentModel){
- Node val = getValuation().getValue(g0);
- Debug("rewriterules") << "getValue:" << g0 << " = "
- << val << " is " << (val == d_false) << std::endl;
- if (val == d_false) return AFALSE;
- };
+ //AJR: removed this code after talking with Francois
+ ///* If it false in one model (current valuation) it's false for all */
+ //if (useCurrentModel){
+ // Node val = getValuation().getValue(g0);
+ // Debug("rewriterules") << "getValue:" << g0 << " = "
+ // << val << " is " << (val == d_false) << std::endl;
+ // if (val == d_false) return AFALSE;
+ //};
/** Currently create a node with a literal */
Node g = getValuation().ensureLiteral(g0);
GuardedMap::iterator l_i = d_guardeds.find(g);
@@ -508,6 +509,10 @@ Node TheoryRewriteRules::explain(TNode n){
return substGuards(&i, TCache ());
}
+void TheoryRewriteRules::collectModelInfo( TheoryModel* m ){
+
+}
+
Theory::PPAssertStatus TheoryRewriteRules::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
addRewriteRule(in);
return PP_ASSERT_STATUS_UNSOLVED;
diff --git a/src/theory/rewriterules/theory_rewriterules.h b/src/theory/rewriterules/theory_rewriterules.h
index e47fd2fd4..d1c3eecf3 100644
--- a/src/theory/rewriterules/theory_rewriterules.h
+++ b/src/theory/rewriterules/theory_rewriterules.h
@@ -30,6 +30,7 @@
#include "theory/inst_match_impl.h"
#include "util/stats.h"
#include "theory/rewriterules/theory_rewriterules_preprocess.h"
+#include "theory/model.h"
namespace CVC4 {
namespace theory {
@@ -182,6 +183,7 @@ private:
inside check */
typedef std::vector< RuleInst* > QRuleInsts;
QRuleInsts d_ruleinsts_to_add;
+
public:
/** true and false for predicate */
Node d_true;
@@ -199,6 +201,7 @@ private:
/** Usual function for theories */
void check(Theory::Effort e);
Node explain(TNode n);
+ void collectModelInfo( TheoryModel* m );
void notifyEq(TNode lhs, TNode rhs);
std::string identify() const {
return "THEORY_REWRITERULES";
diff --git a/src/theory/rewriterules/theory_rewriterules_rules.cpp b/src/theory/rewriterules/theory_rewriterules_rules.cpp
index d66fc78cb..c3116aba0 100644
--- a/src/theory/rewriterules/theory_rewriterules_rules.cpp
+++ b/src/theory/rewriterules/theory_rewriterules_rules.cpp
@@ -22,6 +22,8 @@
#include "theory/rewriterules/theory_rewriterules_preprocess.h"
#include "theory/rewriterules/theory_rewriterules.h"
+#include "theory/quantifiers/term_database.h"
+
using namespace std;
using namespace CVC4;
using namespace CVC4::kind;
@@ -72,7 +74,7 @@ inline void addPattern(TheoryRewriteRules & re,
TNode r){
if (tri.getKind() == kind::NOT && tri[0].getKind() == kind::APPLY_UF)
tri = tri[0];
- pattern.push_back(re.getQuantifiersEngine()->
+ pattern.push_back(re.getQuantifiersEngine()->getTermDatabase()->
convertNodeToPattern(tri,r,vars,inst_constants));
}
diff --git a/src/theory/shared_terms_database.h b/src/theory/shared_terms_database.h
index fb972b73f..7b6527517 100644
--- a/src/theory/shared_terms_database.h
+++ b/src/theory/shared_terms_database.h
@@ -123,14 +123,14 @@ private:
bool propagateEquality(TNode equality, bool polarity);
/** Theory engine */
- TheoryEngine* d_theoryEngine;
+ TheoryEngine* d_theoryEngine;
/** Are we in conflict */
context::CDO<bool> d_inConflict;
-
+
/** Conflicting terms, if any */
Node d_conflictLHS, d_conflictRHS;
-
+
/** Polarity of the conflict */
bool d_conflictPolarity;
@@ -166,7 +166,7 @@ public:
*/
bool isKnown(TNode literal) const;
- /**
+ /**
* Returns an explanation of the propagation that came from the database.
*/
Node explain(TNode literal) const;
@@ -175,10 +175,10 @@ public:
* Add an equality to propagate.
*/
void addEqualityToPropagate(TNode equality);
-
+
/**
- * Add a shared term to the database. The shared term is a subterm of the atom and
- * should be associated with the given theory.
+ * Add a shared term to the database. The shared term is a subterm of the atom and
+ * should be associated with the given theory.
*/
void addSharedTerm(TNode atom, TNode term, theory::Theory::Set theories);
@@ -211,7 +211,7 @@ public:
* Get the theories that share the term and have been notified already.
*/
theory::Theory::Set getNotifiedTheories(TNode term) const;
-
+
/**
* Returns true if the term is currently registered as shared with some theory.
*/
@@ -238,6 +238,10 @@ public:
*/
bool areDisequal(TNode a, TNode b) const;
+ /**
+ * get equality engine
+ */
+ theory::eq::EqualityEngine* getEqualityEngine() { return &d_equalityEngine; }
protected:
/**
diff --git a/src/theory/theory.cpp b/src/theory/theory.cpp
index 1dd0a1209..1301da653 100644
--- a/src/theory/theory.cpp
+++ b/src/theory/theory.cpp
@@ -78,21 +78,21 @@ TheoryId Theory::theoryOf(TheoryOfMode mode, TNode node) {
break;
case THEORY_OF_TERM_BASED:
// Variables
- if (node.getMetaKind() == kind::metakind::VARIABLE) {
- if (theoryOf(node.getType()) != theory::THEORY_BOOL) {
+ if (node.getMetaKind() == kind::metakind::VARIABLE) {
+ if (theoryOf(node.getType()) != theory::THEORY_BOOL) {
// We treat the varibables as uninterpreted
return s_uninterpretedSortOwner;
} else {
// Except for the Boolean ones, which we just ignore anyhow
return theory::THEORY_BOOL;
}
- }
+ }
// Constants
if (node.getMetaKind() == kind::metakind::CONSTANT) {
- // Constants go to the theory of the type
+ // Constants go to the theory of the type
return theoryOf(node.getType());
- }
- // Equality
+ }
+ // Equality
if (node.getKind() == kind::EQUAL) {
// If one of them is an ITE, it's irelevant, since they will get replaced out anyhow
if (node[0].getKind() == kind::ITE) {
@@ -100,7 +100,7 @@ TheoryId Theory::theoryOf(TheoryOfMode mode, TNode node) {
}
if (node[1].getKind() == kind::ITE) {
return theoryOf(node[1].getType());
- }
+ }
// If both sides belong to the same theory the choice is easy
TheoryId T1 = theoryOf(node[0]);
TheoryId T2 = theoryOf(node[1]);
@@ -108,12 +108,12 @@ TheoryId Theory::theoryOf(TheoryOfMode mode, TNode node) {
return T1;
}
TheoryId T3 = theoryOf(node[0].getType());
- // This is a case of
+ // This is a case of
// * x*y = f(z) -> UF
// * x = c -> UF
// * f(x) = read(a, y) -> either UF or ARRAY
// at least one of the theories has to be parametric, i.e. theory of the type is different
- // from the theory of the term
+ // from the theory of the term
if (T1 == T3) {
return T2;
}
@@ -122,13 +122,13 @@ TheoryId Theory::theoryOf(TheoryOfMode mode, TNode node) {
}
// If both are parametric, we take the smaller one (arbitraty)
return T1 < T2 ? T1 : T2;
- }
+ }
// Regular nodes are owned by the kind
- return kindToTheoryId(node.getKind());
- break;
+ return kindToTheoryId(node.getKind());
+ break;
default:
Unreachable();
- }
+ }
}
void Theory::addSharedTermInternal(TNode n) {
@@ -194,31 +194,21 @@ void Instantiator::resetInstantiationRound(Theory::Effort effort) {
processResetInstantiationRound(effort);
}
-int Instantiator::doInstantiation(Node f, Theory::Effort effort, int e, int limitInst) {
+int Instantiator::doInstantiation(Node f, Theory::Effort effort, int e ) {
if(hasConstraintsFrom(f)) {
- int origLemmas = d_quantEngine->getNumLemmasWaiting();
- int status = process(f, effort, e, limitInst);
- if(limitInst <= 0 || (d_quantEngine->getNumLemmasWaiting()-origLemmas) < limitInst) {
- if(d_instStrategies.empty()) {
- Debug("inst-engine-inst") << "There are no instantiation strategies allocated." << endl;
- } else {
- for(int i = 0; i < (int) d_instStrategies.size(); ++i) {
- if(isActiveStrategy(d_instStrategies[i])) {
- Debug("inst-engine-inst") << d_instStrategies[i]->identify() << " process " << effort << endl;
- //call the instantiation strategy's process method
- int s_limitInst = limitInst > 0 ? limitInst - (d_quantEngine->getNumLemmasWaiting() - origLemmas) : 0;
- int s_status = d_instStrategies[i]->doInstantiation(f, effort, e, s_limitInst);
- Debug("inst-engine-inst") << " -> status is " << s_status << endl;
- if(limitInst > 0 && (d_quantEngine->getNumLemmasWaiting() - origLemmas) >= limitInst) {
- Assert( (d_quantEngine->getNumLemmasWaiting() - origLemmas) == limitInst );
- i = (int) d_instStrategies.size();
- status = InstStrategy::STATUS_UNKNOWN;
- } else {
- InstStrategy::updateStatus(status, s_status);
- }
- } else {
- Debug("inst-engine-inst") << d_instStrategies[i]->identify() << " is not active." << endl;
- }
+ int status = process(f, effort, e );
+ if(d_instStrategies.empty()) {
+ Debug("inst-engine-inst") << "There are no instantiation strategies allocated." << endl;
+ } else {
+ for(int i = 0; i < (int) d_instStrategies.size(); ++i) {
+ if(isActiveStrategy(d_instStrategies[i])) {
+ Debug("inst-engine-inst") << d_instStrategies[i]->identify() << " process " << effort << endl;
+ //call the instantiation strategy's process method
+ int s_status = d_instStrategies[i]->doInstantiation( f, effort, e );
+ Debug("inst-engine-inst") << " -> status is " << s_status << endl;
+ InstStrategy::updateStatus(status, s_status);
+ } else {
+ Debug("inst-engine-inst") << d_instStrategies[i]->identify() << " is not active." << endl;
}
}
}
diff --git a/src/theory/theory.h b/src/theory/theory.h
index 217972dce..7d003bf25 100644
--- a/src/theory/theory.h
+++ b/src/theory/theory.h
@@ -50,6 +50,7 @@ namespace theory {
class Instantiator;
class InstStrategy;
class QuantifiersEngine;
+class TheoryModel;
/**
* Information about an assertion for the theories.
@@ -330,12 +331,12 @@ public:
static inline TheoryId theoryOf(TNode node) {
return theoryOf(s_theoryOfMode, node);
}
-
+
/** Set the theoryOf mode */
static void setTheoryOfMode(TheoryOfMode mode) {
s_theoryOfMode = mode;
}
-
+
/**
* Set the owner of the uninterpreted sort.
*/
@@ -545,40 +546,13 @@ public:
}
/**
- * Return the value of a node (typically used after a ). If the
- * theory supports model generation but has no value for this node,
- * it should return Node::null(). If the theory doesn't support
- * model generation at all, or usually would but doesn't in its
- * current state, it should throw an exception saying so.
- *
- * The TheoryEngine is passed in so that you can recursively request
- * values for the Node's children. This is important because the
- * TheoryEngine takes care of simple cases (metakind CONSTANT,
- * Boolean-valued VARIABLES, ...) and can dispatch to other theories
- * if that's necessary. Only call your own getValue() recursively
- * if you *know* that you are responsible handle the Node you're
- * asking for; other theories can use your types, so be careful
- * here! To be safe, it's best to delegate back to the
- * TheoryEngine (by way of the Valuation proxy object, which avoids
- * direct dependence on TheoryEngine).
- *
- * Usually, you need to handle at least the two cases of EQUAL and
- * VARIABLE---EQUAL in case a value of yours is on the LHS of an
- * EQUAL, and VARIABLE for variables of your types. You also need
- * to support any operators that can survive your rewriter. You
- * don't need to handle constants, as they are handled by the
- * TheoryEngine.
- *
- * There are some gotchas here. The user may be requesting the
- * value of an expression that wasn't part of the satisfiable
- * assertion, or has been declared since. If you don't have a value
- * and suspect this situation is the case, return Node::null()
- * rather than throwing an exception.
- */
- virtual Node getValue(TNode n) {
- Unimplemented("Theory %s doesn't support Theory::getValue interface",
+ * Get all relevant information in this theory regarding the current
+ * model. This should be called after a call to check( FULL_EFFORT )
+ * for all theories with no conflicts and no lemmas added.
+ */
+ virtual void collectModelInfo( TheoryModel* m ){
+ Unimplemented("Theory %s doesn't support Theory::getModel interface",
identify().c_str());
- return Node::null();
}
/**
@@ -824,7 +798,7 @@ protected:
/** reset instantiation round */
virtual void processResetInstantiationRound( Theory::Effort effort ) = 0;
/** process quantifier */
- virtual int process( Node f, Theory::Effort effort, int e, int limitInst = 0 ) = 0;
+ virtual int process( Node f, Theory::Effort effort, int e ) = 0;
public:
/** set has constraints from quantifier f */
void setHasConstraintsFrom( Node f );
@@ -844,16 +818,22 @@ public:
virtual void preRegisterTerm( Node t ) { }
/** assertNode function, assertion was asserted to theory */
virtual void assertNode( Node assertion ){}
- /** reset instantiation round */
- void resetInstantiationRound( Theory::Effort effort );
- /** do instantiation method*/
- int doInstantiation( Node f, Theory::Effort effort, int e, int limitInst = 0 );
/** identify */
virtual std::string identify() const { return std::string("Unknown"); }
/** print debug information */
virtual void debugPrint( const char* c ) {}
- /** get status */
- //int getStatus() { return d_status; }
+public:
+ /** reset instantiation round */
+ void resetInstantiationRound( Theory::Effort effort );
+ /** do instantiation method*/
+ int doInstantiation( Node f, Theory::Effort effort, int e );
+public:
+ /** general queries about equality */
+ virtual bool hasTerm( Node a ) { return false; }
+ virtual bool areEqual( Node a, Node b ) { return false; }
+ virtual bool areDisequal( Node a, Node b ) { return false; }
+ virtual Node getRepresentative( Node a ) { return a; }
+ virtual Node getInternalRepresentative( Node a ) { return getRepresentative( a ); }
};/* class Instantiator */
inline Assertion Theory::get() {
diff --git a/src/theory/theory_engine.cpp b/src/theory/theory_engine.cpp
index 50682f647..872924385 100644
--- a/src/theory/theory_engine.cpp
+++ b/src/theory/theory_engine.cpp
@@ -35,8 +35,11 @@
#include "util/node_visitor.h"
#include "util/ite_removal.h"
+#include "theory/model.h"
#include "theory/quantifiers_engine.h"
#include "theory/quantifiers/theory_quantifiers.h"
+#include "theory/quantifiers/model_engine.h"
+#include "theory/quantifiers/first_order_model.h"
using namespace std;
@@ -53,6 +56,8 @@ TheoryEngine::TheoryEngine(context::Context* context,
d_logicInfo(logicInfo),
d_sharedTerms(this, context),
d_quantEngine(NULL),
+ d_curr_model(NULL),
+ d_curr_model_builder(NULL),
d_ppCache(),
d_possiblePropagations(context),
d_hasPropagated(context),
@@ -80,6 +85,10 @@ TheoryEngine::TheoryEngine(context::Context* context,
// initialize the quantifiers engine
d_quantEngine = new QuantifiersEngine(context, this);
+ //build model information if applicable
+ d_curr_model = new theory::DefaultModel( context, "DefaultModel" );
+ d_curr_model_builder = new theory::TheoryEngineModelBuilder( this );
+
Rewriter::init();
StatisticsRegistry::registerStat(&d_combineTheoriesTime);
d_true = NodeManager::currentNM()->mkConst<bool>(true);
@@ -175,7 +184,7 @@ void TheoryEngine::dumpAssertions(const char* tag) {
Dump(tag) << CommentCommand("Completeness check");
Dump(tag) << PushCommand();
- // Dump the shared terms
+ // Dump the shared terms
if (d_logicInfo.isSharingEnabled()) {
Dump(tag) << CommentCommand("Shared terms");
context::CDList<TNode>::const_iterator it = theory->shared_terms_begin(), it_end = theory->shared_terms_end();
@@ -186,14 +195,14 @@ void TheoryEngine::dumpAssertions(const char* tag) {
}
}
- // Dump the assertions
+ // Dump the assertions
Dump(tag) << CommentCommand("Assertions");
context::CDList<Assertion>::const_iterator it = theory->facts_begin(), it_end = theory->facts_end();
for (; it != it_end; ++ it) {
// Get the assertion
Node assertionNode = (*it).assertion;
// Purify all the terms
-
+
BoolExpr assertionExpr(assertionNode.toExpr());
if ((*it).isPreregistered) {
Dump(tag) << CommentCommand("Preregistered");
@@ -223,24 +232,24 @@ void TheoryEngine::dumpAssertions(const char* tag) {
continue;
}
- // Check equality
+ // Check equality
Dump(tag) << PushCommand();
BoolExpr eqExpr(equality.toExpr());
Dump(tag) << AssertCommand(eqExpr);
- Dump(tag) << CheckSatCommand();
+ Dump(tag) << CheckSatCommand();
Dump(tag) << PopCommand();
- // Check disequality
+ // Check disequality
Dump(tag) << PushCommand();
BoolExpr diseqExpr(disequality.toExpr());
Dump(tag) << AssertCommand(diseqExpr);
- Dump(tag) << CheckSatCommand();
- Dump(tag) << PopCommand();
+ Dump(tag) << CheckSatCommand();
+ Dump(tag) << PopCommand();
}
}
}
}
-
+
Dump(tag) << PopCommand();
}
}
@@ -297,8 +306,8 @@ void TheoryEngine::check(Theory::Effort effort) {
// If in full effort, we have a fake new assertion just to jumpstart the checking
if (Theory::fullEffort(effort)) {
d_factsAsserted = true;
- }
-
+ }
+
// Check until done
while (d_factsAsserted && !d_inConflict && !d_lemmasAdded) {
@@ -335,17 +344,22 @@ void TheoryEngine::check(Theory::Effort effort) {
// Must consult quantifiers theory for last call to ensure sat, or otherwise add a lemma
if( effort == Theory::EFFORT_FULL &&
- d_logicInfo.isQuantified() &&
! d_inConflict &&
! d_lemmasAdded ) {
- ((theory::quantifiers::TheoryQuantifiers*) d_theoryTable[THEORY_QUANTIFIERS])->performCheck(Theory::EFFORT_LAST_CALL);
- // if we have given up, then possibly flip decision
- if(Options::current()->flipDecision) {
- if(d_incomplete && !d_inConflict && !d_lemmasAdded) {
- if( ((theory::quantifiers::TheoryQuantifiers*) d_theoryTable[THEORY_QUANTIFIERS])->flipDecision() ) {
- d_incomplete = false;
+ if( d_logicInfo.isQuantified() ){
+ ((theory::quantifiers::TheoryQuantifiers*) d_theoryTable[THEORY_QUANTIFIERS])->performCheck(Theory::EFFORT_LAST_CALL);
+ // if we have given up, then possibly flip decision
+ if(Options::current()->flipDecision) {
+ if(d_incomplete && !d_inConflict && !d_lemmasAdded) {
+ if( ((theory::quantifiers::TheoryQuantifiers*) d_theoryTable[THEORY_QUANTIFIERS])->flipDecision() ) {
+ d_incomplete = false;
+ }
}
}
+ //if returning incomplete or SAT, we have ensured that the model in the quantifiers engine has been built
+ }else if( Options::current()->produceModels ){
+ //must build model at this point
+ d_curr_model_builder->buildModel( d_curr_model );
}
}
@@ -354,8 +368,8 @@ void TheoryEngine::check(Theory::Effort effort) {
} catch(const theory::Interrupted&) {
Trace("theory") << "TheoryEngine::check() => conflict" << endl;
}
-
- // If fulleffort, check all theories
+
+ // If fulleffort, check all theories
if(Dump.isOn("theory::fullcheck") && Theory::fullEffort(effort)) {
if (!d_inConflict && !d_lemmasAdded) {
dumpAssertions("theory::fullcheck");
@@ -415,7 +429,7 @@ void TheoryEngine::combineTheories() {
Node literal = value ? equality : equality.notNode();
Node normalizedLiteral = value ? normalizedEquality : normalizedEquality.notNode();
// We're sending the original literal back, backed by the normalized one
- if (markPropagation(literal, normalizedLiteral, /* to */ carePair.theory, /* from */ THEORY_SAT_SOLVER)) {
+ if (markPropagation(literal, normalizedLiteral, /* to */ carePair.theory, /* from */ THEORY_SAT_SOLVER)) {
// We assert it, and we know it's preregistereed if it's the same theory
bool preregistered = Theory::theoryOf(literal) == carePair.theory;
theoryOf(carePair.theory)->assertFact(literal, preregistered);
@@ -427,7 +441,7 @@ void TheoryEngine::combineTheories() {
}
}
}
-
+
// We need to split on it
Debug("sharing") << "TheoryEngine::combineTheories(): requesting a split " << std::endl;
lemma(equality.orNode(equality.notNode()), false, false);
@@ -528,23 +542,26 @@ bool TheoryEngine::properExplanation(TNode node, TNode expl) const {
return true;
}
-Node TheoryEngine::getValue(TNode node) {
- kind::MetaKind metakind = node.getMetaKind();
-
- // special case: prop engine handles boolean vars
- if(metakind == kind::metakind::VARIABLE && node.getType().isBoolean()) {
- return d_propEngine->getValue(node);
+void TheoryEngine::collectModelInfo( theory::TheoryModel* m ){
+ //consult each theory to get all relevant information concerning the model
+ for( int i=0; i<theory::THEORY_LAST; i++ ){
+ if( d_theoryTable[i] ){
+ d_theoryTable[i]->collectModelInfo( m );
+ }
}
+}
- // special case: value of a constant == itself
- if(metakind == kind::metakind::CONSTANT) {
- return node;
+/* get model */
+TheoryModel* TheoryEngine::getModel(){
+ Debug("model") << "TheoryEngine::getModel()" << std::endl;
+ if( d_logicInfo.isQuantified() ){
+ Debug("model") << "Get model from quantifiers engine." << std::endl;
+ return d_quantEngine->getModel();
+ }else{
+ Debug("model") << "Get default model." << std::endl;
+ return d_curr_model;
}
-
- // otherwise ask the theory-in-charge
- return theoryOf(node)->getValue(node);
-
-}/* TheoryEngine::getValue(TNode node) */
+}
bool TheoryEngine::presolve() {
@@ -777,7 +794,7 @@ bool TheoryEngine::markPropagation(TNode assertion, TNode originalAssertion, the
// What and where it came from
NodeTheoryPair toExplain(originalAssertion, fromTheoryId, d_propagationMapTimestamp);
- // See if the theory already got this literal
+ // See if the theory already got this literal
PropagationMap::const_iterator find = d_propagationMap.find(toAssert);
if (find != d_propagationMap.end()) {
// The theory already knows this
@@ -796,11 +813,11 @@ bool TheoryEngine::markPropagation(TNode assertion, TNode originalAssertion, the
void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId, theory::TheoryId fromTheoryId) {
-
+
Trace("theory::assertToTheory") << "TheoryEngine::assertToTheory(" << assertion << ", " << toTheoryId << ", " << fromTheoryId << ")" << std::endl;
-
+
Assert(toTheoryId != fromTheoryId);
-
+
if (d_inConflict) {
return;
}
@@ -813,7 +830,7 @@ void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId,
// We assert it, and we know it's preregistereed
toTheory->assertFact(assertion, true);
// Mark that we have more information
- d_factsAsserted = true;
+ d_factsAsserted = true;
} else {
Assert(toTheoryId == THEORY_SAT_SOLVER);
// Check for propositional conflict
@@ -825,18 +842,18 @@ void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId,
} else {
return;
}
- }
+ }
d_propagatedLiterals.push_back(assertion);
}
return;
}
-
+
// Polarity of the assertion
bool polarity = assertion.getKind() != kind::NOT;
-
+
// Atom of the assertion
TNode atom = polarity ? assertion : assertion[0];
-
+
// If sending to the shared terms database, it's also simple
if (toTheoryId == THEORY_BUILTIN) {
Assert(atom.getKind() == kind::EQUAL);
@@ -845,11 +862,11 @@ void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId,
}
return;
}
-
- // Things from the SAT solver are already normalized, so they go
+
+ // Things from the SAT solver are already normalized, so they go
// directly to the apropriate theory
if (fromTheoryId == THEORY_SAT_SOLVER) {
- // We know that this is normalized, so just send it off to the theory
+ // We know that this is normalized, so just send it off to the theory
if (markPropagation(assertion, assertion, toTheoryId, fromTheoryId)) {
// We assert it, and we know it's preregistereed coming from the SAT solver directly
theoryOf(toTheoryId)->assertFact(assertion, true);
@@ -858,7 +875,7 @@ void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId,
}
return;
}
-
+
// Propagations to the SAT solver are just enqueued for pickup by
// the SAT solver later
if (toTheoryId == THEORY_SAT_SOLVER) {
@@ -898,14 +915,14 @@ void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId,
// Normalize to lhs < rhs if not a sat literal
Assert(atom.getKind() == kind::EQUAL);
Assert(atom[0] != atom[1]);
-
+
Node normalizedAtom = atom;
if (!d_propEngine->isSatLiteral(normalizedAtom)) {
Node reverse = atom[1].eqNode(atom[0]);
if (d_propEngine->isSatLiteral(reverse) || atom[0] > atom[1]) {
normalizedAtom = reverse;
- }
- }
+ }
+ }
Node normalizedAssertion = polarity ? normalizedAtom : normalizedAtom.notNode();
// Try and assert (note that we assert the non-normalized one)
@@ -915,7 +932,7 @@ void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId,
// Assert away
theoryOf(toTheoryId)->assertFact(normalizedAssertion, preregistered);
d_factsAsserted = true;
- }
+ }
return;
}
@@ -923,7 +940,7 @@ void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId,
void TheoryEngine::assertFact(TNode literal)
{
Trace("theory") << "TheoryEngine::assertFact(" << literal << ")" << std::endl;
-
+
d_propEngine->checkTime();
// If we're in conflict, nothing to do
@@ -997,7 +1014,7 @@ bool TheoryEngine::propagate(TNode literal, theory::TheoryId theory) {
}
if (theory != THEORY_BUILTIN) {
// Assert to the shared terms database
- assertToTheory(literal, /* to */ THEORY_BUILTIN, /* from */ theory);
+ assertToTheory(literal, /* to */ THEORY_BUILTIN, /* from */ theory);
}
} else {
// Just send off to the SAT solver
@@ -1075,7 +1092,7 @@ Node TheoryEngine::getExplanation(TNode node) {
return explanation;
}
- // Initial thing to explain
+ // Initial thing to explain
NodeTheoryPair toExplain(node, THEORY_SAT_SOLVER, d_propagationMapTimestamp);
Assert(d_propagationMap.find(toExplain) != d_propagationMap.end());
// Create the workplace for explanations
@@ -1084,9 +1101,9 @@ Node TheoryEngine::getExplanation(TNode node) {
// Process the explanation
getExplanation(explanationVector);
Node explanation = mkExplanation(explanationVector);
-
+
Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << ") => " << explanation << std::endl;
-
+
return explanation;
}
@@ -1131,7 +1148,7 @@ theory::LemmaStatus TheoryEngine::lemma(TNode node, bool negated, bool removable
if(!removable) {
d_decisionEngine->addAssertions(additionalLemmas, 1, iteSkolemMap);
}
-
+
// Mark that we added some lemmas
d_lemmasAdded = true;
@@ -1151,7 +1168,7 @@ void TheoryEngine::conflict(TNode conflict, TheoryId theoryId) {
Dump("t-conflicts") << CommentCommand("theory conflict: expect unsat")
<< CheckSatCommand(conflict.toExpr());
}
-
+
// In the multiple-theories case, we need to reconstruct the conflict
if (d_logicInfo.isSharingEnabled()) {
// Create the workplace for explanations
@@ -1184,9 +1201,9 @@ void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector
unsigned i = 0; // Index of the current literal we are processing
unsigned j = 0; // Index of the last literal we are keeping
-
+
while (i < explanationVector.size()) {
-
+
// Get the current literal to explain
NodeTheoryPair toExplain = explanationVector[i];
@@ -1196,7 +1213,7 @@ void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector
if (toExplain.node.isConst() && toExplain.node.getConst<bool>()) {
++ i;
continue;
- }
+ }
if (toExplain.node.getKind() == kind::NOT && toExplain.node[0].isConst() && !toExplain.node[0].getConst<bool>()) {
++ i;
continue;
@@ -1219,7 +1236,7 @@ void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector
continue;
}
- // See if it was sent to the theory by another theory
+ // See if it was sent to the theory by another theory
PropagationMap::const_iterator find = d_propagationMap.find(toExplain);
if (find != d_propagationMap.end()) {
// There is some propagation, check if its a timely one
@@ -1244,10 +1261,10 @@ void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector
explanationVector.push_back(newExplain);
++ i;
}
-
+
// Keep only the relevant literals
explanationVector.resize(j);
-}
+}
void TheoryEngine::ppUnconstrainedSimp(vector<Node>& assertions)
diff --git a/src/theory/theory_engine.h b/src/theory/theory_engine.h
index 3d70ffa6b..f55c7c258 100644
--- a/src/theory/theory_engine.h
+++ b/src/theory/theory_engine.h
@@ -42,13 +42,14 @@
#include "util/cache.h"
#include "theory/ite_simplifier.h"
#include "theory/unconstrained_simplifier.h"
+#include "theory/model.h"
namespace CVC4 {
/**
- * A pair of a theory and a node. This is used to mark the flow of
+ * A pair of a theory and a node. This is used to mark the flow of
* propagations between theories.
- */
+ */
struct NodeTheoryPair {
Node node;
theory::TheoryId theory;
@@ -57,7 +58,7 @@ struct NodeTheoryPair {
: node(node), theory(theory), timestamp(timestamp) {}
NodeTheoryPair()
: theory(theory::THEORY_LAST) {}
- // Comparison doesn't take into account the timestamp
+ // Comparison doesn't take into account the timestamp
bool operator == (const NodeTheoryPair& pair) const {
return node == pair.node && theory == pair.theory;
}
@@ -84,7 +85,7 @@ class DecisionEngine;
* CVC4.
*/
class TheoryEngine {
-
+
/** Shared terms database can use the internals notify the theories */
friend class SharedTermsDatabase;
@@ -125,6 +126,15 @@ class TheoryEngine {
*/
theory::QuantifiersEngine* d_quantEngine;
+ /**
+ * Default model object
+ */
+ theory::DefaultModel* d_curr_model;
+ /**
+ * Model builder object
+ */
+ theory::TheoryEngineModelBuilder* d_curr_model_builder;
+
typedef std::hash_map<Node, Node, NodeHashFunction> NodeMap;
typedef std::hash_map<TNode, Node, TNodeHashFunction> TNodeMap;
@@ -389,7 +399,7 @@ class TheoryEngine {
* Adds a new lemma, returning its status.
*/
theory::LemmaStatus lemma(TNode node, bool negated, bool removable);
-
+
/** Time spent in theory combination */
TimerStat d_combineTheoriesTime;
@@ -433,6 +443,13 @@ public:
}
/**
+ * Get a pointer to the underlying sat context.
+ */
+ inline context::Context* getSatContext() const {
+ return d_context;
+ }
+
+ /**
* Get a pointer to the underlying quantifiers engine.
*/
theory::QuantifiersEngine* getQuantifiersEngine() const {
@@ -472,12 +489,12 @@ private:
void assertToTheory(TNode assertion, theory::TheoryId toTheoryId, theory::TheoryId fromTheoryId);
/**
- * Marks a theory propagation from a theory to a theory where a
+ * Marks a theory propagation from a theory to a theory where a
* theory could be the THEORY_SAT_SOLVER for literals coming from
* or being propagated to the SAT solver. If the receiving theory
* already recieved the literal, the method returns false, otherwise
* it returns true.
- *
+ *
* @param assertion the normalized assertion being sent
* @param originalAssertion the actual assertion that was sent
* @param toTheoryId the theory that is on the receiving end
@@ -488,7 +505,7 @@ private:
/**
* Computes the explanation by travarsing the propagation graph and
- * asking relevant theories to explain the propagations. Initially
+ * asking relevant theories to explain the propagations. Initially
* the explanation vector should contain only the element (node, theory)
* where the node is the one to be explained, and the theory is the
* theory that sent the literal.
@@ -623,9 +640,19 @@ public:
Node getExplanation(TNode node);
/**
- * Returns the value of the given node.
+ * collect model info
+ */
+ void collectModelInfo( theory::TheoryModel* m );
+
+ /**
+ * Get the current model
*/
- Node getValue(TNode node);
+ theory::TheoryModel* getModel();
+
+ /**
+ * Get the model builder
+ */
+ theory::TheoryEngineModelBuilder* getModelBuilder() { return d_curr_model_builder; }
/**
* Get the theory associated to a given Node.
@@ -685,6 +712,8 @@ public:
Node ppSimpITE(TNode assertion);
void ppUnconstrainedSimp(std::vector<Node>& assertions);
+ SharedTermsDatabase* getSharedTermsDatabase() { return &d_sharedTerms; }
+
};/* class TheoryEngine */
}/* CVC4 namespace */
diff --git a/src/theory/trigger.cpp b/src/theory/trigger.cpp
index d665fef91..55ca07d77 100644
--- a/src/theory/trigger.cpp
+++ b/src/theory/trigger.cpp
@@ -144,8 +144,8 @@ int Trigger::addTerm( Node t ){
return d_mg->addTerm( d_f, t, d_quantEngine );
}
-int Trigger::addInstantiations( InstMatch& baseMatch, int instLimit, bool addSplits ){
- int addedLemmas = d_mg->addInstantiations( d_f, baseMatch, d_quantEngine, instLimit, addSplits );
+int Trigger::addInstantiations( InstMatch& baseMatch ){
+ int addedLemmas = d_mg->addInstantiations( d_f, baseMatch, d_quantEngine );
if( addedLemmas>0 ){
Debug("inst-trigger") << "Added " << addedLemmas << " lemmas, trigger was ";
for( int i=0; i<(int)d_nodes.size(); i++ ){
diff --git a/src/theory/trigger.h b/src/theory/trigger.h
index 457df0ab4..476ef392e 100644
--- a/src/theory/trigger.h
+++ b/src/theory/trigger.h
@@ -97,7 +97,7 @@ public:
public:
/** add all available instantiations exhaustively, in any equivalence class
if limitInst>0, limitInst is the max # of instantiations to try */
- int addInstantiations( InstMatch& baseMatch, int instLimit = 0, bool addSplits = false );
+ int addInstantiations( InstMatch& baseMatch );
/** mkTrigger method
ie : quantifier engine;
f : forall something ....
diff --git a/src/theory/uf/Makefile.am b/src/theory/uf/Makefile.am
index 2c9cd3b80..b8446761c 100644
--- a/src/theory/uf/Makefile.am
+++ b/src/theory/uf/Makefile.am
@@ -22,6 +22,8 @@ libuf_la_SOURCES = \
theory_uf_candidate_generator.h \
theory_uf_candidate_generator.cpp \
inst_strategy.h \
- inst_strategy.cpp
+ inst_strategy.cpp \
+ theory_uf_model.h \
+ theory_uf_model.cpp
EXTRA_DIST = kinds
diff --git a/src/theory/uf/inst_strategy.cpp b/src/theory/uf/inst_strategy.cpp
index 2ca2dcb5a..669df055a 100644
--- a/src/theory/uf/inst_strategy.cpp
+++ b/src/theory/uf/inst_strategy.cpp
@@ -20,6 +20,7 @@
#include "theory/theory_engine.h"
#include "theory/uf/theory_uf.h"
#include "theory/uf/equality_engine.h"
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
@@ -34,7 +35,7 @@ using namespace CVC4::theory::uf;
struct sortQuantifiersForSymbol {
QuantifiersEngine* d_qe;
- bool operator() (Node i, Node j) {
+ bool operator() (Node i, Node j) {
int nqfsi = d_qe->getNumQuantifiersForSymbol( i.getOperator() );
int nqfsj = d_qe->getNumQuantifiersForSymbol( j.getOperator() );
if( nqfsi<nqfsj ){
@@ -54,7 +55,7 @@ void InstStrategyCheckCESolved::processResetInstantiationRound( Theory::Effort e
}
}
-int InstStrategyCheckCESolved::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategyCheckCESolved::process( Node f, Theory::Effort effort, int e ){
if( e==0 ){
//calc solved if not done so already
if( d_solved.find( f )==d_solved.end() ){
@@ -68,7 +69,7 @@ int InstStrategyCheckCESolved::process( Node f, Theory::Effort effort, int e, in
//d_quantEngine->d_hasInstantiated[f] = true;
}
d_solved[f] = false;
- }
+ }
Debug("quant-uf-strategy") << "done." << std::endl;
}
return STATUS_UNKNOWN;
@@ -78,8 +79,8 @@ void InstStrategyCheckCESolved::calcSolved( Node f ){
d_th->d_baseMatch[f].clear();
d_solved[ f ]= true;
//check if instantiation constants are solved for
- for( int j = 0; j<(int)d_quantEngine->getNumInstantiationConstants( f ); j++ ){
- Node i = d_quantEngine->getInstantiationConstant( f, j );
+ for( int j = 0; j<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); j++ ){
+ Node i = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );
Node rep = d_th->getInternalRepresentative( i );
if( !rep.hasAttribute(InstConstantAttribute()) ){
d_th->d_baseMatch[f].d_map[ i ] = rep;
@@ -99,7 +100,7 @@ void InstStrategyUserPatterns::processResetInstantiationRound( Theory::Effort ef
}
}
-int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e ){
if( e==0 ){
return STATUS_UNFINISHED;
}else if( e==1 ){
@@ -114,10 +115,10 @@ int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e, int
//#endif
}
if( processTrigger ){
- //if( d_user_gen[f][i]->isMultiTrigger() )
+ //if( d_user_gen[f][i]->isMultiTrigger() )
//Notice() << " Process (user) " << (*d_user_gen[f][i]) << " for " << f << "..." << std::endl;
- int numInst = d_user_gen[f][i]->addInstantiations( d_th->d_baseMatch[f], instLimit );
- //if( d_user_gen[f][i]->isMultiTrigger() )
+ int numInst = d_user_gen[f][i]->addInstantiations( d_th->d_baseMatch[f] );
+ //if( d_user_gen[f][i]->isMultiTrigger() )
//Notice() << " Done, numInst = " << numInst << "." << std::endl;
d_th->d_statistics.d_instantiations_user_pattern += numInst;
if( d_user_gen[f][i]->isMultiTrigger() ){
@@ -131,7 +132,7 @@ int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e, int
}
return STATUS_UNKNOWN;
}
-
+
void InstStrategyUserPatterns::addUserPattern( Node f, Node pat ){
//add to generators
std::vector< Node > nodes;
@@ -143,11 +144,11 @@ void InstStrategyUserPatterns::addUserPattern( Node f, Node pat ){
d_quantEngine->getPhaseReqTerms( f, nodes );
//check match option
int matchOption = Options::current()->efficientEMatching ? InstMatchGenerator::MATCH_GEN_EFFICIENT_E_MATCH : 0;
- d_user_gen[f].push_back( Trigger::mkTrigger( d_quantEngine, f, nodes, matchOption, true, Trigger::TR_MAKE_NEW,
+ d_user_gen[f].push_back( Trigger::mkTrigger( d_quantEngine, f, nodes, matchOption, true, Trigger::TR_MAKE_NEW,
Options::current()->smartTriggers ) );
}
}
-
+
void InstStrategyAutoGenTriggers::processResetInstantiationRound( Theory::Effort effort ){
//reset triggers
for( std::map< Node, std::map< Trigger*, bool > >::iterator it = d_auto_gen_trigger.begin(); it != d_auto_gen_trigger.end(); ++it ){
@@ -158,7 +159,7 @@ void InstStrategyAutoGenTriggers::processResetInstantiationRound( Theory::Effort
}
}
-int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e ){
int peffort = f.getNumChildren()==3 ? 2 : 1;
//int peffort = f.getNumChildren()==3 ? 2 : 1;
//int peffort = 1;
@@ -192,10 +193,10 @@ int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e,
#endif
}
if( processTrigger ){
- //if( tr->isMultiTrigger() )
+ //if( tr->isMultiTrigger() )
Debug("quant-uf-strategy-auto-gen-triggers") << " Process " << (*tr) << "..." << std::endl;
- int numInst = tr->addInstantiations( d_th->d_baseMatch[f], instLimit );
- //if( tr->isMultiTrigger() )
+ int numInst = tr->addInstantiations( d_th->d_baseMatch[f] );
+ //if( tr->isMultiTrigger() )
Debug("quant-uf-strategy-auto-gen-triggers") << " Done, numInst = " << numInst << "." << std::endl;
if( d_tr_strategy==Trigger::TS_MIN_TRIGGER ){
d_th->d_statistics.d_instantiations_auto_gen_min += numInst;
@@ -222,8 +223,8 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
d_patTerms[0][f].clear();
d_patTerms[1][f].clear();
std::vector< Node > patTermsF;
- Trigger::collectPatTerms( d_quantEngine, f, d_quantEngine->getCounterexampleBody( f ), patTermsF, d_tr_strategy, true );
- Debug("auto-gen-trigger") << "Collected pat terms for " << d_quantEngine->getCounterexampleBody( f ) << std::endl;
+ Trigger::collectPatTerms( d_quantEngine, f, d_quantEngine->getTermDatabase()->getCounterexampleBody( f ), patTermsF, d_tr_strategy, true );
+ Debug("auto-gen-trigger") << "Collected pat terms for " << d_quantEngine->getTermDatabase()->getCounterexampleBody( f ) << std::endl;
Debug("auto-gen-trigger") << " ";
for( int i=0; i<(int)patTermsF.size(); i++ ){
Debug("auto-gen-trigger") << patTermsF[i] << " ";
@@ -299,7 +300,7 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
int matchOption = Options::current()->efficientEMatching ? InstMatchGenerator::MATCH_GEN_EFFICIENT_E_MATCH : 0;
Trigger* tr = NULL;
if( d_is_single_trigger[ patTerms[0] ] ){
- tr = Trigger::mkTrigger( d_quantEngine, f, patTerms[0], matchOption, false, Trigger::TR_RETURN_NULL,
+ tr = Trigger::mkTrigger( d_quantEngine, f, patTerms[0], matchOption, false, Trigger::TR_RETURN_NULL,
Options::current()->smartTriggers );
d_single_trigger_gen[ patTerms[0] ] = true;
}else{
@@ -313,12 +314,12 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
d_made_multi_trigger[f] = true;
}
//will possibly want to get an old trigger
- tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, false, Trigger::TR_GET_OLD,
+ tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, false, Trigger::TR_GET_OLD,
Options::current()->smartTriggers );
}
if( tr ){
if( tr->isMultiTrigger() ){
- //disable all other multi triggers
+ //disable all other multi triggers
for( std::map< Trigger*, bool >::iterator it = d_auto_gen_trigger[f].begin(); it != d_auto_gen_trigger[f].end(); ++it ){
if( it->first->isMultiTrigger() ){
d_auto_gen_trigger[f][ it->first ] = false;
@@ -344,7 +345,7 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
success = false;
if( d_quantEngine->getNumQuantifiersForSymbol( patTerms[index].getOperator() )<=nqfs_curr ){
d_single_trigger_gen[ patTerms[index] ] = true;
- Trigger* tr2 = Trigger::mkTrigger( d_quantEngine, f, patTerms[index], matchOption, false, Trigger::TR_RETURN_NULL,
+ Trigger* tr2 = Trigger::mkTrigger( d_quantEngine, f, patTerms[index], matchOption, false, Trigger::TR_RETURN_NULL,
Options::current()->smartTriggers );
if( tr2 ){
//Notice() << "Add additional trigger " << patTerms[index] << std::endl;
@@ -368,11 +369,11 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
void InstStrategyAddFailSplits::processResetInstantiationRound( Theory::Effort effort ){
}
-int InstStrategyAddFailSplits::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategyAddFailSplits::process( Node f, Theory::Effort effort, int e ){
if( e<4 ){
return STATUS_UNFINISHED;
}else{
- for( std::map< Node, std::map< Node, std::vector< InstMatchGenerator* > > >::iterator it = InstMatchGenerator::d_match_fails.begin();
+ for( std::map< Node, std::map< Node, std::vector< InstMatchGenerator* > > >::iterator it = InstMatchGenerator::d_match_fails.begin();
it != InstMatchGenerator::d_match_fails.end(); ++it ){
for( std::map< Node, std::vector< InstMatchGenerator* > >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
if( !it2->second.empty() ){
@@ -394,7 +395,7 @@ int InstStrategyAddFailSplits::process( Node f, Theory::Effort effort, int e, in
void InstStrategyFreeVariable::processResetInstantiationRound( Theory::Effort effort ){
}
-int InstStrategyFreeVariable::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategyFreeVariable::process( Node f, Theory::Effort effort, int e ){
if( e<5 ){
return STATUS_UNFINISHED;
}else{
diff --git a/src/theory/uf/inst_strategy.h b/src/theory/uf/inst_strategy.h
index 906169811..09b8087f2 100644
--- a/src/theory/uf/inst_strategy.h
+++ b/src/theory/uf/inst_strategy.h
@@ -45,9 +45,9 @@ private:
void calcSolved( Node f );
/** process functions */
void processResetInstantiationRound( Theory::Effort effort );
- int process( Node f, Theory::Effort effort, int e, int instLimit );
+ int process( Node f, Theory::Effort effort, int e );
public:
- InstStrategyCheckCESolved( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
+ InstStrategyCheckCESolved( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
InstStrategy( ie ), d_th( th ){}
~InstStrategyCheckCESolved(){}
/** identify */
@@ -64,9 +64,9 @@ private:
std::map< Node, int > d_counter;
/** process functions */
void processResetInstantiationRound( Theory::Effort effort );
- int process( Node f, Theory::Effort effort, int e, int instLimit );
+ int process( Node f, Theory::Effort effort, int e );
public:
- InstStrategyUserPatterns( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
+ InstStrategyUserPatterns( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
InstStrategy( ie ), d_th( th ){}
~InstStrategyUserPatterns(){}
public:
@@ -109,11 +109,11 @@ private:
private:
/** process functions */
void processResetInstantiationRound( Theory::Effort effort );
- int process( Node f, Theory::Effort effort, int e, int instLimit );
+ int process( Node f, Theory::Effort effort, int e );
/** generate triggers */
void generateTriggers( Node f );
public:
- InstStrategyAutoGenTriggers( InstantiatorTheoryUf* th, QuantifiersEngine* ie, int tstrt, int rstrt, int rgfr = -1 ) :
+ InstStrategyAutoGenTriggers( InstantiatorTheoryUf* th, QuantifiersEngine* ie, int tstrt, int rstrt, int rgfr = -1 ) :
InstStrategy( ie ), d_th( th ), d_tr_strategy( tstrt ), d_rlv_strategy( rstrt ), d_generate_additional( false ){
setRegenerateFrequency( rgfr );
}
@@ -144,9 +144,9 @@ private:
InstantiatorTheoryUf* d_th;
/** process functions */
void processResetInstantiationRound( Theory::Effort effort );
- int process( Node f, Theory::Effort effort, int e, int instLimit );
+ int process( Node f, Theory::Effort effort, int e );
public:
- InstStrategyAddFailSplits( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
+ InstStrategyAddFailSplits( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
InstStrategy( ie ), d_th( th ){}
~InstStrategyAddFailSplits(){}
/** identify */
@@ -163,9 +163,9 @@ private:
std::map< Node, bool > d_guessed;
/** process functions */
void processResetInstantiationRound( Theory::Effort effort );
- int process( Node f, Theory::Effort effort, int e, int instLimit );
+ int process( Node f, Theory::Effort effort, int e );
public:
- InstStrategyFreeVariable( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
+ InstStrategyFreeVariable( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
InstStrategy( ie ), d_th( th ){}
~InstStrategyFreeVariable(){}
/** identify */
diff --git a/src/theory/uf/kinds b/src/theory/uf/kinds
index ec353dc59..ce8785f86 100644
--- a/src/theory/uf/kinds
+++ b/src/theory/uf/kinds
@@ -17,7 +17,49 @@ parameterized APPLY_UF VARIABLE 1: "uninterpreted function application"
typerule APPLY_UF ::CVC4::theory::uf::UfTypeRule
operator CARDINALITY_CONSTRAINT 2 "cardinality constraint"
-
typerule CARDINALITY_CONSTRAINT ::CVC4::theory::uf::CardinalityConstraintTypeRule
+#
+# For compact function models
+# There are three cases for FUNCTION_MODEL nodes:
+# (1) The node has two children, the first being of kind FUNCTION_CASE_SPLIT. The second child specifies a default value.
+# (2) The node has one child of kind FUNCTION_CASE_SPLIT.
+# (3) The node has one child, it's default value.
+#
+# Semantics of FUNCTION_MODEL kind-ed nodes. The value of n applied to arguments args is
+#
+# getValueFM( n, args, 0 ), where:
+#
+# Node getValueFM( n, args, argIndex )
+# if n.getKind()!=FUNCTION_MODEL
+# return n;
+# else if (1)
+# val = getValueFCS( n[0], args, argIndex );
+# if !val.isNull()
+# return val;
+# else
+# return getValueFM( n[1], args, argIndex+1 );
+# else if (2)
+# return getValueFCS( n[0], args, argIndex );
+# else if (3)
+# return getValueFM( n[0], args, argIndex+1 );
+#
+# Node getValueFCS( n, args, argIndex ) :
+# //n.getKind()==FUNCTION_CASE_SPLIT
+# //n[j].getKind()==FUNCTION_CASE for all 0<=j<n.getNumChildren()
+# if( args[argIndex]=n[i][0] for some i)
+# return getValueFM( n[i][1], args, argIndex+1 );
+# else
+# return null;
+#
+
+operator FUNCTION_MODEL 1:2 "function model"
+typerule FUNCTION_MODEL ::CVC4::theory::uf::FunctionModelTypeRule
+
+operator FUNCTION_CASE_SPLIT 1: "function case split"
+typerule FUNCTION_CASE_SPLIT ::CVC4::theory::uf::FunctionCaseSplitTypeRule
+
+operator FUNCTION_CASE 2 "function case"
+typerule FUNCTION_CASE ::CVC4::theory::uf::FunctionCaseTypeRule
+
endtheory
diff --git a/src/theory/uf/theory_uf.cpp b/src/theory/uf/theory_uf.cpp
index 5d36cd082..ac194d5ed 100644
--- a/src/theory/uf/theory_uf.cpp
+++ b/src/theory/uf/theory_uf.cpp
@@ -20,6 +20,7 @@
#include "theory/uf/theory_uf.h"
#include "theory/uf/theory_uf_instantiator.h"
#include "theory/uf/theory_uf_strong_solver.h"
+#include "theory/model.h"
using namespace std;
using namespace CVC4;
@@ -173,6 +174,10 @@ Node TheoryUF::explain(TNode literal) {
return mkAnd(assumptions);
}
+void TheoryUF::collectModelInfo( TheoryModel* m ){
+ m->assertEqualityEngine( &d_equalityEngine );
+}
+
void TheoryUF::presolve() {
// TimerStat::CodeTimer codeTimer(d_presolveTimer);
diff --git a/src/theory/uf/theory_uf.h b/src/theory/uf/theory_uf.h
index db417b08c..604b1f44c 100644
--- a/src/theory/uf/theory_uf.h
+++ b/src/theory/uf/theory_uf.h
@@ -132,8 +132,8 @@ private:
Node d_conflictNode;
/**
- * Should be called to propagate the literal. We use a node here
- * since some of the propagated literals are not kept anywhere.
+ * Should be called to propagate the literal. We use a node here
+ * since some of the propagated literals are not kept anywhere.
*/
bool propagate(TNode literal);
@@ -193,6 +193,8 @@ public:
void preRegisterTerm(TNode term);
Node explain(TNode n);
+ void collectModelInfo( TheoryModel* m );
+
void ppStaticLearn(TNode in, NodeBuilder<>& learned);
void presolve();
diff --git a/src/theory/uf/theory_uf_candidate_generator.cpp b/src/theory/uf/theory_uf_candidate_generator.cpp
index e8aa98aa7..5342188f7 100644
--- a/src/theory/uf/theory_uf_candidate_generator.cpp
+++ b/src/theory/uf/theory_uf_candidate_generator.cpp
@@ -17,6 +17,7 @@
#include "theory/uf/theory_uf_candidate_generator.h"
#include "theory/theory_engine.h"
#include "theory/uf/theory_uf.h"
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
@@ -25,7 +26,7 @@ using namespace CVC4::context;
using namespace CVC4::theory;
using namespace CVC4::theory::uf;
-CandidateGeneratorTheoryUf::CandidateGeneratorTheoryUf( InstantiatorTheoryUf* ith, Node op ) :
+CandidateGeneratorTheoryUf::CandidateGeneratorTheoryUf( InstantiatorTheoryUf* ith, Node op ) :
d_op( op ), d_ith( ith ), d_term_iter( -2 ){
Assert( !d_op.isNull() );
}
@@ -84,12 +85,12 @@ Node CandidateGeneratorTheoryUf::getNextCandidate(){
}
-//CandidateGeneratorTheoryUfDisequal::CandidateGeneratorTheoryUfDisequal( InstantiatorTheoryUf* ith, Node eqc ) :
+//CandidateGeneratorTheoryUfDisequal::CandidateGeneratorTheoryUfDisequal( InstantiatorTheoryUf* ith, Node eqc ) :
// d_ith( ith ), d_eq_class( eqc ){
// d_eci = NULL;
//}
//void CandidateGeneratorTheoryUfDisequal::resetInstantiationRound(){
-//
+//
//}
////we will iterate over all terms that are disequal from eqc
//void CandidateGeneratorTheoryUfDisequal::reset( Node eqc ){
@@ -119,12 +120,12 @@ Node CandidateGeneratorTheoryUf::getNextCandidate(){
//}
-CandidateGeneratorTheoryUfLitEq::CandidateGeneratorTheoryUfLitEq( InstantiatorTheoryUf* ith, Node mpat ) :
+CandidateGeneratorTheoryUfLitEq::CandidateGeneratorTheoryUfLitEq( InstantiatorTheoryUf* ith, Node mpat ) :
d_match_pattern( mpat ), d_ith( ith ){
-
+
}
void CandidateGeneratorTheoryUfLitEq::resetInstantiationRound(){
-
+
}
void CandidateGeneratorTheoryUfLitEq::reset( Node eqc ){
d_eq = eq::EqClassesIterator( ((TheoryUF*)d_ith->getTheory())->getEqualityEngine() );
@@ -142,15 +143,15 @@ Node CandidateGeneratorTheoryUfLitEq::getNextCandidate(){
}
-CandidateGeneratorTheoryUfLitDeq::CandidateGeneratorTheoryUfLitDeq( InstantiatorTheoryUf* ith, Node mpat ) :
+CandidateGeneratorTheoryUfLitDeq::CandidateGeneratorTheoryUfLitDeq( InstantiatorTheoryUf* ith, Node mpat ) :
d_match_pattern( mpat ), d_ith( ith ){
-
+
}
void CandidateGeneratorTheoryUfLitDeq::resetInstantiationRound(){
-
+
}
void CandidateGeneratorTheoryUfLitDeq::reset( Node eqc ){
- Node false_term = ((TheoryUF*)d_ith->getTheory())->getEqualityEngine()->getRepresentative(
+ Node false_term = ((TheoryUF*)d_ith->getTheory())->getEqualityEngine()->getRepresentative(
NodeManager::currentNM()->mkConst<bool>(false) );
d_eqc_false = eq::EqClassIterator( false_term, ((TheoryUF*)d_ith->getTheory())->getEqualityEngine() );
}
diff --git a/src/theory/uf/theory_uf_instantiator.cpp b/src/theory/uf/theory_uf_instantiator.cpp
index 9fdcb5952..e3999c163 100644
--- a/src/theory/uf/theory_uf_instantiator.cpp
+++ b/src/theory/uf/theory_uf_instantiator.cpp
@@ -18,7 +18,7 @@
#include "theory/theory_engine.h"
#include "theory/uf/theory_uf.h"
#include "theory/uf/equality_engine.h"
-//#include "theory/uf/inst_strategy_model_find.h"
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
@@ -32,7 +32,7 @@ EqClassInfo::EqClassInfo( context::Context* c ) : d_funs( c ), d_pfuns( c ), d_d
}
//set member
-void EqClassInfo::setMember( Node n, TermDb* db ){
+void EqClassInfo::setMember( Node n, quantifiers::TermDb* db ){
if( n.getKind()==APPLY_UF ){
d_funs[n.getOperator()] = true;
}
@@ -65,15 +65,7 @@ void EqClassInfo::merge( EqClassInfo* eci ){
InstantiatorTheoryUf::InstantiatorTheoryUf(context::Context* c, CVC4::theory::QuantifiersEngine* qe, Theory* th) :
Instantiator( c, qe, th )
{
- qe->setEqualityQuery( new EqualityQueryInstantiatorTheoryUf( this ) );
-
- if( Options::current()->finiteModelFind ){
- //if( Options::current()->cbqi ){
- // addInstStrategy( new InstStrategyCheckCESolved( this, qe ) );
- //}
- //addInstStrategy( new InstStrategyFiniteModelFind( c, this, ((TheoryUF*)th)->getStrongSolver(), qe ) );
- qe->getTermDatabase()->setMatchingActive( false );
- }else{
+ if( !Options::current()->finiteModelFind || Options::current()->fmfInstEngine ){
if( Options::current()->cbqi ){
addInstStrategy( new InstStrategyCheckCESolved( this, qe ) );
}
@@ -88,7 +80,9 @@ Instantiator( c, qe, th )
i_ag->setGenerateAdditional( true );
addInstStrategy( i_ag );
//addInstStrategy( new InstStrategyAddFailSplits( this, ie ) );
- addInstStrategy( new InstStrategyFreeVariable( this, qe ) );
+ if( !Options::current()->finiteModelFind ){
+ addInstStrategy( new InstStrategyFreeVariable( this, qe ) );
+ }
//d_isup->setPriorityOver( i_ag );
//d_isup->setPriorityOver( i_agm );
//i_ag->setPriorityOver( i_agm );
@@ -125,7 +119,7 @@ void InstantiatorTheoryUf::processResetInstantiationRound( Theory::Effort effort
d_ground_reps.clear();
}
-int InstantiatorTheoryUf::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstantiatorTheoryUf::process( Node f, Theory::Effort effort, int e ){
Debug("quant-uf") << "UF: Try to solve (" << e << ") for " << f << "... " << std::endl;
return InstStrategy::STATUS_SAT;
}
@@ -405,7 +399,7 @@ bool InstantiatorTheoryUf::collectParentsTermsIps( Node n, Node f, int arg, std:
eqc_iter++;
}
}else{
- TermDb* db = d_quantEngine->getTermDatabase();
+ quantifiers::TermDb* db = d_quantEngine->getTermDatabase();
//see if parent f exists from argument arg
if( db->d_parents.find( n )!=db->d_parents.end() ){
if( db->d_parents[n].find( f )!=db->d_parents[n].end() ){
@@ -481,7 +475,7 @@ void InstantiatorTheoryUf::registerCandidateGenerator( CandidateGenerator* cg, N
//take all terms from the uf term db and add to candidate generator
Node op = pat.getOperator();
- TermDb* db = d_quantEngine->getTermDatabase();
+ quantifiers::TermDb* db = d_quantEngine->getTermDatabase();
for( int i=0; i<(int)db->d_op_map[op].size(); i++ ){
cg->addCandidate( db->d_op_map[op][i] );
}
diff --git a/src/theory/uf/theory_uf_instantiator.h b/src/theory/uf/theory_uf_instantiator.h
index e50e3823c..4ddc01986 100644
--- a/src/theory/uf/theory_uf_instantiator.h
+++ b/src/theory/uf/theory_uf_instantiator.h
@@ -31,7 +31,9 @@
namespace CVC4 {
namespace theory {
-class TermDb;
+namespace quantifiers{
+ class TermDb;
+}
namespace uf {
@@ -56,7 +58,7 @@ public:
EqClassInfo( context::Context* c );
~EqClassInfo(){}
//set member
- void setMember( Node n, TermDb* db );
+ void setMember( Node n, quantifiers::TermDb* db );
//has function "funs"
bool hasFunction( Node op );
//has parent "pfuns"
@@ -67,7 +69,7 @@ public:
class InstantiatorTheoryUf : public Instantiator{
friend class ::CVC4::theory::InstMatchGenerator;
- friend class ::CVC4::theory::TermDb;
+ friend class ::CVC4::theory::quantifiers::TermDb;
protected:
typedef context::CDHashMap<Node, bool, NodeHashFunction> BoolMap;
typedef context::CDHashMap<Node, int, NodeHashFunction> IntMap;
@@ -95,7 +97,7 @@ private:
/** reset instantiation */
void processResetInstantiationRound( Theory::Effort effort );
/** calculate matches for quantifier f at effort */
- int process( Node f, Theory::Effort effort, int e, int instLimit );
+ int process( Node f, Theory::Effort effort, int e );
public:
/** statistics class */
class Statistics {
diff --git a/src/theory/uf/theory_uf_model.cpp b/src/theory/uf/theory_uf_model.cpp
new file mode 100644
index 000000000..a85dea997
--- /dev/null
+++ b/src/theory/uf/theory_uf_model.cpp
@@ -0,0 +1,554 @@
+/********************* */
+/*! \file theory_uf_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 UF Model
+ **/
+
+#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_strong_solver.h"
+#include "theory/uf/theory_uf_instantiator.h"
+#include "theory/quantifiers/first_order_model.h"
+#include "theory/quantifiers/term_database.h"
+
+#define RECONSIDER_FUNC_DEFAULT_VALUE
+#define USE_PARTIAL_DEFAULT_VALUES
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::uf;
+
+//clear
+void UfModelTree::clear(){
+ d_data.clear();
+ d_value = Node::null();
+}
+
+bool UfModelTree::hasConcreteArgumentDefinition(){
+ if( d_data.size()>1 ){
+ return true;
+ }else if( d_data.empty() ){
+ return false;
+ }else{
+ Node r;
+ return d_data.find( r )==d_data.end();
+ }
+}
+
+//set value function
+void UfModelTree::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() ){
+ //take r = null when argument is the model basis
+ Node r;
+ if( ground || !n[ indexOrder[argIndex] ].getAttribute(ModelBasisAttribute()) ){
+ r = m->getRepresentative( n[ indexOrder[argIndex] ] );
+ }
+ d_data[ r ].setValue( m, n, v, indexOrder, ground, argIndex+1 );
+ }
+}
+
+//get value function
+Node UfModelTree::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;
+ return d_value;
+ }else{
+ Node val;
+ int childDepIndex[2] = { argIndex, argIndex };
+ for( int i=0; i<2; i++ ){
+ //first check the argument, then check default
+ Node r;
+ if( i==0 ){
+ r = m->getRepresentative( n[ indexOrder[argIndex] ] );
+ }
+ std::map< Node, UfModelTree >::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() ){
+ break;
+ }
+ }else{
+ //argument is not a defined argument: thus, it depends on this argument
+ childDepIndex[i] = argIndex+1;
+ }
+ }
+ //update depIndex
+ depIndex = childDepIndex[0]>childDepIndex[1] ? childDepIndex[0] : childDepIndex[1];
+ //Notice() << "Return " << val << ", depIndex = " << depIndex;
+ //Notice() << " ( " << childDepIndex[0] << ", " << childDepIndex[1] << " )" << std::endl;
+ return val;
+ }
+}
+
+Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, std::vector< int >& depIndex, int argIndex ){
+ if( argIndex==(int)indexOrder.size() ){
+ return d_value;
+ }else{
+ Node val;
+ bool depArg = false;
+ //will try concrete value first, then default
+ for( int i=0; i<2; i++ ){
+ Node r;
+ if( i==0 ){
+ r = m->getRepresentative( n[ indexOrder[argIndex] ] );
+ }
+ std::map< Node, UfModelTree >::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
+ if( !val.isNull() ){
+ if( i==0 ){
+ depArg = true;
+ }
+ break;
+ }
+ }
+ }
+ //it depends on this argument if we found it via concrete argument value,
+ // or if found by default/disequal from some concrete argument value(s).
+ if( depArg || hasConcreteArgumentDefinition() ){
+ if( std::find( depIndex.begin(), depIndex.end(), indexOrder[argIndex] )==depIndex.end() ){
+ depIndex.push_back( indexOrder[argIndex] );
+ }
+ }
+ return val;
+ }
+}
+
+Node UfModelTree::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 ){
+ if( it->first.isNull() ){
+ defaultValue = it->second.getFunctionValue();
+ }else{
+ caseValues.push_back( NodeManager::currentNM()->mkNode( FUNCTION_CASE, it->first, it->second.getFunctionValue() ) );
+ }
+ }
+ if( caseValues.empty() && defaultValue.getKind()!=FUNCTION_CASE_SPLIT && defaultValue.getKind()!=FUNCTION_MODEL ){
+ return defaultValue;
+ }else{
+ std::vector< Node > children;
+ if( !caseValues.empty() ){
+ children.push_back( NodeManager::currentNM()->mkNode( FUNCTION_CASE_SPLIT, caseValues ) );
+ }
+ if( !defaultValue.isNull() ){
+ children.push_back( defaultValue );
+ }
+ return NodeManager::currentNM()->mkNode( FUNCTION_MODEL, children );
+ }
+ }else{
+ Assert( !d_value.isNull() );
+ return d_value;
+ }
+}
+
+//simplify function
+void UfModelTree::simplify( Node op, Node defaultVal, int argIndex ){
+ if( argIndex<(int)op.getType().getNumChildren()-1 ){
+ std::vector< Node > eraseData;
+ //first process the default argument
+ Node r;
+ std::map< Node, UfModelTree >::iterator it = d_data.find( r );
+ if( it!=d_data.end() ){
+ if( !defaultVal.isNull() && it->second.d_value==defaultVal ){
+ eraseData.push_back( r );
+ }else{
+ it->second.simplify( op, defaultVal, argIndex+1 );
+ if( !it->second.d_value.isNull() && it->second.isTotal( op, argIndex+1 ) ){
+ defaultVal = it->second.d_value;
+ }else{
+ defaultVal = Node::null();
+ if( it->second.isEmpty() ){
+ eraseData.push_back( r );
+ }
+ }
+ }
+ }
+ //now see if any children can be removed, and simplify the ones that cannot
+ for( std::map< Node, UfModelTree >::iterator it = d_data.begin(); it != d_data.end(); ++it ){
+ if( !it->first.isNull() ){
+ if( !defaultVal.isNull() && it->second.d_value==defaultVal ){
+ eraseData.push_back( it->first );
+ }else{
+ it->second.simplify( op, defaultVal, argIndex+1 );
+ if( it->second.isEmpty() ){
+ eraseData.push_back( it->first );
+ }
+ }
+ }
+ }
+ for( int i=0; i<(int)eraseData.size(); i++ ){
+ d_data.erase( eraseData[i] );
+ }
+ }
+}
+
+//is total function
+bool UfModelTree::isTotal( Node op, int argIndex ){
+ if( argIndex==(int)(op.getType().getNumChildren()-1) ){
+ return !d_value.isNull();
+ }else{
+ Node r;
+ std::map< Node, UfModelTree >::iterator it = d_data.find( r );
+ if( it!=d_data.end() ){
+ return it->second.isTotal( op, argIndex+1 );
+ }else{
+ return false;
+ }
+ }
+}
+
+Node UfModelTree::getConstantValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int argIndex ){
+ return d_value;
+}
+
+void indent( std::ostream& out, int ind ){
+ for( int i=0; i<ind; i++ ){
+ out << " ";
+ }
+}
+
+void UfModelTree::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 ){
+ if( !it->first.isNull() ){
+ indent( out, ind );
+ out << "if x_" << indexOrder[arg] << " == " << it->first << std::endl;
+ it->second.debugPrint( out, m, indexOrder, ind+2, arg+1 );
+ }
+ }
+ if( d_data.find( Node::null() )!=d_data.end() ){
+ d_data[ Node::null() ].debugPrint( out, m, indexOrder, ind, arg+1 );
+ }
+ }else{
+ 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;
+ }
+ }
+ 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;
+ }
+ }
+}
+
+Node UfModel::getIntersection( Node n1, Node n2, bool& isGround ){
+ //Notice() << "Get intersection " << n1 << " " << n2 << std::endl;
+ isGround = true;
+ std::vector< Node > children;
+ children.push_back( n1.getOperator() );
+ for( int i=0; i<(int)n1.getNumChildren(); i++ ){
+ if( n1[i]==n2[i] ){
+ if( n1[i].getAttribute(ModelBasisAttribute()) ){
+ isGround = false;
+ }
+ children.push_back( n1[i] );
+ }else if( n1[i].getAttribute(ModelBasisAttribute()) ){
+ 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] ) ){
+ children.push_back( n1[i] );
+ }else{
+ return Node::null();
+ }
+ }
+ return NodeManager::currentNM()->mkNode( APPLY_UF, children );
+}
+
+void UfModel::setValue( 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;
+ if( optUsePartialDefaults() ){
+ if( !ground ){
+ int defSize = (int)d_defaults.size();
+ for( int i=0; i<defSize; i++ ){
+ bool isGround;
+ //for soundness, to allow variable order-independent function interpretations,
+ // we must ensure that the intersection of all default terms
+ // 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 );
+ 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 );
+ }
+ }
+ }
+ d_defaults.push_back( n );
+ }
+ if( isReq && d_set_values[0][ ground ? 1 : 0 ].find( n )!=d_set_values[0][ ground ? 1 : 0 ].end()){
+ d_set_values[0][ ground ? 1 : 0 ].erase( n );
+ }
+ }
+}
+
+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();
+ }
+}
+
+Node UfModel::getFunctionValue(){
+ if( d_func_value.isNull() && d_model_constructed ){
+ d_func_value = d_tree.getFunctionValue();
+ }
+ return d_func_value;
+}
+
+bool UfModel::isConstant(){
+ Node gn = d_model->getTermDatabase()->getModelBasisOpTerm( d_op );
+ Node n = getConstantValue( gn );
+ return !n.isNull();
+}
+
+bool UfModel::optUsePartialDefaults(){
+#ifdef USE_PARTIAL_DEFAULT_VALUES
+ return true;
+#else
+ return false;
+#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(){
+ 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;
+ }
+}
+
+
+void UfModelPreferenceData::setValuePreference( Node f, Node n, Node r, bool isPro ){
+ if( std::find( d_values.begin(), d_values.end(), r )==d_values.end() ){
+ d_values.push_back( r );
+ }
+ int index = isPro ? 0 : 1;
+ if( std::find( d_value_pro_con[index][r].begin(), d_value_pro_con[index][r].end(), f )==d_value_pro_con[index][r].end() ){
+ d_value_pro_con[index][r].push_back( f );
+ }
+ d_term_pro_con[index][n].push_back( f );
+}
+
+Node UfModelPreferenceData::getBestDefaultValue( Node defaultTerm, TheoryModel* m ){
+ Node defaultVal;
+ double maxScore = -1;
+ for( size_t i=0; i<d_values.size(); i++ ){
+ Node v = d_values[i];
+ double score = ( 1.0 + (double)d_value_pro_con[0][v].size() )/( 1.0 + (double)d_value_pro_con[1][v].size() );
+ Debug("fmf-model-cons") << " - score( ";
+ m->printRepresentativeDebug( "fmf-model-cons", v );
+ Debug("fmf-model-cons") << " ) = " << score << std::endl;
+ if( score>maxScore ){
+ defaultVal = v;
+ maxScore = score;
+ }
+ }
+#ifdef RECONSIDER_FUNC_DEFAULT_VALUE
+ if( maxScore<1.0 ){
+ //consider finding another value, if possible
+ Debug("fmf-model-cons-debug") << "Poor choice for default value, score = " << maxScore << std::endl;
+ TypeNode tn = defaultTerm.getType();
+ Node newDefaultVal = m->getDomainValue( tn, d_values );
+ if( !newDefaultVal.isNull() ){
+ defaultVal = newDefaultVal;
+ Debug("fmf-model-cons-debug") << "-> Change default value to ";
+ m->printRepresentativeDebug( "fmf-model-cons-debug", defaultVal );
+ Debug("fmf-model-cons-debug") << std::endl;
+ }else{
+ Debug("fmf-model-cons-debug") << "-> Could not find arbitrary element of type " << tn[(int)tn.getNumChildren()-1] << std::endl;
+ Debug("fmf-model-cons-debug") << " Excluding: ";
+ for( int i=0; i<(int)d_values.size(); i++ ){
+ Debug("fmf-model-cons-debug") << d_values[i] << " ";
+ }
+ Debug("fmf-model-cons-debug") << std::endl;
+ }
+ }
+#endif
+ //get the default term (this term must be defined non-ground in model)
+ Debug("fmf-model-cons") << " Choose ";
+ m->printRepresentativeDebug("fmf-model-cons", defaultVal );
+ Debug("fmf-model-cons") << " as default value (" << defaultTerm << ")" << std::endl;
+ Debug("fmf-model-cons") << " # quantifiers pro = " << d_value_pro_con[0][defaultVal].size() << std::endl;
+ Debug("fmf-model-cons") << " # quantifiers con = " << d_value_pro_con[1][defaultVal].size() << std::endl;
+ return defaultVal;
+} \ No newline at end of file
diff --git a/src/theory/uf/theory_uf_model.h b/src/theory/uf/theory_uf_model.h
new file mode 100644
index 000000000..406c7ff3c
--- /dev/null
+++ b/src/theory/uf/theory_uf_model.h
@@ -0,0 +1,216 @@
+/********************* */
+/*! \file theory_uf_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 UF
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY_UF_MODEL_H
+#define __CVC4__THEORY_UF_MODEL_H
+
+#include "theory/model.h"
+
+namespace CVC4 {
+namespace theory {
+
+namespace quantifiers{
+ class FirstOrderModel;
+}
+
+namespace uf {
+
+class UfModelTree
+{
+public:
+ UfModelTree(){}
+ /** the data */
+ std::map< Node, UfModelTree > d_data;
+ /** the value of this tree node (if all paths lead to same value) */
+ Node d_value;
+ /** has concrete argument defintion */
+ bool hasConcreteArgumentDefinition();
+public:
+ //is this model tree empty?
+ 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
+ *
+ */
+ 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)
+ *
+ */
+ 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
+ // *
+ // */
+ 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 ?
+ 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
+{
+private:
+ Node d_op;
+ std::vector< int > d_index_order;
+ UfModelTree d_tree;
+public:
+ UfModelTreeOrdered(){}
+ UfModelTreeOrdered( Node op ) : d_op( op ){
+ TypeNode tn = d_op.getType();
+ for( int i=0; i<(int)(tn.getNumChildren()-1); i++ ){
+ d_index_order.push_back( i );
+ }
+ }
+ UfModelTreeOrdered( Node op, std::vector< int >& indexOrder ) : d_op( op ){
+ d_index_order.insert( d_index_order.end(), indexOrder.begin(), indexOrder.end() );
+ }
+ bool isEmpty() { return d_tree.isEmpty(); }
+ void clear() { d_tree.clear(); }
+ void setValue( TheoryModel* m, Node n, Node v, bool ground = true ){
+ d_tree.setValue( m, n, v, d_index_order, ground, 0 );
+ }
+ Node getValue( TheoryModel* m, Node n, int& depIndex ){
+ return d_tree.getValue( m, n, d_index_order, depIndex, 0 );
+ }
+ Node getValue( TheoryModel* m, Node n, std::vector< int >& depIndex ){
+ return d_tree.getValue( m, n, d_index_order, depIndex, 0 );
+ }
+ Node getConstantValue( TheoryModel* m, Node n ) {
+ return d_tree.getConstantValue( m, n, d_index_order, 0 );
+ }
+ Node getFunctionValue(){
+ return d_tree.getFunctionValue();
+ }
+ void simplify() { d_tree.simplify( d_op, Node::null(), 0 ); }
+ bool isTotal() { return d_tree.isTotal( d_op, 0 ); }
+public:
+ void debugPrint( std::ostream& out, TheoryModel* m, int ind = 0 ){
+ d_tree.debugPrint( out, m, d_index_order, ind );
+ }
+};
+
+class UfModel
+{
+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
+ std::map< Node, Node > d_set_values[2][2];
+private:
+ // defaults
+ std::vector< Node > d_defaults;
+ Node getIntersection( 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 );
+ /** 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();
+ /** 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() ); }
+};
+
+//this class stores temporary information useful to model engine for constructing model
+class UfModelPreferenceData
+{
+public:
+ UfModelPreferenceData() : d_reconsiderModel( false ){}
+ virtual ~UfModelPreferenceData(){}
+ // preferences for default values
+ std::vector< Node > d_values;
+ std::map< Node, std::vector< Node > > d_value_pro_con[2];
+ std::map< Node, std::vector< Node > > d_term_pro_con[2];
+ bool d_reconsiderModel;
+ /** set value preference */
+ void setValuePreference( Node f, Node n, Node r, bool isPro );
+ /** get best default value */
+ Node getBestDefaultValue( Node defaultTerm, TheoryModel* m );
+};
+
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/uf/theory_uf_strong_solver.cpp b/src/theory/uf/theory_uf_strong_solver.cpp
index ebbbb139d..e2dd55174 100644
--- a/src/theory/uf/theory_uf_strong_solver.cpp
+++ b/src/theory/uf/theory_uf_strong_solver.cpp
@@ -19,8 +19,12 @@
#include "theory/uf/equality_engine.h"
#include "theory/uf/theory_uf_instantiator.h"
#include "theory/theory_engine.h"
+#include "theory/quantifiers/term_database.h"
-//#define USE_REGION_SAT
+//#define USE_SMART_SPLITS
+//#define ONE_SPLIT_REGION
+//#define DISABLE_QUICK_CLIQUE_CHECKS
+//#define COMBINE_REGIONS_SMALL_INTO_LARGE
using namespace std;
using namespace CVC4;
@@ -29,6 +33,10 @@ using namespace CVC4::context;
using namespace CVC4::theory;
using namespace CVC4::theory::uf;
+void StrongSolverTheoryUf::ConflictFind::Region::addRep( Node n ) {
+ setRep( n, true );
+}
+
void StrongSolverTheoryUf::ConflictFind::Region::takeNode( StrongSolverTheoryUf::ConflictFind::Region* r, Node n ){
//Debug("uf-ss") << "takeNode " << r << " " << n << std::endl;
//Debug("uf-ss") << "r : " << std::endl;
@@ -64,7 +72,6 @@ void StrongSolverTheoryUf::ConflictFind::Region::takeNode( StrongSolverTheoryUf:
}
//remove representative
r->setRep( n, false );
- //Debug("uf-ss") << "done takeNode " << r << " " << n << std::endl;
}
void StrongSolverTheoryUf::ConflictFind::Region::combine( StrongSolverTheoryUf::ConflictFind::Region* r ){
@@ -98,29 +105,6 @@ void StrongSolverTheoryUf::ConflictFind::Region::combine( StrongSolverTheoryUf::
r->d_valid = false;
}
-void StrongSolverTheoryUf::ConflictFind::Region::setRep( Node n, bool valid ){
- Assert( hasRep( n )!=valid );
- if( d_nodes.find( n )==d_nodes.end() && valid ){
- d_nodes[n] = new RegionNodeInfo( d_cf->d_th->getSatContext() );
- }
- d_nodes[n]->d_valid = valid;
- d_reps_size = d_reps_size + ( valid ? 1 : -1 );
- if( d_testClique.find( n )!=d_testClique.end() && d_testClique[n] ){
- Assert( !valid );
- d_testClique[n] = false;
- d_testCliqueSize = d_testCliqueSize - 1;
- //remove all splits involving n
- for( NodeBoolMap::iterator it = d_splits.begin(); it != d_splits.end(); ++it ){
- if( (*it).second ){
- if( (*it).first[0]==n || (*it).first[1]==n ){
- d_splits[ (*it).first ] = false;
- d_splitsSize = d_splitsSize - 1;
- }
- }
- }
- }
-}
-
/** setEqual */
void StrongSolverTheoryUf::ConflictFind::Region::setEqual( Node a, Node b ){
Assert( hasRep( a ) && hasRep( b ) );
@@ -170,13 +154,47 @@ void StrongSolverTheoryUf::ConflictFind::Region::setDisequal( Node n1, Node n2,
}
}
+void StrongSolverTheoryUf::ConflictFind::Region::setRep( Node n, bool valid ){
+ Assert( hasRep( n )!=valid );
+ if( valid && d_nodes.find( n )==d_nodes.end() ){
+ d_nodes[n] = new RegionNodeInfo( d_cf->d_th->getSatContext() );
+ }
+ d_nodes[n]->d_valid = valid;
+ d_reps_size = d_reps_size + ( valid ? 1 : -1 );
+ //removing a member of the test clique from this region
+ if( d_testClique.find( n )!=d_testClique.end() && d_testClique[n] ){
+ Assert( !valid );
+ d_testClique[n] = false;
+ d_testCliqueSize = d_testCliqueSize - 1;
+ //remove all splits involving n
+ for( NodeBoolMap::iterator it = d_splits.begin(); it != d_splits.end(); ++it ){
+ if( (*it).second ){
+ if( (*it).first[0]==n || (*it).first[1]==n ){
+ d_splits[ (*it).first ] = false;
+ d_splitsSize = d_splitsSize - 1;
+ }
+ }
+ }
+ }
+}
+
bool StrongSolverTheoryUf::ConflictFind::Region::isDisequal( Node n1, Node n2, int type ){
RegionNodeInfo::DiseqList* del = d_nodes[ n1 ]->d_disequalities[type];
return del->d_disequalities.find( n2 )!=del->d_disequalities.end() && del->d_disequalities[n2];
}
+struct sortInternalDegree {
+ StrongSolverTheoryUf::ConflictFind::Region* r;
+ bool operator() (Node i,Node j) { return (r->d_nodes[i]->getNumInternalDisequalities()>r->d_nodes[j]->getNumInternalDisequalities());}
+};
+
+struct sortExternalDegree {
+ StrongSolverTheoryUf::ConflictFind::Region* r;
+ bool operator() (Node i,Node j) { return (r->d_nodes[i]->getNumExternalDisequalities()>r->d_nodes[j]->getNumExternalDisequalities());}
+};
+
bool StrongSolverTheoryUf::ConflictFind::Region::getMustCombine( int cardinality ){
- if( d_total_diseq_external>=long(cardinality) ){
+ if( Options::current()->ufssRegions && d_total_diseq_external>=long(cardinality) ){
//The number of external disequalities is greater than or equal to cardinality.
//Thus, a clique of size cardinality+1 may exist between nodes in d_regions[i] and other regions
//Check if this is actually the case: must have n nodes with outgoing degree (cardinality+1-n) for some n>0
@@ -189,7 +207,7 @@ bool StrongSolverTheoryUf::ConflictFind::Region::getMustCombine( int cardinality
if( outDeg>=cardinality ){
//we have 1 node of degree greater than (cardinality)
return true;
- }else if( outDeg>0 ){
+ }else if( outDeg>=1 ){
degrees.push_back( outDeg );
if( (int)degrees.size()>=cardinality ){
//we have (cardinality) nodes of degree 1
@@ -199,6 +217,12 @@ bool StrongSolverTheoryUf::ConflictFind::Region::getMustCombine( int cardinality
}
}
}
+ //static int gmcCount = 0;
+ //gmcCount++;
+ //if( gmcCount%100==0 ){
+ // std::cout << gmcCount << " " << cardinality << std::endl;
+ //}
+ //this should happen relatively infrequently....
std::sort( degrees.begin(), degrees.end() );
for( int i=0; i<(int)degrees.size(); i++ ){
if( degrees[i]>=cardinality+1-((int)degrees.size()-i) ){
@@ -209,15 +233,9 @@ bool StrongSolverTheoryUf::ConflictFind::Region::getMustCombine( int cardinality
return false;
}
-struct sortInternalDegree {
- StrongSolverTheoryUf::ConflictFind::Region* r;
- bool operator() (Node i,Node j) { return (r->d_nodes[i]->getNumInternalDisequalities()>r->d_nodes[j]->getNumInternalDisequalities());}
-};
-
-
bool StrongSolverTheoryUf::ConflictFind::Region::check( Theory::Effort level, int cardinality, std::vector< Node >& clique ){
if( d_reps_size>long(cardinality) ){
- if( d_reps_size>long(cardinality) && d_total_diseq_internal==d_reps_size*( d_reps_size - 1 ) ){
+ if( d_total_diseq_internal==d_reps_size*( d_reps_size - 1 ) ){
//quick clique check, all reps form a clique
for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
if( it->second->d_valid ){
@@ -225,7 +243,7 @@ bool StrongSolverTheoryUf::ConflictFind::Region::check( Theory::Effort level, in
}
}
return true;
- }else{
+ }else if( Options::current()->ufssRegions || Options::current()->ufssEagerSplits || level==Theory::EFFORT_FULL ){
//build test clique, up to size cardinality+1
if( d_testCliqueSize<=long(cardinality) ){
std::vector< Node > newClique;
@@ -233,7 +251,9 @@ bool StrongSolverTheoryUf::ConflictFind::Region::check( Theory::Effort level, in
for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
//if not in the test clique, add it to the set of new members
if( it->second->d_valid && ( d_testClique.find( it->first )==d_testClique.end() || !d_testClique[ it->first ] ) ){
+ //if( it->second->getNumInternalDisequalities()>cardinality || level==Theory::EFFORT_FULL ){
newClique.push_back( it->first );
+ //}
}
}
//choose remaining nodes with the highest degrees
@@ -282,8 +302,8 @@ bool StrongSolverTheoryUf::ConflictFind::Region::check( Theory::Effort level, in
d_testCliqueSize = d_testCliqueSize + 1;
}
}
- Assert( d_testCliqueSize==long(cardinality+1) );
- if( d_splitsSize==0 ){
+ //check if test clique has larger size than cardinality, and forms a clique
+ if( d_testCliqueSize>=long(cardinality+1) && d_splitsSize==0 ){
//test clique is a clique
for( NodeBoolMap::iterator it = d_testClique.begin(); it != d_testClique.end(); ++it ){
if( (*it).second ){
@@ -297,7 +317,31 @@ bool StrongSolverTheoryUf::ConflictFind::Region::check( Theory::Effort level, in
return false;
}
+void StrongSolverTheoryUf::ConflictFind::Region::getRepresentatives( std::vector< Node >& reps ){
+ for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
+ RegionNodeInfo* rni = it->second;
+ if( rni->d_valid ){
+ reps.push_back( it->first );
+ }
+ }
+}
+
+void StrongSolverTheoryUf::ConflictFind::Region::getNumExternalDisequalities( std::map< Node, int >& num_ext_disequalities ){
+ for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
+ RegionNodeInfo* rni = it->second;
+ if( rni->d_valid ){
+ RegionNodeInfo::DiseqList* del = rni->d_disequalities[0];
+ for( NodeBoolMap::iterator it2 = del->d_disequalities.begin(); it2 != del->d_disequalities.end(); ++it2 ){
+ if( (*it2).second ){
+ num_ext_disequalities[ (*it2).first ]++;
+ }
+ }
+ }
+ }
+}
+
Node StrongSolverTheoryUf::ConflictFind::Region::getBestSplit(){
+#ifndef USE_SMART_SPLITS
//take the first split you find
for( NodeBoolMap::iterator it = d_splits.begin(); it != d_splits.end(); ++it ){
if( (*it).second ){
@@ -305,6 +349,60 @@ Node StrongSolverTheoryUf::ConflictFind::Region::getBestSplit(){
}
}
return Node::null();
+#else
+ std::vector< Node > splits;
+ for( NodeBoolMap::iterator it = d_splits.begin(); it != d_splits.end(); ++it ){
+ if( (*it).second ){
+ splits.push_back( (*it).first );
+ }
+ }
+ if( splits.size()>1 ){
+ std::map< Node, std::map< Node, bool > > ops;
+ Debug("uf-ss-split") << "Choice for splits: " << std::endl;
+ double maxScore = -1;
+ int maxIndex;
+ for( int i=0; i<(int)splits.size(); i++ ){
+ Debug("uf-ss-split") << " " << splits[i] << std::endl;
+ for( int j=0; j<2; j++ ){
+ if( ops.find( splits[i][j] )==ops.end() ){
+ EqClassIterator eqc( splits[i][j], ((uf::TheoryUF*)d_cf->d_th)->getEqualityEngine() );
+ while( !eqc.isFinished() ){
+ Node n = (*eqc);
+ if( n.getKind()==APPLY_UF ){
+ ops[ splits[i][j] ][ n.getOperator() ] = true;
+ }
+ ++eqc;
+ }
+ }
+ }
+ //now, compute score
+ int common[2] = { 0, 0 };
+ for( int j=0; j<2; j++ ){
+ int j2 = j==0 ? 1 : 0;
+ for( std::map< Node, bool >::iterator it = ops[ splits[i][j] ].begin(); it != ops[ splits[i][j] ].end(); ++it ){
+ if( ops[ splits[i][j2] ].find( it->first )!=ops[ splits[i][j2] ].end() ){
+ common[0]++;
+ }else{
+ common[1]++;
+ }
+ }
+ }
+ double score = ( 1.0 + (double)common[0] )/( 1.0 + (double)common[1] );
+ if( score>maxScore ){
+ maxScore = score;
+ maxIndex = i;
+ }
+ }
+ //if( maxIndex!=0 ){
+ // std::cout << "Chose maxIndex = " << maxIndex << std::endl;
+ //}
+ return splits[maxIndex];
+ }else if( !splits.empty() ){
+ return splits[0];
+ }else{
+ return Node::null();
+ }
+#endif
}
void StrongSolverTheoryUf::ConflictFind::Region::addSplit( OutputChannel* out ){
@@ -324,15 +422,6 @@ void StrongSolverTheoryUf::ConflictFind::Region::addSplit( OutputChannel* out ){
out->requirePhase( s, true );
}
-void StrongSolverTheoryUf::ConflictFind::Region::getRepresentatives( std::vector< Node >& reps ){
- for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
- RegionNodeInfo* rni = it->second;
- if( rni->d_valid ){
- reps.push_back( it->first );
- }
- }
-}
-
bool StrongSolverTheoryUf::ConflictFind::Region::minimize( OutputChannel* out ){
if( hasSplits() ){
addSplit( out );
@@ -342,20 +431,6 @@ bool StrongSolverTheoryUf::ConflictFind::Region::minimize( OutputChannel* out ){
}
}
-void StrongSolverTheoryUf::ConflictFind::Region::getNumExternalDisequalities( std::map< Node, int >& num_ext_disequalities ){
- for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
- RegionNodeInfo* rni = it->second;
- if( rni->d_valid ){
- RegionNodeInfo::DiseqList* del = rni->d_disequalities[0];
- for( NodeBoolMap::iterator it2 = del->d_disequalities.begin(); it2 != del->d_disequalities.end(); ++it2 ){
- if( (*it2).second ){
- num_ext_disequalities[ (*it2).first ]++;
- }
- }
- }
- }
-}
-
void StrongSolverTheoryUf::ConflictFind::Region::debugPrint( const char* c, bool incClique ){
Debug( c ) << "Num reps: " << d_reps_size << std::endl;
for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
@@ -398,35 +473,6 @@ void StrongSolverTheoryUf::ConflictFind::Region::debugPrint( const char* c, bool
}
}
-void StrongSolverTheoryUf::ConflictFind::combineRegions( int ai, int bi ){
- Debug("uf-ss-region") << "uf-ss: Combine Region #" << bi << " with Region #" << ai << std::endl;
- Assert( isValid( ai ) && isValid( bi ) );
- for( std::map< Node, Region::RegionNodeInfo* >::iterator it = d_regions[bi]->d_nodes.begin(); it != d_regions[bi]->d_nodes.end(); ++it ){
- Region::RegionNodeInfo* rni = it->second;
- if( rni->d_valid ){
- d_regions_map[ it->first ] = ai;
- }
- }
- //update regions disequal DO_THIS?
- d_regions[ai]->combine( d_regions[bi] );
- d_regions[bi]->d_valid = false;
-}
-
-void StrongSolverTheoryUf::ConflictFind::moveNode( Node n, int ri ){
- Debug("uf-ss-region") << "uf-ss: Move node " << n << " to Region #" << ri << std::endl;
- Assert( isValid( d_regions_map[ n ] ) );
- Assert( isValid( ri ) );
- ////update regions disequal DO_THIS?
- //Region::RegionNodeInfo::DiseqList* del = d_regions[ d_regions_map[n] ]->d_nodes[n]->d_disequalities[0];
- //for( NodeBoolMap::iterator it = del->d_disequalities.begin(); it != del->d_disequalities.end(); ++it ){
- // if( (*it).second ){
- // }
- //}
- //move node to region ri
- d_regions[ri]->takeNode( d_regions[ d_regions_map[n] ], n );
- d_regions_map[n] = ri;
-}
-
int StrongSolverTheoryUf::ConflictFind::getNumDisequalitiesToRegion( Node n, int ri ){
int ni = d_regions_map[n];
int counter = 0;
@@ -448,10 +494,6 @@ void StrongSolverTheoryUf::ConflictFind::getDisequalitiesToRegions( int ri, std:
Region::RegionNodeInfo::DiseqList* del = it->second->d_disequalities[0];
for( NodeBoolMap::iterator it2 = del->d_disequalities.begin(); it2 != del->d_disequalities.end(); ++it2 ){
if( (*it2).second ){
- //if( !isValid( d_regions_map[ (*it2).first ] ) ){
- // Debug( "uf-ss-temp" ) << "^^^" << ri << " " << d_regions_map[ (*it2).first ].get() << std::endl;
- // debugPrint( "uf-ss-temp" );
- //}
Assert( isValid( d_regions_map[ (*it2).first ] ) );
//Notice() << "Found disequality with " << (*it2).first << ", region = " << d_regions_map[ (*it2).first ] << std::endl;
regions_diseq[ d_regions_map[ (*it2).first ] ]++;
@@ -542,18 +584,21 @@ void StrongSolverTheoryUf::ConflictFind::explainClique( std::vector< Node >& cli
/** new node */
void StrongSolverTheoryUf::ConflictFind::newEqClass( Node n ){
if( d_regions_map.find( n )==d_regions_map.end() ){
+ if( !Options::current()->ufssRegions ){
+ //if not using regions, always add new equivalence classes to region index = 0
+ d_regions_index = 0;
+ }
d_regions_map[n] = d_regions_index;
Debug("uf-ss") << "StrongSolverTheoryUf: New Eq Class " << n << std::endl;
Debug("uf-ss-debug") << d_regions_index << " " << (int)d_regions.size() << std::endl;
if( d_regions_index<d_regions.size() ){
d_regions[ d_regions_index ]->debugPrint("uf-ss-debug",true);
d_regions[ d_regions_index ]->d_valid = true;
- //Assert( d_regions[ d_regions_index ]->d_valid );
- Assert( d_regions[ d_regions_index ]->getNumReps()==0 );
+ Assert( !Options::current()->ufssRegions || d_regions[ d_regions_index ]->getNumReps()==0 );
}else{
d_regions.push_back( new Region( this, d_th->getSatContext() ) );
}
- d_regions[ d_regions_index ]->setRep( n, true );
+ d_regions[ d_regions_index ]->addRep( n );
d_regions_index = d_regions_index + 1;
d_reps = d_reps + 1;
}
@@ -571,14 +616,14 @@ void StrongSolverTheoryUf::ConflictFind::merge( Node a, Node b ){
int bi = d_regions_map[b];
Debug("uf-ss") << " regions: " << ai << " " << bi << std::endl;
if( ai!=bi ){
- if( d_regions[ai]->getNumReps()==1 ){
- combineRegions( bi, ai );
- d_regions[bi]->setEqual( a, b );
- checkRegion( bi );
+ if( d_regions[ai]->getNumReps()==1 ){
+ int ri = combineRegions( bi, ai );
+ d_regions[ri]->setEqual( a, b );
+ checkRegion( ri );
}else if( d_regions[bi]->getNumReps()==1 ){
- combineRegions( ai, bi );
- d_regions[ai]->setEqual( a, b );
- checkRegion( ai );
+ int ri = combineRegions( ai, bi );
+ d_regions[ri]->setEqual( a, b );
+ checkRegion( ri );
}else{
// either move a to d_regions[bi], or b to d_regions[ai]
int aex = d_regions[ai]->d_nodes[a]->getNumInternalDisequalities() - getNumDisequalitiesToRegion( a, bi );
@@ -652,7 +697,7 @@ void StrongSolverTheoryUf::ConflictFind::assertCardinality( int c, bool val ){
}
}
-bool StrongSolverTheoryUf::ConflictFind::checkRegion( int ri, bool rec ){
+void StrongSolverTheoryUf::ConflictFind::checkRegion( int ri, bool rec ){
if( isValid(ri) ){
Assert( d_cardinality>0 );
//first check if region is in conflict
@@ -660,61 +705,98 @@ bool StrongSolverTheoryUf::ConflictFind::checkRegion( int ri, bool rec ){
if( d_regions[ri]->check( Theory::EFFORT_STANDARD, d_cardinality, clique ) ){
//explain clique
explainClique( clique, &d_th->getOutputChannel() );
- return false;
}else if( d_regions[ri]->getMustCombine( d_cardinality ) ){
- //this region must merge with another
- Debug("uf-ss-check-region") << "We must combine Region #" << ri << ". " << std::endl;
- d_regions[ri]->debugPrint("uf-ss-check-region");
////alternatively, check if we can reduce the number of external disequalities by moving single nodes
//for( std::map< Node, bool >::iterator it = d_regions[i]->d_reps.begin(); it != d_regions[i]->d_reps.end(); ++it ){
// if( it->second ){
// int inDeg = d_regions[i]->d_disequalities_size[1][ it-> first ];
- // int outDeg = d_regions[i]->d_disequalities_size[1][ it-> first ];
+ // int outDeg = d_regions[i]->d_disequalities_size[0][ it-> first ];
// if( inDeg<outDeg ){
// }
// }
//}
- //take region with maximum disequality density
- double maxScore = 0;
- int maxRegion = -1;
- std::map< int, int > regions_diseq;
- getDisequalitiesToRegions( ri, regions_diseq );
- for( std::map< int, int >::iterator it = regions_diseq.begin(); it != regions_diseq.end(); ++it ){
- Debug("uf-ss-check-region") << it->first << " : " << it->second << std::endl;
+ int riNew = forceCombineRegion( ri, true );
+ if( riNew>=0 && rec ){
+ checkRegion( riNew, rec );
}
- for( std::map< int, int >::iterator it = regions_diseq.begin(); it != regions_diseq.end(); ++it ){
- Assert( it->first!=ri );
- Assert( isValid( it->first ) );
- Assert( d_regions[ it->first ]->getNumReps()>0 );
- double tempScore = double(it->second)/double(d_regions[it->first]->getNumReps() );
- if( tempScore>maxScore ){
- maxRegion = it->first;
- maxScore = tempScore;
- }
+ }
+ }
+}
+
+int StrongSolverTheoryUf::ConflictFind::forceCombineRegion( int ri, bool useDensity ){
+ if( !useDensity ){
+ for( int i=0; i<(int)d_regions_index; i++ ){
+ if( ri!=i && d_regions[i]->d_valid ){
+ return combineRegions( ri, i );
}
- Assert( maxRegion!=-1 );
+ }
+ return -1;
+ }else{
+ //this region must merge with another
+ Debug("uf-ss-check-region") << "We must combine Region #" << ri << ". " << std::endl;
+ d_regions[ri]->debugPrint("uf-ss-check-region");
+ //take region with maximum disequality density
+ double maxScore = 0;
+ int maxRegion = -1;
+ std::map< int, int > regions_diseq;
+ getDisequalitiesToRegions( ri, regions_diseq );
+ for( std::map< int, int >::iterator it = regions_diseq.begin(); it != regions_diseq.end(); ++it ){
+ Debug("uf-ss-check-region") << it->first << " : " << it->second << std::endl;
+ }
+ for( std::map< int, int >::iterator it = regions_diseq.begin(); it != regions_diseq.end(); ++it ){
+ Assert( it->first!=ri );
+ Assert( isValid( it->first ) );
+ Assert( d_regions[ it->first ]->getNumReps()>0 );
+ double tempScore = double(it->second)/double(d_regions[it->first]->getNumReps() );
+ if( tempScore>maxScore ){
+ maxRegion = it->first;
+ maxScore = tempScore;
+ }
+ }
+ if( maxRegion!=-1 ){
Debug("uf-ss-check-region") << "Combine with region #" << maxRegion << ":" << std::endl;
d_regions[maxRegion]->debugPrint("uf-ss-check-region");
- combineRegions( ri, maxRegion );
- if( rec ){
- checkRegion( ri, rec );
- }
- //std::vector< Node > clique;
- //if( d_regions[ri]->check( Theory::EFFORT_STANDARD, cardinality, clique ) ){
- // //explain clique
- // Notice() << "found clique " << std::endl;
- //}
- return true;
+ return combineRegions( ri, maxRegion );
}
+ return -1;
}
- return false;
+}
+
+
+int StrongSolverTheoryUf::ConflictFind::combineRegions( int ai, int bi ){
+#ifdef COMBINE_REGIONS_SMALL_INTO_LARGE
+ if( d_regions[ai]->getNumReps()<d_regions[bi]->getNumReps() ){
+ return combineRegions( bi, ai );
+ }
+#endif
+ Debug("uf-ss-region") << "uf-ss: Combine Region #" << bi << " with Region #" << ai << std::endl;
+ Assert( isValid( ai ) && isValid( bi ) );
+ for( std::map< Node, Region::RegionNodeInfo* >::iterator it = d_regions[bi]->d_nodes.begin(); it != d_regions[bi]->d_nodes.end(); ++it ){
+ Region::RegionNodeInfo* rni = it->second;
+ if( rni->d_valid ){
+ d_regions_map[ it->first ] = ai;
+ }
+ }
+ //update regions disequal DO_THIS?
+ d_regions[ai]->combine( d_regions[bi] );
+ d_regions[bi]->d_valid = false;
+ return ai;
+}
+
+void StrongSolverTheoryUf::ConflictFind::moveNode( Node n, int ri ){
+ Debug("uf-ss-region") << "uf-ss: Move node " << n << " to Region #" << ri << std::endl;
+ Assert( isValid( d_regions_map[ n ] ) );
+ Assert( isValid( ri ) );
+ //move node to region ri
+ d_regions[ri]->takeNode( d_regions[ d_regions_map[n] ], n );
+ d_regions_map[n] = ri;
}
bool StrongSolverTheoryUf::ConflictFind::disambiguateTerms( OutputChannel* out ){
Debug("uf-ss-disamb") << "Disambiguate terms." << std::endl;
bool lemmaAdded = false;
//otherwise, determine ambiguous pairs of ground terms for relevant sorts
- TermDb* db = d_th->getQuantifiersEngine()->getTermDatabase();
+ quantifiers::TermDb* db = d_th->getQuantifiersEngine()->getTermDatabase();
for( std::map< Node, std::vector< Node > >::iterator it = db->d_op_map.begin(); it != db->d_op_map.end(); ++it ){
Debug("uf-ss-disamb") << "Check " << it->first << std::endl;
if( it->second.size()>1 ){
@@ -798,22 +880,29 @@ void StrongSolverTheoryUf::ConflictFind::check( Theory::Effort level, OutputChan
}
}
}
- if( level==Theory::EFFORT_FULL ){
+ bool addedLemma = false;
+ //do splitting on demand
+ if( level==Theory::EFFORT_FULL || Options::current()->ufssEagerSplits ){
Debug("uf-ss-debug") << "Add splits?" << std::endl;
- //see if we have any recommended splits
- bool addedLemma = false;
+ //see if we have any recommended splits from large regions
for( int i=0; i<(int)d_regions_index; i++ ){
- if( d_regions[i]->d_valid ){
+ if( d_regions[i]->d_valid && d_regions[i]->getNumReps()>d_cardinality ){
if( d_regions[i]->hasSplits() ){
d_regions[i]->addSplit( out );
addedLemma = true;
++( d_th->getStrongSolver()->d_statistics.d_split_lemmas );
+#ifdef ONE_SPLIT_REGION
+ break;
+#endif
}
}
}
+ }
+ //force continuation via term disambiguation or combination of regions
+ if( level==Theory::EFFORT_FULL ){
if( !addedLemma ){
Debug("uf-ss") << "No splits added." << std::endl;
- if( Options::current()->fmfRegionSat ){
+ if( Options::current()->ufssColoringSat ){
//otherwise, try to disambiguate individual terms
if( !disambiguateTerms( out ) ){
//no disequalities can be propagated
@@ -825,18 +914,18 @@ void StrongSolverTheoryUf::ConflictFind::check( Theory::Effort level, OutputChan
debugPrint("uf-ss-sat");
}
}else{
- //naive strategy. combine the first two valid regions
- int regIndex = -1;
+ bool recheck = false;
+ //naive strategy, force region combination involving the first valid region
for( int i=0; i<(int)d_regions_index; i++ ){
if( d_regions[i]->d_valid ){
- if( regIndex==-1 ){
- regIndex = i;
- }else{
- combineRegions( regIndex, i );
- check( level, out );
- }
+ forceCombineRegion( i, false );
+ recheck = true;
+ break;
}
}
+ if( recheck ){
+ check( level, out );
+ }
}
}
}
@@ -846,8 +935,7 @@ void StrongSolverTheoryUf::ConflictFind::check( Theory::Effort level, OutputChan
void StrongSolverTheoryUf::ConflictFind::propagate( Theory::Effort level, OutputChannel* out ){
Assert( d_cardinality>0 );
-
- //propagate the current cardinality as a decision literal
+ //propagate the current cardinality as a decision literal, if not already asserted
Node cn = d_cardinality_literal[ d_cardinality ];
Debug("uf-ss-prop-as-dec") << "Propagate as decision " << d_type << ", cardinality = " << d_cardinality << std::endl;
Assert( !cn.isNull() );
@@ -856,7 +944,6 @@ void StrongSolverTheoryUf::ConflictFind::propagate( Theory::Effort level, Output
Debug("uf-ss-prop-as-dec") << "Propagate as decision " << d_cardinality_literal[ d_cardinality ];
Debug("uf-ss-prop-as-dec") << " " << d_cardinality_literal[ d_cardinality ][0].getType() << std::endl;
}
-
}
void StrongSolverTheoryUf::ConflictFind::debugPrint( const char* c ){
@@ -913,7 +1000,7 @@ void StrongSolverTheoryUf::ConflictFind::setCardinality( int c, OutputChannel* o
}
void StrongSolverTheoryUf::ConflictFind::getRepresentatives( std::vector< Node >& reps ){
- if( !Options::current()->fmfRegionSat ){
+ if( !Options::current()->ufssColoringSat ){
bool foundRegion = false;
for( int i=0; i<(int)d_regions_index; i++ ){
//should not have multiple regions at this point
@@ -932,6 +1019,8 @@ void StrongSolverTheoryUf::ConflictFind::getRepresentatives( std::vector< Node >
}
bool StrongSolverTheoryUf::ConflictFind::minimize( OutputChannel* out ){
+ //ensure that model forms a clique:
+ // if two equivalence classes are neither equal nor disequal, add a split
int validRegionIndex = -1;
for( int i=0; i<(int)d_regions_index; i++ ){
if( d_regions[i]->d_valid ){
@@ -956,10 +1045,9 @@ Node StrongSolverTheoryUf::ConflictFind::getCardinalityLemma(){
if( d_cardinality_lemma.find( d_cardinality )==d_cardinality_lemma.end() ){
if( d_cardinality_lemma_term.isNull() ){
std::stringstream ss;
- ss << "fmf_term_" << d_type;
+ ss << Expr::setlanguage(Options::current()->outputLanguage);
+ ss << "t_" << d_type;
d_cardinality_lemma_term = NodeManager::currentNM()->mkVar( ss.str(), d_type );
- ModelBasisAttribute mba;
- d_cardinality_lemma_term.setAttribute(mba,true);
}
Node lem = NodeManager::currentNM()->mkNode( CARDINALITY_CONSTRAINT, d_cardinality_lemma_term,
NodeManager::currentNM()->mkConst( Rational( d_cardinality ) ) );
@@ -1001,8 +1089,6 @@ void StrongSolverTheoryUf::merge( Node a, Node b ){
Debug("uf-ss-solver") << "StrongSolverTheoryUf: Merge " << a << " " << b << " " << tn << std::endl;
c->merge( a, b );
}
- //else if( isRelevantType( tn ) ){
- //}
}
/** assert terms are disequal */
@@ -1015,8 +1101,6 @@ void StrongSolverTheoryUf::assertDisequal( Node a, Node b, Node reason ){
//Assert( d_th->d_equalityEngine.getRepresentative( b )==b );
c->assertDisequal( a, b, reason );
}
- //else if( isRelevantType( tn ) ){
- //}
}
/** assert a node */
@@ -1187,14 +1271,14 @@ void StrongSolverTheoryUf::getRepresentatives( TypeNode t, std::vector< Node >&
}
}
-Node StrongSolverTheoryUf::getCardinalityTerm( TypeNode t ){
- ConflictFind* c = getConflictFind( t );
- if( c ){
- return c->getCardinalityTerm();
- }else{
- return Node::null();
- }
-}
+//Node StrongSolverTheoryUf::getCardinalityTerm( TypeNode t ){
+// ConflictFind* c = getConflictFind( t );
+// if( c ){
+// return c->getCardinalityTerm();
+// }else{
+// return Node::null();
+// }
+//}
bool StrongSolverTheoryUf::minimize(){
for( std::map< TypeNode, ConflictFind* >::iterator it = d_conf_find.begin(); it != d_conf_find.end(); ++it ){
@@ -1252,7 +1336,8 @@ bool StrongSolverTheoryUf::isRelevantType( TypeNode t ){
t!=NodeManager::currentNM()->realType() &&
t!=NodeManager::currentNM()->builtinOperatorType() &&
!t.isFunction() &&
- !t.isDatatype();
+ !t.isDatatype() &&
+ !t.isArray();
}
bool StrongSolverTheoryUf::involvesRelevantType( Node n ){
diff --git a/src/theory/uf/theory_uf_strong_solver.h b/src/theory/uf/theory_uf_strong_solver.h
index dde24394a..bd4c4cb22 100644
--- a/src/theory/uf/theory_uf_strong_solver.h
+++ b/src/theory/uf/theory_uf_strong_solver.h
@@ -29,10 +29,6 @@
namespace CVC4 {
namespace theory {
-
-struct ModelBasisAttributeId {};
-typedef expr::Attribute<ModelBasisAttributeId, bool> ModelBasisAttribute;
-
namespace uf {
class TheoryUF;
@@ -43,6 +39,7 @@ protected:
typedef context::CDHashMap<Node, int, NodeHashFunction> NodeIntMap;
typedef context::CDChunkList<Node> NodeList;
typedef context::CDList<bool> BoolList;
+ typedef context::CDList<bool> IntList;
typedef context::CDHashMap<TypeNode, bool, TypeNodeHashFunction> TypeNodeBoolMap;
public:
/** information for incremental conflict/clique finding for a particular sort */
@@ -74,7 +71,8 @@ public:
DiseqList d_external;
public:
/** constructor */
- RegionNodeInfo( context::Context* c ) : d_internal( c ), d_external( c ), d_valid( c, true ){
+ RegionNodeInfo( context::Context* c ) :
+ d_internal( c ), d_external( c ), d_valid( c, true ){
d_disequalities[0] = &d_internal;
d_disequalities[1] = &d_external;
}
@@ -103,6 +101,9 @@ public:
context::CDO< unsigned > d_total_diseq_external;
//total disequality size (internal)
context::CDO< unsigned > d_total_diseq_internal;
+ private:
+ /** set rep */
+ void setRep( Node n, bool valid );
public:
//constructor
Region( ConflictFind* cf, context::Context* c ) : d_cf( cf ), d_testClique( c ), d_testCliqueSize( c, 0 ),
@@ -115,37 +116,40 @@ public:
//whether region is valid
context::CDO< bool > d_valid;
public:
- //get num reps
- int getNumReps() { return d_reps_size; }
- // has representative
- bool hasRep( Node n ) { return d_nodes.find( n )!=d_nodes.end() && d_nodes[n]->d_valid; }
+ /** add rep */
+ void addRep( Node n );
//take node from region
void takeNode( Region* r, Node n );
//merge with other region
void combine( Region* r );
- /** set rep */
- void setRep( Node n, bool valid );
/** merge */
void setEqual( Node a, Node b );
//set n1 != n2 to value 'valid', type is whether it is internal/external
void setDisequal( Node n1, Node n2, int type, bool valid );
+ public:
+ //get num reps
+ int getNumReps() { return d_reps_size; }
+ //get test clique size
+ int getTestCliqueSize() { return d_testCliqueSize; }
+ // has representative
+ bool hasRep( Node n ) { return d_nodes.find( n )!=d_nodes.end() && d_nodes[n]->d_valid; }
// is disequal
bool isDisequal( Node n1, Node n2, int type );
- public:
/** get must merge */
bool getMustCombine( int cardinality );
- /** check for cliques */
- bool check( Theory::Effort level, int cardinality, std::vector< Node >& clique );
/** has splits */
bool hasSplits() { return d_splitsSize>0; }
- /** add split */
- void addSplit( OutputChannel* out );
/** get representatives */
void getRepresentatives( std::vector< Node >& reps );
- /** minimize */
- bool minimize( OutputChannel* out );
/** get external disequalities */
void getNumExternalDisequalities( std::map< Node, int >& num_ext_disequalities );
+ public:
+ /** check for cliques */
+ bool check( Theory::Effort level, int cardinality, std::vector< Node >& clique );
+ /** add split */
+ void addSplit( OutputChannel* out );
+ /** minimize */
+ bool minimize( OutputChannel* out );
//print debug
void debugPrint( const char* c, bool incClique = false );
};
@@ -167,16 +171,10 @@ public:
/** whether two terms are ambiguous (indexed by equalities) */
NodeBoolMap d_term_amb;
private:
- /** merge regions */
- void combineRegions( int ai, int bi );
- /** move node n to region ri */
- void moveNode( Node n, int ri );
/** get number of disequalities from node n to region ri */
int getNumDisequalitiesToRegion( Node n, int ri );
/** get number of disequalities from Region r to other regions */
void getDisequalitiesToRegions( int ri, std::map< int, int >& regions_diseq );
- /** check if we need to combine region ri */
- bool checkRegion( int ri, bool rec = true );
/** explain clique */
void explainClique( std::vector< Node >& clique, OutputChannel* out );
/** is valid */
@@ -184,6 +182,15 @@ public:
/** check ambiguous terms */
bool disambiguateTerms( OutputChannel* out );
private:
+ /** check if we need to combine region ri */
+ void checkRegion( int ri, bool rec = true );
+ /** force combine region */
+ int forceCombineRegion( int ri, bool useDensity = true );
+ /** merge regions */
+ int combineRegions( int ai, int bi );
+ /** move node n to region ri */
+ void moveNode( Node n, int ri );
+ private:
/** cardinality operating with */
context::CDO< int > d_cardinality;
/** type */
@@ -226,7 +233,7 @@ public:
/** get representatives */
void getRepresentatives( std::vector< Node >& reps );
/** get model basis term */
- Node getCardinalityTerm() { return d_cardinality_lemma_term; }
+ //Node getCardinalityTerm() { return d_cardinality_lemma_term; }
/** minimize */
bool minimize( OutputChannel* out );
/** get cardinality lemma */
@@ -293,7 +300,7 @@ public:
/** get representatives */
void getRepresentatives( TypeNode t, std::vector< Node >& reps );
/** get cardinality term */
- Node getCardinalityTerm( TypeNode t );
+ //Node getCardinalityTerm( TypeNode t );
/** minimize */
bool minimize();
diff --git a/src/theory/uf/theory_uf_type_rules.h b/src/theory/uf/theory_uf_type_rules.h
index 34a8a805b..d00b69398 100644
--- a/src/theory/uf/theory_uf_type_rules.h
+++ b/src/theory/uf/theory_uf_type_rules.h
@@ -70,7 +70,69 @@ public:
}
return nodeManager->booleanType();
}
-};/* class UfTypeRule */
+};/* class CardinalityConstraintTypeRule */
+
+class FunctionModelTypeRule {
+public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw(TypeCheckingExceptionPrivate) {
+ TypeNode tn = n[0].getType(check);
+ if( check ){
+ if( n.getNumChildren()==2 ){
+ if( n[0].getKind()!=kind::FUNCTION_CASE_SPLIT ){
+ throw TypeCheckingExceptionPrivate(n, "improper function model representation : first child must be case split");
+ }
+ TypeNode tn2 = n[1].getType(check);
+ if( tn!=tn2 ){
+ std::stringstream ss;
+ ss << "function model has inconsistent return types : " << tn << " " << tn2;
+ throw TypeCheckingExceptionPrivate(n, ss.str());
+ }
+ }
+ }
+ return tn;
+ }
+};/* class FunctionModelTypeRule */
+
+class FunctionCaseSplitTypeRule {
+public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw(TypeCheckingExceptionPrivate) {
+ TypeNode retType = n[0][1].getType(check);
+ if( check ){
+ TypeNode argType = n[0][0].getType(check);
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ TypeNode argType2 = n[i][0].getType(check);
+ if( argType!=argType2 ){
+ std::stringstream ss;
+ ss << "function case split has inconsistent argument types : " << argType << " " << argType2;
+ throw TypeCheckingExceptionPrivate(n, ss.str());
+ }
+ TypeNode retType2 = n[i][1].getType(check);
+ if( retType!=retType2 ){
+ std::stringstream ss;
+ ss << "function case split has inconsistent return types : " << retType << " " << retType2;
+ throw TypeCheckingExceptionPrivate(n, ss.str());
+ }
+ }
+ }
+ return retType;
+ }
+};/* class FunctionCaseSplitTypeRule */
+
+
+class FunctionCaseTypeRule {
+public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw(TypeCheckingExceptionPrivate) {
+ TypeNode retType = n[1].getType(check);
+ if( check ){
+ TypeNode argType = n[0].getType(check);
+ }
+ return retType;
+ }
+};/* class FunctionCaseTypeRule */
+
}/* CVC4::theory::uf namespace */
}/* CVC4::theory namespace */
diff --git a/src/theory/valuation.cpp b/src/theory/valuation.cpp
index ef02f6278..948a7a130 100644
--- a/src/theory/valuation.cpp
+++ b/src/theory/valuation.cpp
@@ -55,11 +55,6 @@ bool equalityStatusCompatible(EqualityStatus s1, EqualityStatus s2) {
}
}
-
-Node Valuation::getValue(TNode n) const {
- return d_engine->getValue(n);
-}
-
bool Valuation::isSatLiteral(TNode n) const {
return d_engine->getPropEngine()->isSatLiteral(n);
}
diff --git a/src/theory/valuation.h b/src/theory/valuation.h
index 11467c8db..7f3a00ec1 100644
--- a/src/theory/valuation.h
+++ b/src/theory/valuation.h
@@ -64,8 +64,6 @@ public:
d_engine(engine) {
}
- Node getValue(TNode n) const;
-
/*
* Return true if n has an associated SAT literal
*/
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback