option cbqiInnermost --cbqi-innermost bool :default false
only process innermost quantified formulas in counterexample-based quantifier instantiation
+option quantEpr --quant-epr bool :default false
+ infer whether in effectively propositional fragment, use for cbqi
+
### local theory extensions options
option localTheoryExt --local-t-ext bool :default false
Trace("cbqi") << "Counterexample lemma : " << lem << std::endl;
registerCounterexampleLemma( q, lem );
+ //totality lemmas for EPR
+ QuantEPR * qepr = d_quantEngine->getQuantEPR();
+ if( qepr!=NULL ){
+ for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
+ TypeNode tn = q[0][i].getType();
+ if( tn.isSort() ){
+ if( qepr->isEPR( tn ) ){
+ //add totality lemma
+ std::map< TypeNode, std::vector< Node > >::iterator itc = qepr->d_consts.find( tn );
+ if( itc!=qepr->d_consts.end() ){
+ Assert( !itc->second.empty() );
+ Node ic = d_quantEngine->getTermDatabase()->getInstantiationConstant( q, i );
+ std::vector< Node > disj;
+ for( unsigned j=0; j<itc->second.size(); j++ ){
+ disj.push_back( ic.eqNode( itc->second[j] ) );
+ }
+ Node tlem = disj.size()==1 ? disj[0] : NodeManager::currentNM()->mkNode( kind::OR, disj );
+ Trace("cbqi") << "EPR totality lemma : " << tlem << std::endl;
+ d_quantEngine->getOutputChannel().lemma( tlem );
+ }else{
+ Assert( false );
+ }
+ }else{
+ Assert( !options::cbqiAll() );
+ }
+ }
+ }
+ }
+
//compute dependencies between quantified formulas
if( options::cbqiLitDepend() || options::cbqiInnermost() ){
std::vector< Node > ics;
}
return false;
}
-bool InstStrategyCbqi::hasNonCbqiVariable( Node q ){
+int InstStrategyCbqi::hasNonCbqiVariable( Node q ){
+ int hmin = 1;
for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
TypeNode tn = q[0][i].getType();
- if( !tn.isInteger() && !tn.isReal() && !tn.isBoolean() && !tn.isBitVector() ){
- if( options::cbqiSplx() ){
- return true;
- }else{
- //datatypes supported in new implementation
- if( !tn.isDatatype() ){
- return true;
- }
+ int handled = -1;
+ if( tn.isInteger() || tn.isReal() || tn.isBoolean() || tn.isBitVector() ){
+ handled = 0;
+ }else if( tn.isDatatype() ){
+ handled = !options::cbqiSplx() ? 0 : -1;
+ }else if( tn.isSort() ){
+ QuantEPR * qepr = d_quantEngine->getQuantEPR();
+ if( qepr!=NULL ){
+ handled = qepr->isEPR( tn ) ? 1 : -1;
}
}
+ if( handled==-1 ){
+ return -1;
+ }else if( handled<hmin ){
+ hmin = handled;
+ }
}
- return false;
+ return hmin;
}
bool InstStrategyCbqi::doCbqi( Node q ){
if( options::cbqiAll() ){
ret = true;
}else{
- //if quantifier has a non-arithmetic variable, then do not use cbqi
+ //if quantifier has a non-handled variable, then do not use cbqi
//if quantifier has an APPLY_UF term, then do not use cbqi
//Node cb = d_quantEngine->getTermDatabase()->getInstConstantBody( q );
- std::map< Node, bool > visited;
- ret = !hasNonCbqiVariable( q ) && !hasNonCbqiOperator( q[1], visited );
+ int ncbqiv = hasNonCbqiVariable( q );
+ if( ncbqiv==1 ){
+ //all variables imply this will be handled regardless of body (e.g. for EPR)
+ ret = true;
+ }else if( ncbqiv==0 ){
+ std::map< Node, bool > visited;
+ ret = !hasNonCbqiOperator( q[1], visited );
+ }
}
}
}
if( n.getKind()==SKOLEM && d_quantEngine->getTermDatabase()->containsVtsTerm( n ) ){
return true;
}else{
+ TypeNode tn = n.getType();
+ if( tn.isSort() ){
+ QuantEPR * qepr = d_quantEngine->getQuantEPR();
+ if( qepr!=NULL ){
+ //legal if in the finite set of constants of type tn
+ if( qepr->isEPRConstant( tn, n ) ){
+ return true;
+ }
+ }
+ }
//only legal if current quantified formula contains n
return TermDb::containsTerm( d_curr_quant, n );
}
/** has added cbqi lemma */
bool hasAddedCbqiLemma( Node q ) { return d_added_cbqi_lemma.find( q )!=d_added_cbqi_lemma.end(); }
/** helper functions */
- bool hasNonCbqiVariable( Node q );
+ int hasNonCbqiVariable( Node q );
bool hasNonCbqiOperator( Node n, std::map< Node, bool >& visited );
/** process functions */
virtual void processResetInstantiationRound( Theory::Effort effort ) = 0;
}
}
+void QuantEPR::registerNode( Node n, std::map< int, std::map< Node, bool > >& visited, bool beneathQuant, bool hasPol, bool pol ) {
+ int vindex = hasPol ? ( pol ? 1 : -1 ) : 0;
+ if( visited[vindex].find( n )==visited[vindex].end() ){
+ visited[vindex][n] = true;
+ if( n.getKind()==FORALL ){
+ if( beneathQuant || !hasPol || !pol ){
+ for( unsigned i=0; i<n[0].getNumChildren(); i++ ){
+ d_non_epr[n[0][i].getType()] = true;
+ }
+ }else{
+ beneathQuant = true;
+ }
+ }
+ TypeNode tn = n.getType();
+
+ if( n.getNumChildren()>0 ){
+ if( tn.isSort() ){
+ if( d_non_epr.find( tn )==d_non_epr.end() ){
+ Trace("quant-epr") << "Sort " << tn << " is non-EPR because of " << n << std::endl;
+ d_non_epr[tn] = true;
+ }
+ }
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ bool newHasPol;
+ bool newPol;
+ QuantPhaseReq::getPolarity( n, i, hasPol, pol, newHasPol, newPol );
+ registerNode( n[i], visited, beneathQuant, newHasPol, newPol );
+ }
+ }else if( tn.isSort() ){
+ if( n.getKind()==BOUND_VARIABLE ){
+ if( d_consts.find( tn )==d_consts.end() ){
+ //mark that at least one constant must occur
+ d_consts[tn].clear();
+ }
+ }else if( std::find( d_consts[tn].begin(), d_consts[tn].end(), n )==d_consts[tn].end() ){
+ d_consts[tn].push_back( n );
+ }
+ }
+ }
+}
+
+void QuantEPR::registerAssertion( Node assertion ) {
+ std::map< int, std::map< Node, bool > > visited;
+ registerNode( assertion, visited, false, true, true );
+}
+
+void QuantEPR::finishInit() {
+ for( std::map< TypeNode, std::vector< Node > >::iterator it = d_consts.begin(); it != d_consts.end(); ++it ){
+ if( d_non_epr.find( it->first )!=d_non_epr.end() ){
+ it->second.clear();
+ }else{
+ if( it->second.empty() ){
+ it->second.push_back( NodeManager::currentNM()->mkSkolem( "e", it->first, "EPR base constant" ) );
+ }
+ if( Trace.isOn("quant-epr") ){
+ Trace("quant-epr") << "Type " << it->first << " is EPR, with constants : " << std::endl;
+ for( unsigned i=0; i<it->second.size(); i++ ){
+ Trace("quant-epr") << " " << it->second[i] << std::endl;
+ }
+ }
+ }
+ }
+}
+
+bool QuantEPR::isEPRConstant( TypeNode tn, Node k ) {
+ return std::find( d_consts[tn].begin(), d_consts[tn].end(), k )!=d_consts[tn].end();
+}
+
};
-class EqualityQuery : public QuantifiersUtil{
+class EqualityQuery : public QuantifiersUtil {
public:
EqualityQuery(){}
virtual ~EqualityQuery(){};
virtual TNode getCongruentTerm( Node f, std::vector< TNode >& args ) = 0;
};/* class EqualityQuery */
+class QuantEPR
+{
+private:
+ void registerNode( Node n, std::map< int, std::map< Node, bool > >& visited, bool beneathQuant, bool hasPol, bool pol );
+ /** non-epr */
+ std::map< TypeNode, bool > d_non_epr;
+public:
+ QuantEPR(){}
+ virtual ~QuantEPR(){}
+ /** constants per type */
+ std::map< TypeNode, std::vector< Node > > d_consts;
+ /* reset */
+ //bool reset( Theory::Effort e ) {}
+ /** identify */
+ //std::string identify() const { return "QuantEPR"; }
+ /** register assertion */
+ void registerAssertion( Node assertion );
+ /** finish init */
+ void finishInit();
+ /** is EPR */
+ bool isEPR( TypeNode tn ) { return d_non_epr.find( tn )!=d_non_epr.end() ? false : true; }
+ /** is EPR constant */
+ bool isEPRConstant( TypeNode tn, Node k );
+};
}
}
RDomain * getRDomain( Node n, int i, bool getParent = true );
};/* class RelevantDomain */
+
}/* CVC4::theory::quantifiers namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
std::string name = std::string( str.begin() + found +1, str.end() );
out << name;
}else{
- Trace("ajr-temp") << "[[print operator " << op << "]]" << std::endl;
out << op;
}
if( n.getNumChildren()>0 ){
}
void TheoryQuantifiers::ppNotifyAssertions( std::vector< Node >& assertions ) {
- getQuantifiersEngine()->ppNotifyAssertions( assertions );
+ Trace("quantifiers-presolve") << "TheoryQuantifiers::ppNotifyAssertions" << std::endl;
+ if( getQuantifiersEngine() ){
+ getQuantifiersEngine()->ppNotifyAssertions( assertions );
+ }
}
Node TheoryQuantifiers::getValue(TNode n) {
d_quant_rel = NULL;
}
+ if( options::quantEpr() ){
+ if( !options::incrementalSolving() ){
+ d_qepr = new QuantEPR;
+ }else{
+ d_qepr = NULL;
+ }
+ }else{
+ d_qepr = NULL;
+ }
+
+
d_qcf = NULL;
d_sg_gen = NULL;
d_inst_engine = NULL;
delete d_alpha_equiv;
delete d_builder;
+ delete d_qepr;
delete d_rr_engine;
delete d_bint;
delete d_model_engine;
d_modules.push_back( d_fs );
needsRelDom = true;
}
-
+
if( needsRelDom ){
d_rel_dom = new quantifiers::RelevantDomain( this, d_model );
d_util.push_back( d_rel_dom );
}
void QuantifiersEngine::ppNotifyAssertions( std::vector< Node >& assertions ) {
- if( options::instLevelInputOnly() && options::instMaxLevel()!=-1 ){
+ Trace("quant-engine-proc") << "ppNotifyAssertions in QE" << std::endl;
+ if( ( options::instLevelInputOnly() && options::instMaxLevel()!=-1 ) || d_qepr!=NULL ){
for( unsigned i=0; i<assertions.size(); i++ ) {
- setInstantiationLevelAttr( assertions[i], 0 );
+ if( options::instLevelInputOnly() && options::instMaxLevel()!=-1 ){
+ setInstantiationLevelAttr( assertions[i], 0 );
+ }
+ if( d_qepr!=NULL ){
+ d_qepr->registerAssertion( assertions[i] );
+ }
+ }
+ if( d_qepr!=NULL ){
+ d_qepr->finishInit();
}
}
}
quantifiers::AlphaEquivalence * d_alpha_equiv;
/** model builder */
quantifiers::QModelBuilder* d_builder;
+ /** utility for effectively propositional logic */
+ QuantEPR * d_qepr;
+private:
/** instantiation engine */
quantifiers::InstantiationEngine* d_inst_engine;
/** model engine */
QuantRelevance* getQuantifierRelevance() { return d_quant_rel; }
/** get the model builder */
quantifiers::QModelBuilder* getModelBuilder() { return d_builder; }
+ /** get utility for EPR */
+ QuantEPR* getQuantEPR() { return d_qepr; }
public: //modules
/** get instantiation engine */
quantifiers::InstantiationEngine* getInstantiationEngine() { return d_inst_engine; }
}
for (unsigned c = 0; c < currentPairs.size(); ++ c) {
Trace("strings-cg-pair") << "TheoryStrings::computeCareGraph(): pair : " << currentPairs[c].first << " " << currentPairs[c].second << std::endl;
- Trace("ajr-temp") << currentPairs[c].first << ", " << currentPairs[c].second << std::endl;
addCarePair(currentPairs[c].first, currentPairs[c].second);
}
}