summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>2019-10-04 02:12:02 -0500
committerAndres Noetzli <andres.noetzli@gmail.com>2019-10-04 00:12:02 -0700
commit472c5a592c78e4757b3201f9e20908a4c645921b (patch)
tree43aa40d426af3d8b05fd358951601a1eecbf25ff /src
parent167947ab81094de28251bb885c8cf84e7168c43b (diff)
Avoid duplicate lemmas in datatypes (#3310)
We previously were sending e.g. dt.size >= 0 lemmas when size terms are pre-registered, which can happen multiple times in a user context. This ensures we cache whether a lemma is sent in a user-context dependent way in the datatypes solver. This ensures we don't send the same lemma twice for dt.size >= 0 lemmas.
Diffstat (limited to 'src')
-rw-r--r--src/theory/datatypes/theory_datatypes.cpp142
-rw-r--r--src/theory/datatypes/theory_datatypes.h10
2 files changed, 82 insertions, 70 deletions
diff --git a/src/theory/datatypes/theory_datatypes.cpp b/src/theory/datatypes/theory_datatypes.cpp
index 609cdaf6e..8bac280b6 100644
--- a/src/theory/datatypes/theory_datatypes.cpp
+++ b/src/theory/datatypes/theory_datatypes.cpp
@@ -57,6 +57,7 @@ TheoryDatatypes::TheoryDatatypes(Context* c,
d_addedLemma(false),
d_addedFact(false),
d_collectTermsCache(c),
+ d_collectTermsCacheU(u),
d_functionTerms(c),
d_singleton_eq(u),
d_lemmas_produced_c(u)
@@ -459,8 +460,9 @@ bool TheoryDatatypes::doSendLemma( Node lem ) {
}
bool TheoryDatatypes::doSendLemmas( std::vector< Node >& lemmas ){
bool ret = false;
- for( unsigned i=0; i<lemmas.size(); i++ ){
- bool cret = doSendLemma( lemmas[i] );
+ for (const Node& lem : lemmas)
+ {
+ bool cret = doSendLemma(lem);
ret = ret || cret;
}
lemmas.clear();
@@ -526,9 +528,6 @@ void TheoryDatatypes::preRegisterTerm(TNode n) {
d_equalityEngine.addTriggerPredicate(n);
break;
default:
- if( n.getKind()==kind::DT_SIZE ){
- d_out->lemma( NodeManager::currentNM()->mkNode( LEQ, d_zero, n ) );
- }
// Function applications/predicates
d_equalityEngine.addTerm(n);
if( d_sygus_sym_break ){
@@ -1664,74 +1663,79 @@ Node TheoryDatatypes::getSingletonLemma( TypeNode tn, bool pol ) {
}
void TheoryDatatypes::collectTerms( Node n ) {
- if( d_collectTermsCache.find( n )==d_collectTermsCache.end() ){
- d_collectTermsCache[n] = true;
- //for( int i=0; i<(int)n.getNumChildren(); i++ ) {
- // collectTerms( n[i] );
- //}
- if( n.getKind() == APPLY_CONSTRUCTOR ){
- Debug("datatypes") << " Found constructor " << n << endl;
- if( n.getNumChildren()>0 ){
- d_functionTerms.push_back( n );
- }
- }else{
+ if (d_collectTermsCache.find(n) != d_collectTermsCache.end())
+ {
+ // already processed
+ return;
+ }
+ d_collectTermsCache[n] = true;
+ Kind nk = n.getKind();
+ if (nk == APPLY_CONSTRUCTOR)
+ {
+ Debug("datatypes") << " Found constructor " << n << endl;
+ if (n.getNumChildren() > 0)
+ {
+ d_functionTerms.push_back(n);
+ }
+ return;
+ }
+ if (nk == APPLY_SELECTOR_TOTAL || nk == DT_SIZE || nk == DT_HEIGHT_BOUND)
+ {
+ d_functionTerms.push_back(n);
+ // we must also record which selectors exist
+ Trace("dt-collapse-sel") << " Found selector " << n << endl;
+ Node rep = getRepresentative(n[0]);
+ // record it in the selectors
+ EqcInfo* eqc = getOrMakeEqcInfo(rep, true);
+ // add it to the eqc info
+ addSelector(n, eqc, rep);
+ }
+
+ // now, do user-context-dependent lemmas
+ if (nk != DT_SIZE && nk != DT_HEIGHT_BOUND)
+ {
+ // if not one of these kinds, there are no lemmas
+ return;
+ }
+ if (d_collectTermsCacheU.find(n) != d_collectTermsCacheU.end())
+ {
+ return;
+ }
+ d_collectTermsCacheU[n] = true;
- if( n.getKind() == APPLY_SELECTOR_TOTAL || n.getKind() == DT_SIZE || n.getKind() == DT_HEIGHT_BOUND ){
- d_functionTerms.push_back( n );
- //we must also record which selectors exist
- Trace("dt-collapse-sel") << " Found selector " << n << endl;
- Node rep = getRepresentative( n[0] );
- //record it in the selectors
- EqcInfo* eqc = getOrMakeEqcInfo( rep, true );
- //add it to the eqc info
- addSelector( n, eqc, rep );
-
- if( n.getKind() == DT_SIZE ){
- /*
- //add size = 0 lemma
- Node nn = n.eqNode( NodeManager::currentNM()->mkConst( Rational(0) ) );
- std::vector< Node > children;
- children.push_back( nn.negate() );
- const Datatype& dt = ((DatatypeType)(n[0].getType()).toType()).getDatatype();
- for( unsigned i=0; i<dt.getNumConstructors(); i++ ){
- if( DatatypesRewriter::isNullaryConstructor( dt[i] ) ){
- Node test = DatatypesRewriter::mkTester( n[0], i, dt );
- children.push_back( test );
- }
- }
- conc = children.size()==1 ? children[0] : NodeManager::currentNM()->mkNode( OR, children );
- Trace("datatypes-infer") << "DtInfer : zero size : " << conc << std::endl;
- d_pending.push_back( conc );
- d_pending_exp[ conc ] = d_true;
- d_infer.push_back( conc );
- */
- }
+ NodeManager* nm = NodeManager::currentNM();
- if( n.getKind() == DT_HEIGHT_BOUND ){
- if( n[1].getConst<Rational>().isZero() ){
- std::vector< Node > children;
- const Datatype& dt = ((DatatypeType)(n[0].getType()).toType()).getDatatype();
- for( unsigned i=0; i<dt.getNumConstructors(); i++ ){
- if( DatatypesRewriter::isNullaryConstructor( dt[i] ) ){
- Node test = DatatypesRewriter::mkTester( n[0], i, dt );
- children.push_back( test );
- }
- }
- Node lem;
- if( children.empty() ){
- lem = n.negate();
- }else{
- lem = NodeManager::currentNM()->mkNode( EQUAL, n, children.size()==1 ? children[0] : NodeManager::currentNM()->mkNode( OR, children ) );
- }
- Trace("datatypes-infer") << "DtInfer : zero height : " << lem << std::endl;
- //d_pending.push_back( lem );
- //d_pending_exp[ lem ] = d_true;
- //d_infer.push_back( lem );
- d_pending_lem.push_back( lem );
- }
- }
+ if (nk == DT_SIZE)
+ {
+ Node lem = nm->mkNode(LEQ, d_zero, n);
+ Trace("datatypes-infer")
+ << "DtInfer : size geq zero : " << lem << std::endl;
+ d_pending_lem.push_back(lem);
+ }
+ else if (nk == DT_HEIGHT_BOUND && n[1].getConst<Rational>().isZero())
+ {
+ std::vector<Node> children;
+ const Datatype& dt = n[0].getType().getDatatype();
+ for (unsigned i = 0, ncons = dt.getNumConstructors(); i < ncons; i++)
+ {
+ if (DatatypesRewriter::isNullaryConstructor(dt[i]))
+ {
+ Node test = DatatypesRewriter::mkTester(n[0], i, dt);
+ children.push_back(test);
}
}
+ Node lem;
+ if (children.empty())
+ {
+ lem = n.negate();
+ }
+ else
+ {
+ lem = n.eqNode(children.size() == 1 ? children[0]
+ : nm->mkNode(OR, children));
+ }
+ Trace("datatypes-infer") << "DtInfer : zero height : " << lem << std::endl;
+ d_pending_lem.push_back(lem);
}
}
diff --git a/src/theory/datatypes/theory_datatypes.h b/src/theory/datatypes/theory_datatypes.h
index b4803e69a..e14a78df2 100644
--- a/src/theory/datatypes/theory_datatypes.h
+++ b/src/theory/datatypes/theory_datatypes.h
@@ -205,8 +205,16 @@ private:
bool d_addedFact;
/** The conflict node */
Node d_conflictNode;
- /** cache for which terms we have called collectTerms(...) on */
+ /**
+ * SAT-context dependent cache for which terms we have called
+ * collectTerms(...) on.
+ */
BoolMap d_collectTermsCache;
+ /**
+ * User-context dependent cache for which terms we have called
+ * collectTerms(...) on.
+ */
+ BoolMap d_collectTermsCacheU;
/** pending assertions/merges */
std::vector< Node > d_pending_lem;
std::vector< Node > d_pending;
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback