The namespaces weren't changed, only the file locations.
unconstrained_simplifier.cpp \
quantifiers_engine.h \
quantifiers_engine.cpp \
- instantiator_default.h \
- instantiator_default.cpp \
- rr_inst_match.h \
- rr_inst_match_impl.h \
- rr_inst_match.cpp \
- rr_trigger.h \
- rr_trigger.cpp \
- rr_candidate_generator.h \
- rr_candidate_generator.cpp \
- inst_match.h \
- inst_match.cpp \
- trigger.h \
- trigger.cpp \
model.h \
- model.cpp \
- candidate_generator.h \
- candidate_generator.cpp
+ model.cpp
nodist_libtheory_la_SOURCES = \
rewriter_tables.h \
#include "theory/arrays/theory_arrays_instantiator.h"
#include "theory/arrays/theory_arrays.h"
#include "theory/quantifiers/options.h"
-#include "theory/rr_candidate_generator.h"
+#include "theory/rewriterules/rr_candidate_generator.h"
using namespace std;
using namespace CVC4;
+++ /dev/null
-/********************* */
-/*! \file candidate_generator.cpp
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: mdeters
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Implementation of theory uf candidate generator class
- **/
-
-#include "theory/candidate_generator.h"
-#include "theory/theory_engine.h"
-#include "theory/uf/theory_uf.h"
-#include "theory/quantifiers/term_database.h"
-#include "theory/inst_match.h"
-#include "theory/quantifiers_engine.h"
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::inst;
-
-bool CandidateGenerator::isLegalCandidate( Node n ){
- return ( !n.getAttribute(NoMatchAttribute()) && ( !options::cbqi() || !n.hasAttribute(InstConstantAttribute()) ) );
-}
-
-void CandidateGeneratorQueue::addCandidate( Node n ) {
- if( isLegalCandidate( n ) ){
- d_candidates.push_back( n );
- }
-}
-
-void CandidateGeneratorQueue::reset( Node eqc ){
- if( d_candidate_index>0 ){
- d_candidates.erase( d_candidates.begin(), d_candidates.begin() + d_candidate_index );
- d_candidate_index = 0;
- }
- if( !eqc.isNull() ){
- d_candidates.push_back( eqc );
- }
-}
-Node CandidateGeneratorQueue::getNextCandidate(){
- if( d_candidate_index<(int)d_candidates.size() ){
- Node n = d_candidates[d_candidate_index];
- d_candidate_index++;
- return n;
- }else{
- d_candidate_index = 0;
- d_candidates.clear();
- return Node::null();
- }
-}
-
-#if 0
-
-CandidateGeneratorQE::CandidateGeneratorQE( QuantifiersEngine* qe, Node op ) :
- d_op( op ), d_qe( qe ), d_term_iter( -2 ){
- Assert( !d_op.isNull() );
-}
-void CandidateGeneratorQE::resetInstantiationRound(){
- d_term_iter_limit = d_qe->getTermDatabase()->d_op_map[d_op].size();
-}
-
-void CandidateGeneratorQE::reset( Node eqc ){
- if( eqc.isNull() ){
- d_term_iter = 0;
- }else{
- //create an equivalence class iterator in eq class eqc
- if( d_qe->getEqualityQuery()->getEngine()->hasTerm( eqc ) ){
- eqc = d_qe->getEqualityQuery()->getEngine()->getRepresentative( eqc );
- d_eqc = eq::EqClassIterator( eqc, d_qe->getEqualityQuery()->getEngine() );
- d_retNode = Node::null();
- }else{
- d_retNode = eqc;
- }
- d_term_iter = -1;
- }
-}
-
-Node CandidateGeneratorQE::getNextCandidate(){
- if( d_term_iter>=0 ){
- //get next candidate term in the uf term database
- while( d_term_iter<d_term_iter_limit ){
- Node n = d_qe->getTermDatabase()->d_op_map[d_op][d_term_iter];
- d_term_iter++;
- if( isLegalCandidate( n ) ){
- return n;
- }
- }
- }else if( d_term_iter==-1 ){
- if( d_retNode.isNull() ){
- //get next candidate term in equivalence class
- while( !d_eqc.isFinished() ){
- Node n = (*d_eqc);
- ++d_eqc;
- if( n.hasOperator() && n.getOperator()==d_op ){
- if( isLegalCandidate( n ) ){
- return n;
- }
- }
- }
- }else{
- Node ret;
- if( d_retNode.hasOperator() && d_retNode.getOperator()==d_op ){
- ret = d_retNode;
- }
- d_term_iter = -2; //done returning matches
- return ret;
- }
- }
- return Node::null();
-}
-
-#else
-
-
-CandidateGeneratorQE::CandidateGeneratorQE( QuantifiersEngine* qe, Node op ) :
- d_op( op ), d_qe( qe ), d_term_iter( -1 ){
- Assert( !d_op.isNull() );
-}
-void CandidateGeneratorQE::resetInstantiationRound(){
- d_term_iter_limit = d_qe->getTermDatabase()->d_op_map[d_op].size();
-}
-
-void CandidateGeneratorQE::reset( Node eqc ){
- d_term_iter = 0;
- if( eqc.isNull() ){
- d_using_term_db = true;
- }else{
- //create an equivalence class iterator in eq class eqc
- d_eqc.clear();
- d_qe->getEqualityQuery()->getEquivalenceClass( eqc, d_eqc );
- d_using_term_db = false;
- }
-}
-
-Node CandidateGeneratorQE::getNextCandidate(){
- if( d_term_iter>=0 ){
- if( d_using_term_db ){
- //get next candidate term in the uf term database
- while( d_term_iter<d_term_iter_limit ){
- Node n = d_qe->getTermDatabase()->d_op_map[d_op][d_term_iter];
- d_term_iter++;
- if( isLegalCandidate( n ) ){
- return n;
- }
- }
- }else{
- while( d_term_iter<(int)d_eqc.size() ){
- Node n = d_eqc[d_term_iter];
- d_term_iter++;
- if( n.hasOperator() && n.getOperator()==d_op ){
- if( isLegalCandidate( n ) ){
- return n;
- }
- }
- }
- }
- }
- return Node::null();
-}
-
-#endif
-
-//CandidateGeneratorQEDisequal::CandidateGeneratorQEDisequal( QuantifiersEngine* qe, Node eqc ) :
-// d_qe( qe ), d_eq_class( eqc ){
-// d_eci = NULL;
-//}
-//void CandidateGeneratorQEDisequal::resetInstantiationRound(){
-//
-//}
-////we will iterate over all terms that are disequal from eqc
-//void CandidateGeneratorQEDisequal::reset( Node eqc ){
-// //Assert( !eqc.isNull() );
-// ////begin iterating over equivalence classes that are disequal from eqc
-// //d_eci = d_ith->getEquivalenceClassInfo( eqc );
-// //if( d_eci ){
-// // d_eqci_iter = d_eci->d_disequal.begin();
-// //}
-//}
-//Node CandidateGeneratorQEDisequal::getNextCandidate(){
-// //if( d_eci ){
-// // while( d_eqci_iter != d_eci->d_disequal.end() ){
-// // if( (*d_eqci_iter).second ){
-// // //we have an equivalence class that is disequal from eqc
-// // d_cg->reset( (*d_eqci_iter).first );
-// // Node n = d_cg->getNextCandidate();
-// // //if there is a candidate in this equivalence class, return it
-// // if( !n.isNull() ){
-// // return n;
-// // }
-// // }
-// // ++d_eqci_iter;
-// // }
-// //}
-// return Node::null();
-//}
-
-
-CandidateGeneratorQELitEq::CandidateGeneratorQELitEq( QuantifiersEngine* qe, Node mpat ) :
- d_match_pattern( mpat ), d_qe( qe ){
-
-}
-void CandidateGeneratorQELitEq::resetInstantiationRound(){
-
-}
-void CandidateGeneratorQELitEq::reset( Node eqc ){
- d_eq = eq::EqClassesIterator( d_qe->getEqualityQuery()->getEngine() );
-}
-Node CandidateGeneratorQELitEq::getNextCandidate(){
- while( d_eq.isFinished() ){
- Node n = (*d_eq);
- ++d_eq;
- if( n.getType()==d_match_pattern[0].getType() ){
- //an equivalence class with the same type as the pattern, return reflexive equality
- return NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), n, n );
- }
- }
- return Node::null();
-}
-
-
-CandidateGeneratorQELitDeq::CandidateGeneratorQELitDeq( QuantifiersEngine* qe, Node mpat ) :
- d_match_pattern( mpat ), d_qe( qe ){
-
-}
-void CandidateGeneratorQELitDeq::resetInstantiationRound(){
-
-}
-void CandidateGeneratorQELitDeq::reset( Node eqc ){
- Node false_term = d_qe->getEqualityQuery()->getEngine()->getRepresentative( NodeManager::currentNM()->mkConst<bool>(false) );
- d_eqc_false = eq::EqClassIterator( false_term, d_qe->getEqualityQuery()->getEngine() );
-}
-Node CandidateGeneratorQELitDeq::getNextCandidate(){
- //get next candidate term in equivalence class
- while( !d_eqc_false.isFinished() ){
- Node n = (*d_eqc_false);
- ++d_eqc_false;
- if( n.getKind()==d_match_pattern.getKind() ){
- //found an iff or equality, try to match it
- //DO_THIS: cache to avoid redundancies?
- //DO_THIS: do we need to try the symmetric equality for n? or will it also exist in the eq class of false?
- return n;
- }
- }
- return Node::null();
-}
+++ /dev/null
-/********************* */
-/*! \file candidate_generator.h
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Theory uf candidate generator
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__CANDIDATE_GENERATOR_H
-#define __CVC4__CANDIDATE_GENERATOR_H
-
-#include "theory/theory.h"
-#include "theory/uf/equality_engine.h"
-
-namespace CVC4 {
-namespace theory {
-
-class QuantifiersEngine;
-
-namespace inst {
-
-/** base class for generating candidates for matching */
-class CandidateGenerator {
-public:
- CandidateGenerator(){}
- ~CandidateGenerator(){}
-
- /** Get candidates functions. These set up a context to get all match candidates.
- cg->reset( eqc );
- do{
- Node cand = cg->getNextCandidate();
- //.......
- }while( !cand.isNull() );
-
- eqc is the equivalence class you are searching in
- */
- virtual void reset( Node eqc ) = 0;
- virtual Node getNextCandidate() = 0;
- /** add candidate to list of nodes returned by this generator */
- virtual void addCandidate( Node n ) {}
- /** call this at the beginning of each instantiation round */
- virtual void resetInstantiationRound() = 0;
-public:
- /** legal candidate */
- static bool isLegalCandidate( Node n );
-};/* class CandidateGenerator */
-
-/** candidate generator queue (for manual candidate generation) */
-class CandidateGeneratorQueue : public CandidateGenerator {
-private:
- std::vector< Node > d_candidates;
- int d_candidate_index;
-public:
- CandidateGeneratorQueue() : d_candidate_index( 0 ){}
- ~CandidateGeneratorQueue(){}
-
- void addCandidate( Node n );
-
- void resetInstantiationRound(){}
- void reset( Node eqc );
- Node getNextCandidate();
-};/* class CandidateGeneratorQueue */
-
-class CandidateGeneratorQEDisequal;
-
-#if 0
-
-class CandidateGeneratorQE : public CandidateGenerator
-{
- friend class CandidateGeneratorQEDisequal;
-private:
- //operator you are looking for
- Node d_op;
- //instantiator pointer
- QuantifiersEngine* d_qe;
- //the equality class iterator
- eq::EqClassIterator d_eqc;
- int d_term_iter;
- int d_term_iter_limit;
-private:
- Node d_retNode;
-public:
- CandidateGeneratorQE( QuantifiersEngine* qe, Node op );
- ~CandidateGeneratorQE(){}
-
- void resetInstantiationRound();
- void reset( Node eqc );
- Node getNextCandidate();
-};
-
-#else
-
-class CandidateGeneratorQE : public CandidateGenerator
-{
- friend class CandidateGeneratorQEDisequal;
-private:
- //operator you are looking for
- Node d_op;
- //instantiator pointer
- QuantifiersEngine* d_qe;
- //the equality class iterator
- std::vector< Node > d_eqc;
- int d_term_iter;
- int d_term_iter_limit;
- bool d_using_term_db;
-public:
- CandidateGeneratorQE( QuantifiersEngine* qe, Node op );
- ~CandidateGeneratorQE(){}
-
- void resetInstantiationRound();
- void reset( Node eqc );
- Node getNextCandidate();
-};
-
-#endif
-
-//class CandidateGeneratorQEDisequal : public CandidateGenerator
-//{
-//private:
-// //equivalence class
-// Node d_eq_class;
-// //equivalence class info
-// EqClassInfo* d_eci;
-// //equivalence class iterator
-// EqClassInfo::BoolMap::const_iterator d_eqci_iter;
-// //instantiator pointer
-// QuantifiersEngine* d_qe;
-//public:
-// CandidateGeneratorQEDisequal( QuantifiersEngine* qe, Node eqc );
-// ~CandidateGeneratorQEDisequal(){}
-//
-// void resetInstantiationRound();
-// void reset( Node eqc ); //should be what you want to be disequal from
-// Node getNextCandidate();
-//};
-
-class CandidateGeneratorQELitEq : public CandidateGenerator
-{
-private:
- //the equality classes iterator
- eq::EqClassesIterator d_eq;
- //equality you are trying to match equalities for
- Node d_match_pattern;
- //einstantiator pointer
- QuantifiersEngine* d_qe;
-public:
- CandidateGeneratorQELitEq( QuantifiersEngine* qe, Node mpat );
- ~CandidateGeneratorQELitEq(){}
-
- void resetInstantiationRound();
- void reset( Node eqc );
- Node getNextCandidate();
-};
-
-class CandidateGeneratorQELitDeq : public CandidateGenerator
-{
-private:
- //the equality class iterator for false
- eq::EqClassIterator d_eqc_false;
- //equality you are trying to match disequalities for
- Node d_match_pattern;
- //einstantiator pointer
- QuantifiersEngine* d_qe;
-public:
- CandidateGeneratorQELitDeq( QuantifiersEngine* qe, Node mpat );
- ~CandidateGeneratorQELitDeq(){}
-
- void resetInstantiationRound();
- void reset( Node eqc );
- Node getNextCandidate();
-};
-
-}/* CVC4::theory::inst namespace */
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
-
-#endif /* __CVC4__THEORY_UF_INSTANTIATOR_H */
#include "theory/theory_engine.h"
#include "theory/quantifiers/options.h"
#include "theory/quantifiers/term_database.h"
-#include "theory/rr_candidate_generator.h"
+#include "theory/rewriterules/rr_candidate_generator.h"
using namespace std;
using namespace CVC4;
+++ /dev/null
-/********************* */
-/*! \file inst_match.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 inst match class
- **/
-
-#include "theory/inst_match.h"
-#include "theory/theory_engine.h"
-#include "theory/quantifiers_engine.h"
-#include "theory/candidate_generator.h"
-#include "theory/uf/theory_uf_instantiator.h"
-#include "theory/uf/equality_engine.h"
-#include "theory/quantifiers/options.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;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::inst;
-
-
-InstMatch::InstMatch() {
-}
-
-InstMatch::InstMatch( InstMatch* m ) {
- d_map = m->d_map;
-}
-
-bool InstMatch::setMatch( EqualityQuery* q, TNode v, TNode m, bool & set ){
- std::map< Node, Node >::iterator vn = d_map.find( v );
- if( vn==d_map.end() ){
- set = true;
- this->set(v,m);
- Debug("matching-debug") << "Add partial " << v << "->" << m << std::endl;
- return true;
- }else{
- set = false;
- return q->areEqual( vn->second, m );
- }
-}
-
-bool InstMatch::setMatch( EqualityQuery* q, TNode v, TNode m ){
- bool set;
- return setMatch(q,v,m,set);
-}
-
-bool InstMatch::add( InstMatch& m ){
- for( std::map< Node, Node >::iterator it = m.d_map.begin(); it != m.d_map.end(); ++it ){
- if( d_map.find( it->first )==d_map.end() ){
- d_map[it->first] = it->second;
- }
- }
- return true;
-}
-
-bool InstMatch::merge( EqualityQuery* q, InstMatch& m ){
- for( std::map< Node, Node >::iterator it = m.d_map.begin(); it != m.d_map.end(); ++it ){
- if( d_map.find( it->first )==d_map.end() ){
- d_map[ it->first ] = it->second;
- }else{
- if( it->second!=d_map[it->first] ){
- if( !q->areEqual( it->second, d_map[it->first] ) ){
- d_map.clear();
- return false;
- }
- }
- }
- }
- return true;
-}
-
-void InstMatch::debugPrint( const char* c ){
- for( std::map< Node, Node >::iterator it = d_map.begin(); it != d_map.end(); ++it ){
- Debug( c ) << " " << it->first << " -> " << it->second << std::endl;
- }
- //if( !d_splits.empty() ){
- // Debug( c ) << " Conditions: ";
- // for( std::map< Node, Node >::iterator it = d_splits.begin(); it !=d_splits.end(); ++it ){
- // Debug( c ) << it->first << " = " << it->second << " ";
- // }
- // Debug( c ) << std::endl;
- //}
-}
-
-void InstMatch::makeComplete( Node f, QuantifiersEngine* qe ){
- for( int i=0; i<(int)qe->getTermDatabase()->d_inst_constants[f].size(); i++ ){
- Node ic = qe->getTermDatabase()->d_inst_constants[f][i];
- if( d_map.find( ic )==d_map.end() ){
- d_map[ ic ] = qe->getTermDatabase()->getFreeVariableForInstConstant( ic );
- }
- }
-}
-
-void InstMatch::makeInternal( QuantifiersEngine* qe ){
- if( options::cbqi() ){
- for( std::map< Node, Node >::iterator it = d_map.begin(); it != d_map.end(); ++it ){
- if( it->second.hasAttribute(InstConstantAttribute()) ){
- d_map[ it->first ] = qe->getEqualityQuery()->getInternalRepresentative( it->second );
- if( it->second.hasAttribute(InstConstantAttribute()) ){
- d_map[ it->first ] = qe->getTermDatabase()->getFreeVariableForInstConstant( it->first );
- }
- }
- }
- }
-}
-
-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::cbqi() && it->second.hasAttribute(InstConstantAttribute()) ){
- d_map[ it->first ] = qe->getTermDatabase()->getFreeVariableForInstConstant( it->first );
- }
- }
-}
-
-void InstMatch::applyRewrite(){
- for( std::map< Node, Node >::iterator it = d_map.begin(); it != d_map.end(); ++it ){
- it->second = Rewriter::rewrite(it->second);
- }
-}
-
-void InstMatch::computeTermVec( QuantifiersEngine* qe, const std::vector< Node >& vars, std::vector< Node >& match ){
- for( int i=0; i<(int)vars.size(); i++ ){
- std::map< Node, Node >::iterator it = d_map.find( vars[i] );
- if( it!=d_map.end() && !it->second.isNull() ){
- match.push_back( it->second );
- }else{
- match.push_back( qe->getTermDatabase()->getFreeVariableForInstConstant( vars[i] ) );
- }
- }
-}
-void InstMatch::computeTermVec( const std::vector< Node >& vars, std::vector< Node >& match ){
- for( int i=0; i<(int)vars.size(); i++ ){
- match.push_back( d_map[ vars[i] ] );
- }
-}
-
-
-/** add match m for quantifier f starting at index, take into account equalities q, return true if successful */
-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.get( qe->getTermDatabase()->getInstantiationConstant( f, i_index ) );
- d_data[n].addInstMatch2( qe, f, m, index+1, imtio );
- }
-}
-
-/** exists match */
-bool InstMatchTrie::existsInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m, bool modEq, int index, ImtIndexOrder* imtio ){
- if( long(index)==long(f[0].getNumChildren()) || ( imtio && long(index)==long(imtio->d_order.size()) ) ){
- return true;
- }else{
- int i_index = imtio ? imtio->d_order[index] : index;
- Node n = m.get( 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 ) ){
- return true;
- }
- }
- if( modEq ){
- //check modulo equality if any other instantiation match exists
- if( qe->getEqualityQuery()->getEngine()->hasTerm( n ) ){
- eq::EqClassIterator eqc( qe->getEqualityQuery()->getEngine()->getRepresentative( n ),
- qe->getEqualityQuery()->getEngine() );
- while( !eqc.isFinished() ){
- Node en = (*eqc);
- if( en!=n ){
- std::map< Node, InstMatchTrie >::iterator itc = d_data.find( en );
- if( itc!=d_data.end() ){
- if( itc->second.existsInstMatch( qe, f, m, modEq, index+1, imtio ) ){
- return true;
- }
- }
- }
- ++eqc;
- }
- }
- //for( std::map< Node, InstMatchTrie >::iterator itc = d_data.begin(); itc != d_data.end(); ++itc ){
- // if( itc->first!=n && qe->getEqualityQuery()->areEqual( n, itc->first ) ){
- // if( itc->second.existsInstMatch( qe, f, m, modEq, index+1 ) ){
- // return true;
- // }
- // }
- //}
- }
- return false;
- }
-}
-
-bool InstMatchTrie::addInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m, bool modEq, ImtIndexOrder* imtio ){
- if( !existsInstMatch( qe, f, m, modEq, 0, imtio ) ){
- addInstMatch2( qe, f, m, 0, imtio );
- return true;
- }else{
- return false;
- }
-}
-
-InstMatchGenerator::InstMatchGenerator( Node pat, QuantifiersEngine* qe, int matchPolicy ) : d_matchPolicy( matchPolicy ){
- initializePattern( pat, qe );
-}
-
-InstMatchGenerator::InstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe, int matchPolicy ) : d_matchPolicy( matchPolicy ){
- if( pats.size()==1 ){
- initializePattern( pats[0], qe );
- }else{
- initializePatterns( pats, qe );
- }
-}
-
-void InstMatchGenerator::initializePatterns( std::vector< Node >& pats, QuantifiersEngine* qe ){
- int childMatchPolicy = d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ? 0 : d_matchPolicy;
- for( int i=0; i<(int)pats.size(); i++ ){
- d_children.push_back( new InstMatchGenerator( pats[i], qe, childMatchPolicy ) );
- }
- d_pattern = Node::null();
- d_match_pattern = Node::null();
- d_cg = NULL;
-}
-
-void InstMatchGenerator::initializePattern( Node pat, QuantifiersEngine* qe ){
- Debug("inst-match-gen") << "Pattern term is " << pat << std::endl;
- Assert( pat.hasAttribute(InstConstantAttribute()) );
- d_pattern = pat;
- d_match_pattern = pat;
- if( d_match_pattern.getKind()==NOT ){
- //we want to add the children of the NOT
- d_match_pattern = d_pattern[0];
- }
- if( d_match_pattern.getKind()==IFF || d_match_pattern.getKind()==EQUAL ){
- if( !d_match_pattern[0].hasAttribute(InstConstantAttribute()) ){
- Assert( d_match_pattern[1].hasAttribute(InstConstantAttribute()) );
- //swap sides
- d_pattern = NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), d_match_pattern[1], d_match_pattern[0] );
- d_pattern = pat.getKind()==NOT ? d_pattern.notNode() : d_pattern;
- if( pat.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching
- d_match_pattern = d_match_pattern[1];
- }else{
- d_match_pattern = d_pattern[0][0];
- }
- }else if( !d_match_pattern[1].hasAttribute(InstConstantAttribute()) ){
- Assert( d_match_pattern[0].hasAttribute(InstConstantAttribute()) );
- if( pat.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching
- d_match_pattern = d_match_pattern[0];
- }
- }
- }
- int childMatchPolicy = MATCH_GEN_DEFAULT;
- for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
- if( d_match_pattern[i].hasAttribute(InstConstantAttribute()) ){
- if( d_match_pattern[i].getKind()!=INST_CONSTANT ){
- d_children.push_back( new InstMatchGenerator( d_match_pattern[i], qe, childMatchPolicy ) );
- d_children_index.push_back( i );
- }
- }
- }
-
- Debug("inst-match-gen") << "Pattern is " << d_pattern << ", match pattern is " << d_match_pattern << std::endl;
-
- //create candidate generator
- if( d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==IFF ){
- Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
- //we will be producing candidates via literal matching heuristics
- if( d_pattern.getKind()!=NOT ){
- //candidates will be all equalities
- d_cg = new inst::CandidateGeneratorQELitEq( qe, d_match_pattern );
- }else{
- //candidates will be all disequalities
- d_cg = new inst::CandidateGeneratorQELitDeq( qe, d_match_pattern );
- }
- }else if( d_pattern.getKind()==EQUAL || d_pattern.getKind()==IFF || d_pattern.getKind()==NOT ){
- Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
- if( d_pattern.getKind()==NOT ){
- Unimplemented("Disequal generator unimplemented");
- }else{
- Assert( Trigger::isAtomicTrigger( d_match_pattern ) );
- //we are matching only in a particular equivalence class
- d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
- //store the equivalence class that we will call d_cg->reset( ... ) on
- d_eq_class = d_pattern[1];
- }
- }else if( Trigger::isAtomicTrigger( d_match_pattern ) ){
- //if( d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ){
- //Warning() << "Currently efficient e matching is not taken into account for quantifiers: " << d_pattern << std::endl;
- //}
- //we will be scanning lists trying to find d_match_pattern.getOperator()
- d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
- }else{
- d_cg = new CandidateGeneratorQueue;
- if( !Trigger::getPatternArithmetic( d_match_pattern.getAttribute(InstConstantAttribute()), d_match_pattern, d_arith_coeffs ) ){
- Debug("inst-match-gen") << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
- Warning() << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
- d_matchPolicy = MATCH_GEN_INTERNAL_ERROR;
- }else{
- Debug("matching-arith") << "Generated arithmetic pattern for " << d_match_pattern << ": " << std::endl;
- for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
- Debug("matching-arith") << " " << it->first << " -> " << it->second << std::endl;
- }
- //we will treat this as match gen internal arithmetic
- d_matchPolicy = MATCH_GEN_INTERNAL_ARITHMETIC;
- }
- }
-}
-
-/** get match (not modulo equality) */
-bool InstMatchGenerator::getMatch( Node t, InstMatch& m, QuantifiersEngine* qe ){
- Debug("matching") << "Matching " << t << " against pattern " << d_match_pattern << " ("
- << m.size() << ")" << ", " << d_children.size() << std::endl;
- Assert( !d_match_pattern.isNull() );
- 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;
- }else{
- EqualityQuery* q = qe->getEqualityQuery();
- //add m to partial match vector
- std::vector< InstMatch > partial;
- partial.push_back( InstMatch( &m ) );
- //if t is null
- Assert( !t.isNull() );
- Assert( !t.hasAttribute(InstConstantAttribute()) );
- Assert( t.getKind()==d_match_pattern.getKind() );
- Assert( !Trigger::isAtomicTrigger( d_match_pattern ) || t.getOperator()==d_match_pattern.getOperator() );
- //first, check if ground arguments are not equal, or a match is in conflict
- for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
- if( d_match_pattern[i].hasAttribute(InstConstantAttribute()) ){
- if( d_match_pattern[i].getKind()==INST_CONSTANT ){
- if( !partial[0].setMatch( q, d_match_pattern[i], t[i] ) ){
- //match is in conflict
- Debug("matching-debug") << "Match in conflict " << t[i] << " and "
- << d_match_pattern[i] << " because "
- << partial[0].get(d_match_pattern[i])
- << std::endl;
- Debug("matching-fail") << "Match fail: " << partial[0].get(d_match_pattern[i]) << " and " << t[i] << std::endl;
- return false;
- }
- }
- }else{
- if( !q->areEqual( d_match_pattern[i], t[i] ) ){
- Debug("matching-fail") << "Match fail arg: " << d_match_pattern[i] << " and " << t[i] << std::endl;
- //ground arguments are not equal
- return false;
- }
- }
- }
- //now, fit children into match
- //we will be requesting candidates for matching terms for each child
- std::vector< Node > reps;
- for( int i=0; i<(int)d_children.size(); i++ ){
- Node rep = q->getRepresentative( t[ d_children_index[i] ] );
- reps.push_back( rep );
- d_children[i]->d_cg->reset( rep );
- }
-
- //combine child matches
- int index = 0;
- while( index>=0 && index<(int)d_children.size() ){
- partial.push_back( InstMatch( &partial[index] ) );
- if( d_children[index]->getNextMatch2( partial[index+1], qe ) ){
- index++;
- }else{
- d_children[index]->d_cg->reset( reps[index] );
- partial.pop_back();
- if( !partial.empty() ){
- partial.pop_back();
- }
- index--;
- }
- }
- if( index>=0 ){
- m = partial.back();
- return true;
- }else{
- return false;
- }
- }
-}
-
-bool InstMatchGenerator::getNextMatch2( InstMatch& m, QuantifiersEngine* qe, bool saveMatched ){
- bool success = false;
- Node t;
- do{
- //get the next candidate term t
- t = d_cg->getNextCandidate();
- //if t not null, try to fit it into match m
- if( !t.isNull() && t.getType()==d_match_pattern.getType() ){
- success = getMatch( t, m, qe );
- }
- }while( !success && !t.isNull() );
- if (saveMatched) m.d_matched = t;
- return success;
-}
-
-bool InstMatchGenerator::getMatchArithmetic( Node t, InstMatch& m, QuantifiersEngine* qe ){
- Debug("matching-arith") << "Matching " << t << " " << d_match_pattern << std::endl;
- if( !d_arith_coeffs.empty() ){
- NodeBuilder<> tb(kind::PLUS);
- Node ic = Node::null();
- for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
- Debug("matching-arith") << it->first << " -> " << it->second << std::endl;
- if( !it->first.isNull() ){
- if( m.find( it->first )==m.end() ){
- //see if we can choose this to set
- if( ic.isNull() && ( it->second.isNull() || !it->first.getType().isInteger() ) ){
- ic = it->first;
- }
- }else{
- Debug("matching-arith") << "already set " << m.get( it->first ) << std::endl;
- Node tm = m.get( it->first );
- if( !it->second.isNull() ){
- tm = NodeManager::currentNM()->mkNode( MULT, it->second, tm );
- }
- tb << tm;
- }
- }else{
- tb << it->second;
- }
- }
- if( !ic.isNull() ){
- Node tm;
- if( tb.getNumChildren()==0 ){
- tm = t;
- }else{
- tm = tb.getNumChildren()==1 ? tb.getChild( 0 ) : tb;
- tm = NodeManager::currentNM()->mkNode( MINUS, t, tm );
- }
- if( !d_arith_coeffs[ ic ].isNull() ){
- Assert( !ic.getType().isInteger() );
- Node coeff = NodeManager::currentNM()->mkConst( Rational(1) / d_arith_coeffs[ ic ].getConst<Rational>() );
- tm = NodeManager::currentNM()->mkNode( MULT, coeff, tm );
- }
- m.set( ic, Rewriter::rewrite( tm ));
- //set the rest to zeros
- for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
- if( !it->first.isNull() ){
- if( m.find( it->first )==m.end() ){
- m.set( it->first, NodeManager::currentNM()->mkConst( Rational(0) ) );
- }
- }
- }
- Debug("matching-arith") << "Setting " << ic << " to " << tm << std::endl;
- return true;
- }else{
- return false;
- }
- }else{
- return false;
- }
-}
-
-
-/** reset instantiation round */
-void InstMatchGenerator::resetInstantiationRound( QuantifiersEngine* qe ){
- if( d_match_pattern.isNull() ){
- for( int i=0; i<(int)d_children.size(); i++ ){
- d_children[i]->resetInstantiationRound( qe );
- }
- }else{
- if( d_cg ){
- d_cg->resetInstantiationRound();
- }
- }
-}
-
-void InstMatchGenerator::reset( Node eqc, QuantifiersEngine* qe ){
- if( d_match_pattern.isNull() ){
- for( int i=0; i<(int)d_children.size(); i++ ){
- d_children[i]->reset( eqc, qe );
- }
- d_partial.clear();
- }else{
- if( !d_eq_class.isNull() ){
- //we have a specific equivalence class in mind
- //we are producing matches for f(E) ~ t, where E is a non-ground vector of terms, and t is a ground term
- //just look in equivalence class of the RHS
- d_cg->reset( d_eq_class );
- }else{
- d_cg->reset( eqc );
- }
- }
-}
-
-bool InstMatchGenerator::getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- m.d_matched = Node::null();
- if( d_match_pattern.isNull() ){
- int index = (int)d_partial.size();
- while( index>=0 && index<(int)d_children.size() ){
- if( index>0 ){
- d_partial.push_back( InstMatch( &d_partial[index-1] ) );
- }else{
- d_partial.push_back( InstMatch() );
- }
- if( d_children[index]->getNextMatch( d_partial[index], qe ) ){
- index++;
- }else{
- d_children[index]->reset( Node::null(), qe );
- d_partial.pop_back();
- if( !d_partial.empty() ){
- d_partial.pop_back();
- }
- index--;
- }
- }
- if( index>=0 ){
- m = d_partial.back();
- d_partial.pop_back();
- return true;
- }else{
- return false;
- }
- }else{
- bool res = getNextMatch2( m, qe, true );
- Assert(!res || !m.d_matched.isNull());
- return res;
- }
-}
-
-
-
-// Currently the implementation doesn't take into account that
-// variable should have the same value given.
-// TODO use the d_children way perhaps
-// TODO replace by a real dictionnary
-// We should create a real substitution? slower more precise
-// We don't do that often
-bool InstMatchGenerator::nonunifiable( TNode t0, const std::vector<Node> & vars){
- if(d_match_pattern.isNull()) return true;
-
- typedef std::vector<std::pair<TNode,TNode> > tstack;
- tstack stack(1,std::make_pair(t0,d_match_pattern)); // t * pat
-
- while(!stack.empty()){
- const std::pair<TNode,TNode> p = stack.back(); stack.pop_back();
- const TNode & t = p.first;
- const TNode & pat = p.second;
-
- // t or pat is a variable currently we consider that can match anything
- if( find(vars.begin(),vars.end(),t) != vars.end() ) continue;
- if( pat.getKind() == INST_CONSTANT ) continue;
-
- // t and pat are nonunifiable
- if( !Trigger::isAtomicTrigger( t ) || !Trigger::isAtomicTrigger( pat ) ) {
- if(t == pat) continue;
- else return true;
- };
- if( t.getOperator() != pat.getOperator() ) return true;
-
- //put the children on the stack
- for( size_t i=0; i < pat.getNumChildren(); i++ ){
- stack.push_back(std::make_pair(t[i],pat[i]));
- };
- }
- // The heuristic can't find non-unifiability
- return false;
-}
-
-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 ) ){
- addedLemmas++;
- if( qe->d_optInstLimitActive && qe->d_optInstLimit<=0 ){
- return addedLemmas;
- }
- }
- m.clear();
- }
- //return number of lemmas added
- return addedLemmas;
-}
-
-int InstMatchGenerator::addTerm( Node f, Node t, QuantifiersEngine* qe ){
- Assert( options::eagerInstQuant() );
- if( !d_match_pattern.isNull() ){
- InstMatch m;
- if( getMatch( t, m, qe ) ){
- if( qe->addInstantiation( f, m ) ){
- return 1;
- }
- }
- }else{
- for( int i=0; i<(int)d_children.size(); i++ ){
- d_children[i]->addTerm( f, t, qe );
- }
- }
- return 0;
-}
-
-/** constructors */
-InstMatchGeneratorMulti::InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption ) :
-d_f( f ){
- Debug("smart-multi-trigger") << "Making smart multi-trigger for " << f << std::endl;
- std::map< Node, std::vector< Node > > var_contains;
- Trigger::getVarContains( f, pats, var_contains );
- //convert to indicies
- for( std::map< Node, std::vector< Node > >::iterator it = var_contains.begin(); it != var_contains.end(); ++it ){
- Debug("smart-multi-trigger") << "Pattern " << it->first << " contains: ";
- for( int i=0; i<(int)it->second.size(); i++ ){
- Debug("smart-multi-trigger") << it->second[i] << " ";
- int index = it->second[i].getAttribute(InstVarNumAttribute());
- d_var_contains[ it->first ].push_back( index );
- d_var_to_node[ index ].push_back( it->first );
- }
- Debug("smart-multi-trigger") << std::endl;
- }
- for( int i=0; i<(int)pats.size(); i++ ){
- Node n = pats[i];
- //make the match generator
- d_children.push_back( new InstMatchGenerator( n, qe, matchOption ) );
- //compute unique/shared variables
- std::vector< int > unique_vars;
- std::map< int, bool > shared_vars;
- int numSharedVars = 0;
- for( int j=0; j<(int)d_var_contains[n].size(); j++ ){
- if( d_var_to_node[ d_var_contains[n][j] ].size()==1 ){
- Debug("smart-multi-trigger") << "Var " << d_var_contains[n][j] << " is unique to " << pats[i] << std::endl;
- unique_vars.push_back( d_var_contains[n][j] );
- }else{
- shared_vars[ d_var_contains[n][j] ] = true;
- numSharedVars++;
- }
- }
- //we use the latest shared variables, then unique variables
- std::vector< int > vars;
- int index = i==0 ? (int)(pats.size()-1) : (i-1);
- while( numSharedVars>0 && index!=i ){
- for( std::map< int, bool >::iterator it = shared_vars.begin(); it != shared_vars.end(); ++it ){
- if( it->second ){
- if( std::find( d_var_contains[ pats[index] ].begin(), d_var_contains[ pats[index] ].end(), it->first )!=
- d_var_contains[ pats[index] ].end() ){
- vars.push_back( it->first );
- shared_vars[ it->first ] = false;
- numSharedVars--;
- }
- }
- }
- index = index==0 ? (int)(pats.size()-1) : (index-1);
- }
- vars.insert( vars.end(), unique_vars.begin(), unique_vars.end() );
- Debug("smart-multi-trigger") << " Index[" << i << "]: ";
- for( int i=0; i<(int)vars.size(); i++ ){
- Debug("smart-multi-trigger") << vars[i] << " ";
- }
- Debug("smart-multi-trigger") << std::endl;
- //make ordered inst match trie
- InstMatchTrie::ImtIndexOrder* imtio = new InstMatchTrie::ImtIndexOrder;
- imtio->d_order.insert( imtio->d_order.begin(), vars.begin(), vars.end() );
- d_children_trie.push_back( InstMatchTrieOrdered( imtio ) );
- }
-
-}
-
-/** reset instantiation round (call this whenever equivalence classes have changed) */
-void InstMatchGeneratorMulti::resetInstantiationRound( QuantifiersEngine* qe ){
- for( int i=0; i<(int)d_children.size(); i++ ){
- d_children[i]->resetInstantiationRound( qe );
- }
-}
-
-/** reset, eqc is the equivalence class to search in (any if eqc=null) */
-void InstMatchGeneratorMulti::reset( Node eqc, QuantifiersEngine* qe ){
- for( int i=0; i<(int)d_children.size(); i++ ){
- d_children[i]->reset( eqc, qe );
- }
-}
-
-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
- 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->getTermDatabase()->getInstantiationConstant( d_f, curr_index );
- if( m.find( curr_ic )==m.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();
- // 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.set( curr_ic, it->first);
- processNewInstantiations( qe, mn, addedLemmas, &(it->second), unique_var_tries,
- trieIndex+1, childIndex, endChildIndex, modEq );
- }
- //}
- }else{
- //shared and set variable, try to merge
- Node n = m.get( curr_ic );
- std::map< Node, InstMatchTrie >::iterator it = tr->d_data.find( n );
- if( it!=tr->d_data.end() ){
- processNewInstantiations( qe, m, addedLemmas, &(it->second), unique_var_tries,
- trieIndex+1, childIndex, endChildIndex, modEq );
- }
- if( modEq ){
- //check modulo equality for other possible instantiations
- if( qe->getEqualityQuery()->getEngine()->hasTerm( n ) ){
- eq::EqClassIterator eqc( qe->getEqualityQuery()->getEngine()->getRepresentative( n ),
- qe->getEqualityQuery()->getEngine() );
- while( !eqc.isFinished() ){
- Node en = (*eqc);
- if( en!=n ){
- std::map< Node, InstMatchTrie >::iterator itc = tr->d_data.find( en );
- if( itc!=tr->d_data.end() ){
- processNewInstantiations( qe, m, addedLemmas, &(itc->second), unique_var_tries,
- trieIndex+1, childIndex, endChildIndex, modEq );
- }
- }
- ++eqc;
- }
- }
- }
- }
- }else{
- int newChildIndex = (childIndex+1)%(int)d_children.size();
- processNewInstantiations( qe, m, addedLemmas, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
- 0, newChildIndex, endChildIndex, modEq );
- }
-}
-
-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 ){
- tr = unique_var_tries[uvtIndex].second;
- trieIndex = unique_var_tries[uvtIndex].first.second;
- }
- 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->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.set( curr_ic, it->first);
- processNewInstantiations2( qe, mn, addedLemmas, unique_var_tries, uvtIndex, &(it->second), trieIndex+1 );
- }
- }else{
- processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, uvtIndex+1 );
- }
- }else{
- //m is an instantiation
- if( qe->addInstantiation( d_f, m ) ){
- addedLemmas++;
- Debug("smart-multi-trigger") << "-> Produced instantiation " << m << std::endl;
- }
- }
-}
-
-int InstMatchGeneratorMulti::addTerm( Node f, Node t, QuantifiersEngine* qe ){
- Assert( options::eagerInstQuant() );
- int addedLemmas = 0;
- for( int i=0; i<(int)d_children.size(); i++ ){
- if( ((InstMatchGenerator*)d_children[i])->d_match_pattern.getOperator()==t.getOperator() ){
- InstMatch m;
- //if it produces a match, then process it with the rest
- if( ((InstMatchGenerator*)d_children[i])->getMatch( t, m, qe ) ){
- processNewMatch( qe, m, i, addedLemmas );
- }
- }
- }
- return addedLemmas;
-}
-
-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() ]) );
- }
- }else{
- 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, quantifiers::TermArgTrie* tat ){
- if( argIndex==(int)d_match_pattern.getNumChildren() ){
- //m is an instantiation
- 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, quantifiers::TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
- Node t = it->first;
- if( m.get( ic ).isNull() || m.get( ic )==t ){
- Node prev = m.get( ic );
- m.set( ic, t);
- addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
- m.set( ic, prev);
- }
- }
- }else{
- Node r = qe->getEqualityQuery()->getRepresentative( d_match_pattern[argIndex] );
- 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) );
- }
- }
- }
-}
-
-int InstMatchGeneratorSimple::addTerm( Node f, Node t, QuantifiersEngine* qe ){
- Assert( options::eagerInstQuant() );
- InstMatch m;
- for( int i=0; i<(int)t.getNumChildren(); i++ ){
- if( d_match_pattern[i].getKind()==INST_CONSTANT ){
- m.set(d_match_pattern[i], t[i]);
- }else if( !qe->getEqualityQuery()->areEqual( d_match_pattern[i], t[i] ) ){
- return 0;
- }
- }
- return qe->addInstantiation( f, m ) ? 1 : 0;
-}
+++ /dev/null
-/********************* */
-/*! \file inst_match.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 inst match class
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__INST_MATCH_H
-#define __CVC4__INST_MATCH_H
-
-#include "util/hash.h"
-
-#include <ext/hash_set>
-#include <iostream>
-#include <map>
-
-#include "context/cdlist.h"
-#include "theory/candidate_generator.h"
-
-//#define USE_EFFICIENT_E_MATCHING
-
-namespace CVC4 {
-namespace theory {
-
-/** Attribute true for nodes that should not be used for matching */
-struct NoMatchAttributeId {};
-/** use the special for boolean flag */
-typedef expr::Attribute< NoMatchAttributeId,
- bool,
- expr::attr::NullCleanupStrategy,
- true // context dependent
- > NoMatchAttribute;
-
-// attribute for "contains instantiation constants from"
-struct InstConstantAttributeId {};
-typedef expr::Attribute<InstConstantAttributeId, Node> InstConstantAttribute;
-
-struct InstLevelAttributeId {};
-typedef expr::Attribute<InstLevelAttributeId, uint64_t> InstLevelAttribute;
-
-struct InstVarNumAttributeId {};
-typedef expr::Attribute<InstVarNumAttributeId, uint64_t> InstVarNumAttribute;
-
-// Attribute that tell if a node have been asserted in this branch
-struct AvailableInTermDbId {};
-/** use the special for boolean flag */
-typedef expr::Attribute<AvailableInTermDbId,
- bool,
- expr::attr::NullCleanupStrategy,
- true // context dependent
- > AvailableInTermDb;
-
-
-class QuantifiersEngine;
-namespace quantifiers{
- class TermArgTrie;
-}
-
-namespace uf{
- class InstantiatorTheoryUf;
- class TheoryUF;
-}/* CVC4::theory::uf namespace */
-
-namespace inst {
-
-class EqualityQuery {
-public:
- EqualityQuery(){}
- virtual ~EqualityQuery(){};
- /** contains term */
- virtual bool hasTerm( Node a ) = 0;
- /** get the representative of the equivalence class of a */
- virtual Node getRepresentative( Node a ) = 0;
- /** returns true if a and b are equal in the current context */
- virtual bool areEqual( Node a, Node b ) = 0;
- /** returns true is a and b are disequal in the current context */
- virtual bool areDisequal( Node a, Node b ) = 0;
- /** getInternalRepresentative gets the current best representative in the equivalence class of a, based on some criteria.
- If cbqi is active, this will return a term in the equivalence class of "a" that does
- not contain instantiation constants, if such a term exists.
- */
- virtual Node getInternalRepresentative( Node a ) = 0;
- /** get the equality engine associated with this query */
- virtual eq::EqualityEngine* getEngine() = 0;
- /** get the equivalence class of a */
- virtual void getEquivalenceClass( Node a, std::vector< Node >& eqc ) = 0;
-};/* class EqualityQuery */
-
-/** basic class defining an instantiation */
-class InstMatch {
- /* map from variable to ground terms */
- std::map< Node, Node > d_map;
-public:
- InstMatch();
- InstMatch( InstMatch* m );
-
- /** set the match of v to m */
- bool setMatch( EqualityQuery* q, TNode v, TNode m );
- /* This version tell if the variable has been set */
- bool setMatch( EqualityQuery* q, TNode v, TNode m, bool & set);
- /** fill all unfilled values with m */
- bool add( InstMatch& m );
- /** if compatible, fill all unfilled values with m and return true
- return false otherwise */
- bool merge( EqualityQuery* q, InstMatch& m );
- /** debug print method */
- void debugPrint( const char* c );
- /** make complete */
- void makeComplete( Node f, QuantifiersEngine* qe );
- /** make internal: ensure that no term in d_map contains instantiation constants */
- void makeInternal( QuantifiersEngine* qe );
- /** make representative */
- void makeRepresentative( QuantifiersEngine* qe );
- /** apply rewrite */
- void applyRewrite();
- /** compute d_match */
- void computeTermVec( QuantifiersEngine* qe, const std::vector< Node >& vars, std::vector< Node >& match );
- /** compute d_match */
- void computeTermVec( const std::vector< Node >& vars, std::vector< Node >& match );
- /** clear */
- void clear(){ d_map.clear(); }
- /** erase */
- template<class Iterator>
- void erase(Iterator begin, Iterator end){
- for(Iterator i = begin; i != end; ++i){
- d_map.erase(*i);
- };
- }
- void erase(Node node){ d_map.erase(node); }
- /** is_empty */
- bool empty(){ return d_map.empty(); }
- /** set */
- void set(TNode var, TNode n){
- //std::cout << "var.getType() " << var.getType() << "n.getType() " << n.getType() << std::endl ;
- Assert( !var.isNull() );
- Assert( n.isNull() ||// For a strange use in inst_match.cpp InstMatchGeneratorSimple::addInstantiations
- var.getType() == n.getType() );
- d_map[var] = n;
- }
- Node get(TNode var){ return d_map[var]; }
- size_t size(){ return d_map.size(); }
- /* iterator */
- std::map< Node, Node >::iterator begin(){ return d_map.begin(); };
- std::map< Node, Node >::iterator end(){ return d_map.end(); };
- std::map< Node, Node >::iterator find(Node var){ return d_map.find(var); };
- /* Node used for matching the trigger only for mono-trigger (just for
- efficiency because I need only that) */
- Node d_matched;
- /** to stream */
- inline void toStream(std::ostream& out) const {
- out << "INST_MATCH( ";
- for( std::map< Node, Node >::const_iterator it = d_map.begin(); it != d_map.end(); ++it ){
- if( it != d_map.begin() ){ out << ", "; }
- out << it->first << " -> " << it->second;
- }
- out << " )";
- }
-};/* class InstMatch */
-
-inline std::ostream& operator<<(std::ostream& out, const InstMatch& m) {
- m.toStream(out);
- return out;
-}
-
-/** trie for InstMatch objects */
-class InstMatchTrie {
-public:
- class ImtIndexOrder {
- public:
- std::vector< int > d_order;
- };/* class InstMatchTrie ImtIndexOrder */
-private:
- /** add match m for quantifier f starting at index, take into account equalities q, return true if successful */
- void addInstMatch2( QuantifiersEngine* qe, Node f, InstMatch& m, int index, ImtIndexOrder* imtio );
- /** exists match */
- bool existsInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m, bool modEq, int index, ImtIndexOrder* imtio );
-public:
- /** the data */
- std::map< Node, InstMatchTrie > d_data;
-public:
- InstMatchTrie(){}
- ~InstMatchTrie(){}
-public:
- /** add match m for quantifier f, take into account equalities if modEq = true,
- if imtio is non-null, this is the order to add to trie
- return true if successful
- */
- bool addInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m, bool modEq = false, ImtIndexOrder* imtio = NULL );
-};/* class InstMatchTrie */
-
-class InstMatchTrieOrdered {
-private:
- InstMatchTrie::ImtIndexOrder* d_imtio;
- InstMatchTrie d_imt;
-public:
- InstMatchTrieOrdered( InstMatchTrie::ImtIndexOrder* imtio ) : d_imtio( imtio ){}
- ~InstMatchTrieOrdered(){}
- /** get ordering */
- InstMatchTrie::ImtIndexOrder* getOrdering() { return d_imtio; }
- /** get trie */
- InstMatchTrie* getTrie() { return &d_imt; }
-public:
- /** add match m, return true if successful */
- bool addInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m, bool modEq = false ){
- return d_imt.addInstMatch( qe, f, m, modEq, d_imtio );
- }
-};/* class InstMatchTrieOrdered */
-
-/** base class for producing InstMatch objects */
-class IMGenerator {
-public:
- /** reset instantiation round (call this at beginning of instantiation round) */
- virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
- /** reset, eqc is the equivalence class to search in (any if eqc=null) */
- virtual void reset( Node eqc, QuantifiersEngine* qe ) = 0;
- /** get the next match. must call reset( eqc ) before this function. */
- virtual bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) = 0;
- /** return true if whatever Node is substituted for the variables the
- 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 ) = 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 */
-
-
-class InstMatchGenerator : public IMGenerator {
-private:
- /** candidate generator */
- CandidateGenerator* d_cg;
- /** policy to use for matching */
- int d_matchPolicy;
- /** children generators */
- std::vector< InstMatchGenerator* > d_children;
- std::vector< int > d_children_index;
- /** partial vector */
- std::vector< InstMatch > d_partial;
- /** eq class */
- Node d_eq_class;
- /** for arithmetic matching */
- std::map< Node, Node > d_arith_coeffs;
- /** initialize pattern */
- void initializePatterns( std::vector< Node >& pats, QuantifiersEngine* qe );
- void initializePattern( Node pat, QuantifiersEngine* qe );
-public:
- enum {
- //options for producing matches
- MATCH_GEN_DEFAULT = 0,
- MATCH_GEN_EFFICIENT_E_MATCH, //generate matches via Efficient E-matching for SMT solvers
- //others (internally used)
- MATCH_GEN_INTERNAL_ARITHMETIC,
- MATCH_GEN_INTERNAL_ERROR,
- };
-private:
- /** get the next match. must call d_cg->reset( ... ) before using.
- only valid for use where !d_match_pattern.isNull().
- */
- bool getNextMatch2( InstMatch& m, QuantifiersEngine* qe, bool saveMatched = false );
- /** for arithmetic */
- bool getMatchArithmetic( Node t, InstMatch& m, QuantifiersEngine* qe );
-public:
- /** get the match against ground term or formula t.
- d_match_pattern and t should have the same shape.
- only valid for use where !d_match_pattern.isNull().
- */
- bool getMatch( Node t, InstMatch& m, QuantifiersEngine* qe );
-
- /** constructors */
- InstMatchGenerator( Node pat, QuantifiersEngine* qe, int matchOption = 0 );
- InstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption = 0 );
- /** destructor */
- ~InstMatchGenerator(){}
- /** The pattern we are producing matches for.
- If null, this is a multi trigger that is merging matches from d_children.
- */
- Node d_pattern;
- /** match pattern */
- Node d_match_pattern;
-public:
- /** reset instantiation round (call this whenever equivalence classes have changed) */
- void resetInstantiationRound( QuantifiersEngine* qe );
- /** reset, eqc is the equivalence class to search in (any if eqc=null) */
- void reset( Node eqc, QuantifiersEngine* qe );
- /** get the next match. must call reset( eqc ) before this function. */
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe );
- /** return true if whatever Node is substituted for the variables the
- 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 );
- /** add ground term t */
- int addTerm( Node f, Node t, QuantifiersEngine* qe );
-};/* class InstMatchGenerator */
-
-/** smart multi-trigger implementation */
-class InstMatchGeneratorMulti : public IMGenerator {
-private:
- /** indexed trie */
- typedef std::pair< std::pair< int, int >, InstMatchTrie* > IndexedTrie;
- /** 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;
- /** variable indices contained to pattern nodes */
- std::map< int, std::vector< Node > > d_var_to_node;
- /** quantifier to use */
- Node d_f;
- /** policy to use for matching */
- int d_matchPolicy;
- /** children generators */
- std::vector< InstMatchGenerator* > d_children;
- /** inst match tries for each child */
- std::vector< InstMatchTrieOrdered > d_children_trie;
- /** calculate matches */
- void calculateMatches( QuantifiersEngine* qe );
-public:
- /** constructors */
- InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption = 0 );
- /** destructor */
- ~InstMatchGeneratorMulti(){}
- /** reset instantiation round (call this whenever equivalence classes have changed) */
- void resetInstantiationRound( QuantifiersEngine* qe );
- /** reset, eqc is the equivalence class to search in (any if eqc=null) */
- void reset( Node eqc, QuantifiersEngine* qe );
- /** get the next match. must call reset( eqc ) before this function. (not implemented) */
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) { return false; }
- /** return true if whatever Node is substituted for the variables the
- 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 );
- /** add ground term t */
- int addTerm( Node f, Node t, QuantifiersEngine* qe );
-};/* class InstMatchGeneratorMulti */
-
-/** smart (single)-trigger implementation */
-class InstMatchGeneratorSimple : public IMGenerator {
-private:
- /** quantifier for match term */
- Node d_f;
- /** match term */
- Node d_match_pattern;
- /** add instantiations */
- 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 ){}
- /** destructor */
- ~InstMatchGeneratorSimple(){}
- /** reset instantiation round (call this whenever equivalence classes have changed) */
- void resetInstantiationRound( QuantifiersEngine* qe ) {}
- /** reset, eqc is the equivalence class to search in (any if eqc=null) */
- void reset( Node eqc, QuantifiersEngine* qe ) {}
- /** get the next match. must call reset( eqc ) before this function. (not implemented) */
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) { return false; }
- /** return true if whatever Node is substituted for the variables the
- 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 );
- /** add ground term t, possibly add instantiations */
- int addTerm( Node f, Node t, QuantifiersEngine* qe );
-};/* class InstMatchGeneratorSimple */
-
-}/* CVC4::theory::inst namespace */
-
-typedef CVC4::theory::inst::InstMatch InstMatch;
-typedef CVC4::theory::inst::EqualityQuery EqualityQuery;
-
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
-
-#endif /* __CVC4__INST_MATCH_H */
+++ /dev/null
-/********************* */
-/*! \file instantiator_default.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 instantiator_default class
- **/
-
-#include "theory/instantiator_default.h"
-#include "theory/theory_engine.h"
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-
-InstantiatorDefault::InstantiatorDefault(context::Context* c, QuantifiersEngine* ie, Theory* th) :
- Instantiator( c, ie, th ) {
-}
-
-void InstantiatorDefault::assertNode( Node assertion ){
-}
-
-void InstantiatorDefault::processResetInstantiationRound( Theory::Effort effort ){
-}
-
-int InstantiatorDefault::process( Node f, Theory::Effort effort, int e ){
- /*
- if( e < 4 ){
- return InstStrategy::STATUS_UNFINISHED;
- }else if( e == 4 ){
- Debug("quant-default") << "Process " << f << " : " << std::endl;
- InstMatch m;
- for( int j=0; j<(int)d_quantEngine->getNumInstantiationConstants( f ); j++ ){
- Node i = d_quantEngine->getInstantiationConstant( f, j );
- Debug("quant-default") << "Getting value for " << i << std::endl;
- if( d_quantEngine->getTheoryEngine()->theoryOf( i )==getTheory() ){ //if it belongs to this theory
- Node val = d_th->getValue( i );
- Debug("quant-default") << "Default Instantiate for " << d_th->getId() << ", setting " << i << " = " << val << std::endl;
- m.set( i, val);
- }
- }
- d_quantEngine->addInstantiation( f, m );
- }
- */
- return InstStrategy::STATUS_UNKNOWN;
-}
+++ /dev/null
-/********************* */
-/*! \file instantiator_default.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 instantiator_default
- **/
-
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__INSTANTIATOR_DEFAULT_H
-#define __CVC4__INSTANTIATOR_DEFAULT_H
-
-#include <string>
-#include "theory/quantifiers_engine.h"
-
-namespace CVC4 {
-namespace theory {
-
-class InstantiatorDefault : public Instantiator {
- friend class QuantifiersEngine;
-protected:
- /** reset instantiation round */
- void processResetInstantiationRound(Theory::Effort effort);
- /** process quantifier */
- int process( Node f, Theory::Effort effort, int e );
-public:
- InstantiatorDefault(context::Context* c, QuantifiersEngine* ie, Theory* th);
- ~InstantiatorDefault() { }
- /** check function, assertion is asserted to theory */
- void assertNode( Node assertion );
- /** identify */
- std::string identify() const { return std::string("InstantiatorDefault"); }
-};/* class InstantiatorDefault */
-
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
-
-#endif /* __CVC4__INSTANTIATOR_DEFAULT_H */
theory_quantifiers_instantiator.cpp \
instantiation_engine.h \
instantiation_engine.cpp \
+ trigger.h \
+ trigger.cpp \
+ candidate_generator.h \
+ candidate_generator.cpp \
+ instantiator_default.h \
+ instantiator_default.cpp \
+ inst_match.h \
+ inst_match.cpp \
model_engine.h \
model_engine.cpp \
inst_when_mode.cpp \
--- /dev/null
+/********************* */
+/*! \file candidate_generator.cpp
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: mdeters
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Implementation of theory uf candidate generator class
+ **/
+
+#include "theory/quantifiers/candidate_generator.h"
+#include "theory/theory_engine.h"
+#include "theory/uf/theory_uf.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/inst_match.h"
+#include "theory/quantifiers_engine.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::inst;
+
+bool CandidateGenerator::isLegalCandidate( Node n ){
+ return ( !n.getAttribute(NoMatchAttribute()) && ( !options::cbqi() || !n.hasAttribute(InstConstantAttribute()) ) );
+}
+
+void CandidateGeneratorQueue::addCandidate( Node n ) {
+ if( isLegalCandidate( n ) ){
+ d_candidates.push_back( n );
+ }
+}
+
+void CandidateGeneratorQueue::reset( Node eqc ){
+ if( d_candidate_index>0 ){
+ d_candidates.erase( d_candidates.begin(), d_candidates.begin() + d_candidate_index );
+ d_candidate_index = 0;
+ }
+ if( !eqc.isNull() ){
+ d_candidates.push_back( eqc );
+ }
+}
+Node CandidateGeneratorQueue::getNextCandidate(){
+ if( d_candidate_index<(int)d_candidates.size() ){
+ Node n = d_candidates[d_candidate_index];
+ d_candidate_index++;
+ return n;
+ }else{
+ d_candidate_index = 0;
+ d_candidates.clear();
+ return Node::null();
+ }
+}
+
+#if 0
+
+CandidateGeneratorQE::CandidateGeneratorQE( QuantifiersEngine* qe, Node op ) :
+ d_op( op ), d_qe( qe ), d_term_iter( -2 ){
+ Assert( !d_op.isNull() );
+}
+void CandidateGeneratorQE::resetInstantiationRound(){
+ d_term_iter_limit = d_qe->getTermDatabase()->d_op_map[d_op].size();
+}
+
+void CandidateGeneratorQE::reset( Node eqc ){
+ if( eqc.isNull() ){
+ d_term_iter = 0;
+ }else{
+ //create an equivalence class iterator in eq class eqc
+ if( d_qe->getEqualityQuery()->getEngine()->hasTerm( eqc ) ){
+ eqc = d_qe->getEqualityQuery()->getEngine()->getRepresentative( eqc );
+ d_eqc = eq::EqClassIterator( eqc, d_qe->getEqualityQuery()->getEngine() );
+ d_retNode = Node::null();
+ }else{
+ d_retNode = eqc;
+ }
+ d_term_iter = -1;
+ }
+}
+
+Node CandidateGeneratorQE::getNextCandidate(){
+ if( d_term_iter>=0 ){
+ //get next candidate term in the uf term database
+ while( d_term_iter<d_term_iter_limit ){
+ Node n = d_qe->getTermDatabase()->d_op_map[d_op][d_term_iter];
+ d_term_iter++;
+ if( isLegalCandidate( n ) ){
+ return n;
+ }
+ }
+ }else if( d_term_iter==-1 ){
+ if( d_retNode.isNull() ){
+ //get next candidate term in equivalence class
+ while( !d_eqc.isFinished() ){
+ Node n = (*d_eqc);
+ ++d_eqc;
+ if( n.hasOperator() && n.getOperator()==d_op ){
+ if( isLegalCandidate( n ) ){
+ return n;
+ }
+ }
+ }
+ }else{
+ Node ret;
+ if( d_retNode.hasOperator() && d_retNode.getOperator()==d_op ){
+ ret = d_retNode;
+ }
+ d_term_iter = -2; //done returning matches
+ return ret;
+ }
+ }
+ return Node::null();
+}
+
+#else
+
+
+CandidateGeneratorQE::CandidateGeneratorQE( QuantifiersEngine* qe, Node op ) :
+ d_op( op ), d_qe( qe ), d_term_iter( -1 ){
+ Assert( !d_op.isNull() );
+}
+void CandidateGeneratorQE::resetInstantiationRound(){
+ d_term_iter_limit = d_qe->getTermDatabase()->d_op_map[d_op].size();
+}
+
+void CandidateGeneratorQE::reset( Node eqc ){
+ d_term_iter = 0;
+ if( eqc.isNull() ){
+ d_using_term_db = true;
+ }else{
+ //create an equivalence class iterator in eq class eqc
+ d_eqc.clear();
+ d_qe->getEqualityQuery()->getEquivalenceClass( eqc, d_eqc );
+ d_using_term_db = false;
+ }
+}
+
+Node CandidateGeneratorQE::getNextCandidate(){
+ if( d_term_iter>=0 ){
+ if( d_using_term_db ){
+ //get next candidate term in the uf term database
+ while( d_term_iter<d_term_iter_limit ){
+ Node n = d_qe->getTermDatabase()->d_op_map[d_op][d_term_iter];
+ d_term_iter++;
+ if( isLegalCandidate( n ) ){
+ return n;
+ }
+ }
+ }else{
+ while( d_term_iter<(int)d_eqc.size() ){
+ Node n = d_eqc[d_term_iter];
+ d_term_iter++;
+ if( n.hasOperator() && n.getOperator()==d_op ){
+ if( isLegalCandidate( n ) ){
+ return n;
+ }
+ }
+ }
+ }
+ }
+ return Node::null();
+}
+
+#endif
+
+//CandidateGeneratorQEDisequal::CandidateGeneratorQEDisequal( QuantifiersEngine* qe, Node eqc ) :
+// d_qe( qe ), d_eq_class( eqc ){
+// d_eci = NULL;
+//}
+//void CandidateGeneratorQEDisequal::resetInstantiationRound(){
+//
+//}
+////we will iterate over all terms that are disequal from eqc
+//void CandidateGeneratorQEDisequal::reset( Node eqc ){
+// //Assert( !eqc.isNull() );
+// ////begin iterating over equivalence classes that are disequal from eqc
+// //d_eci = d_ith->getEquivalenceClassInfo( eqc );
+// //if( d_eci ){
+// // d_eqci_iter = d_eci->d_disequal.begin();
+// //}
+//}
+//Node CandidateGeneratorQEDisequal::getNextCandidate(){
+// //if( d_eci ){
+// // while( d_eqci_iter != d_eci->d_disequal.end() ){
+// // if( (*d_eqci_iter).second ){
+// // //we have an equivalence class that is disequal from eqc
+// // d_cg->reset( (*d_eqci_iter).first );
+// // Node n = d_cg->getNextCandidate();
+// // //if there is a candidate in this equivalence class, return it
+// // if( !n.isNull() ){
+// // return n;
+// // }
+// // }
+// // ++d_eqci_iter;
+// // }
+// //}
+// return Node::null();
+//}
+
+
+CandidateGeneratorQELitEq::CandidateGeneratorQELitEq( QuantifiersEngine* qe, Node mpat ) :
+ d_match_pattern( mpat ), d_qe( qe ){
+
+}
+void CandidateGeneratorQELitEq::resetInstantiationRound(){
+
+}
+void CandidateGeneratorQELitEq::reset( Node eqc ){
+ d_eq = eq::EqClassesIterator( d_qe->getEqualityQuery()->getEngine() );
+}
+Node CandidateGeneratorQELitEq::getNextCandidate(){
+ while( d_eq.isFinished() ){
+ Node n = (*d_eq);
+ ++d_eq;
+ if( n.getType()==d_match_pattern[0].getType() ){
+ //an equivalence class with the same type as the pattern, return reflexive equality
+ return NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), n, n );
+ }
+ }
+ return Node::null();
+}
+
+
+CandidateGeneratorQELitDeq::CandidateGeneratorQELitDeq( QuantifiersEngine* qe, Node mpat ) :
+ d_match_pattern( mpat ), d_qe( qe ){
+
+}
+void CandidateGeneratorQELitDeq::resetInstantiationRound(){
+
+}
+void CandidateGeneratorQELitDeq::reset( Node eqc ){
+ Node false_term = d_qe->getEqualityQuery()->getEngine()->getRepresentative( NodeManager::currentNM()->mkConst<bool>(false) );
+ d_eqc_false = eq::EqClassIterator( false_term, d_qe->getEqualityQuery()->getEngine() );
+}
+Node CandidateGeneratorQELitDeq::getNextCandidate(){
+ //get next candidate term in equivalence class
+ while( !d_eqc_false.isFinished() ){
+ Node n = (*d_eqc_false);
+ ++d_eqc_false;
+ if( n.getKind()==d_match_pattern.getKind() ){
+ //found an iff or equality, try to match it
+ //DO_THIS: cache to avoid redundancies?
+ //DO_THIS: do we need to try the symmetric equality for n? or will it also exist in the eq class of false?
+ return n;
+ }
+ }
+ return Node::null();
+}
--- /dev/null
+/********************* */
+/*! \file candidate_generator.h
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: none
+ ** Minor contributors (to current version): mdeters
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Theory uf candidate generator
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANTIFIERS__CANDIDATE_GENERATOR_H
+#define __CVC4__THEORY__QUANTIFIERS__CANDIDATE_GENERATOR_H
+
+#include "theory/theory.h"
+#include "theory/uf/equality_engine.h"
+
+namespace CVC4 {
+namespace theory {
+
+class QuantifiersEngine;
+
+namespace inst {
+
+/** base class for generating candidates for matching */
+class CandidateGenerator {
+public:
+ CandidateGenerator(){}
+ ~CandidateGenerator(){}
+
+ /** Get candidates functions. These set up a context to get all match candidates.
+ cg->reset( eqc );
+ do{
+ Node cand = cg->getNextCandidate();
+ //.......
+ }while( !cand.isNull() );
+
+ eqc is the equivalence class you are searching in
+ */
+ virtual void reset( Node eqc ) = 0;
+ virtual Node getNextCandidate() = 0;
+ /** add candidate to list of nodes returned by this generator */
+ virtual void addCandidate( Node n ) {}
+ /** call this at the beginning of each instantiation round */
+ virtual void resetInstantiationRound() = 0;
+public:
+ /** legal candidate */
+ static bool isLegalCandidate( Node n );
+};/* class CandidateGenerator */
+
+/** candidate generator queue (for manual candidate generation) */
+class CandidateGeneratorQueue : public CandidateGenerator {
+private:
+ std::vector< Node > d_candidates;
+ int d_candidate_index;
+public:
+ CandidateGeneratorQueue() : d_candidate_index( 0 ){}
+ ~CandidateGeneratorQueue(){}
+
+ void addCandidate( Node n );
+
+ void resetInstantiationRound(){}
+ void reset( Node eqc );
+ Node getNextCandidate();
+};/* class CandidateGeneratorQueue */
+
+class CandidateGeneratorQEDisequal;
+
+#if 0
+
+class CandidateGeneratorQE : public CandidateGenerator
+{
+ friend class CandidateGeneratorQEDisequal;
+private:
+ //operator you are looking for
+ Node d_op;
+ //instantiator pointer
+ QuantifiersEngine* d_qe;
+ //the equality class iterator
+ eq::EqClassIterator d_eqc;
+ int d_term_iter;
+ int d_term_iter_limit;
+private:
+ Node d_retNode;
+public:
+ CandidateGeneratorQE( QuantifiersEngine* qe, Node op );
+ ~CandidateGeneratorQE(){}
+
+ void resetInstantiationRound();
+ void reset( Node eqc );
+ Node getNextCandidate();
+};
+
+#else
+
+class CandidateGeneratorQE : public CandidateGenerator
+{
+ friend class CandidateGeneratorQEDisequal;
+private:
+ //operator you are looking for
+ Node d_op;
+ //instantiator pointer
+ QuantifiersEngine* d_qe;
+ //the equality class iterator
+ std::vector< Node > d_eqc;
+ int d_term_iter;
+ int d_term_iter_limit;
+ bool d_using_term_db;
+public:
+ CandidateGeneratorQE( QuantifiersEngine* qe, Node op );
+ ~CandidateGeneratorQE(){}
+
+ void resetInstantiationRound();
+ void reset( Node eqc );
+ Node getNextCandidate();
+};
+
+#endif
+
+//class CandidateGeneratorQEDisequal : public CandidateGenerator
+//{
+//private:
+// //equivalence class
+// Node d_eq_class;
+// //equivalence class info
+// EqClassInfo* d_eci;
+// //equivalence class iterator
+// EqClassInfo::BoolMap::const_iterator d_eqci_iter;
+// //instantiator pointer
+// QuantifiersEngine* d_qe;
+//public:
+// CandidateGeneratorQEDisequal( QuantifiersEngine* qe, Node eqc );
+// ~CandidateGeneratorQEDisequal(){}
+//
+// void resetInstantiationRound();
+// void reset( Node eqc ); //should be what you want to be disequal from
+// Node getNextCandidate();
+//};
+
+class CandidateGeneratorQELitEq : public CandidateGenerator
+{
+private:
+ //the equality classes iterator
+ eq::EqClassesIterator d_eq;
+ //equality you are trying to match equalities for
+ Node d_match_pattern;
+ //einstantiator pointer
+ QuantifiersEngine* d_qe;
+public:
+ CandidateGeneratorQELitEq( QuantifiersEngine* qe, Node mpat );
+ ~CandidateGeneratorQELitEq(){}
+
+ void resetInstantiationRound();
+ void reset( Node eqc );
+ Node getNextCandidate();
+};
+
+class CandidateGeneratorQELitDeq : public CandidateGenerator
+{
+private:
+ //the equality class iterator for false
+ eq::EqClassIterator d_eqc_false;
+ //equality you are trying to match disequalities for
+ Node d_match_pattern;
+ //einstantiator pointer
+ QuantifiersEngine* d_qe;
+public:
+ CandidateGeneratorQELitDeq( QuantifiersEngine* qe, Node mpat );
+ ~CandidateGeneratorQELitDeq(){}
+
+ void resetInstantiationRound();
+ void reset( Node eqc );
+ Node getNextCandidate();
+};
+
+}/* CVC4::theory::inst namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
+
+#endif /* __CVC4__THEORY__QUANTIFIERS__CANDIDATE_GENERATOR_H */
TermDb* getTermDatabase();
/** to stream function */
void toStream( std::ostream& out );
-};
+};/* class FirstOrderModel */
-}
-}
-}
+}/* CVC4::theory::quantifiers namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
-#endif
+#endif /* __CVC4__FIRST_ORDER_MODEL_H */
--- /dev/null
+/********************* */
+/*! \file inst_match.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 inst match class
+ **/
+
+#include "theory/quantifiers/inst_match.h"
+#include "theory/theory_engine.h"
+#include "theory/quantifiers_engine.h"
+#include "theory/quantifiers/candidate_generator.h"
+#include "theory/uf/theory_uf_instantiator.h"
+#include "theory/uf/equality_engine.h"
+#include "theory/quantifiers/options.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;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::inst;
+
+
+InstMatch::InstMatch() {
+}
+
+InstMatch::InstMatch( InstMatch* m ) {
+ d_map = m->d_map;
+}
+
+bool InstMatch::setMatch( EqualityQuery* q, TNode v, TNode m, bool & set ){
+ std::map< Node, Node >::iterator vn = d_map.find( v );
+ if( vn==d_map.end() ){
+ set = true;
+ this->set(v,m);
+ Debug("matching-debug") << "Add partial " << v << "->" << m << std::endl;
+ return true;
+ }else{
+ set = false;
+ return q->areEqual( vn->second, m );
+ }
+}
+
+bool InstMatch::setMatch( EqualityQuery* q, TNode v, TNode m ){
+ bool set;
+ return setMatch(q,v,m,set);
+}
+
+bool InstMatch::add( InstMatch& m ){
+ for( std::map< Node, Node >::iterator it = m.d_map.begin(); it != m.d_map.end(); ++it ){
+ if( d_map.find( it->first )==d_map.end() ){
+ d_map[it->first] = it->second;
+ }
+ }
+ return true;
+}
+
+bool InstMatch::merge( EqualityQuery* q, InstMatch& m ){
+ for( std::map< Node, Node >::iterator it = m.d_map.begin(); it != m.d_map.end(); ++it ){
+ if( d_map.find( it->first )==d_map.end() ){
+ d_map[ it->first ] = it->second;
+ }else{
+ if( it->second!=d_map[it->first] ){
+ if( !q->areEqual( it->second, d_map[it->first] ) ){
+ d_map.clear();
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+void InstMatch::debugPrint( const char* c ){
+ for( std::map< Node, Node >::iterator it = d_map.begin(); it != d_map.end(); ++it ){
+ Debug( c ) << " " << it->first << " -> " << it->second << std::endl;
+ }
+ //if( !d_splits.empty() ){
+ // Debug( c ) << " Conditions: ";
+ // for( std::map< Node, Node >::iterator it = d_splits.begin(); it !=d_splits.end(); ++it ){
+ // Debug( c ) << it->first << " = " << it->second << " ";
+ // }
+ // Debug( c ) << std::endl;
+ //}
+}
+
+void InstMatch::makeComplete( Node f, QuantifiersEngine* qe ){
+ for( int i=0; i<(int)qe->getTermDatabase()->d_inst_constants[f].size(); i++ ){
+ Node ic = qe->getTermDatabase()->d_inst_constants[f][i];
+ if( d_map.find( ic )==d_map.end() ){
+ d_map[ ic ] = qe->getTermDatabase()->getFreeVariableForInstConstant( ic );
+ }
+ }
+}
+
+void InstMatch::makeInternal( QuantifiersEngine* qe ){
+ if( options::cbqi() ){
+ for( std::map< Node, Node >::iterator it = d_map.begin(); it != d_map.end(); ++it ){
+ if( it->second.hasAttribute(InstConstantAttribute()) ){
+ d_map[ it->first ] = qe->getEqualityQuery()->getInternalRepresentative( it->second );
+ if( it->second.hasAttribute(InstConstantAttribute()) ){
+ d_map[ it->first ] = qe->getTermDatabase()->getFreeVariableForInstConstant( it->first );
+ }
+ }
+ }
+ }
+}
+
+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::cbqi() && it->second.hasAttribute(InstConstantAttribute()) ){
+ d_map[ it->first ] = qe->getTermDatabase()->getFreeVariableForInstConstant( it->first );
+ }
+ }
+}
+
+void InstMatch::applyRewrite(){
+ for( std::map< Node, Node >::iterator it = d_map.begin(); it != d_map.end(); ++it ){
+ it->second = Rewriter::rewrite(it->second);
+ }
+}
+
+void InstMatch::computeTermVec( QuantifiersEngine* qe, const std::vector< Node >& vars, std::vector< Node >& match ){
+ for( int i=0; i<(int)vars.size(); i++ ){
+ std::map< Node, Node >::iterator it = d_map.find( vars[i] );
+ if( it!=d_map.end() && !it->second.isNull() ){
+ match.push_back( it->second );
+ }else{
+ match.push_back( qe->getTermDatabase()->getFreeVariableForInstConstant( vars[i] ) );
+ }
+ }
+}
+void InstMatch::computeTermVec( const std::vector< Node >& vars, std::vector< Node >& match ){
+ for( int i=0; i<(int)vars.size(); i++ ){
+ match.push_back( d_map[ vars[i] ] );
+ }
+}
+
+
+/** add match m for quantifier f starting at index, take into account equalities q, return true if successful */
+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.get( qe->getTermDatabase()->getInstantiationConstant( f, i_index ) );
+ d_data[n].addInstMatch2( qe, f, m, index+1, imtio );
+ }
+}
+
+/** exists match */
+bool InstMatchTrie::existsInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m, bool modEq, int index, ImtIndexOrder* imtio ){
+ if( long(index)==long(f[0].getNumChildren()) || ( imtio && long(index)==long(imtio->d_order.size()) ) ){
+ return true;
+ }else{
+ int i_index = imtio ? imtio->d_order[index] : index;
+ Node n = m.get( 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 ) ){
+ return true;
+ }
+ }
+ if( modEq ){
+ //check modulo equality if any other instantiation match exists
+ if( qe->getEqualityQuery()->getEngine()->hasTerm( n ) ){
+ eq::EqClassIterator eqc( qe->getEqualityQuery()->getEngine()->getRepresentative( n ),
+ qe->getEqualityQuery()->getEngine() );
+ while( !eqc.isFinished() ){
+ Node en = (*eqc);
+ if( en!=n ){
+ std::map< Node, InstMatchTrie >::iterator itc = d_data.find( en );
+ if( itc!=d_data.end() ){
+ if( itc->second.existsInstMatch( qe, f, m, modEq, index+1, imtio ) ){
+ return true;
+ }
+ }
+ }
+ ++eqc;
+ }
+ }
+ //for( std::map< Node, InstMatchTrie >::iterator itc = d_data.begin(); itc != d_data.end(); ++itc ){
+ // if( itc->first!=n && qe->getEqualityQuery()->areEqual( n, itc->first ) ){
+ // if( itc->second.existsInstMatch( qe, f, m, modEq, index+1 ) ){
+ // return true;
+ // }
+ // }
+ //}
+ }
+ return false;
+ }
+}
+
+bool InstMatchTrie::addInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m, bool modEq, ImtIndexOrder* imtio ){
+ if( !existsInstMatch( qe, f, m, modEq, 0, imtio ) ){
+ addInstMatch2( qe, f, m, 0, imtio );
+ return true;
+ }else{
+ return false;
+ }
+}
+
+InstMatchGenerator::InstMatchGenerator( Node pat, QuantifiersEngine* qe, int matchPolicy ) : d_matchPolicy( matchPolicy ){
+ initializePattern( pat, qe );
+}
+
+InstMatchGenerator::InstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe, int matchPolicy ) : d_matchPolicy( matchPolicy ){
+ if( pats.size()==1 ){
+ initializePattern( pats[0], qe );
+ }else{
+ initializePatterns( pats, qe );
+ }
+}
+
+void InstMatchGenerator::initializePatterns( std::vector< Node >& pats, QuantifiersEngine* qe ){
+ int childMatchPolicy = d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ? 0 : d_matchPolicy;
+ for( int i=0; i<(int)pats.size(); i++ ){
+ d_children.push_back( new InstMatchGenerator( pats[i], qe, childMatchPolicy ) );
+ }
+ d_pattern = Node::null();
+ d_match_pattern = Node::null();
+ d_cg = NULL;
+}
+
+void InstMatchGenerator::initializePattern( Node pat, QuantifiersEngine* qe ){
+ Debug("inst-match-gen") << "Pattern term is " << pat << std::endl;
+ Assert( pat.hasAttribute(InstConstantAttribute()) );
+ d_pattern = pat;
+ d_match_pattern = pat;
+ if( d_match_pattern.getKind()==NOT ){
+ //we want to add the children of the NOT
+ d_match_pattern = d_pattern[0];
+ }
+ if( d_match_pattern.getKind()==IFF || d_match_pattern.getKind()==EQUAL ){
+ if( !d_match_pattern[0].hasAttribute(InstConstantAttribute()) ){
+ Assert( d_match_pattern[1].hasAttribute(InstConstantAttribute()) );
+ //swap sides
+ d_pattern = NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), d_match_pattern[1], d_match_pattern[0] );
+ d_pattern = pat.getKind()==NOT ? d_pattern.notNode() : d_pattern;
+ if( pat.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching
+ d_match_pattern = d_match_pattern[1];
+ }else{
+ d_match_pattern = d_pattern[0][0];
+ }
+ }else if( !d_match_pattern[1].hasAttribute(InstConstantAttribute()) ){
+ Assert( d_match_pattern[0].hasAttribute(InstConstantAttribute()) );
+ if( pat.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching
+ d_match_pattern = d_match_pattern[0];
+ }
+ }
+ }
+ int childMatchPolicy = MATCH_GEN_DEFAULT;
+ for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
+ if( d_match_pattern[i].hasAttribute(InstConstantAttribute()) ){
+ if( d_match_pattern[i].getKind()!=INST_CONSTANT ){
+ d_children.push_back( new InstMatchGenerator( d_match_pattern[i], qe, childMatchPolicy ) );
+ d_children_index.push_back( i );
+ }
+ }
+ }
+
+ Debug("inst-match-gen") << "Pattern is " << d_pattern << ", match pattern is " << d_match_pattern << std::endl;
+
+ //create candidate generator
+ if( d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==IFF ){
+ Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
+ //we will be producing candidates via literal matching heuristics
+ if( d_pattern.getKind()!=NOT ){
+ //candidates will be all equalities
+ d_cg = new inst::CandidateGeneratorQELitEq( qe, d_match_pattern );
+ }else{
+ //candidates will be all disequalities
+ d_cg = new inst::CandidateGeneratorQELitDeq( qe, d_match_pattern );
+ }
+ }else if( d_pattern.getKind()==EQUAL || d_pattern.getKind()==IFF || d_pattern.getKind()==NOT ){
+ Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
+ if( d_pattern.getKind()==NOT ){
+ Unimplemented("Disequal generator unimplemented");
+ }else{
+ Assert( Trigger::isAtomicTrigger( d_match_pattern ) );
+ //we are matching only in a particular equivalence class
+ d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
+ //store the equivalence class that we will call d_cg->reset( ... ) on
+ d_eq_class = d_pattern[1];
+ }
+ }else if( Trigger::isAtomicTrigger( d_match_pattern ) ){
+ //if( d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ){
+ //Warning() << "Currently efficient e matching is not taken into account for quantifiers: " << d_pattern << std::endl;
+ //}
+ //we will be scanning lists trying to find d_match_pattern.getOperator()
+ d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
+ }else{
+ d_cg = new CandidateGeneratorQueue;
+ if( !Trigger::getPatternArithmetic( d_match_pattern.getAttribute(InstConstantAttribute()), d_match_pattern, d_arith_coeffs ) ){
+ Debug("inst-match-gen") << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
+ Warning() << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
+ d_matchPolicy = MATCH_GEN_INTERNAL_ERROR;
+ }else{
+ Debug("matching-arith") << "Generated arithmetic pattern for " << d_match_pattern << ": " << std::endl;
+ for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+ Debug("matching-arith") << " " << it->first << " -> " << it->second << std::endl;
+ }
+ //we will treat this as match gen internal arithmetic
+ d_matchPolicy = MATCH_GEN_INTERNAL_ARITHMETIC;
+ }
+ }
+}
+
+/** get match (not modulo equality) */
+bool InstMatchGenerator::getMatch( Node t, InstMatch& m, QuantifiersEngine* qe ){
+ Debug("matching") << "Matching " << t << " against pattern " << d_match_pattern << " ("
+ << m.size() << ")" << ", " << d_children.size() << std::endl;
+ Assert( !d_match_pattern.isNull() );
+ 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;
+ }else{
+ EqualityQuery* q = qe->getEqualityQuery();
+ //add m to partial match vector
+ std::vector< InstMatch > partial;
+ partial.push_back( InstMatch( &m ) );
+ //if t is null
+ Assert( !t.isNull() );
+ Assert( !t.hasAttribute(InstConstantAttribute()) );
+ Assert( t.getKind()==d_match_pattern.getKind() );
+ Assert( !Trigger::isAtomicTrigger( d_match_pattern ) || t.getOperator()==d_match_pattern.getOperator() );
+ //first, check if ground arguments are not equal, or a match is in conflict
+ for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
+ if( d_match_pattern[i].hasAttribute(InstConstantAttribute()) ){
+ if( d_match_pattern[i].getKind()==INST_CONSTANT ){
+ if( !partial[0].setMatch( q, d_match_pattern[i], t[i] ) ){
+ //match is in conflict
+ Debug("matching-debug") << "Match in conflict " << t[i] << " and "
+ << d_match_pattern[i] << " because "
+ << partial[0].get(d_match_pattern[i])
+ << std::endl;
+ Debug("matching-fail") << "Match fail: " << partial[0].get(d_match_pattern[i]) << " and " << t[i] << std::endl;
+ return false;
+ }
+ }
+ }else{
+ if( !q->areEqual( d_match_pattern[i], t[i] ) ){
+ Debug("matching-fail") << "Match fail arg: " << d_match_pattern[i] << " and " << t[i] << std::endl;
+ //ground arguments are not equal
+ return false;
+ }
+ }
+ }
+ //now, fit children into match
+ //we will be requesting candidates for matching terms for each child
+ std::vector< Node > reps;
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ Node rep = q->getRepresentative( t[ d_children_index[i] ] );
+ reps.push_back( rep );
+ d_children[i]->d_cg->reset( rep );
+ }
+
+ //combine child matches
+ int index = 0;
+ while( index>=0 && index<(int)d_children.size() ){
+ partial.push_back( InstMatch( &partial[index] ) );
+ if( d_children[index]->getNextMatch2( partial[index+1], qe ) ){
+ index++;
+ }else{
+ d_children[index]->d_cg->reset( reps[index] );
+ partial.pop_back();
+ if( !partial.empty() ){
+ partial.pop_back();
+ }
+ index--;
+ }
+ }
+ if( index>=0 ){
+ m = partial.back();
+ return true;
+ }else{
+ return false;
+ }
+ }
+}
+
+bool InstMatchGenerator::getNextMatch2( InstMatch& m, QuantifiersEngine* qe, bool saveMatched ){
+ bool success = false;
+ Node t;
+ do{
+ //get the next candidate term t
+ t = d_cg->getNextCandidate();
+ //if t not null, try to fit it into match m
+ if( !t.isNull() && t.getType()==d_match_pattern.getType() ){
+ success = getMatch( t, m, qe );
+ }
+ }while( !success && !t.isNull() );
+ if (saveMatched) m.d_matched = t;
+ return success;
+}
+
+bool InstMatchGenerator::getMatchArithmetic( Node t, InstMatch& m, QuantifiersEngine* qe ){
+ Debug("matching-arith") << "Matching " << t << " " << d_match_pattern << std::endl;
+ if( !d_arith_coeffs.empty() ){
+ NodeBuilder<> tb(kind::PLUS);
+ Node ic = Node::null();
+ for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+ Debug("matching-arith") << it->first << " -> " << it->second << std::endl;
+ if( !it->first.isNull() ){
+ if( m.find( it->first )==m.end() ){
+ //see if we can choose this to set
+ if( ic.isNull() && ( it->second.isNull() || !it->first.getType().isInteger() ) ){
+ ic = it->first;
+ }
+ }else{
+ Debug("matching-arith") << "already set " << m.get( it->first ) << std::endl;
+ Node tm = m.get( it->first );
+ if( !it->second.isNull() ){
+ tm = NodeManager::currentNM()->mkNode( MULT, it->second, tm );
+ }
+ tb << tm;
+ }
+ }else{
+ tb << it->second;
+ }
+ }
+ if( !ic.isNull() ){
+ Node tm;
+ if( tb.getNumChildren()==0 ){
+ tm = t;
+ }else{
+ tm = tb.getNumChildren()==1 ? tb.getChild( 0 ) : tb;
+ tm = NodeManager::currentNM()->mkNode( MINUS, t, tm );
+ }
+ if( !d_arith_coeffs[ ic ].isNull() ){
+ Assert( !ic.getType().isInteger() );
+ Node coeff = NodeManager::currentNM()->mkConst( Rational(1) / d_arith_coeffs[ ic ].getConst<Rational>() );
+ tm = NodeManager::currentNM()->mkNode( MULT, coeff, tm );
+ }
+ m.set( ic, Rewriter::rewrite( tm ));
+ //set the rest to zeros
+ for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+ if( !it->first.isNull() ){
+ if( m.find( it->first )==m.end() ){
+ m.set( it->first, NodeManager::currentNM()->mkConst( Rational(0) ) );
+ }
+ }
+ }
+ Debug("matching-arith") << "Setting " << ic << " to " << tm << std::endl;
+ return true;
+ }else{
+ return false;
+ }
+ }else{
+ return false;
+ }
+}
+
+
+/** reset instantiation round */
+void InstMatchGenerator::resetInstantiationRound( QuantifiersEngine* qe ){
+ if( d_match_pattern.isNull() ){
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ d_children[i]->resetInstantiationRound( qe );
+ }
+ }else{
+ if( d_cg ){
+ d_cg->resetInstantiationRound();
+ }
+ }
+}
+
+void InstMatchGenerator::reset( Node eqc, QuantifiersEngine* qe ){
+ if( d_match_pattern.isNull() ){
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ d_children[i]->reset( eqc, qe );
+ }
+ d_partial.clear();
+ }else{
+ if( !d_eq_class.isNull() ){
+ //we have a specific equivalence class in mind
+ //we are producing matches for f(E) ~ t, where E is a non-ground vector of terms, and t is a ground term
+ //just look in equivalence class of the RHS
+ d_cg->reset( d_eq_class );
+ }else{
+ d_cg->reset( eqc );
+ }
+ }
+}
+
+bool InstMatchGenerator::getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ m.d_matched = Node::null();
+ if( d_match_pattern.isNull() ){
+ int index = (int)d_partial.size();
+ while( index>=0 && index<(int)d_children.size() ){
+ if( index>0 ){
+ d_partial.push_back( InstMatch( &d_partial[index-1] ) );
+ }else{
+ d_partial.push_back( InstMatch() );
+ }
+ if( d_children[index]->getNextMatch( d_partial[index], qe ) ){
+ index++;
+ }else{
+ d_children[index]->reset( Node::null(), qe );
+ d_partial.pop_back();
+ if( !d_partial.empty() ){
+ d_partial.pop_back();
+ }
+ index--;
+ }
+ }
+ if( index>=0 ){
+ m = d_partial.back();
+ d_partial.pop_back();
+ return true;
+ }else{
+ return false;
+ }
+ }else{
+ bool res = getNextMatch2( m, qe, true );
+ Assert(!res || !m.d_matched.isNull());
+ return res;
+ }
+}
+
+
+
+// Currently the implementation doesn't take into account that
+// variable should have the same value given.
+// TODO use the d_children way perhaps
+// TODO replace by a real dictionnary
+// We should create a real substitution? slower more precise
+// We don't do that often
+bool InstMatchGenerator::nonunifiable( TNode t0, const std::vector<Node> & vars){
+ if(d_match_pattern.isNull()) return true;
+
+ typedef std::vector<std::pair<TNode,TNode> > tstack;
+ tstack stack(1,std::make_pair(t0,d_match_pattern)); // t * pat
+
+ while(!stack.empty()){
+ const std::pair<TNode,TNode> p = stack.back(); stack.pop_back();
+ const TNode & t = p.first;
+ const TNode & pat = p.second;
+
+ // t or pat is a variable currently we consider that can match anything
+ if( find(vars.begin(),vars.end(),t) != vars.end() ) continue;
+ if( pat.getKind() == INST_CONSTANT ) continue;
+
+ // t and pat are nonunifiable
+ if( !Trigger::isAtomicTrigger( t ) || !Trigger::isAtomicTrigger( pat ) ) {
+ if(t == pat) continue;
+ else return true;
+ };
+ if( t.getOperator() != pat.getOperator() ) return true;
+
+ //put the children on the stack
+ for( size_t i=0; i < pat.getNumChildren(); i++ ){
+ stack.push_back(std::make_pair(t[i],pat[i]));
+ };
+ }
+ // The heuristic can't find non-unifiability
+ return false;
+}
+
+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 ) ){
+ addedLemmas++;
+ if( qe->d_optInstLimitActive && qe->d_optInstLimit<=0 ){
+ return addedLemmas;
+ }
+ }
+ m.clear();
+ }
+ //return number of lemmas added
+ return addedLemmas;
+}
+
+int InstMatchGenerator::addTerm( Node f, Node t, QuantifiersEngine* qe ){
+ Assert( options::eagerInstQuant() );
+ if( !d_match_pattern.isNull() ){
+ InstMatch m;
+ if( getMatch( t, m, qe ) ){
+ if( qe->addInstantiation( f, m ) ){
+ return 1;
+ }
+ }
+ }else{
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ d_children[i]->addTerm( f, t, qe );
+ }
+ }
+ return 0;
+}
+
+/** constructors */
+InstMatchGeneratorMulti::InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption ) :
+d_f( f ){
+ Debug("smart-multi-trigger") << "Making smart multi-trigger for " << f << std::endl;
+ std::map< Node, std::vector< Node > > var_contains;
+ Trigger::getVarContains( f, pats, var_contains );
+ //convert to indicies
+ for( std::map< Node, std::vector< Node > >::iterator it = var_contains.begin(); it != var_contains.end(); ++it ){
+ Debug("smart-multi-trigger") << "Pattern " << it->first << " contains: ";
+ for( int i=0; i<(int)it->second.size(); i++ ){
+ Debug("smart-multi-trigger") << it->second[i] << " ";
+ int index = it->second[i].getAttribute(InstVarNumAttribute());
+ d_var_contains[ it->first ].push_back( index );
+ d_var_to_node[ index ].push_back( it->first );
+ }
+ Debug("smart-multi-trigger") << std::endl;
+ }
+ for( int i=0; i<(int)pats.size(); i++ ){
+ Node n = pats[i];
+ //make the match generator
+ d_children.push_back( new InstMatchGenerator( n, qe, matchOption ) );
+ //compute unique/shared variables
+ std::vector< int > unique_vars;
+ std::map< int, bool > shared_vars;
+ int numSharedVars = 0;
+ for( int j=0; j<(int)d_var_contains[n].size(); j++ ){
+ if( d_var_to_node[ d_var_contains[n][j] ].size()==1 ){
+ Debug("smart-multi-trigger") << "Var " << d_var_contains[n][j] << " is unique to " << pats[i] << std::endl;
+ unique_vars.push_back( d_var_contains[n][j] );
+ }else{
+ shared_vars[ d_var_contains[n][j] ] = true;
+ numSharedVars++;
+ }
+ }
+ //we use the latest shared variables, then unique variables
+ std::vector< int > vars;
+ int index = i==0 ? (int)(pats.size()-1) : (i-1);
+ while( numSharedVars>0 && index!=i ){
+ for( std::map< int, bool >::iterator it = shared_vars.begin(); it != shared_vars.end(); ++it ){
+ if( it->second ){
+ if( std::find( d_var_contains[ pats[index] ].begin(), d_var_contains[ pats[index] ].end(), it->first )!=
+ d_var_contains[ pats[index] ].end() ){
+ vars.push_back( it->first );
+ shared_vars[ it->first ] = false;
+ numSharedVars--;
+ }
+ }
+ }
+ index = index==0 ? (int)(pats.size()-1) : (index-1);
+ }
+ vars.insert( vars.end(), unique_vars.begin(), unique_vars.end() );
+ Debug("smart-multi-trigger") << " Index[" << i << "]: ";
+ for( int i=0; i<(int)vars.size(); i++ ){
+ Debug("smart-multi-trigger") << vars[i] << " ";
+ }
+ Debug("smart-multi-trigger") << std::endl;
+ //make ordered inst match trie
+ InstMatchTrie::ImtIndexOrder* imtio = new InstMatchTrie::ImtIndexOrder;
+ imtio->d_order.insert( imtio->d_order.begin(), vars.begin(), vars.end() );
+ d_children_trie.push_back( InstMatchTrieOrdered( imtio ) );
+ }
+
+}
+
+/** reset instantiation round (call this whenever equivalence classes have changed) */
+void InstMatchGeneratorMulti::resetInstantiationRound( QuantifiersEngine* qe ){
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ d_children[i]->resetInstantiationRound( qe );
+ }
+}
+
+/** reset, eqc is the equivalence class to search in (any if eqc=null) */
+void InstMatchGeneratorMulti::reset( Node eqc, QuantifiersEngine* qe ){
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ d_children[i]->reset( eqc, qe );
+ }
+}
+
+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
+ 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->getTermDatabase()->getInstantiationConstant( d_f, curr_index );
+ if( m.find( curr_ic )==m.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();
+ // 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.set( curr_ic, it->first);
+ processNewInstantiations( qe, mn, addedLemmas, &(it->second), unique_var_tries,
+ trieIndex+1, childIndex, endChildIndex, modEq );
+ }
+ //}
+ }else{
+ //shared and set variable, try to merge
+ Node n = m.get( curr_ic );
+ std::map< Node, InstMatchTrie >::iterator it = tr->d_data.find( n );
+ if( it!=tr->d_data.end() ){
+ processNewInstantiations( qe, m, addedLemmas, &(it->second), unique_var_tries,
+ trieIndex+1, childIndex, endChildIndex, modEq );
+ }
+ if( modEq ){
+ //check modulo equality for other possible instantiations
+ if( qe->getEqualityQuery()->getEngine()->hasTerm( n ) ){
+ eq::EqClassIterator eqc( qe->getEqualityQuery()->getEngine()->getRepresentative( n ),
+ qe->getEqualityQuery()->getEngine() );
+ while( !eqc.isFinished() ){
+ Node en = (*eqc);
+ if( en!=n ){
+ std::map< Node, InstMatchTrie >::iterator itc = tr->d_data.find( en );
+ if( itc!=tr->d_data.end() ){
+ processNewInstantiations( qe, m, addedLemmas, &(itc->second), unique_var_tries,
+ trieIndex+1, childIndex, endChildIndex, modEq );
+ }
+ }
+ ++eqc;
+ }
+ }
+ }
+ }
+ }else{
+ int newChildIndex = (childIndex+1)%(int)d_children.size();
+ processNewInstantiations( qe, m, addedLemmas, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
+ 0, newChildIndex, endChildIndex, modEq );
+ }
+}
+
+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 ){
+ tr = unique_var_tries[uvtIndex].second;
+ trieIndex = unique_var_tries[uvtIndex].first.second;
+ }
+ 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->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.set( curr_ic, it->first);
+ processNewInstantiations2( qe, mn, addedLemmas, unique_var_tries, uvtIndex, &(it->second), trieIndex+1 );
+ }
+ }else{
+ processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, uvtIndex+1 );
+ }
+ }else{
+ //m is an instantiation
+ if( qe->addInstantiation( d_f, m ) ){
+ addedLemmas++;
+ Debug("smart-multi-trigger") << "-> Produced instantiation " << m << std::endl;
+ }
+ }
+}
+
+int InstMatchGeneratorMulti::addTerm( Node f, Node t, QuantifiersEngine* qe ){
+ Assert( options::eagerInstQuant() );
+ int addedLemmas = 0;
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ if( ((InstMatchGenerator*)d_children[i])->d_match_pattern.getOperator()==t.getOperator() ){
+ InstMatch m;
+ //if it produces a match, then process it with the rest
+ if( ((InstMatchGenerator*)d_children[i])->getMatch( t, m, qe ) ){
+ processNewMatch( qe, m, i, addedLemmas );
+ }
+ }
+ }
+ return addedLemmas;
+}
+
+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() ]) );
+ }
+ }else{
+ 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, quantifiers::TermArgTrie* tat ){
+ if( argIndex==(int)d_match_pattern.getNumChildren() ){
+ //m is an instantiation
+ 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, quantifiers::TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
+ Node t = it->first;
+ if( m.get( ic ).isNull() || m.get( ic )==t ){
+ Node prev = m.get( ic );
+ m.set( ic, t);
+ addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
+ m.set( ic, prev);
+ }
+ }
+ }else{
+ Node r = qe->getEqualityQuery()->getRepresentative( d_match_pattern[argIndex] );
+ 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) );
+ }
+ }
+ }
+}
+
+int InstMatchGeneratorSimple::addTerm( Node f, Node t, QuantifiersEngine* qe ){
+ Assert( options::eagerInstQuant() );
+ InstMatch m;
+ for( int i=0; i<(int)t.getNumChildren(); i++ ){
+ if( d_match_pattern[i].getKind()==INST_CONSTANT ){
+ m.set(d_match_pattern[i], t[i]);
+ }else if( !qe->getEqualityQuery()->areEqual( d_match_pattern[i], t[i] ) ){
+ return 0;
+ }
+ }
+ return qe->addInstantiation( f, m ) ? 1 : 0;
+}
--- /dev/null
+/********************* */
+/*! \file inst_match.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 inst match class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANTIFIERS__INST_MATCH_H
+#define __CVC4__THEORY__QUANTIFIERS__INST_MATCH_H
+
+#include "util/hash.h"
+
+#include <ext/hash_set>
+#include <iostream>
+#include <map>
+
+#include "context/cdlist.h"
+#include "theory/quantifiers/candidate_generator.h"
+
+//#define USE_EFFICIENT_E_MATCHING
+
+namespace CVC4 {
+namespace theory {
+
+/** Attribute true for nodes that should not be used for matching */
+struct NoMatchAttributeId {};
+/** use the special for boolean flag */
+typedef expr::Attribute< NoMatchAttributeId,
+ bool,
+ expr::attr::NullCleanupStrategy,
+ true // context dependent
+ > NoMatchAttribute;
+
+// attribute for "contains instantiation constants from"
+struct InstConstantAttributeId {};
+typedef expr::Attribute<InstConstantAttributeId, Node> InstConstantAttribute;
+
+struct InstLevelAttributeId {};
+typedef expr::Attribute<InstLevelAttributeId, uint64_t> InstLevelAttribute;
+
+struct InstVarNumAttributeId {};
+typedef expr::Attribute<InstVarNumAttributeId, uint64_t> InstVarNumAttribute;
+
+// Attribute that tell if a node have been asserted in this branch
+struct AvailableInTermDbId {};
+/** use the special for boolean flag */
+typedef expr::Attribute<AvailableInTermDbId,
+ bool,
+ expr::attr::NullCleanupStrategy,
+ true // context dependent
+ > AvailableInTermDb;
+
+
+class QuantifiersEngine;
+namespace quantifiers{
+ class TermArgTrie;
+}
+
+namespace uf{
+ class InstantiatorTheoryUf;
+ class TheoryUF;
+}/* CVC4::theory::uf namespace */
+
+namespace inst {
+
+class EqualityQuery {
+public:
+ EqualityQuery(){}
+ virtual ~EqualityQuery(){};
+ /** contains term */
+ virtual bool hasTerm( Node a ) = 0;
+ /** get the representative of the equivalence class of a */
+ virtual Node getRepresentative( Node a ) = 0;
+ /** returns true if a and b are equal in the current context */
+ virtual bool areEqual( Node a, Node b ) = 0;
+ /** returns true is a and b are disequal in the current context */
+ virtual bool areDisequal( Node a, Node b ) = 0;
+ /** getInternalRepresentative gets the current best representative in the equivalence class of a, based on some criteria.
+ If cbqi is active, this will return a term in the equivalence class of "a" that does
+ not contain instantiation constants, if such a term exists.
+ */
+ virtual Node getInternalRepresentative( Node a ) = 0;
+ /** get the equality engine associated with this query */
+ virtual eq::EqualityEngine* getEngine() = 0;
+ /** get the equivalence class of a */
+ virtual void getEquivalenceClass( Node a, std::vector< Node >& eqc ) = 0;
+};/* class EqualityQuery */
+
+/** basic class defining an instantiation */
+class InstMatch {
+ /* map from variable to ground terms */
+ std::map< Node, Node > d_map;
+public:
+ InstMatch();
+ InstMatch( InstMatch* m );
+
+ /** set the match of v to m */
+ bool setMatch( EqualityQuery* q, TNode v, TNode m );
+ /* This version tell if the variable has been set */
+ bool setMatch( EqualityQuery* q, TNode v, TNode m, bool & set);
+ /** fill all unfilled values with m */
+ bool add( InstMatch& m );
+ /** if compatible, fill all unfilled values with m and return true
+ return false otherwise */
+ bool merge( EqualityQuery* q, InstMatch& m );
+ /** debug print method */
+ void debugPrint( const char* c );
+ /** make complete */
+ void makeComplete( Node f, QuantifiersEngine* qe );
+ /** make internal: ensure that no term in d_map contains instantiation constants */
+ void makeInternal( QuantifiersEngine* qe );
+ /** make representative */
+ void makeRepresentative( QuantifiersEngine* qe );
+ /** apply rewrite */
+ void applyRewrite();
+ /** compute d_match */
+ void computeTermVec( QuantifiersEngine* qe, const std::vector< Node >& vars, std::vector< Node >& match );
+ /** compute d_match */
+ void computeTermVec( const std::vector< Node >& vars, std::vector< Node >& match );
+ /** clear */
+ void clear(){ d_map.clear(); }
+ /** erase */
+ template<class Iterator>
+ void erase(Iterator begin, Iterator end){
+ for(Iterator i = begin; i != end; ++i){
+ d_map.erase(*i);
+ };
+ }
+ void erase(Node node){ d_map.erase(node); }
+ /** is_empty */
+ bool empty(){ return d_map.empty(); }
+ /** set */
+ void set(TNode var, TNode n){
+ //std::cout << "var.getType() " << var.getType() << "n.getType() " << n.getType() << std::endl ;
+ Assert( !var.isNull() );
+ Assert( n.isNull() ||// For a strange use in inst_match.cpp InstMatchGeneratorSimple::addInstantiations
+ var.getType() == n.getType() );
+ d_map[var] = n;
+ }
+ Node get(TNode var){ return d_map[var]; }
+ size_t size(){ return d_map.size(); }
+ /* iterator */
+ std::map< Node, Node >::iterator begin(){ return d_map.begin(); };
+ std::map< Node, Node >::iterator end(){ return d_map.end(); };
+ std::map< Node, Node >::iterator find(Node var){ return d_map.find(var); };
+ /* Node used for matching the trigger only for mono-trigger (just for
+ efficiency because I need only that) */
+ Node d_matched;
+ /** to stream */
+ inline void toStream(std::ostream& out) const {
+ out << "INST_MATCH( ";
+ for( std::map< Node, Node >::const_iterator it = d_map.begin(); it != d_map.end(); ++it ){
+ if( it != d_map.begin() ){ out << ", "; }
+ out << it->first << " -> " << it->second;
+ }
+ out << " )";
+ }
+};/* class InstMatch */
+
+inline std::ostream& operator<<(std::ostream& out, const InstMatch& m) {
+ m.toStream(out);
+ return out;
+}
+
+/** trie for InstMatch objects */
+class InstMatchTrie {
+public:
+ class ImtIndexOrder {
+ public:
+ std::vector< int > d_order;
+ };/* class InstMatchTrie ImtIndexOrder */
+private:
+ /** add match m for quantifier f starting at index, take into account equalities q, return true if successful */
+ void addInstMatch2( QuantifiersEngine* qe, Node f, InstMatch& m, int index, ImtIndexOrder* imtio );
+ /** exists match */
+ bool existsInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m, bool modEq, int index, ImtIndexOrder* imtio );
+public:
+ /** the data */
+ std::map< Node, InstMatchTrie > d_data;
+public:
+ InstMatchTrie(){}
+ ~InstMatchTrie(){}
+public:
+ /** add match m for quantifier f, take into account equalities if modEq = true,
+ if imtio is non-null, this is the order to add to trie
+ return true if successful
+ */
+ bool addInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m, bool modEq = false, ImtIndexOrder* imtio = NULL );
+};/* class InstMatchTrie */
+
+class InstMatchTrieOrdered {
+private:
+ InstMatchTrie::ImtIndexOrder* d_imtio;
+ InstMatchTrie d_imt;
+public:
+ InstMatchTrieOrdered( InstMatchTrie::ImtIndexOrder* imtio ) : d_imtio( imtio ){}
+ ~InstMatchTrieOrdered(){}
+ /** get ordering */
+ InstMatchTrie::ImtIndexOrder* getOrdering() { return d_imtio; }
+ /** get trie */
+ InstMatchTrie* getTrie() { return &d_imt; }
+public:
+ /** add match m, return true if successful */
+ bool addInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m, bool modEq = false ){
+ return d_imt.addInstMatch( qe, f, m, modEq, d_imtio );
+ }
+};/* class InstMatchTrieOrdered */
+
+/** base class for producing InstMatch objects */
+class IMGenerator {
+public:
+ /** reset instantiation round (call this at beginning of instantiation round) */
+ virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
+ /** reset, eqc is the equivalence class to search in (any if eqc=null) */
+ virtual void reset( Node eqc, QuantifiersEngine* qe ) = 0;
+ /** get the next match. must call reset( eqc ) before this function. */
+ virtual bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) = 0;
+ /** return true if whatever Node is substituted for the variables the
+ 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 ) = 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 */
+
+
+class InstMatchGenerator : public IMGenerator {
+private:
+ /** candidate generator */
+ CandidateGenerator* d_cg;
+ /** policy to use for matching */
+ int d_matchPolicy;
+ /** children generators */
+ std::vector< InstMatchGenerator* > d_children;
+ std::vector< int > d_children_index;
+ /** partial vector */
+ std::vector< InstMatch > d_partial;
+ /** eq class */
+ Node d_eq_class;
+ /** for arithmetic matching */
+ std::map< Node, Node > d_arith_coeffs;
+ /** initialize pattern */
+ void initializePatterns( std::vector< Node >& pats, QuantifiersEngine* qe );
+ void initializePattern( Node pat, QuantifiersEngine* qe );
+public:
+ enum {
+ //options for producing matches
+ MATCH_GEN_DEFAULT = 0,
+ MATCH_GEN_EFFICIENT_E_MATCH, //generate matches via Efficient E-matching for SMT solvers
+ //others (internally used)
+ MATCH_GEN_INTERNAL_ARITHMETIC,
+ MATCH_GEN_INTERNAL_ERROR,
+ };
+private:
+ /** get the next match. must call d_cg->reset( ... ) before using.
+ only valid for use where !d_match_pattern.isNull().
+ */
+ bool getNextMatch2( InstMatch& m, QuantifiersEngine* qe, bool saveMatched = false );
+ /** for arithmetic */
+ bool getMatchArithmetic( Node t, InstMatch& m, QuantifiersEngine* qe );
+public:
+ /** get the match against ground term or formula t.
+ d_match_pattern and t should have the same shape.
+ only valid for use where !d_match_pattern.isNull().
+ */
+ bool getMatch( Node t, InstMatch& m, QuantifiersEngine* qe );
+
+ /** constructors */
+ InstMatchGenerator( Node pat, QuantifiersEngine* qe, int matchOption = 0 );
+ InstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption = 0 );
+ /** destructor */
+ ~InstMatchGenerator(){}
+ /** The pattern we are producing matches for.
+ If null, this is a multi trigger that is merging matches from d_children.
+ */
+ Node d_pattern;
+ /** match pattern */
+ Node d_match_pattern;
+public:
+ /** reset instantiation round (call this whenever equivalence classes have changed) */
+ void resetInstantiationRound( QuantifiersEngine* qe );
+ /** reset, eqc is the equivalence class to search in (any if eqc=null) */
+ void reset( Node eqc, QuantifiersEngine* qe );
+ /** get the next match. must call reset( eqc ) before this function. */
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe );
+ /** return true if whatever Node is substituted for the variables the
+ 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 );
+ /** add ground term t */
+ int addTerm( Node f, Node t, QuantifiersEngine* qe );
+};/* class InstMatchGenerator */
+
+/** smart multi-trigger implementation */
+class InstMatchGeneratorMulti : public IMGenerator {
+private:
+ /** indexed trie */
+ typedef std::pair< std::pair< int, int >, InstMatchTrie* > IndexedTrie;
+ /** 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;
+ /** variable indices contained to pattern nodes */
+ std::map< int, std::vector< Node > > d_var_to_node;
+ /** quantifier to use */
+ Node d_f;
+ /** policy to use for matching */
+ int d_matchPolicy;
+ /** children generators */
+ std::vector< InstMatchGenerator* > d_children;
+ /** inst match tries for each child */
+ std::vector< InstMatchTrieOrdered > d_children_trie;
+ /** calculate matches */
+ void calculateMatches( QuantifiersEngine* qe );
+public:
+ /** constructors */
+ InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption = 0 );
+ /** destructor */
+ ~InstMatchGeneratorMulti(){}
+ /** reset instantiation round (call this whenever equivalence classes have changed) */
+ void resetInstantiationRound( QuantifiersEngine* qe );
+ /** reset, eqc is the equivalence class to search in (any if eqc=null) */
+ void reset( Node eqc, QuantifiersEngine* qe );
+ /** get the next match. must call reset( eqc ) before this function. (not implemented) */
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) { return false; }
+ /** return true if whatever Node is substituted for the variables the
+ 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 );
+ /** add ground term t */
+ int addTerm( Node f, Node t, QuantifiersEngine* qe );
+};/* class InstMatchGeneratorMulti */
+
+/** smart (single)-trigger implementation */
+class InstMatchGeneratorSimple : public IMGenerator {
+private:
+ /** quantifier for match term */
+ Node d_f;
+ /** match term */
+ Node d_match_pattern;
+ /** add instantiations */
+ 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 ){}
+ /** destructor */
+ ~InstMatchGeneratorSimple(){}
+ /** reset instantiation round (call this whenever equivalence classes have changed) */
+ void resetInstantiationRound( QuantifiersEngine* qe ) {}
+ /** reset, eqc is the equivalence class to search in (any if eqc=null) */
+ void reset( Node eqc, QuantifiersEngine* qe ) {}
+ /** get the next match. must call reset( eqc ) before this function. (not implemented) */
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) { return false; }
+ /** return true if whatever Node is substituted for the variables the
+ 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 );
+ /** add ground term t, possibly add instantiations */
+ int addTerm( Node f, Node t, QuantifiersEngine* qe );
+};/* class InstMatchGeneratorSimple */
+
+}/* CVC4::theory::inst namespace */
+
+typedef CVC4::theory::inst::InstMatch InstMatch;
+typedef CVC4::theory::inst::EqualityQuery EqualityQuery;
+
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
+
+#endif /* __CVC4__THEORY__QUANTIFIERS__INST_MATCH_H */
#include "cvc4_private.h"
-#ifndef __CVC4__INSTANTIATION_ENGINE_H
-#define __CVC4__INSTANTIATION_ENGINE_H
+#ifndef __CVC4__THEORY__QUANTIFIERS__INSTANTIATION_ENGINE_H
+#define __CVC4__THEORY__QUANTIFIERS__INSTANTIATION_ENGINE_H
#include "theory/quantifiers_engine.h"
#include "theory/quantifiers/theory_quantifiers.h"
public:
/** get the corresponding counterexample literal for quantified formula node n */
Node getCounterexampleLiteralFor( Node f ) { return d_ce_lit.find( f )==d_ce_lit.end() ? Node::null() : d_ce_lit[ f ]; }
-};
+};/* class InstantiationEngine */
-}
-}
-}
+}/* CVC4::theory::quantifiers namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
-#endif
+#endif /* __CVC4__THEORY__QUANTIFIERS__INSTANTIATION_ENGINE_H */
--- /dev/null
+/********************* */
+/*! \file instantiator_default.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 instantiator_default class
+ **/
+
+#include "theory/quantifiers/instantiator_default.h"
+#include "theory/theory_engine.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+
+InstantiatorDefault::InstantiatorDefault(context::Context* c, QuantifiersEngine* ie, Theory* th) :
+ Instantiator( c, ie, th ) {
+}
+
+void InstantiatorDefault::assertNode( Node assertion ){
+}
+
+void InstantiatorDefault::processResetInstantiationRound( Theory::Effort effort ){
+}
+
+int InstantiatorDefault::process( Node f, Theory::Effort effort, int e ){
+ /*
+ if( e < 4 ){
+ return InstStrategy::STATUS_UNFINISHED;
+ }else if( e == 4 ){
+ Debug("quant-default") << "Process " << f << " : " << std::endl;
+ InstMatch m;
+ for( int j=0; j<(int)d_quantEngine->getNumInstantiationConstants( f ); j++ ){
+ Node i = d_quantEngine->getInstantiationConstant( f, j );
+ Debug("quant-default") << "Getting value for " << i << std::endl;
+ if( d_quantEngine->getTheoryEngine()->theoryOf( i )==getTheory() ){ //if it belongs to this theory
+ Node val = d_th->getValue( i );
+ Debug("quant-default") << "Default Instantiate for " << d_th->getId() << ", setting " << i << " = " << val << std::endl;
+ m.set( i, val);
+ }
+ }
+ d_quantEngine->addInstantiation( f, m );
+ }
+ */
+ return InstStrategy::STATUS_UNKNOWN;
+}
--- /dev/null
+/********************* */
+/*! \file instantiator_default.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 instantiator_default
+ **/
+
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANTIFIERS__INSTANTIATOR_DEFAULT_H
+#define __CVC4__THEORY__QUANTIFIERS__INSTANTIATOR_DEFAULT_H
+
+#include <string>
+#include "theory/quantifiers_engine.h"
+
+namespace CVC4 {
+namespace theory {
+
+class InstantiatorDefault : public Instantiator {
+ friend class QuantifiersEngine;
+protected:
+ /** reset instantiation round */
+ void processResetInstantiationRound(Theory::Effort effort);
+ /** process quantifier */
+ int process( Node f, Theory::Effort effort, int e );
+public:
+ InstantiatorDefault(context::Context* c, QuantifiersEngine* ie, Theory* th);
+ ~InstantiatorDefault() { }
+ /** check function, assertion is asserted to theory */
+ void assertNode( Node assertion );
+ /** identify */
+ std::string identify() const { return std::string("InstantiatorDefault"); }
+};/* class InstantiatorDefault */
+
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
+
+#endif /* __CVC4__THEORY__QUANTIFIERS__INSTANTIATOR_DEFAULT_H */
#include "cvc4_private.h"
-#ifndef __CVC4__QUANTIFIERS_MODEL_BUILDER_H
-#define __CVC4__QUANTIFIERS_MODEL_BUILDER_H
+#ifndef __CVC4__THEORY__QUANTIFIERS__MODEL_BUILDER_H
+#define __CVC4__THEORY__QUANTIFIERS__MODEL_BUILDER_H
#include "theory/quantifiers_engine.h"
#include "theory/model.h"
~Statistics();
};
Statistics d_statistics;
-};
+};/* class ModelEngineBuilder */
-}
-}
-}
+}/* CVC4::theory::quantifiers namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
-#endif
+#endif /* __CVC4__THEORY__QUANTIFIERS__MODEL_BUILDER_H */
#include "cvc4_private.h"
-#ifndef __CVC4__QUANTIFIERS_MODEL_ENGINE_H
-#define __CVC4__QUANTIFIERS_MODEL_ENGINE_H
+#ifndef __CVC4__THEORY__QUANTIFIERS__MODEL_ENGINE_H
+#define __CVC4__THEORY__QUANTIFIERS__MODEL_ENGINE_H
#include "theory/quantifiers_engine.h"
#include "theory/quantifiers/model_builder.h"
~Statistics();
};
Statistics d_statistics;
-};
+};/* class ModelEngine */
-}
-}
-}
+}/* CVC4::theory::quantifiers namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
-#endif
+#endif /* __CVC4__THEORY__QUANTIFIERS__MODEL_ENGINE_H */
#include "cvc4_private.h"
-#ifndef __CVC4__RELEVANT_DOMAIN_H
-#define __CVC4__RELEVANT_DOMAIN_H
+#ifndef __CVC4__THEORY__QUANTIFIERS__RELEVANT_DOMAIN_H
+#define __CVC4__THEORY__QUANTIFIERS__RELEVANT_DOMAIN_H
#include "theory/quantifiers/first_order_model.h"
void compute();
//relevant instantiation domain for each quantifier
std::map< Node, std::vector< RepDomain > > d_quant_inst_domain;
-};
+};/* class RelevantDomain */
-}
-}
-}
+}/* CVC4::theory::quantifiers namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
-#endif
+#endif /* __CVC4__THEORY__QUANTIFIERS__RELEVANT_DOMAIN_H */
#include "cvc4_private.h"
-#ifndef __CVC4__REP_SET_ITERATOR_H
-#define __CVC4__REP_SET_ITERATOR_H
+#ifndef __CVC4__THEORY__QUANTIFIERS__REP_SET_ITERATOR_H
+#define __CVC4__THEORY__QUANTIFIERS__REP_SET_ITERATOR_H
#include "theory/quantifiers_engine.h"
#include "theory/quantifiers/first_order_model.h"
int d_eval_uf_terms;
int d_eval_lits;
int d_eval_lits_unknown;
-};
-
+};/* class RepSetEvaluator */
-}
-}
-}
+}/* CVC4::theory::quantifiers namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
#endif
#include "cvc4_private.h"
-#ifndef __CVC4__QUANTIFIERS_TERM_DATABASE_H
-#define __CVC4__QUANTIFIERS_TERM_DATABASE_H
+#ifndef __CVC4__THEORY__QUANTIFIERS__TERM_DATABASE_H
+#define __CVC4__THEORY__QUANTIFIERS__TERM_DATABASE_H
#include "theory/theory.h"
Node getFreeVariableForInstConstant( Node n );
};/* class TermDb */
-}
-}
-}
+}/* CVC4::theory::quantifiers namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
-#endif
+#endif /* __CVC4__THEORY__QUANTIFIERS__TERM_DATABASE_H */
#include "cvc4_private.h"
-#ifndef __CVC4__INSTANTIATOR_QUANTIFIERS_H
-#define __CVC4__INSTANTIATOR_QUANTIFIERS_H
+#ifndef __CVC4__THEORY__QUANTIFIERS__THEORY_QUANTIFIERS_INSTANTIATOR_H
+#define __CVC4__THEORY__QUANTIFIERS__THEORY_QUANTIFIERS_INSTANTIATOR_H
#include "theory/quantifiers_engine.h"
~Statistics();
};
Statistics d_statistics;
-};/* class InstantiatiorTheoryArith */
+};/* class InstantiatiorTheoryQuantifiers */
-}
-}
-}
+}/* CVC4::theory::quantifiers namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
-#endif
\ No newline at end of file
+#endif /* __CVC4__THEORY__QUANTIFIERS__THEORY_QUANTIFIERS_INSTANTIATOR_H */
--- /dev/null
+/********************* */
+/*! \file trigger.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 trigger class
+ **/
+
+#include "theory/quantifiers/trigger.h"
+#include "theory/theory_engine.h"
+#include "theory/quantifiers_engine.h"
+#include "theory/uf/theory_uf_instantiator.h"
+#include "theory/quantifiers/candidate_generator.h"
+#include "theory/uf/equality_engine.h"
+#include "theory/quantifiers/options.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::inst;
+
+//#define NESTED_PATTERN_SELECTION
+
+Trigger* Trigger::TrTrie::getTrigger2( std::vector< Node >& nodes ){
+ if( nodes.empty() ){
+ return d_tr;
+ }else{
+ Node n = nodes.back();
+ nodes.pop_back();
+ if( d_children.find( n )!=d_children.end() ){
+ return d_children[n]->getTrigger2( nodes );
+ }else{
+ return NULL;
+ }
+ }
+}
+void Trigger::TrTrie::addTrigger2( std::vector< Node >& nodes, Trigger* t ){
+ if( nodes.empty() ){
+ d_tr = t;
+ }else{
+ Node n = nodes.back();
+ nodes.pop_back();
+ if( d_children.find( n )==d_children.end() ){
+ d_children[n] = new TrTrie;
+ }
+ d_children[n]->addTrigger2( nodes, t );
+ }
+}
+
+/** trigger static members */
+std::map< TNode, std::vector< TNode > > Trigger::d_var_contains;
+Trigger::TrTrie Trigger::d_tr_trie;
+
+/** trigger class constructor */
+Trigger::Trigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool smartTriggers ) :
+d_quantEngine( qe ), d_f( f ){
+ d_nodes.insert( d_nodes.begin(), nodes.begin(), nodes.end() );
+ if( smartTriggers ){
+ if( d_nodes.size()==1 ){
+ if( isSimpleTrigger( d_nodes[0] ) ){
+ d_mg = new InstMatchGeneratorSimple( f, d_nodes[0] );
+ }else{
+ d_mg = new InstMatchGenerator( d_nodes[0], qe, matchOption );
+ }
+ }else{
+ d_mg = new InstMatchGeneratorMulti( f, d_nodes, qe, matchOption );
+ }
+ }else{
+ d_mg = new InstMatchGenerator( d_nodes, qe, matchOption );
+ }
+ Debug("trigger") << "Trigger for " << f << ": " << std::endl;
+ for( int i=0; i<(int)d_nodes.size(); i++ ){
+ Debug("trigger") << " " << d_nodes[i] << std::endl;
+ }
+ Debug("trigger") << std::endl;
+ if( d_nodes.size()==1 ){
+ if( isSimpleTrigger( d_nodes[0] ) ){
+ ++(qe->d_statistics.d_triggers);
+ }else{
+ ++(qe->d_statistics.d_simple_triggers);
+ }
+ }else{
+ Debug("multi-trigger") << "Multi-trigger " << (*this) << std::endl;
+ //Notice() << "Multi-trigger for " << f << " : " << std::endl;
+ //Notice() << " " << (*this) << std::endl;
+ ++(qe->d_statistics.d_multi_triggers);
+ }
+ //Notice() << "Trigger : " << (*this) << " for " << f << std::endl;
+ if( options::eagerInstQuant() ){
+ Theory* th_uf = qe->getTheoryEngine()->getTheory( theory::THEORY_UF );
+ uf::InstantiatorTheoryUf* ith = (uf::InstantiatorTheoryUf*)th_uf->getInstantiator();
+ for( int i=0; i<(int)d_nodes.size(); i++ ){
+ ith->registerTrigger( this, d_nodes[i].getOperator() );
+ }
+ }
+}
+void Trigger::computeVarContains( Node n ) {
+ if( d_var_contains.find( n )==d_var_contains.end() ){
+ d_var_contains[n].clear();
+ computeVarContains2( n, n );
+ }
+}
+
+void Trigger::computeVarContains2( Node n, Node parent ){
+ if( n.getKind()==INST_CONSTANT ){
+ if( std::find( d_var_contains[parent].begin(), d_var_contains[parent].end(), n )==d_var_contains[parent].end() ){
+ d_var_contains[parent].push_back( n );
+ }
+ }else{
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ computeVarContains2( n[i], parent );
+ }
+ }
+}
+
+void Trigger::resetInstantiationRound(){
+ d_mg->resetInstantiationRound( d_quantEngine );
+}
+
+void Trigger::reset( Node eqc ){
+ d_mg->reset( eqc, d_quantEngine );
+}
+
+bool Trigger::getNextMatch( InstMatch& m ){
+ bool retVal = d_mg->getNextMatch( m, d_quantEngine );
+ //m.makeInternal( d_quantEngine->getEqualityQuery() );
+ return retVal;
+}
+
+bool Trigger::getMatch( Node t, InstMatch& m ){
+ //FIXME: this assumes d_mg is an inst match generator
+ return ((InstMatchGenerator*)d_mg)->getMatch( t, m, d_quantEngine );
+}
+
+int Trigger::addTerm( Node t ){
+ return d_mg->addTerm( d_f, t, d_quantEngine );
+}
+
+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++ ){
+ Debug("inst-trigger") << d_nodes[i] << " ";
+ }
+ Debug("inst-trigger") << std::endl;
+ }
+ return addedLemmas;
+}
+
+Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool keepAll, int trOption,
+ bool smartTriggers ){
+ std::vector< Node > trNodes;
+ if( !keepAll ){
+ //only take nodes that contribute variables to the trigger when added
+ std::vector< Node > temp;
+ temp.insert( temp.begin(), nodes.begin(), nodes.end() );
+ std::map< Node, bool > vars;
+ std::map< Node, std::vector< Node > > patterns;
+ for( int i=0; i<(int)temp.size(); i++ ){
+ bool foundVar = false;
+ computeVarContains( temp[i] );
+ for( int j=0; j<(int)d_var_contains[ temp[i] ].size(); j++ ){
+ Node v = d_var_contains[ temp[i] ][j];
+ if( v.getAttribute(InstConstantAttribute())==f ){
+ if( vars.find( v )==vars.end() ){
+ vars[ v ] = true;
+ foundVar = true;
+ }
+ }
+ }
+ if( foundVar ){
+ trNodes.push_back( temp[i] );
+ for( int j=0; j<(int)d_var_contains[ temp[i] ].size(); j++ ){
+ Node v = d_var_contains[ temp[i] ][j];
+ patterns[ v ].push_back( temp[i] );
+ }
+ }
+ }
+ //now, minimalize the trigger
+ for( int i=0; i<(int)trNodes.size(); i++ ){
+ bool keepPattern = false;
+ Node n = trNodes[i];
+ for( int j=0; j<(int)d_var_contains[ n ].size(); j++ ){
+ Node v = d_var_contains[ n ][j];
+ if( patterns[v].size()==1 ){
+ keepPattern = true;
+ break;
+ }
+ }
+ if( !keepPattern ){
+ //remove from pattern vector
+ for( int j=0; j<(int)d_var_contains[ n ].size(); j++ ){
+ Node v = d_var_contains[ n ][j];
+ for( int k=0; k<(int)patterns[v].size(); k++ ){
+ if( patterns[v][k]==n ){
+ patterns[v].erase( patterns[v].begin() + k, patterns[v].begin() + k + 1 );
+ break;
+ }
+ }
+ }
+ //remove from trigger nodes
+ trNodes.erase( trNodes.begin() + i, trNodes.begin() + i + 1 );
+ i--;
+ }
+ }
+ }else{
+ trNodes.insert( trNodes.begin(), nodes.begin(), nodes.end() );
+ }
+
+ //check for duplicate?
+ if( trOption==TR_MAKE_NEW ){
+ //static int trNew = 0;
+ //static int trOld = 0;
+ //Trigger* t = d_tr_trie.getTrigger( trNodes );
+ //if( t ){
+ // trOld++;
+ //}else{
+ // trNew++;
+ //}
+ //if( (trNew+trOld)%100==0 ){
+ // Notice() << "Trigger new old = " << trNew << " " << trOld << std::endl;
+ //}
+ }else{
+ Trigger* t = d_tr_trie.getTrigger( trNodes );
+ if( t ){
+ if( trOption==TR_GET_OLD ){
+ //just return old trigger
+ return t;
+ }else{
+ return NULL;
+ }
+ }
+ }
+ Trigger* t = new Trigger( qe, f, trNodes, matchOption, smartTriggers );
+ d_tr_trie.addTrigger( trNodes, t );
+ return t;
+}
+Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, Node n, int matchOption, bool keepAll, int trOption, bool smartTriggers ){
+ std::vector< Node > nodes;
+ nodes.push_back( n );
+ return mkTrigger( qe, f, nodes, matchOption, keepAll, trOption, smartTriggers );
+}
+
+bool Trigger::isUsableTrigger( std::vector< Node >& nodes, Node f ){
+ for( int i=0; i<(int)nodes.size(); i++ ){
+ if( !isUsableTrigger( nodes[i], f ) ){
+ return false;
+ }
+ }
+ return true;
+}
+
+bool Trigger::isUsable( Node n, Node f ){
+ if( n.getAttribute(InstConstantAttribute())==f ){
+ if( !isAtomicTrigger( n ) && n.getKind()!=INST_CONSTANT ){
+ std::map< Node, Node > coeffs;
+ return getPatternArithmetic( f, n, coeffs );
+ }else{
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( !isUsable( n[i], f ) ){
+ return false;
+ }
+ }
+ return true;
+ }
+ }else{
+ return true;
+ }
+}
+
+bool Trigger::isUsableTrigger( Node n, Node f ){
+ //return n.getAttribute(InstConstantAttribute())==f && n.getKind()==APPLY_UF;
+ return n.getAttribute(InstConstantAttribute())==f && isAtomicTrigger( n ) && isUsable( n, f );
+}
+
+bool Trigger::isAtomicTrigger( Node n ){
+ return n.getKind()==APPLY_UF || n.getKind()==SELECT || n.getKind()==STORE ||
+ n.getKind()==APPLY_CONSTRUCTOR || n.getKind()==APPLY_SELECTOR || n.getKind()==APPLY_TESTER;
+}
+bool Trigger::isSimpleTrigger( Node n ){
+ if( isAtomicTrigger( n ) ){
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( n[i].getKind()!=INST_CONSTANT && n[i].hasAttribute(InstConstantAttribute()) ){
+ return false;
+ }
+ }
+ return true;
+ }else{
+ return false;
+ }
+}
+
+/** filter all nodes that have instances */
+void Trigger::filterInstances( std::vector< Node >& nodes ){
+ std::vector< bool > active;
+ active.resize( nodes.size(), true );
+ for( int i=0; i<(int)nodes.size(); i++ ){
+ for( int j=i+1; j<(int)nodes.size(); j++ ){
+ if( active[i] && active[j] ){
+ int result = isInstanceOf( nodes[i], nodes[j] );
+ if( result==1 ){
+ active[j] = false;
+ }else if( result==-1 ){
+ active[i] = false;
+ }
+ }
+ }
+ }
+ std::vector< Node > temp;
+ for( int i=0; i<(int)nodes.size(); i++ ){
+ if( active[i] ){
+ temp.push_back( nodes[i] );
+ }
+ }
+ nodes.clear();
+ nodes.insert( nodes.begin(), temp.begin(), temp.end() );
+}
+
+
+bool Trigger::collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt ){
+ if( patMap.find( n )==patMap.end() ){
+ patMap[ n ] = false;
+ if( tstrt==TS_MIN_TRIGGER ){
+ if( n.getKind()==FORALL ){
+#ifdef NESTED_PATTERN_SELECTION
+ //return collectPatTerms2( qe, f, qe->getOrCreateCounterexampleBody( n ), patMap, tstrt );
+ return collectPatTerms2( qe, f, qe->getBoundBody( n ), patMap, tstrt );
+#else
+ return false;
+#endif
+ }else{
+ bool retVal = false;
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( collectPatTerms2( qe, f, n[i], patMap, tstrt ) ){
+ retVal = true;
+ }
+ }
+ if( retVal ){
+ return true;
+ }else if( isUsableTrigger( n, f ) ){
+ patMap[ n ] = true;
+ return true;
+ }else{
+ return false;
+ }
+ }
+ }else{
+ bool retVal = false;
+ if( isUsableTrigger( n, f ) ){
+ patMap[ n ] = true;
+ if( tstrt==TS_MAX_TRIGGER ){
+ return true;
+ }else{
+ retVal = true;
+ }
+ }
+ if( n.getKind()==FORALL ){
+#ifdef NESTED_PATTERN_SELECTION
+ //if( collectPatTerms2( qe, f, qe->getOrCreateCounterexampleBody( n ), patMap, tstrt ) ){
+ // retVal = true;
+ //}
+ if( collectPatTerms2( qe, f, qe->getBoundBody( n ), patMap, tstrt ) ){
+ retVal = true;
+ }
+#endif
+ }else{
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( collectPatTerms2( qe, f, n[i], patMap, tstrt ) ){
+ retVal = true;
+ }
+ }
+ }
+ return retVal;
+ }
+ }else{
+ return patMap[ n ];
+ }
+}
+
+void Trigger::collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, bool filterInst ){
+ std::map< Node, bool > patMap;
+ if( filterInst ){
+ //immediately do not consider any term t for which another term is an instance of t
+ std::vector< Node > patTerms2;
+ collectPatTerms( qe, f, n, patTerms2, TS_ALL, false );
+ std::vector< Node > temp;
+ temp.insert( temp.begin(), patTerms2.begin(), patTerms2.end() );
+ filterInstances( temp );
+ if( temp.size()!=patTerms2.size() ){
+ Debug("trigger-filter-instance") << "Filtered an instance: " << std::endl;
+ Debug("trigger-filter-instance") << "Old: ";
+ for( int i=0; i<(int)patTerms2.size(); i++ ){
+ Debug("trigger-filter-instance") << patTerms2[i] << " ";
+ }
+ Debug("trigger-filter-instance") << std::endl << "New: ";
+ for( int i=0; i<(int)temp.size(); i++ ){
+ Debug("trigger-filter-instance") << temp[i] << " ";
+ }
+ Debug("trigger-filter-instance") << std::endl;
+ }
+ if( tstrt==TS_ALL ){
+ patTerms.insert( patTerms.begin(), temp.begin(), temp.end() );
+ return;
+ }else{
+ //do not consider terms that have instances
+ for( int i=0; i<(int)patTerms2.size(); i++ ){
+ if( std::find( temp.begin(), temp.end(), patTerms2[i] )==temp.end() ){
+ patMap[ patTerms2[i] ] = false;
+ }
+ }
+ }
+ }
+ collectPatTerms2( qe, f, n, patMap, tstrt );
+ for( std::map< Node, bool >::iterator it = patMap.begin(); it != patMap.end(); ++it ){
+ if( it->second ){
+ patTerms.push_back( it->first );
+ }
+ }
+}
+
+/** is n1 an instance of n2 or vice versa? */
+int Trigger::isInstanceOf( Node n1, Node n2 ){
+ if( n1==n2 ){
+ return 1;
+ }else if( n1.getKind()==n2.getKind() ){
+ if( n1.getKind()==APPLY_UF ){
+ if( n1.getOperator()==n2.getOperator() ){
+ int result = 0;
+ for( int i=0; i<(int)n1.getNumChildren(); i++ ){
+ if( n1[i]!=n2[i] ){
+ int cResult = isInstanceOf( n1[i], n2[i] );
+ if( cResult==0 ){
+ return 0;
+ }else if( cResult!=result ){
+ if( result!=0 ){
+ return 0;
+ }else{
+ result = cResult;
+ }
+ }
+ }
+ }
+ return result;
+ }
+ }
+ return 0;
+ }else if( n2.getKind()==INST_CONSTANT ){
+ computeVarContains( n1 );
+ //if( std::find( d_var_contains[ n1 ].begin(), d_var_contains[ n1 ].end(), n2 )!=d_var_contains[ n1 ].end() ){
+ // return 1;
+ //}
+ if( d_var_contains[ n1 ].size()==1 && d_var_contains[ n1 ][ 0 ]==n2 ){
+ return 1;
+ }
+ }else if( n1.getKind()==INST_CONSTANT ){
+ computeVarContains( n2 );
+ //if( std::find( d_var_contains[ n2 ].begin(), d_var_contains[ n2 ].end(), n1 )!=d_var_contains[ n2 ].end() ){
+ // return -1;
+ //}
+ if( d_var_contains[ n2 ].size()==1 && d_var_contains[ n2 ][ 0 ]==n1 ){
+ return 1;
+ }
+ }
+ return 0;
+}
+
+bool Trigger::isVariableSubsume( Node n1, Node n2 ){
+ if( n1==n2 ){
+ return true;
+ }else{
+ //Notice() << "is variable subsume ? " << n1 << " " << n2 << std::endl;
+ computeVarContains( n1 );
+ computeVarContains( n2 );
+ for( int i=0; i<(int)d_var_contains[n2].size(); i++ ){
+ if( std::find( d_var_contains[n1].begin(), d_var_contains[n1].end(), d_var_contains[n2][i] )==d_var_contains[n1].end() ){
+ //Notice() << "no" << std::endl;
+ return false;
+ }
+ }
+ //Notice() << "yes" << std::endl;
+ return true;
+ }
+}
+
+void Trigger::getVarContains( Node f, std::vector< Node >& pats, std::map< Node, std::vector< Node > >& varContains ){
+ for( int i=0; i<(int)pats.size(); i++ ){
+ computeVarContains( pats[i] );
+ varContains[ pats[i] ].clear();
+ for( int j=0; j<(int)d_var_contains[pats[i]].size(); j++ ){
+ if( d_var_contains[pats[i]][j].getAttribute(InstConstantAttribute())==f ){
+ varContains[ pats[i] ].push_back( d_var_contains[pats[i]][j] );
+ }
+ }
+ }
+}
+
+void Trigger::getVarContainsNode( Node f, Node n, std::vector< Node >& varContains ){
+ computeVarContains( n );
+ for( int j=0; j<(int)d_var_contains[n].size(); j++ ){
+ if( d_var_contains[n][j].getAttribute(InstConstantAttribute())==f ){
+ varContains.push_back( d_var_contains[n][j] );
+ }
+ }
+}
+
+bool Trigger::getPatternArithmetic( Node f, Node n, std::map< Node, Node >& coeffs ){
+ if( n.getKind()==PLUS ){
+ Assert( coeffs.empty() );
+ NodeBuilder<> t(kind::PLUS);
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( n[i].hasAttribute(InstConstantAttribute()) ){
+ if( n[i].getKind()==INST_CONSTANT ){
+ if( n[i].getAttribute(InstConstantAttribute())==f ){
+ coeffs[ n[i] ] = Node::null();
+ }else{
+ coeffs.clear();
+ return false;
+ }
+ }else if( !getPatternArithmetic( f, n[i], coeffs ) ){
+ coeffs.clear();
+ return false;
+ }
+ }else{
+ t << n[i];
+ }
+ }
+ if( t.getNumChildren()==0 ){
+ coeffs[ Node::null() ] = NodeManager::currentNM()->mkConst( Rational(0) );
+ }else if( t.getNumChildren()==1 ){
+ coeffs[ Node::null() ] = t.getChild( 0 );
+ }else{
+ coeffs[ Node::null() ] = t;
+ }
+ return true;
+ }else if( n.getKind()==MULT ){
+ if( n[0].getKind()==INST_CONSTANT && n[0].getAttribute(InstConstantAttribute())==f ){
+ Assert( !n[1].hasAttribute(InstConstantAttribute()) );
+ coeffs[ n[0] ] = n[1];
+ return true;
+ }else if( n[1].getKind()==INST_CONSTANT && n[1].getAttribute(InstConstantAttribute())==f ){
+ Assert( !n[0].hasAttribute(InstConstantAttribute()) );
+ coeffs[ n[1] ] = n[0];
+ return true;
+ }
+ }
+ return false;
+}
--- /dev/null
+/********************* */
+/*! \file trigger.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 trigger class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANTIFIERS__TRIGGER_H
+#define __CVC4__THEORY__QUANTIFIERS__TRIGGER_H
+
+#include "theory/quantifiers/inst_match.h"
+
+namespace CVC4 {
+namespace theory {
+namespace inst {
+
+//a collect of nodes representing a trigger
+class Trigger {
+private:
+ /** computation of variable contains */
+ static std::map< TNode, std::vector< TNode > > d_var_contains;
+ static void computeVarContains( Node n );
+ static void computeVarContains2( Node n, Node parent );
+private:
+ /** the quantifiers engine */
+ QuantifiersEngine* d_quantEngine;
+ /** the quantifier this trigger is for */
+ Node d_f;
+ /** match generators */
+ IMGenerator* d_mg;
+private:
+ /** a trie of triggers */
+ class TrTrie {
+ private:
+ Trigger* getTrigger2( std::vector< Node >& nodes );
+ void addTrigger2( std::vector< Node >& nodes, Trigger* t );
+ public:
+ TrTrie() : d_tr( NULL ){}
+ Trigger* d_tr;
+ std::map< TNode, TrTrie* > d_children;
+ Trigger* getTrigger( std::vector< Node >& nodes ){
+ std::vector< Node > temp;
+ temp.insert( temp.begin(), nodes.begin(), nodes.end() );
+ std::sort( temp.begin(), temp.end() );
+ return getTrigger2( temp );
+ }
+ void addTrigger( std::vector< Node >& nodes, Trigger* t ){
+ std::vector< Node > temp;
+ temp.insert( temp.begin(), nodes.begin(), nodes.end() );
+ std::sort( temp.begin(), temp.end() );
+ return addTrigger2( temp, t );
+ }
+ };/* class Trigger::TrTrie */
+ /** all triggers will be stored in this trie */
+ static TrTrie d_tr_trie;
+private:
+ /** trigger constructor */
+ Trigger( QuantifiersEngine* ie, Node f, std::vector< Node >& nodes, int matchOption = 0, bool smartTriggers = false );
+public:
+ ~Trigger(){}
+public:
+ std::vector< Node > d_nodes;
+public:
+ void debugPrint( const char* c );
+ IMGenerator* getGenerator() { return d_mg; }
+public:
+ /** reset instantiation round (call this whenever equivalence classes have changed) */
+ void resetInstantiationRound();
+ /** reset, eqc is the equivalence class to search in (search in any if eqc=null) */
+ void reset( Node eqc );
+ /** get next match. must call reset( eqc ) once before this function. */
+ bool getNextMatch( InstMatch& m );
+ /** get the match against ground term or formula t.
+ the trigger and t should have the same shape.
+ Currently the trigger should not be a multi-trigger.
+ */
+ bool getMatch( Node t, InstMatch& m);
+ /** add ground term t, called when t is added to the TermDb */
+ int addTerm( Node t );
+ /** return true if whatever Node is subsituted for the variables the
+ given Node can't match the pattern */
+ bool nonunifiable( TNode t, const std::vector<Node> & vars){
+ return d_mg->nonunifiable(t,vars);
+ }
+ /** return whether this is a multi-trigger */
+ bool isMultiTrigger() { return d_nodes.size()>1; }
+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 );
+ /** mkTrigger method
+ ie : quantifier engine;
+ f : forall something ....
+ nodes : (multi-)trigger
+ matchOption : which policy to use for creating matches (one of InstMatchGenerator::MATCH_GEN_* )
+ keepAll: don't remove unneeded patterns;
+ trOption : policy for dealing with triggers that already existed (see below)
+ */
+ enum{
+ TR_MAKE_NEW, //make new trigger even if it already may exist
+ TR_GET_OLD, //return a previous trigger if it had already been created
+ TR_RETURN_NULL //return null if a duplicate is found
+ };
+ static Trigger* mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes,
+ int matchOption = 0, bool keepAll = true, int trOption = TR_MAKE_NEW,
+ bool smartTriggers = false );
+ static Trigger* mkTrigger( QuantifiersEngine* qe, Node f, Node n,
+ int matchOption = 0, bool keepAll = true, int trOption = TR_MAKE_NEW,
+ bool smartTriggers = false );
+private:
+ /** is subterm of trigger usable */
+ static bool isUsable( Node n, Node f );
+ /** collect all APPLY_UF pattern terms for f in n */
+ static bool collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt );
+public:
+ //different strategies for choosing trigger terms
+ enum {
+ TS_MAX_TRIGGER = 0,
+ TS_MIN_TRIGGER,
+ TS_ALL,
+ };
+ static void collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, bool filterInst = false );
+public:
+ /** is usable trigger */
+ static bool isUsableTrigger( std::vector< Node >& nodes, Node f );
+ static bool isUsableTrigger( Node n, Node f );
+ static bool isAtomicTrigger( Node n );
+ static bool isSimpleTrigger( Node n );
+ /** filter all nodes that have instances */
+ static void filterInstances( std::vector< Node >& nodes );
+ /** -1: n1 is an instance of n2, 1: n1 is an instance of n2 */
+ static int isInstanceOf( Node n1, Node n2 );
+ /** variables subsume, return true if n1 contains all free variables in n2 */
+ static bool isVariableSubsume( Node n1, Node n2 );
+ /** get var contains */
+ static void getVarContains( Node f, std::vector< Node >& pats, std::map< Node, std::vector< Node > >& varContains );
+ static void getVarContainsNode( Node f, Node n, std::vector< Node >& varContains );
+ /** get pattern arithmetic */
+ static bool getPatternArithmetic( Node f, Node n, std::map< Node, Node >& coeffs );
+
+ inline void toStream(std::ostream& out) const {
+ out << "TRIGGER( ";
+ for( int i=0; i<(int)d_nodes.size(); i++ ){
+ if( i>0 ){ out << ", "; }
+ out << d_nodes[i];
+ }
+ out << " )";
+ }
+};
+
+inline std::ostream& operator<<(std::ostream& out, const Trigger & tr) {
+ tr.toStream(out);
+ return out;
+}
+
+}/* CVC4::theory::inst namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
+
+#endif /* __CVC4__THEORY__QUANTIFIERS__TRIGGER_H */
#include "theory/quantifiers/instantiation_engine.h"
#include "theory/quantifiers/first_order_model.h"
#include "theory/quantifiers/term_database.h"
-#include "theory/rr_candidate_generator.h"
+#include "theory/rewriterules/rr_candidate_generator.h"
using namespace std;
using namespace CVC4;
// if(eq == NULL) return getInstantiator(id)->getRRCanGenClass();
// else return eq;
return getRRCanGenClass();
-}
\ No newline at end of file
+}
#include "theory/theory.h"
#include "util/hash.h"
-#include "theory/inst_match.h"
-#include "theory/rr_inst_match.h"
+#include "theory/quantifiers/inst_match.h"
+#include "theory/rewriterules/rr_inst_match.h"
#include "util/stats.h"
theory_rewriterules_rewriter.h \
theory_rewriterules_type_rules.h \
theory_rewriterules_preprocess.h \
- theory_rewriterules_params.h
+ theory_rewriterules_params.h \
+ rr_inst_match.h \
+ rr_inst_match_impl.h \
+ rr_inst_match.cpp \
+ rr_trigger.h \
+ rr_trigger.cpp \
+ rr_candidate_generator.h \
+ rr_candidate_generator.cpp
EXTRA_DIST = \
kinds
--- /dev/null
+/********************* */
+/*! \file rr_candidate_generator.cpp
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: bobot
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Implementation of rr candidate generator class
+ **/
+
+#include "theory/rewriterules/rr_candidate_generator.h"
+#include "theory/theory_engine.h"
+#include "theory/uf/theory_uf.h"
+#include "theory/quantifiers/term_database.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::rrinst;
+
+GenericCandidateGeneratorClasses::GenericCandidateGeneratorClasses(QuantifiersEngine * qe){
+ for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+ if(qe->getInstantiator(i) != NULL)
+ d_can_gen[i] = qe->getInstantiator(i)->getRRCanGenClasses();
+ else d_can_gen[i] = NULL;
+ }
+}
+
+GenericCandidateGeneratorClasses::~GenericCandidateGeneratorClasses(){
+ for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+ delete(d_can_gen[i]);
+ }
+}
+
+void GenericCandidateGeneratorClasses::resetInstantiationRound(){
+ for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+ if(d_can_gen[i] != NULL) d_can_gen[i]->resetInstantiationRound();
+ }
+ d_can_gen_id=THEORY_FIRST;
+}
+
+void GenericCandidateGeneratorClasses::reset(TNode eqc){
+ Assert(eqc.isNull());
+ for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+ if(d_can_gen[i] != NULL) d_can_gen[i]->reset(eqc);
+ }
+ d_can_gen_id=THEORY_FIRST;
+ lookForNextTheory();
+}
+
+TNode GenericCandidateGeneratorClasses::getNextCandidate(){
+ Assert(THEORY_FIRST <= d_can_gen_id && d_can_gen_id <= THEORY_LAST);
+ /** No more */
+ if(d_can_gen_id == THEORY_LAST) return TNode::null();
+ /** Try with this theory */
+ TNode cand = d_can_gen[d_can_gen_id]->getNextCandidate();
+ if( !cand.isNull() ) return cand;
+ lookForNextTheory();
+ return getNextCandidate();
+}
+
+void GenericCandidateGeneratorClasses::lookForNextTheory(){
+ do{ /* look for the next available generator */
+ ++d_can_gen_id;
+ } while( d_can_gen_id < THEORY_LAST && d_can_gen[d_can_gen_id] == NULL);
+}
+
+GenericCandidateGeneratorClass::GenericCandidateGeneratorClass(QuantifiersEngine * qe): d_qe(qe) {
+ for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+ if(d_qe->getInstantiator(i) != NULL)
+ d_can_gen[i] = d_qe->getInstantiator(i)->getRRCanGenClass();
+ else d_can_gen[i] = NULL;
+ }
+}
+
+GenericCandidateGeneratorClass::~GenericCandidateGeneratorClass(){
+ for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+ delete(d_can_gen[i]);
+ }
+}
+
+void GenericCandidateGeneratorClass::resetInstantiationRound(){
+ for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+ if(d_can_gen[i] != NULL) d_can_gen[i]->resetInstantiationRound();
+ }
+ d_can_gen_id=THEORY_FIRST;
+}
+
+void GenericCandidateGeneratorClass::reset(TNode eqc){
+ for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
+ if(d_can_gen[i] != NULL) d_can_gen[i]->reset(eqc);
+ }
+ d_can_gen_id=THEORY_FIRST;
+ d_node = eqc;
+ lookForNextTheory();
+}
+
+TNode GenericCandidateGeneratorClass::getNextCandidate(){
+ Assert(THEORY_FIRST <= d_can_gen_id && d_can_gen_id <= THEORY_LAST);
+ /** No more */
+ if(d_can_gen_id == THEORY_LAST) return TNode::null();
+ /** Try with this theory */
+ TNode cand = d_can_gen[d_can_gen_id]->getNextCandidate();
+ if( !cand.isNull() ) return cand;
+ lookForNextTheory();
+ return getNextCandidate();
+}
+
+void GenericCandidateGeneratorClass::lookForNextTheory(){
+ do{ /* look for the next available generator, where the element is */
+ ++d_can_gen_id;
+ } while(
+ d_can_gen_id < THEORY_LAST &&
+ (d_can_gen[d_can_gen_id] == NULL ||
+ !d_qe->getInstantiator( d_can_gen_id )->hasTerm( d_node ))
+ );
+}
--- /dev/null
+/********************* */
+/*! \file rr_candidate_generator.h
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: bobot
+ ** Minor contributors (to current version): mdeters
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief rr candidate generator
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__REWRITERULES__RR_CANDIDATE_GENERATOR_H
+#define __CVC4__THEORY__REWRITERULES__RR_CANDIDATE_GENERATOR_H
+
+#include "theory/quantifiers_engine.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/rewriterules/rr_inst_match.h"
+
+using namespace CVC4::theory::quantifiers;
+
+namespace CVC4 {
+namespace theory {
+namespace eq {
+
+namespace rrinst{
+typedef CVC4::theory::rrinst::CandidateGenerator CandidateGenerator;
+
+//New CandidateGenerator. They have a simpler semantic than the old one
+
+// Just iterate amoung the equivalence classes
+// node::Null() must be given to reset
+class CandidateGeneratorTheoryEeClasses : public CandidateGenerator{
+private:
+ //the equality classes iterator
+ eq::EqClassesIterator d_eq;
+ //equalityengine pointer
+ EqualityEngine* d_ee;
+public:
+ CandidateGeneratorTheoryEeClasses( EqualityEngine * ee): d_ee( ee ){}
+ ~CandidateGeneratorTheoryEeClasses(){}
+ void resetInstantiationRound(){};
+ void reset( TNode eqc ){
+ Assert(eqc.isNull());
+ d_eq = eq::EqClassesIterator( d_ee );
+ }; //* the argument is not used
+ TNode getNextCandidate(){
+ if( !d_eq.isFinished() ) return (*(d_eq++));
+ else return Node::null();
+ };
+};
+
+// Just iterate amoung the equivalence class of the given node
+// node::Null() *can't* be given to reset
+class CandidateGeneratorTheoryEeClass : public CandidateGenerator{
+private:
+ //instantiator pointer
+ EqualityEngine* d_ee;
+ //the equality class iterator
+ eq::EqClassIterator d_eqc;
+ /* For the case where the given term doesn't exists in uf */
+ Node d_retNode;
+public:
+ CandidateGeneratorTheoryEeClass( EqualityEngine* ee): d_ee( ee ){}
+ ~CandidateGeneratorTheoryEeClass(){}
+ void resetInstantiationRound(){};
+ void reset( TNode eqc ){
+ Assert(!eqc.isNull());
+ if( d_ee->hasTerm( eqc ) ){
+ /* eqc is in uf */
+ eqc = d_ee->getRepresentative( eqc );
+ d_eqc = eq::EqClassIterator( eqc, d_ee );
+ d_retNode = Node::null();
+ }else{
+ /* If eqc if not a term known by uf, it is the only one in its
+ equivalence class. So we will return only it */
+ d_retNode = eqc;
+ d_eqc = eq::EqClassIterator();
+ }
+ }; //* the argument is not used
+ TNode getNextCandidate(){
+ if(d_retNode.isNull()){
+ if( !d_eqc.isFinished() ) return (*(d_eqc++));
+ else return Node::null();
+ }else{
+ /* the case where eqc not in uf */
+ Node ret = d_retNode;
+ d_retNode = Node::null(); /* d_eqc.isFinished() must be true */
+ return ret;
+ }
+ };
+};
+
+
+} /* namespace rrinst */
+} /* namespace eq */
+
+namespace uf{
+namespace rrinst {
+
+typedef CVC4::theory::rrinst::CandidateGenerator CandidateGenerator;
+
+class CandidateGeneratorTheoryUfOp : public CandidateGenerator{
+private:
+ Node d_op;
+ //instantiator pointer
+ TermDb* d_tdb;
+ // Since new term can appears we restrict ourself to the one that
+ // exists at resetInstantiationRound
+ size_t d_term_iter_limit;
+ size_t d_term_iter;
+public:
+ CandidateGeneratorTheoryUfOp(Node op, TermDb* tdb): d_op(op), d_tdb( tdb ){}
+ ~CandidateGeneratorTheoryUfOp(){}
+ void resetInstantiationRound(){
+ d_term_iter_limit = d_tdb->d_op_map[d_op].size();
+ };
+ void reset( TNode eqc ){
+ Assert(eqc.isNull());
+ d_term_iter = 0;
+ }; //* the argument is not used
+ TNode getNextCandidate(){
+ if( d_term_iter<d_term_iter_limit ){
+ TNode n = d_tdb->d_op_map[d_op][d_term_iter];
+ ++d_term_iter;
+ return n;
+ } else return Node::null();
+ };
+};
+
+class CandidateGeneratorTheoryUfType : public CandidateGenerator{
+private:
+ TypeNode d_type;
+ //instantiator pointer
+ TermDb* d_tdb;
+ // Since new term can appears we restrict ourself to the one that
+ // exists at resetInstantiationRound
+ size_t d_term_iter_limit;
+ size_t d_term_iter;
+public:
+ CandidateGeneratorTheoryUfType(TypeNode type, TermDb* tdb): d_type(type), d_tdb( tdb ){}
+ ~CandidateGeneratorTheoryUfType(){}
+ void resetInstantiationRound(){
+ d_term_iter_limit = d_tdb->d_type_map[d_type].size();
+ };
+ void reset( TNode eqc ){
+ Assert(eqc.isNull());
+ d_term_iter = 0;
+ }; //* the argument is not used
+ TNode getNextCandidate(){
+ if( d_term_iter<d_term_iter_limit ){
+ TNode n = d_tdb->d_type_map[d_type][d_term_iter];
+ ++d_term_iter;
+ return n;
+ } else return Node::null();
+ };
+};
+
+} /* namespace rrinst */
+} /* namespace uf */
+
+class GenericCandidateGeneratorClasses: public rrinst::CandidateGenerator{
+
+ /** The candidate generators */
+ rrinst::CandidateGenerator* d_can_gen[theory::THEORY_LAST];
+ /** The current theory which candidategenerator is used */
+ TheoryId d_can_gen_id;
+
+public:
+ GenericCandidateGeneratorClasses(QuantifiersEngine * qe);
+ ~GenericCandidateGeneratorClasses();
+
+ void resetInstantiationRound();
+ void reset(TNode eqc);
+ TNode getNextCandidate();
+ void lookForNextTheory();
+};
+
+class GenericCandidateGeneratorClass: public rrinst::CandidateGenerator{
+
+ /** The candidate generators */
+ rrinst::CandidateGenerator* d_can_gen[theory::THEORY_LAST];
+ /** The current theory which candidategenerator is used */
+ TheoryId d_can_gen_id;
+ /** current node to look for equivalence class */
+ Node d_node;
+ /** QuantifierEngine */
+ QuantifiersEngine* d_qe;
+
+public:
+ GenericCandidateGeneratorClass(QuantifiersEngine * qe);
+ ~GenericCandidateGeneratorClass();
+ void resetInstantiationRound();
+
+ void reset(TNode eqc);
+ TNode getNextCandidate();
+ void lookForNextTheory();
+};
+
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
+
+#endif /* __CVC4__THEORY__REWRITERULES__RR_CANDIDATE_GENERATOR_H */
--- /dev/null
+/********************* */
+/*! \file rr_inst_match.cpp
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: bobot
+ ** Minor contributors (to current version): mdeters
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Implementation of inst match class
+ **/
+
+#include "theory/quantifiers/inst_match.h"
+#include "theory/theory_engine.h"
+#include "theory/quantifiers_engine.h"
+#include "theory/uf/theory_uf_instantiator.h"
+#include "theory/uf/equality_engine.h"
+#include "theory/arrays/theory_arrays.h"
+#include "theory/datatypes/theory_datatypes.h"
+#include "theory/rewriterules/rr_inst_match.h"
+#include "theory/rewriterules/rr_trigger.h"
+#include "theory/rewriterules/rr_inst_match_impl.h"
+#include "theory/rewriterules/rr_candidate_generator.h"
+
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::rrinst;
+using namespace CVC4::theory::uf::rrinst;
+using namespace CVC4::theory::eq::rrinst;
+
+namespace CVC4{
+namespace theory{
+namespace rrinst{
+
+typedef CVC4::theory::inst::InstMatch InstMatch;
+typedef CVC4::theory::inst::CandidateGeneratorQueue CandidateGeneratorQueue;
+
+template<bool modEq>
+class InstMatchTrie2Pairs
+{
+ typename std::vector< std::vector < typename InstMatchTrie2Gen<modEq>::Tree > > d_data;
+ InstMatchTrie2Gen<modEq> d_backtrack;
+public:
+ InstMatchTrie2Pairs(context::Context* c, QuantifiersEngine* q, size_t n):
+ d_backtrack(c,q) {
+ // resize to a triangle
+ //
+ // | *
+ // | * *
+ // | * * *
+ // | -----> i
+ d_data.resize(n);
+ for(size_t i=0; i < n; ++i){
+ d_data[i].resize(i+1,typename InstMatchTrie2Gen<modEq>::Tree(0));
+ }
+ };
+ InstMatchTrie2Pairs(const InstMatchTrie2Pairs &) CVC4_UNDEFINED;
+ const InstMatchTrie2Pairs & operator =(const InstMatchTrie2Pairs & e) CVC4_UNDEFINED;
+ /** add match m in the trie,
+ return true if it was never seen */
+ inline bool addInstMatch( size_t i, size_t j, InstMatch& m){
+ size_t k = std::min(i,j);
+ size_t l = std::max(i,j);
+ return d_backtrack.addInstMatch(m,&(d_data[l][k]));
+ };
+ inline bool addInstMatch( size_t i, InstMatch& m){
+ return d_backtrack.addInstMatch(m,&(d_data[i][i]));
+ };
+
+};
+
+
+// Currently the implementation doesn't take into account that
+// variable should have the same value given.
+// TODO use the d_children way perhaps
+// TODO replace by a real dictionnary
+// We should create a real substitution? slower more precise
+// We don't do that often
+bool nonunifiable( TNode t0, TNode pat, const std::vector<Node> & vars){
+ if(pat.isNull()) return true;
+
+ typedef std::vector<std::pair<TNode,TNode> > tstack;
+ tstack stack(1,std::make_pair(t0,pat)); // t * pat
+
+ while(!stack.empty()){
+ const std::pair<TNode,TNode> p = stack.back(); stack.pop_back();
+ const TNode & t = p.first;
+ const TNode & pat = p.second;
+
+ // t or pat is a variable currently we consider that can match anything
+ if( find(vars.begin(),vars.end(),t) != vars.end() ) continue;
+ if( pat.getKind() == INST_CONSTANT ) continue;
+
+ // t and pat are nonunifiable
+ if( !Trigger::isAtomicTrigger( t ) || !Trigger::isAtomicTrigger( pat ) ) {
+ if(t == pat) continue;
+ else return true;
+ };
+ if( t.getOperator() != pat.getOperator() ) return true;
+
+ //put the children on the stack
+ for( size_t i=0; i < pat.getNumChildren(); i++ ){
+ stack.push_back(std::make_pair(t[i],pat[i]));
+ };
+ }
+ // The heuristic can't find non-unifiability
+ return false;
+};
+
+/** New things */
+class DumbMatcher: public Matcher{
+ void resetInstantiationRound( QuantifiersEngine* qe ){};
+ bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe ){
+ return false;
+ }
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ return false;
+ }
+};
+
+class DumbPatMatcher: public PatMatcher{
+ void resetInstantiationRound( QuantifiersEngine* qe ){};
+ bool reset( InstMatch& m, QuantifiersEngine* qe ){
+ return false;
+ }
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ return false;
+ }
+};
+
+
+/* The order of the matching is:
+ reset arg1, nextMatch arg1, reset arg2, nextMatch arg2, ... */
+ApplyMatcher::ApplyMatcher( Node pat, QuantifiersEngine* qe): d_pattern(pat){
+ // Assert( pat.hasAttribute(InstConstantAttribute()) );
+
+ //set-up d_variables, d_constants, d_childrens
+ for( size_t i=0; i< d_pattern.getNumChildren(); ++i ){
+ EqualityQuery* q = qe->getEqualityQuery(d_pattern[i].getType());
+ Assert( q != NULL );
+ if( d_pattern[i].hasAttribute(InstConstantAttribute()) ){
+ if( d_pattern[i].getKind()==INST_CONSTANT ){
+ //It's a variable
+ d_variables.push_back(make_triple((TNode)d_pattern[i],i,q));
+ }else{
+ //It's neither a constant argument neither a variable
+ //we create the matcher for the subpattern
+ d_childrens.push_back(make_triple(mkMatcher((TNode)d_pattern[i], qe),i,q));
+ };
+ }else{
+ // It's a constant
+ d_constants.push_back(make_triple((TNode)d_pattern[i],i,q));
+ }
+ }
+}
+
+void ApplyMatcher::resetInstantiationRound( QuantifiersEngine* qe ){
+ for( size_t i=0; i< d_childrens.size(); i++ ){
+ d_childrens[i].first->resetInstantiationRound( qe );
+ }
+}
+
+bool ApplyMatcher::reset(TNode t, InstMatch & m, QuantifiersEngine* qe){
+ Debug("matching") << "Matching " << t << " against pattern " << d_pattern << " ("
+ << m.size() << ")" << std::endl;
+
+ //if t is null
+ Assert( !t.isNull() );
+ Assert( !t.hasAttribute(InstConstantAttribute()) );
+ Assert( t.getKind()==d_pattern.getKind() );
+ Assert( (t.getKind()!=APPLY_UF && t.getKind()!=APPLY_CONSTRUCTOR)
+ || t.getOperator()==d_pattern.getOperator() );
+
+ typedef std::vector< triple<TNode,size_t,EqualityQuery*> >::iterator iterator;
+ for(iterator i = d_constants.begin(), end = d_constants.end();
+ i != end; ++i){
+ if( !i->third->areEqual( i->first, t[i->second] ) ){
+ Debug("matching-fail") << "Match fail arg: " << i->first << " and " << t[i->second] << std::endl;
+ //setMatchFail( qe, d_pattern[i], t[i] );
+ //ground arguments are not equal
+ return false;
+ }
+ }
+
+ d_binded.clear();
+ bool set;
+ for(iterator i = d_variables.begin(), end = d_variables.end();
+ i != end; ++i){
+ if( !m.setMatch( i->third, i->first, t[i->second], set) ){
+ //match is in conflict
+ Debug("matching-debug") << "Match in conflict " << t[i->second] << " and "
+ << i->first << " because "
+ << m.get(i->first)
+ << std::endl;
+ Debug("matching-fail") << "Match fail: " << m.get(i->first) << " and " << t[i->second] << std::endl;
+ //setMatchFail( qe, partial[0].d_map[d_pattern[i]], t[i] );
+ m.erase(d_binded.begin(), d_binded.end());
+ return false;
+ }else{
+ if(set){ //The variable has just been set
+ d_binded.push_back(i->first);
+ }
+ }
+ }
+
+ //now, fit children into match
+ //we will be requesting candidates for matching terms for each child
+ d_reps.clear();
+ for( size_t i=0; i< d_childrens.size(); i++ ){
+ Debug("matching-debug") << "Take the representative of " << t[ d_childrens[i].second ] << std::endl;
+ Assert( d_childrens[i].third->hasTerm(t[ d_childrens[i].second ]) );
+ Node rep = d_childrens[i].third->getRepresentative( t[ d_childrens[i].second ] );
+ d_reps.push_back( rep );
+ }
+
+ if(d_childrens.size() == 0) return true;
+ else return getNextMatch(m, qe, true);
+}
+
+bool ApplyMatcher::getNextMatch(InstMatch& m, QuantifiersEngine* qe, bool reset){
+ Assert(d_childrens.size() > 0);
+ const size_t max = d_childrens.size() - 1;
+ size_t index = reset ? 0 : max;
+ Assert(d_childrens.size() == d_reps.size());
+ while(true){
+ if(reset ?
+ d_childrens[index].first->reset( d_reps[index], m, qe ) :
+ d_childrens[index].first->getNextMatch( m, qe )){
+ if(index==max) return true;
+ ++index;
+ reset=true;
+ }else{
+ if(index==0){
+ m.erase(d_binded.begin(), d_binded.end());
+ return false;
+ }
+ --index;
+ reset=false;
+ };
+ }
+}
+
+bool ApplyMatcher::getNextMatch(InstMatch& m, QuantifiersEngine* qe){
+ if(d_childrens.size() == 0){
+ m.erase(d_binded.begin(), d_binded.end());
+ return false;
+ } else return getNextMatch(m, qe, false);
+}
+
+/** Proxy that call the sub-matcher on the result return by the given candidate generator */
+template <class CG, class M>
+class CandidateGeneratorMatcher: public Matcher{
+ /** candidate generator */
+ CG d_cg;
+ /** the sub-matcher */
+ M d_m;
+public:
+ CandidateGeneratorMatcher(CG cg, M m): d_cg(cg), d_m(m)
+ {/* last is Null */};
+ void resetInstantiationRound( QuantifiersEngine* qe ){
+ d_cg.resetInstantiationRound();
+ d_m.resetInstantiationRound(qe);
+ };
+ bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe ){
+ d_cg.reset(n);
+ return findMatch(m,qe);
+ }
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ // The sub-matcher has another match
+ return d_m.getNextMatch(m, qe) || findMatch(m,qe);
+ }
+private:
+ bool findMatch( InstMatch& m, QuantifiersEngine* qe ){
+ // Otherwise try to find a new candidate that has at least one match
+ while(true){
+ TNode n = d_cg.getNextCandidate();//kept somewhere Term-db
+ Debug("matching") << "GenCand " << n << " (" << this << ")" << std::endl;
+ if(n.isNull()) return false;
+ if(d_m.reset(n,m,qe)) return true;
+ };
+ }
+};
+
+/** Proxy that call the sub-matcher on the result return by the given candidate generator */
+template<class M>
+class PatOfMatcher: public PatMatcher{
+ M d_m;
+public:
+ inline PatOfMatcher(M m): d_m(m){}
+ void resetInstantiationRound(QuantifiersEngine* qe){
+ d_m.resetInstantiationRound(qe);
+ }
+ bool reset(InstMatch& m, QuantifiersEngine* qe){
+ return d_m.reset(Node::null(),m,qe);
+ };
+ bool getNextMatch(InstMatch& m, QuantifiersEngine* qe){
+ return d_m.getNextMatch(m,qe);
+ };
+};
+
+class ArithMatcher: public Matcher{
+private:
+ /** for arithmetic matching */
+ std::map< Node, Node > d_arith_coeffs;
+ /** get the match against ground term or formula t.
+ d_match_mattern and t should have the same shape.
+ only valid for use where !d_match_pattern.isNull().
+ */
+ /** the variable that are set by this matcher */
+ std::vector< TNode > d_binded; /* TNode because the variables are already in d_arith_coeffs */
+ Node d_pattern; //for debugging
+public:
+ ArithMatcher(Node pat, QuantifiersEngine* qe);
+ void resetInstantiationRound( QuantifiersEngine* qe ){};
+ bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe );
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe );
+};
+
+/** Match just a variable */
+class VarMatcher: public Matcher{
+ Node d_var;
+ bool d_binded; /* True if the reset bind the variable to some value */
+ EqualityQuery* d_q;
+public:
+ VarMatcher(Node var, QuantifiersEngine* qe): d_var(var), d_binded(false){
+ d_q = qe->getEqualityQuery(var.getType());
+ }
+ void resetInstantiationRound( QuantifiersEngine* qe ){};
+ bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe ){
+ if(!m.setMatch( d_q, d_var, n, d_binded )){
+ //match is in conflict
+ Debug("matching-fail") << "Match fail: " << m.get(d_var)
+ << " and " << n << std::endl;
+ return false;
+ } else return true;
+ };
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ //match is in conflict
+ if (d_binded) m.erase(d_var);
+ return false;
+ }
+};
+
+template <class M, class Test >
+class TestMatcher: public Matcher{
+ M d_m;
+ Test d_test;
+public:
+ inline TestMatcher(M m, Test test): d_m(m), d_test(test){}
+ inline void resetInstantiationRound(QuantifiersEngine* qe){
+ d_m.resetInstantiationRound(qe);
+ }
+ inline bool reset(TNode n, InstMatch& m, QuantifiersEngine* qe){
+ return d_test(n) && d_m.reset(n, m, qe);
+ }
+ inline bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ return d_m.getNextMatch(m, qe);
+ }
+};
+
+class LegalOpTest/*: public unary_function<TNode,bool>*/ {
+ Node d_op;
+public:
+ inline LegalOpTest(Node op): d_op(op){}
+ inline bool operator() (TNode n) {
+ return
+ CandidateGenerator::isLegalCandidate(n) &&
+ // ( // n.getKind()==SELECT || n.getKind()==STORE ||
+ // n.getKind()==APPLY_UF || n.getKind()==APPLY_CONSTRUCTOR) &&
+ n.hasOperator() &&
+ n.getOperator()==d_op;
+ };
+};
+
+class LegalKindTest/* : public unary_function<TNode,bool>*/ {
+ Kind d_kind;
+public:
+ inline LegalKindTest(Kind kind): d_kind(kind){}
+ inline bool operator() (TNode n) {
+ return
+ CandidateGenerator::isLegalCandidate(n) &&
+ n.getKind()==d_kind;
+ };
+};
+
+class LegalTypeTest/* : public unary_function<TNode,bool>*/ {
+ TypeNode d_type;
+public:
+ inline LegalTypeTest(TypeNode type): d_type(type){}
+ inline bool operator() (TNode n) {
+ return
+ CandidateGenerator::isLegalCandidate(n) &&
+ n.getType()==d_type;
+ };
+};
+
+class LegalTest/* : public unary_function<TNode,bool>*/ {
+public:
+ inline bool operator() (TNode n) {
+ return CandidateGenerator::isLegalCandidate(n);
+ };
+};
+
+size_t numFreeVar(TNode t){
+ size_t n = 0;
+ for( size_t i=0, size =t.getNumChildren(); i < size; ++i ){
+ if( t[i].hasAttribute(InstConstantAttribute()) ){
+ if( t[i].getKind()==INST_CONSTANT ){
+ //variable
+ ++n;
+ }else{
+ //neither variable nor constant
+ n += numFreeVar(t[i]);
+ }
+ }
+ }
+ return n;
+}
+
+class OpMatcher: public Matcher{
+ /* The matcher */
+ typedef ApplyMatcher AuxMatcher3;
+ typedef TestMatcher< AuxMatcher3, LegalOpTest > AuxMatcher2;
+ typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClass, AuxMatcher2> AuxMatcher1;
+ AuxMatcher1 d_cgm;
+ static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
+ Assert( pat.getKind() == kind::APPLY_UF );
+ /** In reverse order of matcher sequence */
+ AuxMatcher3 am3(pat,qe);
+ /** Keep only the one that have the good operator */
+ AuxMatcher2 am2(am3,LegalOpTest(pat.getOperator()));
+ /** Iter on the equivalence class of the given term */
+ uf::TheoryUF* uf = static_cast<uf::TheoryUF *>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF ));
+ eq::EqualityEngine* ee = static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
+ CandidateGeneratorTheoryEeClass cdtUfEq(ee);
+ /* Create a matcher from the candidate generator */
+ AuxMatcher1 am1(cdtUfEq,am2);
+ return am1;
+ }
+ size_t d_num_var;
+ Node d_pat;
+public:
+ OpMatcher( Node pat, QuantifiersEngine* qe ):
+ d_cgm(createCgm(pat, qe)),d_num_var(numFreeVar(pat)),
+ d_pat(pat) {}
+
+ void resetInstantiationRound( QuantifiersEngine* qe ){
+ d_cgm.resetInstantiationRound(qe);
+ };
+ bool reset( TNode t, InstMatch& m, QuantifiersEngine* qe ){
+ // size_t m_size = m.d_map.size();
+ // if(m_size == d_num_var){
+ // uf::EqualityEngine<uf::TheoryUF::NotifyClass>* ee = (static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF )))->getEqualityEngine();
+ // std::cout << "!";
+ // return ee->areEqual(m.subst(d_pat),t);
+ // }else{
+ // std::cout << m.d_map.size() << std::endl;
+ return d_cgm.reset(t, m, qe);
+ // }
+ }
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ return d_cgm.getNextMatch(m, qe);
+ }
+};
+
+class DatatypesMatcher: public Matcher{
+ /* The matcher */
+ typedef ApplyMatcher AuxMatcher3;
+ typedef TestMatcher< AuxMatcher3, LegalOpTest > AuxMatcher2;
+ typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClass, AuxMatcher2> AuxMatcher1;
+ AuxMatcher1 d_cgm;
+ static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
+ Assert( pat.getKind() == kind::APPLY_CONSTRUCTOR,
+ "For datatypes only constructor are accepted in pattern" );
+ /** In reverse order of matcher sequence */
+ AuxMatcher3 am3(pat,qe);
+ /** Keep only the one that have the good operator */
+ AuxMatcher2 am2(am3,LegalOpTest(pat.getOperator()));
+ /** Iter on the equivalence class of the given term */
+ datatypes::TheoryDatatypes* dt = static_cast<datatypes::TheoryDatatypes *>(qe->getTheoryEngine()->getTheory( theory::THEORY_DATATYPES ));
+ eq::EqualityEngine* ee = static_cast<eq::EqualityEngine*>(dt->getEqualityEngine());
+ CandidateGeneratorTheoryEeClass cdtDtEq(ee);
+ /* Create a matcher from the candidate generator */
+ AuxMatcher1 am1(cdtDtEq,am2);
+ return am1;
+ }
+ Node d_pat;
+public:
+ DatatypesMatcher( Node pat, QuantifiersEngine* qe ):
+ d_cgm(createCgm(pat, qe)),
+ d_pat(pat) {}
+
+ void resetInstantiationRound( QuantifiersEngine* qe ){
+ d_cgm.resetInstantiationRound(qe);
+ };
+ bool reset( TNode t, InstMatch& m, QuantifiersEngine* qe ){
+ Debug("matching") << "datatypes: " << t << " matches " << d_pat << std::endl;
+ return d_cgm.reset(t, m, qe);
+ }
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ return d_cgm.getNextMatch(m, qe);
+ }
+};
+
+class ArrayMatcher: public Matcher{
+ /* The matcher */
+ typedef ApplyMatcher AuxMatcher3;
+ typedef TestMatcher< AuxMatcher3, LegalKindTest > AuxMatcher2;
+ typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClass, AuxMatcher2> AuxMatcher1;
+ AuxMatcher1 d_cgm;
+ static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
+ Assert( pat.getKind() == kind::SELECT || pat.getKind() == kind::STORE );
+ /** In reverse order of matcher sequence */
+ AuxMatcher3 am3(pat,qe);
+ /** Keep only the one that have the good operator */
+ AuxMatcher2 am2(am3, LegalKindTest(pat.getKind()));
+ /** Iter on the equivalence class of the given term */
+ arrays::TheoryArrays* ar = static_cast<arrays::TheoryArrays *>(qe->getTheoryEngine()->getTheory( theory::THEORY_ARRAY ));
+ eq::EqualityEngine* ee =
+ static_cast<eq::EqualityEngine*>(ar->getEqualityEngine());
+ CandidateGeneratorTheoryEeClass cdtUfEq(ee);
+ /* Create a matcher from the candidate generator */
+ AuxMatcher1 am1(cdtUfEq,am2);
+ return am1;
+ }
+ size_t d_num_var;
+ Node d_pat;
+public:
+ ArrayMatcher( Node pat, QuantifiersEngine* qe ):
+ d_cgm(createCgm(pat, qe)),d_num_var(numFreeVar(pat)),
+ d_pat(pat) {}
+
+ void resetInstantiationRound( QuantifiersEngine* qe ){
+ d_cgm.resetInstantiationRound(qe);
+ };
+ bool reset( TNode t, InstMatch& m, QuantifiersEngine* qe ){
+ // size_t m_size = m.d_map.size();
+ // if(m_size == d_num_var){
+ // uf::EqualityEngine<uf::TheoryUF::NotifyClass>* ee = (static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF )))->getEqualityEngine();
+ // std::cout << "!";
+ // return ee->areEqual(m.subst(d_pat),t);
+ // }else{
+ // std::cout << m.d_map.size() << std::endl;
+ return d_cgm.reset(t, m, qe);
+ // }
+ }
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ return d_cgm.getNextMatch(m, qe);
+ }
+};
+
+class AllOpMatcher: public PatMatcher{
+ /* The matcher */
+ typedef ApplyMatcher AuxMatcher3;
+ typedef TestMatcher< AuxMatcher3, LegalTest > AuxMatcher2;
+ typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryUfOp, AuxMatcher2> AuxMatcher1;
+ AuxMatcher1 d_cgm;
+ static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
+ Assert( pat.hasOperator() );
+ /** In reverse order of matcher sequence */
+ AuxMatcher3 am3(pat,qe);
+ /** Keep only the one that have the good operator */
+ AuxMatcher2 am2(am3,LegalTest());
+ /** Iter on the equivalence class of the given term */
+ TermDb* tdb = qe->getTermDatabase();
+ CandidateGeneratorTheoryUfOp cdtUfEq(pat.getOperator(),tdb);
+ /* Create a matcher from the candidate generator */
+ AuxMatcher1 am1(cdtUfEq,am2);
+ return am1;
+ }
+ size_t d_num_var;
+ Node d_pat;
+public:
+ AllOpMatcher( TNode pat, QuantifiersEngine* qe ):
+ d_cgm(createCgm(pat, qe)), d_num_var(numFreeVar(pat)),
+ d_pat(pat) {}
+
+ void resetInstantiationRound( QuantifiersEngine* qe ){
+ d_cgm.resetInstantiationRound(qe);
+ };
+ bool reset( InstMatch& m, QuantifiersEngine* qe ){
+ // std::cout << m.d_map.size() << "/" << d_num_var << std::endl;
+ return d_cgm.reset(Node::null(), m, qe);
+ }
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ return d_cgm.getNextMatch(m, qe);
+ }
+};
+
+template <bool classes> /** true classes | false class */
+class GenericCandidateGeneratorClasses: public CandidateGenerator{
+private:
+ CandidateGenerator* d_cg;
+ QuantifiersEngine* d_qe;
+
+public:
+ void mkCandidateGenerator(){
+ if(classes)
+ d_cg = d_qe->getRRCanGenClasses();
+ else
+ d_cg = d_qe->getRRCanGenClass();
+ }
+
+ GenericCandidateGeneratorClasses(QuantifiersEngine* qe):
+ d_qe(qe) {
+ mkCandidateGenerator();
+ }
+ ~GenericCandidateGeneratorClasses(){
+ delete(d_cg);
+ }
+ const GenericCandidateGeneratorClasses & operator =(const GenericCandidateGeneratorClasses & m){
+ mkCandidateGenerator();
+ return m;
+ };
+ GenericCandidateGeneratorClasses(const GenericCandidateGeneratorClasses & m):
+ d_qe(m.d_qe){
+ mkCandidateGenerator();
+ }
+ void resetInstantiationRound(){
+ d_cg->resetInstantiationRound();
+ };
+ void reset( TNode eqc ){
+ Assert( !classes || eqc.isNull() );
+ d_cg->reset(eqc);
+ }; //* the argument is not used
+ TNode getNextCandidate(){
+ return d_cg->getNextCandidate();
+ };
+}; /* MetaCandidateGeneratorClasses */
+
+
+class GenericMatcher: public Matcher{
+ /* The matcher */
+ typedef ApplyMatcher AuxMatcher3;
+ typedef TestMatcher< AuxMatcher3, LegalOpTest > AuxMatcher2;
+ typedef CandidateGeneratorMatcher< GenericCandidateGeneratorClasses<false>, AuxMatcher2> AuxMatcher1;
+ AuxMatcher1 d_cgm;
+ static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
+ /** In reverse order of matcher sequence */
+ AuxMatcher3 am3(pat,qe);
+ /** Keep only the one that have the good operator */
+ AuxMatcher2 am2(am3,LegalOpTest(pat.getOperator()));
+ /** Iter on the equivalence class of the given term */
+ GenericCandidateGeneratorClasses<false> cdtG(qe);
+ /* Create a matcher from the candidate generator */
+ AuxMatcher1 am1(cdtG,am2);
+ return am1;
+ }
+ Node d_pat;
+public:
+ GenericMatcher( Node pat, QuantifiersEngine* qe ):
+ d_cgm(createCgm(pat, qe)),
+ d_pat(pat) {}
+
+ void resetInstantiationRound( QuantifiersEngine* qe ){
+ d_cgm.resetInstantiationRound(qe);
+ };
+ bool reset( TNode t, InstMatch& m, QuantifiersEngine* qe ){
+ return d_cgm.reset(t, m, qe);
+ }
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ return d_cgm.getNextMatch(m, qe);
+ }
+};
+
+
+class GenericPatMatcher: public PatMatcher{
+ /* The matcher */
+ typedef ApplyMatcher AuxMatcher3;
+ typedef TestMatcher< AuxMatcher3, LegalOpTest > AuxMatcher2;
+ typedef CandidateGeneratorMatcher< GenericCandidateGeneratorClasses<true>, AuxMatcher2> AuxMatcher1;
+ AuxMatcher1 d_cgm;
+ static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
+ /** In reverse order of matcher sequence */
+ AuxMatcher3 am3(pat,qe);
+ /** Keep only the one that have the good operator */
+ AuxMatcher2 am2(am3,LegalOpTest(pat.getOperator()));
+ /** Iter on the equivalence class of the given term */
+ GenericCandidateGeneratorClasses<true> cdtG(qe);
+ /* Create a matcher from the candidate generator */
+ AuxMatcher1 am1(cdtG,am2);
+ return am1;
+ }
+ Node d_pat;
+public:
+ GenericPatMatcher( Node pat, QuantifiersEngine* qe ):
+ d_cgm(createCgm(pat, qe)),
+ d_pat(pat) {}
+
+ void resetInstantiationRound( QuantifiersEngine* qe ){
+ d_cgm.resetInstantiationRound(qe);
+ };
+ bool reset( InstMatch& m, QuantifiersEngine* qe ){
+ return d_cgm.reset(Node::null(), m, qe);
+ }
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ return d_cgm.getNextMatch(m, qe);
+ }
+};
+
+class MetaCandidateGeneratorClasses: public CandidateGenerator{
+private:
+ CandidateGenerator* d_cg;
+ TypeNode d_ty;
+ TheoryEngine* d_te;
+
+public:
+ CandidateGenerator* mkCandidateGenerator(TypeNode ty, TheoryEngine* te){
+ Debug("inst-match-gen") << "MetaCandidateGenerator for type: " << ty
+ << " Theory : " << Theory::theoryOf(ty) << std::endl;
+ if( Theory::theoryOf(ty) == theory::THEORY_DATATYPES ){
+ // datatypes::TheoryDatatypes* dt = static_cast<datatypes::TheoryDatatypes *>(te->getTheory( theory::THEORY_DATATYPES ));
+ // return new datatypes::rrinst::CandidateGeneratorTheoryClasses(dt);
+ Unimplemented("MetaCandidateGeneratorClasses for THEORY_DATATYPES");
+ }else if ( Theory::theoryOf(ty) == theory::THEORY_ARRAY ){
+ arrays::TheoryArrays* ar = static_cast<arrays::TheoryArrays *>(te->getTheory( theory::THEORY_ARRAY ));
+ eq::EqualityEngine* ee =
+ static_cast<eq::EqualityEngine*>(ar->getEqualityEngine());
+ return new CandidateGeneratorTheoryEeClasses(ee);
+ } else {
+ uf::TheoryUF* uf = static_cast<uf::TheoryUF*>(te->getTheory( theory::THEORY_UF ));
+ eq::EqualityEngine* ee =
+ static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
+ return new CandidateGeneratorTheoryEeClasses(ee);
+ }
+ }
+ MetaCandidateGeneratorClasses(TypeNode ty, TheoryEngine* te):
+ d_ty(ty), d_te(te) {
+ d_cg = mkCandidateGenerator(ty,te);
+ }
+ ~MetaCandidateGeneratorClasses(){
+ delete(d_cg);
+ }
+ const MetaCandidateGeneratorClasses & operator =(const MetaCandidateGeneratorClasses & m){
+ d_cg = mkCandidateGenerator(m.d_ty, m.d_te);
+ return m;
+ };
+ MetaCandidateGeneratorClasses(const MetaCandidateGeneratorClasses & m):
+ d_ty(m.d_ty), d_te(m.d_te){
+ d_cg = mkCandidateGenerator(m.d_ty, m.d_te);
+ }
+ void resetInstantiationRound(){
+ d_cg->resetInstantiationRound();
+ };
+ void reset( TNode eqc ){
+ d_cg->reset(eqc);
+ }; //* the argument is not used
+ TNode getNextCandidate(){
+ return d_cg->getNextCandidate();
+ };
+}; /* MetaCandidateGeneratorClasses */
+
+/** Match just a variable */
+class AllVarMatcher: public PatMatcher{
+private:
+ /* generator */
+ typedef VarMatcher AuxMatcher3;
+ typedef TestMatcher< AuxMatcher3, LegalTypeTest > AuxMatcher2;
+ typedef CandidateGeneratorMatcher< MetaCandidateGeneratorClasses, AuxMatcher2 > AuxMatcher1;
+ AuxMatcher1 d_cgm;
+ static inline AuxMatcher1 createCgm(TNode pat, QuantifiersEngine* qe){
+ Assert( pat.getKind()==INST_CONSTANT );
+ TypeNode ty = pat.getType();
+ Debug("inst-match-gen") << "create AllVarMatcher for type: " << ty << std::endl;
+ /** In reverse order of matcher sequence */
+ /** Distribute it to all the pattern */
+ AuxMatcher3 am3(pat,qe);
+ /** Keep only the one that have the good type */
+ AuxMatcher2 am2(am3,LegalTypeTest(ty));
+ /** Generate one term by eq classes */
+ MetaCandidateGeneratorClasses mcdt(ty,qe->getTheoryEngine());
+ /* Create a matcher from the candidate generator */
+ AuxMatcher1 am1(mcdt,am2);
+ return am1;
+ }
+public:
+ AllVarMatcher( TNode pat, QuantifiersEngine* qe ):
+ d_cgm(createCgm(pat, qe)){}
+
+ void resetInstantiationRound( QuantifiersEngine* qe ){
+ d_cgm.resetInstantiationRound(qe);
+ };
+ bool reset( InstMatch& m, QuantifiersEngine* qe ){
+ return d_cgm.reset(Node::null(), m, qe); //cdtUfEq doesn't use it's argument for reset
+ }
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ return d_cgm.getNextMatch(m, qe);
+ }
+};
+
+/** Match all the pattern with the same term */
+class SplitMatcher: public Matcher{
+private:
+ const size_t size;
+ ApplyMatcher d_m; /** Use ApplyMatcher by creating a fake application */
+public:
+ SplitMatcher(std::vector< Node > pats, QuantifiersEngine* qe):
+ size(pats.size()),
+ d_m(NodeManager::currentNM()->mkNode(kind::INST_PATTERN,pats), qe) {}
+ void resetInstantiationRound( QuantifiersEngine* qe ){
+ d_m.resetInstantiationRound(qe);
+ };
+ bool reset( TNode ex, InstMatch& m, QuantifiersEngine* qe ){
+ NodeBuilder<> n(kind::INST_PATTERN);
+ for(size_t i = 0; i < size; ++i) n << ex;
+ Node nn = n;
+ return d_m.reset(nn,m,qe);
+ };
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ return getNextMatch(m, qe);
+ }
+};
+
+
+/** Match uf term in a fixed equivalence class */
+class UfCstEqMatcher: public PatMatcher{
+private:
+ /* equivalence class to match */
+ Node d_cst;
+ /* generator */
+ OpMatcher d_cgm;
+public:
+ UfCstEqMatcher( Node pat, Node cst, QuantifiersEngine* qe ):
+ d_cst(cst),
+ d_cgm(OpMatcher(pat,qe)) {};
+ void resetInstantiationRound( QuantifiersEngine* qe ){
+ d_cgm.resetInstantiationRound(qe);
+ };
+ bool reset( InstMatch& m, QuantifiersEngine* qe ){
+ return d_cgm.reset(d_cst, m, qe);
+ }
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ return d_cgm.getNextMatch(m, qe);
+ }
+};
+
+/** Match equalities */
+class UfEqMatcher: public PatMatcher{
+private:
+ /* generator */
+ typedef SplitMatcher AuxMatcher3;
+ typedef TestMatcher< AuxMatcher3, LegalTypeTest > AuxMatcher2;
+ typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClasses, AuxMatcher2 > AuxMatcher1;
+ AuxMatcher1 d_cgm;
+ static inline AuxMatcher1 createCgm(std::vector<Node> & pat, QuantifiersEngine* qe){
+ Assert( pat.size() > 0);
+ TypeNode ty = pat[0].getType();
+ for(size_t i = 1; i < pat.size(); ++i){
+ Assert(pat[i].getType() == ty);
+ }
+ /** In reverse order of matcher sequence */
+ /** Distribute it to all the pattern */
+ AuxMatcher3 am3(pat,qe);
+ /** Keep only the one that have the good type */
+ AuxMatcher2 am2(am3,LegalTypeTest(ty));
+ /** Generate one term by eq classes */
+ uf::TheoryUF* uf = static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF ));
+ eq::EqualityEngine* ee =
+ static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
+ CandidateGeneratorTheoryEeClasses cdtUfEq(ee);
+ /* Create a matcher from the candidate generator */
+ AuxMatcher1 am1(cdtUfEq,am2);
+ return am1;
+ }
+public:
+ UfEqMatcher( std::vector<Node> & pat, QuantifiersEngine* qe ):
+ d_cgm(createCgm(pat, qe)){}
+
+ void resetInstantiationRound( QuantifiersEngine* qe ){
+ d_cgm.resetInstantiationRound(qe);
+ };
+ bool reset( InstMatch& m, QuantifiersEngine* qe ){
+ return d_cgm.reset(Node::null(), m, qe); //cdtUfEq doesn't use it's argument for reset
+ }
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ return d_cgm.getNextMatch(m, qe);
+ }
+};
+
+
+/** Match dis-equalities */
+class UfDeqMatcher: public PatMatcher{
+private:
+ /* generator */
+ typedef ApplyMatcher AuxMatcher3;
+
+ class EqTest/* : public unary_function<Node,bool>*/ {
+ TypeNode d_type;
+ public:
+ inline EqTest(TypeNode type): d_type(type){};
+ inline bool operator() (Node n) {
+ return
+ CandidateGenerator::isLegalCandidate(n) &&
+ n.getKind() == kind::EQUAL &&
+ n[0].getType()==d_type;
+ };
+ };
+ typedef TestMatcher< AuxMatcher3, EqTest > AuxMatcher2;
+ typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClass, AuxMatcher2 > AuxMatcher1;
+ AuxMatcher1 d_cgm;
+ Node false_term;
+ static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
+ Assert( pat.getKind() == kind::NOT);
+ TNode eq = pat[0];
+ Assert( eq.getKind() == kind::EQUAL);
+ TypeNode ty = eq[0].getType();
+ /** In reverse order of matcher sequence */
+ /** Distribute it to all the pattern */
+ AuxMatcher3 am3(eq,qe);
+ /** Keep only the one that have the good type */
+ AuxMatcher2 am2(am3,EqTest(ty));
+ /** Will generate all the terms of the eq class of false */
+ uf::TheoryUF* uf = static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF ));
+ eq::EqualityEngine* ee =
+ static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
+ CandidateGeneratorTheoryEeClass cdtUfEq(ee);
+ /* Create a matcher from the candidate generator */
+ AuxMatcher1 am1(cdtUfEq,am2);
+ return am1;
+ }
+public:
+ UfDeqMatcher( Node pat, QuantifiersEngine* qe ):
+ d_cgm(createCgm(pat, qe)),
+ false_term((static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF )))->getEqualityEngine()->
+ getRepresentative(NodeManager::currentNM()->mkConst<bool>(false) )){};
+ void resetInstantiationRound( QuantifiersEngine* qe ){
+ d_cgm.resetInstantiationRound(qe);
+ };
+ bool reset( InstMatch& m, QuantifiersEngine* qe ){
+ return d_cgm.reset(false_term, m, qe);
+ }
+ bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ return d_cgm.getNextMatch(m, qe);
+ }
+};
+
+Matcher* mkMatcher( Node pat, QuantifiersEngine* qe ){
+ Debug("inst-match-gen") << "mkMatcher: Pattern term is " << pat << std::endl;
+
+ // if( pat.getKind() == kind::APPLY_UF){
+ // return new OpMatcher(pat, qe);
+ // } else if( pat.getKind() == kind::APPLY_CONSTRUCTOR ){
+ // return new DatatypesMatcher(pat, qe);
+ // } else if( pat.getKind() == kind::SELECT || pat.getKind() == kind::STORE ){
+ // return new ArrayMatcher(pat, qe);
+ if( pat.getKind() == kind::APPLY_UF ||
+ pat.getKind() == kind::APPLY_CONSTRUCTOR ||
+ pat.getKind() == kind::SELECT || pat.getKind() == kind::STORE ){
+ return new GenericMatcher(pat, qe);
+ } else { /* Arithmetic? */
+ /** TODO: something simpler to see if the pattern is a good
+ arithmetic pattern */
+ std::map< Node, Node > d_arith_coeffs;
+ if( !Trigger::getPatternArithmetic( pat.getAttribute(InstConstantAttribute()), pat, d_arith_coeffs ) ){
+ Message() << "(?) Unknown matching pattern is " << pat << std::endl;
+ Unimplemented("pattern not implemented");
+ return new DumbMatcher();
+ }else{
+ Debug("matching-arith") << "Generated arithmetic pattern for " << pat << ": " << std::endl;
+ for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+ Debug("matching-arith") << " " << it->first << " -> " << it->second << std::endl;
+ }
+ ArithMatcher am3 (pat, qe);
+ TestMatcher<ArithMatcher, LegalTypeTest>
+ am2(am3,LegalTypeTest(pat.getType()));
+ /* generator */
+ uf::TheoryUF* uf = static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF ));
+ eq::EqualityEngine* ee =
+ static_cast<eq::EqualityEngine*> (uf->getEqualityEngine());
+ CandidateGeneratorTheoryEeClass cdtUfEq(ee);
+ return new CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClass,
+ TestMatcher<ArithMatcher, LegalTypeTest> > (cdtUfEq,am2);
+ }
+ }
+};
+
+PatMatcher* mkPattern( Node pat, QuantifiersEngine* qe ){
+ Debug("inst-match-gen") << "Pattern term is " << pat << std::endl;
+ Assert( pat.hasAttribute(InstConstantAttribute()) );
+
+ if( pat.getKind()==kind::NOT && pat[0].getKind() == kind::EQUAL){
+ /* Difference */
+ return new UfDeqMatcher(pat, qe);
+ } else if (pat.getKind() == kind::EQUAL){
+ if( !pat[0].hasAttribute(InstConstantAttribute() )){
+ Assert(pat[1].hasAttribute(InstConstantAttribute()));
+ return new UfCstEqMatcher(pat[1], pat[0], qe);
+ }else if( !pat[1].hasAttribute(InstConstantAttribute() )){
+ Assert(pat[0].hasAttribute(InstConstantAttribute()));
+ return new UfCstEqMatcher(pat[0], pat[1], qe);
+ }else{
+ std::vector< Node > pats(pat.begin(),pat.end());
+ return new UfEqMatcher(pats,qe);
+ }
+ } else if( Trigger::isAtomicTrigger( pat ) ){
+ return new AllOpMatcher(pat, qe);
+ // return new GenericPatMatcher(pat, qe);
+ } else if( pat.getKind()==INST_CONSTANT ){
+ // just a variable
+ return new AllVarMatcher(pat, qe);
+ } else { /* Arithmetic? */
+ /** TODO: something simpler to see if the pattern is a good
+ arithmetic pattern */
+ std::map< Node, Node > d_arith_coeffs;
+ if( !Trigger::getPatternArithmetic( pat.getAttribute(InstConstantAttribute()), pat, d_arith_coeffs ) ){
+ Debug("inst-match-gen") << "(?) Unknown matching pattern is " << pat << std::endl;
+ Message() << "(?) Unknown matching pattern is " << pat << std::endl;
+ return new DumbPatMatcher();
+ }else{
+ Debug("matching-arith") << "Generated arithmetic pattern for " << pat << ": " << std::endl;
+ for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+ Debug("matching-arith") << " " << it->first << " -> " << it->second << std::endl;
+ }
+ ArithMatcher am3 (pat, qe);
+ TestMatcher<ArithMatcher, LegalTest>
+ am2(am3,LegalTest());
+ /* generator */
+ TermDb* tdb = qe->getTermDatabase();
+ CandidateGeneratorTheoryUfType cdtUfEq(pat.getType(),tdb);
+ typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryUfType,
+ TestMatcher<ArithMatcher, LegalTest> > AuxMatcher1;
+ return new PatOfMatcher<AuxMatcher1>(AuxMatcher1(cdtUfEq,am2));
+ }
+ }
+};
+
+ArithMatcher::ArithMatcher(Node pat, QuantifiersEngine* qe): d_pattern(pat){
+
+ if(Trigger::getPatternArithmetic(pat.getAttribute(InstConstantAttribute()), pat, d_arith_coeffs ) )
+ {
+ Debug("inst-match-gen") << "(?) Unknown matching pattern is " << d_pattern << std::endl;
+ Assert(false);
+ }else{
+ Debug("matching-arith") << "Generated arithmetic pattern for " << d_pattern << ": " << std::endl;
+ for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+ Debug("matching-arith") << " " << it->first << " -> " << it->second << std::endl;
+ }
+ }
+
+};
+
+bool ArithMatcher::reset( TNode t, InstMatch& m, QuantifiersEngine* qe ){
+ Debug("matching-arith") << "Matching " << t << " " << d_pattern << std::endl;
+ d_binded.clear();
+ if( !d_arith_coeffs.empty() ){
+ NodeBuilder<> tb(kind::PLUS);
+ Node ic = Node::null();
+ for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+ Debug("matching-arith") << it->first << " -> " << it->second << std::endl;
+ if( !it->first.isNull() ){
+ if( m.find( it->first )==m.end() ){
+ //see if we can choose this to set
+ if( ic.isNull() && ( it->second.isNull() || !it->first.getType().isInteger() ) ){
+ ic = it->first;
+ }
+ }else{
+ Debug("matching-arith") << "already set " << m.get( it->first ) << std::endl;
+ Node tm = m.get( it->first );
+ if( !it->second.isNull() ){
+ tm = NodeManager::currentNM()->mkNode( MULT, it->second, tm );
+ }
+ tb << tm;
+ }
+ }else{
+ tb << it->second;
+ }
+ }
+ if( !ic.isNull() ){
+ Node tm;
+ if( tb.getNumChildren()==0 ){
+ tm = t;
+ }else{
+ tm = tb.getNumChildren()==1 ? tb.getChild( 0 ) : tb;
+ tm = NodeManager::currentNM()->mkNode( MINUS, t, tm );
+ }
+ if( !d_arith_coeffs[ ic ].isNull() ){
+ Assert( !ic.getType().isInteger() );
+ Node coeff = NodeManager::currentNM()->mkConst( Rational(1) / d_arith_coeffs[ ic ].getConst<Rational>() );
+ tm = NodeManager::currentNM()->mkNode( MULT, coeff, tm );
+ }
+ m.set( ic, Rewriter::rewrite( tm ));
+ d_binded.push_back(ic);
+ //set the rest to zeros
+ for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+ if( !it->first.isNull() ){
+ if( m.find( it->first )==m.end() ){
+ m.set( it->first, NodeManager::currentNM()->mkConst( Rational(0) ));
+ d_binded.push_back(ic);
+ }
+ }
+ }
+ Debug("matching-arith") << "Setting " << ic << " to " << tm << std::endl;
+ return true;
+ }else{
+ m.erase(d_binded.begin(), d_binded.end());
+ return false;
+ }
+ }else{
+ m.erase(d_binded.begin(), d_binded.end());
+ return false;
+ }
+};
+
+bool ArithMatcher::getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+ m.erase(d_binded.begin(), d_binded.end());
+ return false;
+};
+
+
+class MultiPatsMatcher: public PatsMatcher{
+private:
+ bool d_reset_done;
+ std::vector< PatMatcher* > d_patterns;
+ InstMatch d_im;
+ bool reset( QuantifiersEngine* qe ){
+ d_im.clear();
+ d_reset_done = true;
+
+ return getNextMatch(qe,true);
+ };
+
+ bool getNextMatch(QuantifiersEngine* qe, bool reset){
+ const size_t max = d_patterns.size() - 1;
+ size_t index = reset ? 0 : max;
+ while(true){
+ Debug("matching") << "MultiPatsMatcher::index " << index << "/"
+ << max << (reset ? " reset_phase" : "") << std::endl;
+ if(reset ?
+ d_patterns[index]->reset( d_im, qe ) :
+ d_patterns[index]->getNextMatch( d_im, qe )){
+ if(index==max) return true;
+ ++index;
+ reset=true;
+ }else{
+ if(index==0) return false;
+ --index;
+ reset=false;
+ };
+ }
+ }
+
+public:
+ MultiPatsMatcher(std::vector< Node > & pats, QuantifiersEngine* qe):
+ d_reset_done(false){
+ Assert(pats.size() > 0);
+ for( size_t i=0; i< pats.size(); i++ ){
+ d_patterns.push_back(mkPattern(pats[i],qe));
+ };
+ };
+ void resetInstantiationRound( QuantifiersEngine* qe ){
+ for( size_t i=0; i< d_patterns.size(); i++ ){
+ d_patterns[i]->resetInstantiationRound( qe );
+ };
+ d_reset_done = false;
+ d_im.clear();
+ };
+ bool getNextMatch( QuantifiersEngine* qe ){
+ Assert(d_patterns.size()>0);
+ if(d_reset_done) return getNextMatch(qe,false);
+ else return reset(qe);
+ }
+ const InstMatch& getInstMatch(){return d_im;};
+
+ int addInstantiations( InstMatch& baseMatch, Node quant, QuantifiersEngine* qe);
+};
+
+enum EffiStep{
+ ES_STOP,
+ ES_GET_MONO_CANDIDATE,
+ ES_GET_MULTI_CANDIDATE,
+ ES_RESET1,
+ ES_RESET2,
+ ES_NEXT1,
+ ES_NEXT2,
+ ES_RESET_OTHER,
+ ES_NEXT_OTHER,
+};
+static inline std::ostream& operator<<(std::ostream& out, const EffiStep& step) {
+ switch(step){
+ case ES_STOP: out << "STOP"; break;
+ case ES_GET_MONO_CANDIDATE: out << "GET_MONO_CANDIDATE"; break;
+ case ES_GET_MULTI_CANDIDATE: out << "GET_MULTI_CANDIDATE"; break;
+ case ES_RESET1: out << "RESET1"; break;
+ case ES_RESET2: out << "RESET2"; break;
+ case ES_NEXT1: out << "NEXT1"; break;
+ case ES_NEXT2: out << "NEXT2"; break;
+ case ES_RESET_OTHER: out << "RESET_OTHER"; break;
+ case ES_NEXT_OTHER: out << "NEXT_OTHER"; break;
+ }
+ return out;
+}
+
+
+int MultiPatsMatcher::addInstantiations( InstMatch& baseMatch, Node quant, QuantifiersEngine* qe){
+ //now, try to add instantiation for each match produced
+ int addedLemmas = 0;
+ resetInstantiationRound( qe );
+ d_im.add( baseMatch );
+ while( getNextMatch( qe ) ){
+ InstMatch im_copy = getInstMatch();
+ //m.makeInternal( d_quantEngine->getEqualityQuery() );
+ if( qe->addInstantiation( quant, im_copy ) ){
+ addedLemmas++;
+ }
+ }
+ //return number of lemmas added
+ return addedLemmas;
+}
+
+PatsMatcher* mkPatterns( std::vector< Node > pat, QuantifiersEngine* qe ){
+ return new MultiPatsMatcher( pat, qe);
+}
+
+class MultiEfficientPatsMatcher: public PatsMatcher{
+private:
+ bool d_phase_mono;
+ bool d_phase_new_term;
+ std::vector< PatMatcher* > d_patterns;
+ std::vector< Matcher* > d_direct_patterns;
+ InstMatch d_im;
+ uf::EfficientHandler d_eh;
+ uf::EfficientHandler::MultiCandidate d_mc;
+ InstMatchTrie2Pairs<true> d_cache;
+ std::vector<Node> d_pats;
+ // bool indexDone( size_t i){
+ // return i == d_c.first.second ||
+ // ( i == d_c.second.second && d_c.second.first.empty());
+ // }
+
+
+
+ static const EffiStep ES_START = ES_GET_MONO_CANDIDATE;
+ EffiStep d_step;
+
+ //return true if it becomes bigger than d_patterns.size() - 1
+ bool incrIndex(size_t & index){
+ if(index == d_patterns.size() - 1) return true;
+ ++index;
+ if(index == d_mc.first.second
+ || (!d_phase_mono && index == d_mc.second.second))
+ return incrIndex(index);
+ else return false;
+ }
+
+ //return true if it becomes smaller than 0
+ bool decrIndex(size_t & index){
+ if(index == 0) return true;
+ --index;
+ if(index == d_mc.first.second
+ || (!d_phase_mono && index == d_mc.second.second))
+ return decrIndex(index);
+ else return false;
+ }
+
+ bool resetOther( QuantifiersEngine* qe ){
+ return getNextMatchOther(qe,true);
+ };
+
+
+ bool getNextMatchOther(QuantifiersEngine* qe, bool reset){
+ size_t index = reset ? 0 : d_patterns.size();
+ if(!reset && decrIndex(index)) return false;
+ if( reset &&
+ (index == d_mc.first.second
+ || (!d_phase_mono && index == d_mc.second.second))
+ && incrIndex(index)) return true;
+ while(true){
+ Debug("matching") << "MultiEfficientPatsMatcher::index " << index << "/"
+ << d_patterns.size() - 1 << std::endl;
+ if(reset ?
+ d_patterns[index]->reset( d_im, qe ) :
+ d_patterns[index]->getNextMatch( d_im, qe )){
+ if(incrIndex(index)) return true;
+ reset=true;
+ }else{
+ if(decrIndex(index)) return false;
+ reset=false;
+ };
+ }
+ }
+
+ inline EffiStep TestMonoCache(QuantifiersEngine* qe){
+ if( //!d_phase_new_term ||
+ d_pats.size() == 1) return ES_RESET_OTHER;
+ if(d_cache.addInstMatch(d_mc.first.second,d_im)){
+ Debug("inst-match::cache") << "Cache miss" << d_im << std::endl;
+ ++qe->d_statistics.d_mono_candidates_cache_miss;
+ return ES_RESET_OTHER;
+ } else {
+ Debug("inst-match::cache") << "Cache hit" << d_im << std::endl;
+ ++qe->d_statistics.d_mono_candidates_cache_hit;
+ return ES_NEXT1;
+ }
+ // ++qe->d_statistics.d_mono_candidates_cache_miss;
+ // return ES_RESET_OTHER;
+ }
+
+ inline EffiStep TestMultiCache(QuantifiersEngine* qe){
+ if(d_cache.addInstMatch(d_mc.first.second,d_mc.second.second,d_im)){
+ ++qe->d_statistics.d_multi_candidates_cache_miss;
+ return ES_RESET_OTHER;
+ } else {
+ ++qe->d_statistics.d_multi_candidates_cache_hit;
+ return ES_NEXT2;
+ }
+ }
+
+
+public:
+
+ bool getNextMatch( QuantifiersEngine* qe ){
+ Assert( d_step == ES_START || d_step == ES_NEXT_OTHER || d_step == ES_STOP );
+ while(true){
+ Debug("matching") << "d_step=" << d_step << " "
+ << "d_im=" << d_im << std::endl;
+ switch(d_step){
+ case ES_GET_MONO_CANDIDATE:
+ Assert(d_im.empty());
+ if(d_phase_new_term ? d_eh.getNextMonoCandidate(d_mc.first) : d_eh.getNextMonoCandidateNewTerm(d_mc.first)){
+ if(d_phase_new_term) ++qe->d_statistics.d_num_mono_candidates_new_term;
+ else ++qe->d_statistics.d_num_mono_candidates;
+ d_phase_mono = true;
+ d_step = ES_RESET1;
+ } else if (!d_phase_new_term){
+ d_phase_new_term = true;
+ d_step = ES_GET_MONO_CANDIDATE;
+ } else {
+ d_phase_new_term = false;
+ d_step = ES_GET_MULTI_CANDIDATE;
+ }
+ break;
+ case ES_GET_MULTI_CANDIDATE:
+ Assert(d_im.empty());
+ if(d_eh.getNextMultiCandidate(d_mc)){
+ ++qe->d_statistics.d_num_multi_candidates;
+ d_phase_mono = false;
+ d_step = ES_RESET1;
+ } else d_step = ES_STOP;
+ break;
+ case ES_RESET1:
+ if(d_direct_patterns[d_mc.first.second]->reset(d_mc.first.first,d_im,qe))
+ d_step = d_phase_mono ? TestMonoCache(qe) : ES_RESET2;
+ else d_step = d_phase_mono ? ES_GET_MONO_CANDIDATE : ES_GET_MULTI_CANDIDATE;
+ break;
+ case ES_RESET2:
+ Assert(!d_phase_mono);
+ if(d_direct_patterns[d_mc.second.second]->reset(d_mc.second.first,d_im,qe))
+ d_step = TestMultiCache(qe);
+ else d_step = ES_NEXT1;
+ break;
+ case ES_NEXT1:
+ if(d_direct_patterns[d_mc.first.second]->getNextMatch(d_im,qe))
+ d_step = d_phase_mono ? TestMonoCache(qe) : ES_RESET2;
+ else d_step = d_phase_mono ? ES_GET_MONO_CANDIDATE : ES_GET_MULTI_CANDIDATE;
+ break;
+ case ES_NEXT2:
+ if(d_direct_patterns[d_mc.second.second]->getNextMatch(d_im,qe))
+ d_step = TestMultiCache(qe);
+ else d_step = ES_NEXT1;
+ break;
+ case ES_RESET_OTHER:
+ if(resetOther(qe)){
+ d_step = ES_NEXT_OTHER;
+ return true;
+ } else d_step = d_phase_mono ? ES_NEXT1 : ES_NEXT2;
+ break;
+ case ES_NEXT_OTHER:
+ {
+ if(!getNextMatchOther(qe,false)){
+ d_step = d_phase_mono ? ES_NEXT1 : ES_NEXT2;
+ }else{
+ d_step = ES_NEXT_OTHER;
+ return true;
+ }
+ }
+ break;
+ case ES_STOP:
+ Assert(d_im.empty());
+ return false;
+ }
+ }
+ }
+
+ MultiEfficientPatsMatcher(std::vector< Node > & pats, QuantifiersEngine* qe):
+ d_eh(qe->getTheoryEngine()->getSatContext()),
+ d_cache(qe->getTheoryEngine()->getSatContext(),qe,pats.size()),
+ d_pats(pats), d_step(ES_START) {
+ Assert(pats.size() > 0);
+ for( size_t i=0; i< pats.size(); i++ ){
+ d_patterns.push_back(mkPattern(pats[i],qe));
+ if(pats[i].getKind()==kind::INST_CONSTANT){
+ d_direct_patterns.push_back(new VarMatcher(pats[i],qe));
+ } else if( pats[i].getKind() == kind::NOT && pats[i][0].getKind() == kind::EQUAL){
+ d_direct_patterns.push_back(new ApplyMatcher(pats[i][0],qe));
+ } else {
+ d_direct_patterns.push_back(new ApplyMatcher(pats[i],qe));
+ }
+ };
+ Theory* th_uf = qe->getTheoryEngine()->getTheory( theory::THEORY_UF );
+ uf::InstantiatorTheoryUf* ith = (uf::InstantiatorTheoryUf*)th_uf->getInstantiator();
+ ith->registerEfficientHandler(d_eh, pats);
+ };
+ void resetInstantiationRound( QuantifiersEngine* qe ){
+ Assert(d_step == ES_START || d_step == ES_STOP);
+ for( size_t i=0; i< d_patterns.size(); i++ ){
+ d_patterns[i]->resetInstantiationRound( qe );
+ d_direct_patterns[i]->resetInstantiationRound( qe );
+ };
+ d_step = ES_START;
+ d_phase_new_term = false;
+ Assert(d_im.empty());
+ };
+
+ const InstMatch& getInstMatch(){return d_im;};
+
+ int addInstantiations( InstMatch& baseMatch, Node quant, QuantifiersEngine* qe);
+};
+
+int MultiEfficientPatsMatcher::addInstantiations( InstMatch& baseMatch, Node quant, QuantifiersEngine* qe){
+ //now, try to add instantiation for each match produced
+ int addedLemmas = 0;
+ Assert(baseMatch.empty());
+ resetInstantiationRound( qe );
+ while( getNextMatch( qe ) ){
+ InstMatch im_copy = getInstMatch();
+ //m.makeInternal( d_quantEngine->getEqualityQuery() );
+ if( qe->addInstantiation( quant, im_copy ) ){
+ addedLemmas++;
+ }
+ }
+ //return number of lemmas added
+ return addedLemmas;
+};
+
+PatsMatcher* mkPatternsEfficient( std::vector< Node > pat, QuantifiersEngine* qe ){
+ return new MultiEfficientPatsMatcher( pat, qe);
+}
+
+} /* CVC4::theory::rrinst */
+} /* CVC4::theory */
+} /* CVC4 */
--- /dev/null
+/********************* */
+/*! \file rr_inst_match.h
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: bobot
+ ** Minor contributors (to current version): mdeters
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief inst match class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__REWRITERULES__RR_INST_MATCH_H
+#define __CVC4__THEORY__REWRITERULES__RR_INST_MATCH_H
+
+#include "theory/theory.h"
+#include "util/hash.h"
+#include "util/ntuple.h"
+
+#include <ext/hash_set>
+#include <iostream>
+#include <map>
+
+#include "theory/uf/equality_engine.h"
+#include "theory/uf/theory_uf.h"
+#include "context/cdlist.h"
+
+#include "theory/quantifiers/inst_match.h"
+#include "expr/node_manager.h"
+#include "expr/node_builder.h"
+
+#include "theory/quantifiers/options.h"
+#include "theory/rewriterules/options.h"
+
+//#define USE_EFFICIENT_E_MATCHING
+
+namespace CVC4 {
+namespace theory {
+
+namespace rrinst{
+
+class CandidateGenerator
+{
+public:
+ CandidateGenerator(){}
+ virtual ~CandidateGenerator(){};
+
+ /** Get candidates functions. These set up a context to get all match candidates.
+ cg->reset( eqc );
+ do{
+ Node cand = cg->getNextCandidate();
+ //.......
+ }while( !cand.isNull() );
+
+ eqc is the equivalence class you are searching in
+ */
+ virtual void reset( TNode eqc ) = 0;
+ virtual TNode getNextCandidate() = 0;
+ /** call this at the beginning of each instantiation round */
+ virtual void resetInstantiationRound() = 0;
+public:
+ /** legal candidate */
+ static inline bool isLegalCandidate( TNode n ){
+ return !n.getAttribute(NoMatchAttribute()) &&
+ ( !options::cbqi() || !n.hasAttribute(InstConstantAttribute())) &&
+ ( !options::efficientEMatching() || n.hasAttribute(AvailableInTermDb()) );
+}
+
+};
+
+
+inline std::ostream& operator<<(std::ostream& out, const InstMatch& m) {
+ m.toStream(out);
+ return out;
+}
+
+template<bool modEq = false> class InstMatchTrie2;
+template<bool modEq = false> class InstMatchTrie2Pairs;
+
+template<bool modEq = false>
+class InstMatchTrie2Gen
+{
+ friend class InstMatchTrie2<modEq>;
+ friend class InstMatchTrie2Pairs<modEq>;
+
+private:
+
+ class Tree {
+ public:
+ typedef std::hash_map< Node, Tree *, NodeHashFunction > MLevel;
+ MLevel e;
+ const size_t level; //context level of creation
+ Tree() CVC4_UNDEFINED;
+ const Tree & operator =(const Tree & t){
+ Assert(t.e.empty()); Assert(e.empty());
+ Assert(t.level == level);
+ return t;
+ }
+ Tree(size_t l): level(l) {};
+ ~Tree(){
+ for(typename MLevel::iterator i = e.begin(); i!=e.end(); ++i)
+ delete(i->second);
+ };
+ };
+
+
+ typedef std::pair<Tree *, TNode> Mod;
+
+ class CleanUp{
+ public:
+ inline void operator()(Mod * m){
+ typename Tree::MLevel::iterator i = m->first->e.find(m->second);
+ Assert (i != m->first->e.end()); //should not have been already removed
+ m->first->e.erase(i);
+ };
+ };
+
+ EqualityQuery* d_eQ;
+ CandidateGenerator * d_cG;
+
+ context::Context* d_context;
+ context::CDList<Mod, CleanUp, std::allocator<Mod> > d_mods;
+
+
+ typedef std::map<Node, Node>::const_iterator mapIter;
+
+ /** add the substitution given by the iterator*/
+ void addSubTree( Tree * root, mapIter current, mapIter end, size_t currLevel);
+ /** test if it exists match, modulo uf-equations if modEq is true if
+ * return false the deepest point of divergence is put in [e] and
+ * [diverge].
+ */
+ bool existsInstMatch( Tree * root,
+ mapIter & current, mapIter & end,
+ Tree * & e, mapIter & diverge) const;
+
+ /** add match m in the trie root
+ return true if it was never seen */
+ bool addInstMatch( InstMatch& m, Tree * root);
+
+public:
+ InstMatchTrie2Gen(context::Context* c, QuantifiersEngine* q);
+ InstMatchTrie2Gen(const InstMatchTrie2Gen &) CVC4_UNDEFINED;
+ const InstMatchTrie2Gen & operator =(const InstMatchTrie2Gen & e) CVC4_UNDEFINED;
+};
+
+template<bool modEq>
+class InstMatchTrie2
+{
+ typename InstMatchTrie2Gen<modEq>::Tree d_data;
+ InstMatchTrie2Gen<modEq> d_backtrack;
+public:
+ InstMatchTrie2(context::Context* c, QuantifiersEngine* q): d_data(0),
+ d_backtrack(c,q) {};
+ InstMatchTrie2(const InstMatchTrie2 &) CVC4_UNDEFINED;
+ const InstMatchTrie2 & operator =(const InstMatchTrie2 & e) CVC4_UNDEFINED;
+ /** add match m in the trie,
+ return true if it was never seen */
+ inline bool addInstMatch( InstMatch& m){
+ return d_backtrack.addInstMatch(m,&d_data);
+ };
+
+};/* class InstMatchTrie2 */
+
+class Matcher
+{
+public:
+ /** reset instantiation round (call this whenever equivalence classes have changed) */
+ virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
+ /** reset the term to match, return false if there is no such term */
+ virtual bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe ) = 0;
+ /** get the next match. If it return false once you shouldn't call
+ getNextMatch again before doing a reset */
+ virtual bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) = 0;
+ /** If reset, or getNextMatch return false they remove from the
+ InstMatch the binding that they have previously created */
+
+ /** virtual Matcher in order to have definned behavior */
+ virtual ~Matcher(){};
+};
+
+
+class ApplyMatcher: public Matcher{
+private:
+ /** What to check first: constant and variable */
+ std::vector< triple< TNode,size_t,EqualityQuery* > > d_constants;
+ std::vector< triple< TNode,size_t,EqualityQuery* > > d_variables;
+ /** children generators, only the sub-pattern which are
+ neither a variable neither a constant appears */
+ std::vector< triple< Matcher*, size_t, EqualityQuery* > > d_childrens;
+ /** the variable that have been set by this matcher (during its own reset) */
+ std::vector< TNode > d_binded; /* TNode because the variable are already in d_pattern */
+ /** the representant of the argument of the term given by the last reset */
+ std::vector< Node > d_reps;
+public:
+ /** The pattern we are producing matches for */
+ Node d_pattern;
+public:
+ /** constructors */
+ ApplyMatcher( Node pat, QuantifiersEngine* qe);
+ /** destructor */
+ ~ApplyMatcher(){/*TODO delete dandling pointers? */}
+ /** reset instantiation round (call this whenever equivalence classes have changed) */
+ void resetInstantiationRound( QuantifiersEngine* qe );
+ /** reset the term to match */
+ bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe );
+ /** get the next match. */
+ bool getNextMatch(InstMatch& m, QuantifiersEngine* qe);
+private:
+ bool getNextMatch(InstMatch& m, QuantifiersEngine* qe, bool reset);
+};
+
+
+/* Match literal so you don't choose the equivalence class( */
+class PatMatcher
+{
+public:
+ /** reset instantiation round (call this whenever equivalence classes have changed) */
+ virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
+ /** reset the matcher, return false if there is no such term */
+ virtual bool reset( InstMatch& m, QuantifiersEngine* qe ) = 0;
+ /** get the next match. If it return false once you shouldn't call
+ getNextMatch again before doing a reset */
+ virtual bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) = 0;
+ /** If reset, or getNextMatch return false they remove from the
+ InstMatch the binding that they have previously created */
+};
+
+Matcher* mkMatcher( Node pat, QuantifiersEngine* qe );
+PatMatcher* mkPattern( Node pat, QuantifiersEngine* qe );
+
+/* Match literal so you don't choose the equivalence class( */
+class PatsMatcher
+{
+public:
+ /** reset instantiation round (call this whenever equivalence classes have changed) */
+ virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
+ /** reset the matcher, return false if there is no such term */
+ virtual bool getNextMatch( QuantifiersEngine* qe ) = 0;
+ virtual const InstMatch& getInstMatch() = 0;
+ /** Add directly the instantiation to quantifiers engine */
+ virtual int addInstantiations( InstMatch& baseMatch, Node quant, QuantifiersEngine* qe) = 0;
+};
+
+PatsMatcher* mkPatterns( std::vector< Node > pat, QuantifiersEngine* qe );
+PatsMatcher* mkPatternsEfficient( std::vector< Node > pat, QuantifiersEngine* qe );
+
+/** return true if whatever Node is subsituted for the variables the
+ given Node can't match the pattern */
+bool nonunifiable( TNode t, TNode pat, const std::vector<Node> & vars);
+
+class InstMatchGenerator;
+
+}/* CVC4::theory rrinst */
+
+}/* CVC4::theory namespace */
+
+}/* CVC4 namespace */
+
+#endif /* __CVC4__THEORY__REWRITERULES__RR_INST_MATCH_H */
--- /dev/null
+/********************* */
+/*! \file rr_inst_match_impl.h
+ ** \verbatim
+ ** Original author: bobot
+ ** Major contributors: none
+ ** Minor contributors (to current version): ajreynol, mdeters
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief inst match class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__REWRITERULES__RR_INST_MATCH_IMPL_H
+#define __CVC4__THEORY__REWRITERULES__RR_INST_MATCH_IMPL_H
+
+#include "theory/rewriterules/rr_inst_match.h"
+#include "theory/theory_engine.h"
+#include "theory/quantifiers_engine.h"
+#include "theory/rewriterules/rr_candidate_generator.h"
+#include "theory/uf/equality_engine.h"
+
+namespace CVC4 {
+namespace theory {
+namespace rrinst {
+
+template<bool modEq>
+InstMatchTrie2Gen<modEq>::InstMatchTrie2Gen(context::Context* c, QuantifiersEngine* qe):
+ d_context(c), d_mods(c) {
+ d_eQ = qe->getEqualityQuery();
+ d_cG = qe->getRRCanGenClass();
+};
+
+/** add match m for quantifier f starting at index, take into account equalities q, return true if successful */
+template<bool modEq>
+void InstMatchTrie2Gen<modEq>::addSubTree( Tree * root, mapIter current, mapIter end, size_t currLevel ) {
+ if( current == end ) return;
+
+ Assert(root->e.find(current->second) == root->e.end());
+ Tree * root2 = new Tree(currLevel);
+ root->e.insert(std::make_pair(current->second, root2));
+ addSubTree(root2, ++current, end, currLevel );
+}
+
+/** exists match */
+template<bool modEq>
+bool InstMatchTrie2Gen<modEq>::existsInstMatch(InstMatchTrie2Gen<modEq>::Tree * root,
+ mapIter & current, mapIter & end,
+ Tree * & e, mapIter & diverge) const{
+ if( current == end ) {
+ Debug("Trie2") << "Trie2 Bottom " << std::endl;
+ --current;
+ return true;
+ }; //Already their
+
+ if (current->first > diverge->first){
+ // this point is the deepest point currently seen map are ordered
+ e = root;
+ diverge = current;
+ };
+
+ TNode n = current->second;
+ typename InstMatchTrie2Gen<modEq>::Tree::MLevel::iterator it =
+ root->e.find( n );
+ if( it!=root->e.end() &&
+ existsInstMatch( (*it).second, ++current, end, e, diverge) ){
+ Debug("Trie2") << "Trie2 Directly here " << n << std::endl;
+ --current;
+ return true;
+ }
+ Assert( it==root->e.end() || e != root );
+
+ // Even if n is in the trie others of the equivalence class
+ // can also be in it since the equality can have appeared
+ // after they have been added
+ if( modEq && d_eQ->hasTerm( n ) ){
+ //check modulo equality if any other instantiation match exists
+ d_cG->reset( d_eQ->getRepresentative( n ) );
+ for(TNode en = d_cG->getNextCandidate() ; !en.isNull() ;
+ en = d_cG->getNextCandidate() ){
+ if( en == n ) continue; // already tested
+ typename InstMatchTrie2Gen<modEq>::Tree::MLevel::iterator itc =
+ root->e.find( en );
+ if( itc!=root->e.end() &&
+ existsInstMatch( (*itc).second, ++current, end, e, diverge) ){
+ Debug("Trie2") << "Trie2 Indirectly here by equality " << n << " = " << en << std::endl;
+ --current;
+ return true;
+ }
+ Assert( itc==root->e.end() || e != root );
+ }
+ }
+ --current;
+ return false;
+}
+
+template<bool modEq>
+bool InstMatchTrie2Gen<modEq>::
+addInstMatch( InstMatch& m, InstMatchTrie2Gen<modEq>::Tree* e ) {
+ d_cG->resetInstantiationRound();
+ mapIter begin = m.begin();
+ mapIter end = m.end();
+ mapIter diverge = begin;
+ if( !existsInstMatch(e, begin, end, e, diverge ) ){
+ Assert(!diverge->second.isNull());
+ size_t currLevel = d_context->getLevel();
+ addSubTree( e, diverge, end, currLevel );
+ if(e->level != currLevel)
+ //If same level that e, will be removed at the same time than e
+ d_mods.push_back(std::make_pair(e,diverge->second));
+ return true;
+ }else{
+ return false;
+ }
+}
+
+}/* CVC4::theory::rrinst namespace */
+
+}/* CVC4::theory namespace */
+
+}/* CVC4 namespace */
+
+#endif /* __CVC4__THEORY__REWRITERULES__RR_INST_MATCH_IMPL_H */
--- /dev/null
+/********************* */
+/*! \file rr_trigger.cpp
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: mdeters
+ ** Minor contributors (to current version): bobot
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Implementation of trigger class
+ **/
+
+#include "theory/rewriterules/rr_trigger.h"
+#include "theory/theory_engine.h"
+#include "theory/quantifiers_engine.h"
+#include "theory/uf/theory_uf_instantiator.h"
+#include "theory/rewriterules/rr_candidate_generator.h"
+#include "theory/uf/equality_engine.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::rrinst;
+
+//#define NESTED_PATTERN_SELECTION
+
+Trigger* Trigger::TrTrie::getTrigger2( std::vector< Node >& nodes ){
+ if( nodes.empty() ){
+ return d_tr;
+ }else{
+ Node n = nodes.back();
+ nodes.pop_back();
+ if( d_children.find( n )!=d_children.end() ){
+ return d_children[n]->getTrigger2( nodes );
+ }else{
+ return NULL;
+ }
+ }
+}
+void Trigger::TrTrie::addTrigger2( std::vector< Node >& nodes, Trigger* t ){
+ if( nodes.empty() ){
+ d_tr = t;
+ }else{
+ Node n = nodes.back();
+ nodes.pop_back();
+ if( d_children.find( n )==d_children.end() ){
+ d_children[n] = new TrTrie;
+ }
+ d_children[n]->addTrigger2( nodes, t );
+ }
+}
+
+/** trigger static members */
+std::map< Node, std::vector< Node > > Trigger::d_var_contains;
+int Trigger::trCount = 0;
+Trigger::TrTrie Trigger::d_tr_trie;
+
+/** trigger class constructor */
+Trigger::Trigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool smartTriggers ) :
+d_quantEngine( qe ), d_f( f ){
+ trCount++;
+ d_nodes.insert( d_nodes.begin(), nodes.begin(), nodes.end() );
+ Debug("trigger") << "Trigger for " << f << ": " << d_nodes << std::endl;
+ if(matchOption == MATCH_GEN_DEFAULT) d_mg = mkPatterns( d_nodes, qe );
+ else d_mg = mkPatternsEfficient( d_nodes, qe );
+ if( d_nodes.size()==1 ){
+ if( isSimpleTrigger( d_nodes[0] ) ){
+ ++(qe->d_statistics.d_triggers);
+ }else{
+ ++(qe->d_statistics.d_simple_triggers);
+ }
+ }else{
+ Debug("multi-trigger") << "Multi-trigger " << (*this) << std::endl;
+ //std::cout << "Multi-trigger for " << f << " : " << std::endl;
+ //std::cout << " " << (*this) << std::endl;
+ ++(qe->d_statistics.d_multi_triggers);
+ }
+}
+void Trigger::computeVarContains( Node n ) {
+ if( d_var_contains.find( n )==d_var_contains.end() ){
+ d_var_contains[n].clear();
+ computeVarContains2( n, n );
+ }
+}
+
+void Trigger::computeVarContains2( Node n, Node parent ){
+ if( n.getKind()==INST_CONSTANT ){
+ if( std::find( d_var_contains[parent].begin(), d_var_contains[parent].end(), n )==d_var_contains[parent].end() ){
+ d_var_contains[parent].push_back( n );
+ }
+ }else{
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ computeVarContains2( n[i], parent );
+ }
+ }
+}
+
+void Trigger::resetInstantiationRound(){
+ d_mg->resetInstantiationRound( d_quantEngine );
+}
+
+
+bool Trigger::getNextMatch(){
+ bool retVal = d_mg->getNextMatch( d_quantEngine );
+ //m.makeInternal( d_quantEngine->getEqualityQuery() );
+ return retVal;
+}
+
+// bool Trigger::getMatch( Node t, InstMatch& m ){
+// //FIXME: this assumes d_mg is an inst match generator
+// return ((InstMatchGenerator*)d_mg)->getMatch( t, m, d_quantEngine );
+// }
+
+
+int Trigger::addInstantiations( InstMatch& baseMatch ){
+ int addedLemmas = d_mg->addInstantiations( baseMatch,
+ d_nodes[0].getAttribute(InstConstantAttribute()),
+ d_quantEngine);
+ if( addedLemmas>0 ){
+ Debug("inst-trigger") << "Added " << addedLemmas << " lemmas, trigger was ";
+ for( int i=0; i<(int)d_nodes.size(); i++ ){
+ Debug("inst-trigger") << d_nodes[i] << " ";
+ }
+ Debug("inst-trigger") << std::endl;
+ }
+ return addedLemmas;
+}
+
+Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool keepAll, int trOption,
+ bool smartTriggers ){
+ std::vector< Node > trNodes;
+ if( !keepAll ){
+ //only take nodes that contribute variables to the trigger when added
+ std::vector< Node > temp;
+ temp.insert( temp.begin(), nodes.begin(), nodes.end() );
+ std::map< Node, bool > vars;
+ std::map< Node, std::vector< Node > > patterns;
+ for( int i=0; i<(int)temp.size(); i++ ){
+ bool foundVar = false;
+ computeVarContains( temp[i] );
+ for( int j=0; j<(int)d_var_contains[ temp[i] ].size(); j++ ){
+ Node v = d_var_contains[ temp[i] ][j];
+ if( v.getAttribute(InstConstantAttribute())==f ){
+ if( vars.find( v )==vars.end() ){
+ vars[ v ] = true;
+ foundVar = true;
+ }
+ }
+ }
+ if( foundVar ){
+ trNodes.push_back( temp[i] );
+ for( int j=0; j<(int)d_var_contains[ temp[i] ].size(); j++ ){
+ Node v = d_var_contains[ temp[i] ][j];
+ patterns[ v ].push_back( temp[i] );
+ }
+ }
+ }
+ //now, minimalize the trigger
+ for( int i=0; i<(int)trNodes.size(); i++ ){
+ bool keepPattern = false;
+ Node n = trNodes[i];
+ for( int j=0; j<(int)d_var_contains[ n ].size(); j++ ){
+ Node v = d_var_contains[ n ][j];
+ if( patterns[v].size()==1 ){
+ keepPattern = true;
+ break;
+ }
+ }
+ if( !keepPattern ){
+ //remove from pattern vector
+ for( int j=0; j<(int)d_var_contains[ n ].size(); j++ ){
+ Node v = d_var_contains[ n ][j];
+ for( int k=0; k<(int)patterns[v].size(); k++ ){
+ if( patterns[v][k]==n ){
+ patterns[v].erase( patterns[v].begin() + k, patterns[v].begin() + k + 1 );
+ break;
+ }
+ }
+ }
+ //remove from trigger nodes
+ trNodes.erase( trNodes.begin() + i, trNodes.begin() + i + 1 );
+ i--;
+ }
+ }
+ }else{
+ trNodes.insert( trNodes.begin(), nodes.begin(), nodes.end() );
+ }
+
+ //check for duplicate?
+ if( trOption==TR_MAKE_NEW ){
+ //static int trNew = 0;
+ //static int trOld = 0;
+ //Trigger* t = d_tr_trie.getTrigger( trNodes );
+ //if( t ){
+ // trOld++;
+ //}else{
+ // trNew++;
+ //}
+ //if( (trNew+trOld)%100==0 ){
+ // std::cout << "Trigger new old = " << trNew << " " << trOld << std::endl;
+ //}
+ }else{
+ Trigger* t = d_tr_trie.getTrigger( trNodes );
+ if( t ){
+ if( trOption==TR_GET_OLD ){
+ //just return old trigger
+ return t;
+ }else{
+ return NULL;
+ }
+ }
+ }
+ Trigger* t = new Trigger( qe, f, trNodes, matchOption, smartTriggers );
+ d_tr_trie.addTrigger( trNodes, t );
+ return t;
+}
+Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, Node n, int matchOption, bool keepAll, int trOption, bool smartTriggers ){
+ std::vector< Node > nodes;
+ nodes.push_back( n );
+ return mkTrigger( qe, f, nodes, matchOption, keepAll, trOption, smartTriggers );
+}
+
+bool Trigger::isUsableTrigger( std::vector< Node >& nodes, Node f ){
+ for( int i=0; i<(int)nodes.size(); i++ ){
+ if( !isUsableTrigger( nodes[i], f ) ){
+ return false;
+ }
+ }
+ return true;
+}
+
+bool Trigger::isUsable( Node n, Node f ){
+ if( n.getAttribute(InstConstantAttribute())==f ){
+ if( !isAtomicTrigger( n ) && n.getKind()!=INST_CONSTANT ){
+ std::map< Node, Node > coeffs;
+ return getPatternArithmetic( f, n, coeffs );
+ }else{
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( !isUsable( n[i], f ) ){
+ return false;
+ }
+ }
+ return true;
+ }
+ }else{
+ return true;
+ }
+}
+
+bool Trigger::isSimpleTrigger( Node n ){
+ if( isAtomicTrigger( n ) ){
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( n[i].getKind()!=INST_CONSTANT && n[i].hasAttribute(InstConstantAttribute()) ){
+ return false;
+ }
+ }
+ return true;
+ }else{
+ return false;
+ }
+}
+
+/** filter all nodes that have instances */
+void Trigger::filterInstances( std::vector< Node >& nodes ){
+ std::vector< bool > active;
+ active.resize( nodes.size(), true );
+ for( int i=0; i<(int)nodes.size(); i++ ){
+ for( int j=i+1; j<(int)nodes.size(); j++ ){
+ if( active[i] && active[j] ){
+ int result = isInstanceOf( nodes[i], nodes[j] );
+ if( result==1 ){
+ active[j] = false;
+ }else if( result==-1 ){
+ active[i] = false;
+ }
+ }
+ }
+ }
+ std::vector< Node > temp;
+ for( int i=0; i<(int)nodes.size(); i++ ){
+ if( active[i] ){
+ temp.push_back( nodes[i] );
+ }
+ }
+ nodes.clear();
+ nodes.insert( nodes.begin(), temp.begin(), temp.end() );
+}
+
+
+bool Trigger::collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt ){
+ if( patMap.find( n )==patMap.end() ){
+ patMap[ n ] = false;
+ if( tstrt==TS_MIN_TRIGGER ){
+ if( n.getKind()==FORALL ){
+#ifdef NESTED_PATTERN_SELECTION
+ //return collectPatTerms2( qe, f, qe->getOrCreateCounterexampleBody( n ), patMap, tstrt );
+ return collectPatTerms2( qe, f, qe->getBoundBody( n ), patMap, tstrt );
+#else
+ return false;
+#endif
+ }else{
+ bool retVal = false;
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( collectPatTerms2( qe, f, n[i], patMap, tstrt ) ){
+ retVal = true;
+ }
+ }
+ if( retVal ){
+ return true;
+ }else if( isUsableTrigger( n, f ) ){
+ patMap[ n ] = true;
+ return true;
+ }else{
+ return false;
+ }
+ }
+ }else{
+ bool retVal = false;
+ if( isUsableTrigger( n, f ) ){
+ patMap[ n ] = true;
+ if( tstrt==TS_MAX_TRIGGER ){
+ return true;
+ }else{
+ retVal = true;
+ }
+ }
+ if( n.getKind()==FORALL ){
+#ifdef NESTED_PATTERN_SELECTION
+ //if( collectPatTerms2( qe, f, qe->getOrCreateCounterexampleBody( n ), patMap, tstrt ) ){
+ // retVal = true;
+ //}
+ if( collectPatTerms2( qe, f, qe->getBoundBody( n ), patMap, tstrt ) ){
+ retVal = true;
+ }
+#endif
+ }else{
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( collectPatTerms2( qe, f, n[i], patMap, tstrt ) ){
+ retVal = true;
+ }
+ }
+ }
+ return retVal;
+ }
+ }else{
+ return patMap[ n ];
+ }
+}
+
+void Trigger::collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, bool filterInst ){
+ std::map< Node, bool > patMap;
+ if( filterInst ){
+ //immediately do not consider any term t for which another term is an instance of t
+ std::vector< Node > patTerms2;
+ collectPatTerms( qe, f, n, patTerms2, TS_ALL, false );
+ std::vector< Node > temp;
+ temp.insert( temp.begin(), patTerms2.begin(), patTerms2.end() );
+ filterInstances( temp );
+ if( temp.size()!=patTerms2.size() ){
+ Debug("trigger-filter-instance") << "Filtered an instance: " << std::endl;
+ Debug("trigger-filter-instance") << "Old: ";
+ for( int i=0; i<(int)patTerms2.size(); i++ ){
+ Debug("trigger-filter-instance") << patTerms2[i] << " ";
+ }
+ Debug("trigger-filter-instance") << std::endl << "New: ";
+ for( int i=0; i<(int)temp.size(); i++ ){
+ Debug("trigger-filter-instance") << temp[i] << " ";
+ }
+ Debug("trigger-filter-instance") << std::endl;
+ }
+ if( tstrt==TS_ALL ){
+ patTerms.insert( patTerms.begin(), temp.begin(), temp.end() );
+ return;
+ }else{
+ //do not consider terms that have instances
+ for( int i=0; i<(int)patTerms2.size(); i++ ){
+ if( std::find( temp.begin(), temp.end(), patTerms2[i] )==temp.end() ){
+ patMap[ patTerms2[i] ] = false;
+ }
+ }
+ }
+ }
+ collectPatTerms2( qe, f, n, patMap, tstrt );
+ for( std::map< Node, bool >::iterator it = patMap.begin(); it != patMap.end(); ++it ){
+ if( it->second ){
+ patTerms.push_back( it->first );
+ }
+ }
+}
+
+/** is n1 an instance of n2 or vice versa? */
+int Trigger::isInstanceOf( Node n1, Node n2 ){
+ if( n1==n2 ){
+ return 1;
+ }else if( n1.getKind()==n2.getKind() ){
+ if( n1.getKind()==APPLY_UF ){
+ if( n1.getOperator()==n2.getOperator() ){
+ int result = 0;
+ for( int i=0; i<(int)n1.getNumChildren(); i++ ){
+ if( n1[i]!=n2[i] ){
+ int cResult = isInstanceOf( n1[i], n2[i] );
+ if( cResult==0 ){
+ return 0;
+ }else if( cResult!=result ){
+ if( result!=0 ){
+ return 0;
+ }else{
+ result = cResult;
+ }
+ }
+ }
+ }
+ return result;
+ }
+ }
+ return 0;
+ }else if( n2.getKind()==INST_CONSTANT ){
+ computeVarContains( n1 );
+ //if( std::find( d_var_contains[ n1 ].begin(), d_var_contains[ n1 ].end(), n2 )!=d_var_contains[ n1 ].end() ){
+ // return 1;
+ //}
+ if( d_var_contains[ n1 ].size()==1 && d_var_contains[ n1 ][ 0 ]==n2 ){
+ return 1;
+ }
+ }else if( n1.getKind()==INST_CONSTANT ){
+ computeVarContains( n2 );
+ //if( std::find( d_var_contains[ n2 ].begin(), d_var_contains[ n2 ].end(), n1 )!=d_var_contains[ n2 ].end() ){
+ // return -1;
+ //}
+ if( d_var_contains[ n2 ].size()==1 && d_var_contains[ n2 ][ 0 ]==n1 ){
+ return 1;
+ }
+ }
+ return 0;
+}
+
+bool Trigger::isVariableSubsume( Node n1, Node n2 ){
+ if( n1==n2 ){
+ return true;
+ }else{
+ //std::cout << "is variable subsume ? " << n1 << " " << n2 << std::endl;
+ computeVarContains( n1 );
+ computeVarContains( n2 );
+ for( int i=0; i<(int)d_var_contains[n2].size(); i++ ){
+ if( std::find( d_var_contains[n1].begin(), d_var_contains[n1].end(), d_var_contains[n2][i] )==d_var_contains[n1].end() ){
+ //std::cout << "no" << std::endl;
+ return false;
+ }
+ }
+ //std::cout << "yes" << std::endl;
+ return true;
+ }
+}
+
+void Trigger::getVarContains( Node f, std::vector< Node >& pats, std::map< Node, std::vector< Node > >& varContains ){
+ for( int i=0; i<(int)pats.size(); i++ ){
+ computeVarContains( pats[i] );
+ varContains[ pats[i] ].clear();
+ for( int j=0; j<(int)d_var_contains[pats[i]].size(); j++ ){
+ if( d_var_contains[pats[i]][j].getAttribute(InstConstantAttribute())==f ){
+ varContains[ pats[i] ].push_back( d_var_contains[pats[i]][j] );
+ }
+ }
+ }
+}
+
+void Trigger::getVarContainsNode( Node f, Node n, std::vector< Node >& varContains ){
+ computeVarContains( n );
+ for( int j=0; j<(int)d_var_contains[n].size(); j++ ){
+ if( d_var_contains[n][j].getAttribute(InstConstantAttribute())==f ){
+ varContains.push_back( d_var_contains[n][j] );
+ }
+ }
+}
+
+bool Trigger::getPatternArithmetic( Node f, Node n, std::map< Node, Node >& coeffs ){
+ if( n.getKind()==PLUS ){
+ Assert( coeffs.empty() );
+ NodeBuilder<> t(kind::PLUS);
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( n[i].hasAttribute(InstConstantAttribute()) ){
+ if( n[i].getKind()==INST_CONSTANT ){
+ if( n[i].getAttribute(InstConstantAttribute())==f ){
+ coeffs[ n[i] ] = Node::null();
+ }else{
+ coeffs.clear();
+ return false;
+ }
+ }else if( !getPatternArithmetic( f, n[i], coeffs ) ){
+ coeffs.clear();
+ return false;
+ }
+ }else{
+ t << n[i];
+ }
+ }
+ if( t.getNumChildren()==0 ){
+ coeffs[ Node::null() ] = NodeManager::currentNM()->mkConst( Rational(0) );
+ }else if( t.getNumChildren()==1 ){
+ coeffs[ Node::null() ] = t.getChild( 0 );
+ }else{
+ coeffs[ Node::null() ] = t;
+ }
+ return true;
+ }else if( n.getKind()==MULT ){
+ if( n[0].getKind()==INST_CONSTANT && n[0].getAttribute(InstConstantAttribute())==f ){
+ Assert( !n[1].hasAttribute(InstConstantAttribute()) );
+ coeffs[ n[0] ] = n[1];
+ return true;
+ }else if( n[1].getKind()==INST_CONSTANT && n[1].getAttribute(InstConstantAttribute())==f ){
+ Assert( !n[0].hasAttribute(InstConstantAttribute()) );
+ coeffs[ n[1] ] = n[0];
+ return true;
+ }
+ }
+ return false;
+}
--- /dev/null
+/********************* */
+/*! \file rr_trigger.h
+ ** \verbatim
+ ** Original author: ajreynol
+ ** Major contributors: bobot
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief trigger class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__REWRITERULES__RR_TRIGGER_H
+#define __CVC4__THEORY__REWRITERULES__RR_TRIGGER_H
+
+#include "theory/rewriterules/rr_inst_match.h"
+
+namespace CVC4 {
+namespace theory {
+namespace rrinst {
+
+//a collect of nodes representing a trigger
+class Trigger {
+public:
+ static int trCount;
+private:
+ /** computation of variable contains */
+ static std::map< Node, std::vector< Node > > d_var_contains;
+ static void computeVarContains( Node n );
+ static void computeVarContains2( Node n, Node parent );
+private:
+ /** the quantifiers engine */
+ QuantifiersEngine* d_quantEngine;
+ /** the quantifier this trigger is for */
+ Node d_f;
+ /** match generators */
+ PatsMatcher * d_mg;
+private:
+ /** a trie of triggers */
+ class TrTrie
+ {
+ private:
+ Trigger* getTrigger2( std::vector< Node >& nodes );
+ void addTrigger2( std::vector< Node >& nodes, Trigger* t );
+ public:
+ TrTrie() : d_tr( NULL ){}
+ Trigger* d_tr;
+ std::map< Node, TrTrie* > d_children;
+ Trigger* getTrigger( std::vector< Node >& nodes ){
+ std::vector< Node > temp;
+ temp.insert( temp.begin(), nodes.begin(), nodes.end() );
+ std::sort( temp.begin(), temp.end() );
+ return getTrigger2( temp );
+ }
+ void addTrigger( std::vector< Node >& nodes, Trigger* t ){
+ std::vector< Node > temp;
+ temp.insert( temp.begin(), nodes.begin(), nodes.end() );
+ std::sort( temp.begin(), temp.end() );
+ return addTrigger2( temp, t );
+ }
+ };
+ /** all triggers will be stored in this trie */
+ static TrTrie d_tr_trie;
+private:
+ /** trigger constructor */
+ Trigger( QuantifiersEngine* ie, Node f, std::vector< Node >& nodes, int matchOption = 0, bool smartTriggers = false );
+public:
+ ~Trigger(){}
+public:
+ std::vector< Node > d_nodes;
+public:
+ void debugPrint( const char* c );
+ PatsMatcher* getGenerator() { return d_mg; }
+public:
+ /** reset instantiation round (call this whenever equivalence classes have changed) */
+ void resetInstantiationRound();
+ /** get next match. must call reset( eqc ) once before this function. */
+ bool getNextMatch();
+ const InstMatch & getInstMatch(){return d_mg->getInstMatch();};
+ /** return whether this is a multi-trigger */
+ bool isMultiTrigger() { return d_nodes.size()>1; }
+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);
+ /** mkTrigger method
+ ie : quantifier engine;
+ f : forall something ....
+ nodes : (multi-)trigger
+ matchOption : which policy to use for creating matches (one of InstMatchGenerator::MATCH_GEN_* )
+ keepAll: don't remove unneeded patterns;
+ trOption : policy for dealing with triggers that already existed (see below)
+ */
+ enum {
+ //options for producing matches
+ MATCH_GEN_DEFAULT = 0,
+ MATCH_GEN_EFFICIENT_E_MATCH, //generate matches via Efficient E
+ };
+ enum{
+ TR_MAKE_NEW, //make new trigger even if it already may exist
+ TR_GET_OLD, //return a previous trigger if it had already been created
+ TR_RETURN_NULL //return null if a duplicate is found
+ };
+ static Trigger* mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes,
+ int matchOption = 0, bool keepAll = true, int trOption = TR_MAKE_NEW,
+ bool smartTriggers = false );
+ static Trigger* mkTrigger( QuantifiersEngine* qe, Node f, Node n,
+ int matchOption = 0, bool keepAll = true, int trOption = TR_MAKE_NEW,
+ bool smartTriggers = false );
+private:
+ /** is subterm of trigger usable */
+ static bool isUsable( Node n, Node f );
+ /** collect all APPLY_UF pattern terms for f in n */
+ static bool collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt );
+public:
+ //different strategies for choosing trigger terms
+ enum {
+ TS_MAX_TRIGGER = 0,
+ TS_MIN_TRIGGER,
+ TS_ALL,
+ };
+ static void collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, bool filterInst = false );
+public:
+ /** is usable trigger */
+ static inline bool isUsableTrigger( TNode n, TNode f ){
+ //return n.getAttribute(InstConstantAttribute())==f && n.getKind()==APPLY_UF;
+ return n.getAttribute(InstConstantAttribute())==f && isAtomicTrigger( n ) && isUsable( n, f );
+ }
+ static inline bool isAtomicTrigger( TNode n ){
+ return
+ n.getKind()==kind::APPLY_UF ||
+ n.getKind()==kind::SELECT ||
+ n.getKind()==kind::STORE;
+ }
+ static bool isUsableTrigger( std::vector< Node >& nodes, Node f );
+ static bool isSimpleTrigger( Node n );
+ /** filter all nodes that have instances */
+ static void filterInstances( std::vector< Node >& nodes );
+ /** -1: n1 is an instance of n2, 1: n1 is an instance of n2 */
+ static int isInstanceOf( Node n1, Node n2 );
+ /** variables subsume, return true if n1 contains all free variables in n2 */
+ static bool isVariableSubsume( Node n1, Node n2 );
+ /** get var contains */
+ static void getVarContains( Node f, std::vector< Node >& pats, std::map< Node, std::vector< Node > >& varContains );
+ static void getVarContainsNode( Node f, Node n, std::vector< Node >& varContains );
+ /** get pattern arithmetic */
+ static bool getPatternArithmetic( Node f, Node n, std::map< Node, Node >& coeffs );
+
+ inline void toStream(std::ostream& out) const {
+ out << "TRIGGER( ";
+ for( int i=0; i<(int)d_nodes.size(); i++ ){
+ if( i>0 ){ out << ", "; }
+ out << d_nodes[i];
+ }
+ out << " )";
+ }
+};
+
+inline std::ostream& operator<<(std::ostream& out, const Trigger & tr) {
+ tr.toStream(out);
+ return out;
+}
+
+}/* CVC4::theory::rrinst namespace */
+
+}/* CVC4::theory namespace */
+
+}/* CVC4 namespace */
+
+#endif /* __CVC4__THEORY__REWRITERULES__RR_TRIGGER_H */
#include "theory/theory_engine.h"
#include "theory/quantifiers_engine.h"
#include "context/context_mm.h"
-#include "theory/rr_inst_match_impl.h"
-#include "theory/rr_trigger.h"
-#include "theory/rr_inst_match.h"
+#include "theory/rewriterules/rr_inst_match_impl.h"
+#include "theory/rewriterules/rr_trigger.h"
+#include "theory/rewriterules/rr_inst_match.h"
#include "util/stats.h"
#include "theory/rewriterules/theory_rewriterules_preprocess.h"
#include "theory/model.h"
+++ /dev/null
-/********************* */
-/*! \file rr_candidate_generator.cpp
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: bobot
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Implementation of rr candidate generator class
- **/
-
-#include "theory/rr_candidate_generator.h"
-#include "theory/theory_engine.h"
-#include "theory/uf/theory_uf.h"
-#include "theory/quantifiers/term_database.h"
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::rrinst;
-
-GenericCandidateGeneratorClasses::GenericCandidateGeneratorClasses(QuantifiersEngine * qe){
- for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
- if(qe->getInstantiator(i) != NULL)
- d_can_gen[i] = qe->getInstantiator(i)->getRRCanGenClasses();
- else d_can_gen[i] = NULL;
- }
-}
-
-GenericCandidateGeneratorClasses::~GenericCandidateGeneratorClasses(){
- for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
- delete(d_can_gen[i]);
- }
-}
-
-void GenericCandidateGeneratorClasses::resetInstantiationRound(){
- for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
- if(d_can_gen[i] != NULL) d_can_gen[i]->resetInstantiationRound();
- }
- d_can_gen_id=THEORY_FIRST;
-}
-
-void GenericCandidateGeneratorClasses::reset(TNode eqc){
- Assert(eqc.isNull());
- for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
- if(d_can_gen[i] != NULL) d_can_gen[i]->reset(eqc);
- }
- d_can_gen_id=THEORY_FIRST;
- lookForNextTheory();
-}
-
-TNode GenericCandidateGeneratorClasses::getNextCandidate(){
- Assert(THEORY_FIRST <= d_can_gen_id && d_can_gen_id <= THEORY_LAST);
- /** No more */
- if(d_can_gen_id == THEORY_LAST) return TNode::null();
- /** Try with this theory */
- TNode cand = d_can_gen[d_can_gen_id]->getNextCandidate();
- if( !cand.isNull() ) return cand;
- lookForNextTheory();
- return getNextCandidate();
-}
-
-void GenericCandidateGeneratorClasses::lookForNextTheory(){
- do{ /* look for the next available generator */
- ++d_can_gen_id;
- } while( d_can_gen_id < THEORY_LAST && d_can_gen[d_can_gen_id] == NULL);
-}
-
-GenericCandidateGeneratorClass::GenericCandidateGeneratorClass(QuantifiersEngine * qe): d_qe(qe) {
- for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
- if(d_qe->getInstantiator(i) != NULL)
- d_can_gen[i] = d_qe->getInstantiator(i)->getRRCanGenClass();
- else d_can_gen[i] = NULL;
- }
-}
-
-GenericCandidateGeneratorClass::~GenericCandidateGeneratorClass(){
- for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
- delete(d_can_gen[i]);
- }
-}
-
-void GenericCandidateGeneratorClass::resetInstantiationRound(){
- for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
- if(d_can_gen[i] != NULL) d_can_gen[i]->resetInstantiationRound();
- }
- d_can_gen_id=THEORY_FIRST;
-}
-
-void GenericCandidateGeneratorClass::reset(TNode eqc){
- for(TheoryId i = THEORY_FIRST; i < theory::THEORY_LAST; ++i){
- if(d_can_gen[i] != NULL) d_can_gen[i]->reset(eqc);
- }
- d_can_gen_id=THEORY_FIRST;
- d_node = eqc;
- lookForNextTheory();
-}
-
-TNode GenericCandidateGeneratorClass::getNextCandidate(){
- Assert(THEORY_FIRST <= d_can_gen_id && d_can_gen_id <= THEORY_LAST);
- /** No more */
- if(d_can_gen_id == THEORY_LAST) return TNode::null();
- /** Try with this theory */
- TNode cand = d_can_gen[d_can_gen_id]->getNextCandidate();
- if( !cand.isNull() ) return cand;
- lookForNextTheory();
- return getNextCandidate();
-}
-
-void GenericCandidateGeneratorClass::lookForNextTheory(){
- do{ /* look for the next available generator, where the element is */
- ++d_can_gen_id;
- } while(
- d_can_gen_id < THEORY_LAST &&
- (d_can_gen[d_can_gen_id] == NULL ||
- !d_qe->getInstantiator( d_can_gen_id )->hasTerm( d_node ))
- );
-}
+++ /dev/null
-/********************* */
-/*! \file rr_candidate_generator.h
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: bobot
- ** Minor contributors (to current version): mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief rr candidate generator
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__THEORY_UF_CANDIDATE_GENERATOR_H
-#define __CVC4__THEORY_UF_CANDIDATE_GENERATOR_H
-
-#include "theory/quantifiers_engine.h"
-#include "theory/quantifiers/term_database.h"
-#include "theory/rr_inst_match.h"
-
-using namespace CVC4::theory::quantifiers;
-
-namespace CVC4 {
-namespace theory {
-namespace eq {
-
-namespace rrinst{
-typedef CVC4::theory::rrinst::CandidateGenerator CandidateGenerator;
-
-//New CandidateGenerator. They have a simpler semantic than the old one
-
-// Just iterate amoung the equivalence classes
-// node::Null() must be given to reset
-class CandidateGeneratorTheoryEeClasses : public CandidateGenerator{
-private:
- //the equality classes iterator
- eq::EqClassesIterator d_eq;
- //equalityengine pointer
- EqualityEngine* d_ee;
-public:
- CandidateGeneratorTheoryEeClasses( EqualityEngine * ee): d_ee( ee ){}
- ~CandidateGeneratorTheoryEeClasses(){}
- void resetInstantiationRound(){};
- void reset( TNode eqc ){
- Assert(eqc.isNull());
- d_eq = eq::EqClassesIterator( d_ee );
- }; //* the argument is not used
- TNode getNextCandidate(){
- if( !d_eq.isFinished() ) return (*(d_eq++));
- else return Node::null();
- };
-};
-
-// Just iterate amoung the equivalence class of the given node
-// node::Null() *can't* be given to reset
-class CandidateGeneratorTheoryEeClass : public CandidateGenerator{
-private:
- //instantiator pointer
- EqualityEngine* d_ee;
- //the equality class iterator
- eq::EqClassIterator d_eqc;
- /* For the case where the given term doesn't exists in uf */
- Node d_retNode;
-public:
- CandidateGeneratorTheoryEeClass( EqualityEngine* ee): d_ee( ee ){}
- ~CandidateGeneratorTheoryEeClass(){}
- void resetInstantiationRound(){};
- void reset( TNode eqc ){
- Assert(!eqc.isNull());
- if( d_ee->hasTerm( eqc ) ){
- /* eqc is in uf */
- eqc = d_ee->getRepresentative( eqc );
- d_eqc = eq::EqClassIterator( eqc, d_ee );
- d_retNode = Node::null();
- }else{
- /* If eqc if not a term known by uf, it is the only one in its
- equivalence class. So we will return only it */
- d_retNode = eqc;
- d_eqc = eq::EqClassIterator();
- }
- }; //* the argument is not used
- TNode getNextCandidate(){
- if(d_retNode.isNull()){
- if( !d_eqc.isFinished() ) return (*(d_eqc++));
- else return Node::null();
- }else{
- /* the case where eqc not in uf */
- Node ret = d_retNode;
- d_retNode = Node::null(); /* d_eqc.isFinished() must be true */
- return ret;
- }
- };
-};
-
-
-} /* namespace rrinst */
-} /* namespace eq */
-
-namespace uf{
-namespace rrinst {
-
-typedef CVC4::theory::rrinst::CandidateGenerator CandidateGenerator;
-
-class CandidateGeneratorTheoryUfOp : public CandidateGenerator{
-private:
- Node d_op;
- //instantiator pointer
- TermDb* d_tdb;
- // Since new term can appears we restrict ourself to the one that
- // exists at resetInstantiationRound
- size_t d_term_iter_limit;
- size_t d_term_iter;
-public:
- CandidateGeneratorTheoryUfOp(Node op, TermDb* tdb): d_op(op), d_tdb( tdb ){}
- ~CandidateGeneratorTheoryUfOp(){}
- void resetInstantiationRound(){
- d_term_iter_limit = d_tdb->d_op_map[d_op].size();
- };
- void reset( TNode eqc ){
- Assert(eqc.isNull());
- d_term_iter = 0;
- }; //* the argument is not used
- TNode getNextCandidate(){
- if( d_term_iter<d_term_iter_limit ){
- TNode n = d_tdb->d_op_map[d_op][d_term_iter];
- ++d_term_iter;
- return n;
- } else return Node::null();
- };
-};
-
-class CandidateGeneratorTheoryUfType : public CandidateGenerator{
-private:
- TypeNode d_type;
- //instantiator pointer
- TermDb* d_tdb;
- // Since new term can appears we restrict ourself to the one that
- // exists at resetInstantiationRound
- size_t d_term_iter_limit;
- size_t d_term_iter;
-public:
- CandidateGeneratorTheoryUfType(TypeNode type, TermDb* tdb): d_type(type), d_tdb( tdb ){}
- ~CandidateGeneratorTheoryUfType(){}
- void resetInstantiationRound(){
- d_term_iter_limit = d_tdb->d_type_map[d_type].size();
- };
- void reset( TNode eqc ){
- Assert(eqc.isNull());
- d_term_iter = 0;
- }; //* the argument is not used
- TNode getNextCandidate(){
- if( d_term_iter<d_term_iter_limit ){
- TNode n = d_tdb->d_type_map[d_type][d_term_iter];
- ++d_term_iter;
- return n;
- } else return Node::null();
- };
-};
-
-} /* namespace rrinst */
-} /* namespace uf */
-
-class GenericCandidateGeneratorClasses: public rrinst::CandidateGenerator{
-
- /** The candidate generators */
- rrinst::CandidateGenerator* d_can_gen[theory::THEORY_LAST];
- /** The current theory which candidategenerator is used */
- TheoryId d_can_gen_id;
-
-public:
- GenericCandidateGeneratorClasses(QuantifiersEngine * qe);
- ~GenericCandidateGeneratorClasses();
-
- void resetInstantiationRound();
- void reset(TNode eqc);
- TNode getNextCandidate();
- void lookForNextTheory();
-};
-
-class GenericCandidateGeneratorClass: public rrinst::CandidateGenerator{
-
- /** The candidate generators */
- rrinst::CandidateGenerator* d_can_gen[theory::THEORY_LAST];
- /** The current theory which candidategenerator is used */
- TheoryId d_can_gen_id;
- /** current node to look for equivalence class */
- Node d_node;
- /** QuantifierEngine */
- QuantifiersEngine* d_qe;
-
-public:
- GenericCandidateGeneratorClass(QuantifiersEngine * qe);
- ~GenericCandidateGeneratorClass();
- void resetInstantiationRound();
-
- void reset(TNode eqc);
- TNode getNextCandidate();
- void lookForNextTheory();
-};
-
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
-
-#endif /* __CVC4__THEORY_UF_INSTANTIATOR_H */
+++ /dev/null
-/********************* */
-/*! \file rr_inst_match.cpp
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: bobot
- ** Minor contributors (to current version): mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Implementation of inst match class
- **/
-
-#include "theory/inst_match.h"
-#include "theory/theory_engine.h"
-#include "theory/quantifiers_engine.h"
-#include "theory/uf/theory_uf_instantiator.h"
-#include "theory/uf/equality_engine.h"
-#include "theory/arrays/theory_arrays.h"
-#include "theory/datatypes/theory_datatypes.h"
-#include "theory/rr_inst_match.h"
-#include "theory/rr_trigger.h"
-#include "theory/rr_inst_match_impl.h"
-#include "theory/rr_candidate_generator.h"
-
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::rrinst;
-using namespace CVC4::theory::uf::rrinst;
-using namespace CVC4::theory::eq::rrinst;
-
-namespace CVC4{
-namespace theory{
-namespace rrinst{
-
-typedef CVC4::theory::inst::InstMatch InstMatch;
-typedef CVC4::theory::inst::CandidateGeneratorQueue CandidateGeneratorQueue;
-
-template<bool modEq>
-class InstMatchTrie2Pairs
-{
- typename std::vector< std::vector < typename InstMatchTrie2Gen<modEq>::Tree > > d_data;
- InstMatchTrie2Gen<modEq> d_backtrack;
-public:
- InstMatchTrie2Pairs(context::Context* c, QuantifiersEngine* q, size_t n):
- d_backtrack(c,q) {
- // resize to a triangle
- //
- // | *
- // | * *
- // | * * *
- // | -----> i
- d_data.resize(n);
- for(size_t i=0; i < n; ++i){
- d_data[i].resize(i+1,typename InstMatchTrie2Gen<modEq>::Tree(0));
- }
- };
- InstMatchTrie2Pairs(const InstMatchTrie2Pairs &) CVC4_UNDEFINED;
- const InstMatchTrie2Pairs & operator =(const InstMatchTrie2Pairs & e) CVC4_UNDEFINED;
- /** add match m in the trie,
- return true if it was never seen */
- inline bool addInstMatch( size_t i, size_t j, InstMatch& m){
- size_t k = std::min(i,j);
- size_t l = std::max(i,j);
- return d_backtrack.addInstMatch(m,&(d_data[l][k]));
- };
- inline bool addInstMatch( size_t i, InstMatch& m){
- return d_backtrack.addInstMatch(m,&(d_data[i][i]));
- };
-
-};
-
-
-// Currently the implementation doesn't take into account that
-// variable should have the same value given.
-// TODO use the d_children way perhaps
-// TODO replace by a real dictionnary
-// We should create a real substitution? slower more precise
-// We don't do that often
-bool nonunifiable( TNode t0, TNode pat, const std::vector<Node> & vars){
- if(pat.isNull()) return true;
-
- typedef std::vector<std::pair<TNode,TNode> > tstack;
- tstack stack(1,std::make_pair(t0,pat)); // t * pat
-
- while(!stack.empty()){
- const std::pair<TNode,TNode> p = stack.back(); stack.pop_back();
- const TNode & t = p.first;
- const TNode & pat = p.second;
-
- // t or pat is a variable currently we consider that can match anything
- if( find(vars.begin(),vars.end(),t) != vars.end() ) continue;
- if( pat.getKind() == INST_CONSTANT ) continue;
-
- // t and pat are nonunifiable
- if( !Trigger::isAtomicTrigger( t ) || !Trigger::isAtomicTrigger( pat ) ) {
- if(t == pat) continue;
- else return true;
- };
- if( t.getOperator() != pat.getOperator() ) return true;
-
- //put the children on the stack
- for( size_t i=0; i < pat.getNumChildren(); i++ ){
- stack.push_back(std::make_pair(t[i],pat[i]));
- };
- }
- // The heuristic can't find non-unifiability
- return false;
-};
-
-/** New things */
-class DumbMatcher: public Matcher{
- void resetInstantiationRound( QuantifiersEngine* qe ){};
- bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe ){
- return false;
- }
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- return false;
- }
-};
-
-class DumbPatMatcher: public PatMatcher{
- void resetInstantiationRound( QuantifiersEngine* qe ){};
- bool reset( InstMatch& m, QuantifiersEngine* qe ){
- return false;
- }
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- return false;
- }
-};
-
-
-/* The order of the matching is:
- reset arg1, nextMatch arg1, reset arg2, nextMatch arg2, ... */
-ApplyMatcher::ApplyMatcher( Node pat, QuantifiersEngine* qe): d_pattern(pat){
- // Assert( pat.hasAttribute(InstConstantAttribute()) );
-
- //set-up d_variables, d_constants, d_childrens
- for( size_t i=0; i< d_pattern.getNumChildren(); ++i ){
- EqualityQuery* q = qe->getEqualityQuery(d_pattern[i].getType());
- Assert( q != NULL );
- if( d_pattern[i].hasAttribute(InstConstantAttribute()) ){
- if( d_pattern[i].getKind()==INST_CONSTANT ){
- //It's a variable
- d_variables.push_back(make_triple((TNode)d_pattern[i],i,q));
- }else{
- //It's neither a constant argument neither a variable
- //we create the matcher for the subpattern
- d_childrens.push_back(make_triple(mkMatcher((TNode)d_pattern[i], qe),i,q));
- };
- }else{
- // It's a constant
- d_constants.push_back(make_triple((TNode)d_pattern[i],i,q));
- }
- }
-}
-
-void ApplyMatcher::resetInstantiationRound( QuantifiersEngine* qe ){
- for( size_t i=0; i< d_childrens.size(); i++ ){
- d_childrens[i].first->resetInstantiationRound( qe );
- }
-}
-
-bool ApplyMatcher::reset(TNode t, InstMatch & m, QuantifiersEngine* qe){
- Debug("matching") << "Matching " << t << " against pattern " << d_pattern << " ("
- << m.size() << ")" << std::endl;
-
- //if t is null
- Assert( !t.isNull() );
- Assert( !t.hasAttribute(InstConstantAttribute()) );
- Assert( t.getKind()==d_pattern.getKind() );
- Assert( (t.getKind()!=APPLY_UF && t.getKind()!=APPLY_CONSTRUCTOR)
- || t.getOperator()==d_pattern.getOperator() );
-
- typedef std::vector< triple<TNode,size_t,EqualityQuery*> >::iterator iterator;
- for(iterator i = d_constants.begin(), end = d_constants.end();
- i != end; ++i){
- if( !i->third->areEqual( i->first, t[i->second] ) ){
- Debug("matching-fail") << "Match fail arg: " << i->first << " and " << t[i->second] << std::endl;
- //setMatchFail( qe, d_pattern[i], t[i] );
- //ground arguments are not equal
- return false;
- }
- }
-
- d_binded.clear();
- bool set;
- for(iterator i = d_variables.begin(), end = d_variables.end();
- i != end; ++i){
- if( !m.setMatch( i->third, i->first, t[i->second], set) ){
- //match is in conflict
- Debug("matching-debug") << "Match in conflict " << t[i->second] << " and "
- << i->first << " because "
- << m.get(i->first)
- << std::endl;
- Debug("matching-fail") << "Match fail: " << m.get(i->first) << " and " << t[i->second] << std::endl;
- //setMatchFail( qe, partial[0].d_map[d_pattern[i]], t[i] );
- m.erase(d_binded.begin(), d_binded.end());
- return false;
- }else{
- if(set){ //The variable has just been set
- d_binded.push_back(i->first);
- }
- }
- }
-
- //now, fit children into match
- //we will be requesting candidates for matching terms for each child
- d_reps.clear();
- for( size_t i=0; i< d_childrens.size(); i++ ){
- Debug("matching-debug") << "Take the representative of " << t[ d_childrens[i].second ] << std::endl;
- Assert( d_childrens[i].third->hasTerm(t[ d_childrens[i].second ]) );
- Node rep = d_childrens[i].third->getRepresentative( t[ d_childrens[i].second ] );
- d_reps.push_back( rep );
- }
-
- if(d_childrens.size() == 0) return true;
- else return getNextMatch(m, qe, true);
-}
-
-bool ApplyMatcher::getNextMatch(InstMatch& m, QuantifiersEngine* qe, bool reset){
- Assert(d_childrens.size() > 0);
- const size_t max = d_childrens.size() - 1;
- size_t index = reset ? 0 : max;
- Assert(d_childrens.size() == d_reps.size());
- while(true){
- if(reset ?
- d_childrens[index].first->reset( d_reps[index], m, qe ) :
- d_childrens[index].first->getNextMatch( m, qe )){
- if(index==max) return true;
- ++index;
- reset=true;
- }else{
- if(index==0){
- m.erase(d_binded.begin(), d_binded.end());
- return false;
- }
- --index;
- reset=false;
- };
- }
-}
-
-bool ApplyMatcher::getNextMatch(InstMatch& m, QuantifiersEngine* qe){
- if(d_childrens.size() == 0){
- m.erase(d_binded.begin(), d_binded.end());
- return false;
- } else return getNextMatch(m, qe, false);
-}
-
-/** Proxy that call the sub-matcher on the result return by the given candidate generator */
-template <class CG, class M>
-class CandidateGeneratorMatcher: public Matcher{
- /** candidate generator */
- CG d_cg;
- /** the sub-matcher */
- M d_m;
-public:
- CandidateGeneratorMatcher(CG cg, M m): d_cg(cg), d_m(m)
- {/* last is Null */};
- void resetInstantiationRound( QuantifiersEngine* qe ){
- d_cg.resetInstantiationRound();
- d_m.resetInstantiationRound(qe);
- };
- bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe ){
- d_cg.reset(n);
- return findMatch(m,qe);
- }
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- // The sub-matcher has another match
- return d_m.getNextMatch(m, qe) || findMatch(m,qe);
- }
-private:
- bool findMatch( InstMatch& m, QuantifiersEngine* qe ){
- // Otherwise try to find a new candidate that has at least one match
- while(true){
- TNode n = d_cg.getNextCandidate();//kept somewhere Term-db
- Debug("matching") << "GenCand " << n << " (" << this << ")" << std::endl;
- if(n.isNull()) return false;
- if(d_m.reset(n,m,qe)) return true;
- };
- }
-};
-
-/** Proxy that call the sub-matcher on the result return by the given candidate generator */
-template<class M>
-class PatOfMatcher: public PatMatcher{
- M d_m;
-public:
- inline PatOfMatcher(M m): d_m(m){}
- void resetInstantiationRound(QuantifiersEngine* qe){
- d_m.resetInstantiationRound(qe);
- }
- bool reset(InstMatch& m, QuantifiersEngine* qe){
- return d_m.reset(Node::null(),m,qe);
- };
- bool getNextMatch(InstMatch& m, QuantifiersEngine* qe){
- return d_m.getNextMatch(m,qe);
- };
-};
-
-class ArithMatcher: public Matcher{
-private:
- /** for arithmetic matching */
- std::map< Node, Node > d_arith_coeffs;
- /** get the match against ground term or formula t.
- d_match_mattern and t should have the same shape.
- only valid for use where !d_match_pattern.isNull().
- */
- /** the variable that are set by this matcher */
- std::vector< TNode > d_binded; /* TNode because the variables are already in d_arith_coeffs */
- Node d_pattern; //for debugging
-public:
- ArithMatcher(Node pat, QuantifiersEngine* qe);
- void resetInstantiationRound( QuantifiersEngine* qe ){};
- bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe );
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe );
-};
-
-/** Match just a variable */
-class VarMatcher: public Matcher{
- Node d_var;
- bool d_binded; /* True if the reset bind the variable to some value */
- EqualityQuery* d_q;
-public:
- VarMatcher(Node var, QuantifiersEngine* qe): d_var(var), d_binded(false){
- d_q = qe->getEqualityQuery(var.getType());
- }
- void resetInstantiationRound( QuantifiersEngine* qe ){};
- bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe ){
- if(!m.setMatch( d_q, d_var, n, d_binded )){
- //match is in conflict
- Debug("matching-fail") << "Match fail: " << m.get(d_var)
- << " and " << n << std::endl;
- return false;
- } else return true;
- };
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- //match is in conflict
- if (d_binded) m.erase(d_var);
- return false;
- }
-};
-
-template <class M, class Test >
-class TestMatcher: public Matcher{
- M d_m;
- Test d_test;
-public:
- inline TestMatcher(M m, Test test): d_m(m), d_test(test){}
- inline void resetInstantiationRound(QuantifiersEngine* qe){
- d_m.resetInstantiationRound(qe);
- }
- inline bool reset(TNode n, InstMatch& m, QuantifiersEngine* qe){
- return d_test(n) && d_m.reset(n, m, qe);
- }
- inline bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- return d_m.getNextMatch(m, qe);
- }
-};
-
-class LegalOpTest/*: public unary_function<TNode,bool>*/ {
- Node d_op;
-public:
- inline LegalOpTest(Node op): d_op(op){}
- inline bool operator() (TNode n) {
- return
- CandidateGenerator::isLegalCandidate(n) &&
- // ( // n.getKind()==SELECT || n.getKind()==STORE ||
- // n.getKind()==APPLY_UF || n.getKind()==APPLY_CONSTRUCTOR) &&
- n.hasOperator() &&
- n.getOperator()==d_op;
- };
-};
-
-class LegalKindTest/* : public unary_function<TNode,bool>*/ {
- Kind d_kind;
-public:
- inline LegalKindTest(Kind kind): d_kind(kind){}
- inline bool operator() (TNode n) {
- return
- CandidateGenerator::isLegalCandidate(n) &&
- n.getKind()==d_kind;
- };
-};
-
-class LegalTypeTest/* : public unary_function<TNode,bool>*/ {
- TypeNode d_type;
-public:
- inline LegalTypeTest(TypeNode type): d_type(type){}
- inline bool operator() (TNode n) {
- return
- CandidateGenerator::isLegalCandidate(n) &&
- n.getType()==d_type;
- };
-};
-
-class LegalTest/* : public unary_function<TNode,bool>*/ {
-public:
- inline bool operator() (TNode n) {
- return CandidateGenerator::isLegalCandidate(n);
- };
-};
-
-size_t numFreeVar(TNode t){
- size_t n = 0;
- for( size_t i=0, size =t.getNumChildren(); i < size; ++i ){
- if( t[i].hasAttribute(InstConstantAttribute()) ){
- if( t[i].getKind()==INST_CONSTANT ){
- //variable
- ++n;
- }else{
- //neither variable nor constant
- n += numFreeVar(t[i]);
- }
- }
- }
- return n;
-}
-
-class OpMatcher: public Matcher{
- /* The matcher */
- typedef ApplyMatcher AuxMatcher3;
- typedef TestMatcher< AuxMatcher3, LegalOpTest > AuxMatcher2;
- typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClass, AuxMatcher2> AuxMatcher1;
- AuxMatcher1 d_cgm;
- static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
- Assert( pat.getKind() == kind::APPLY_UF );
- /** In reverse order of matcher sequence */
- AuxMatcher3 am3(pat,qe);
- /** Keep only the one that have the good operator */
- AuxMatcher2 am2(am3,LegalOpTest(pat.getOperator()));
- /** Iter on the equivalence class of the given term */
- uf::TheoryUF* uf = static_cast<uf::TheoryUF *>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF ));
- eq::EqualityEngine* ee = static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
- CandidateGeneratorTheoryEeClass cdtUfEq(ee);
- /* Create a matcher from the candidate generator */
- AuxMatcher1 am1(cdtUfEq,am2);
- return am1;
- }
- size_t d_num_var;
- Node d_pat;
-public:
- OpMatcher( Node pat, QuantifiersEngine* qe ):
- d_cgm(createCgm(pat, qe)),d_num_var(numFreeVar(pat)),
- d_pat(pat) {}
-
- void resetInstantiationRound( QuantifiersEngine* qe ){
- d_cgm.resetInstantiationRound(qe);
- };
- bool reset( TNode t, InstMatch& m, QuantifiersEngine* qe ){
- // size_t m_size = m.d_map.size();
- // if(m_size == d_num_var){
- // uf::EqualityEngine<uf::TheoryUF::NotifyClass>* ee = (static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF )))->getEqualityEngine();
- // std::cout << "!";
- // return ee->areEqual(m.subst(d_pat),t);
- // }else{
- // std::cout << m.d_map.size() << std::endl;
- return d_cgm.reset(t, m, qe);
- // }
- }
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- return d_cgm.getNextMatch(m, qe);
- }
-};
-
-class DatatypesMatcher: public Matcher{
- /* The matcher */
- typedef ApplyMatcher AuxMatcher3;
- typedef TestMatcher< AuxMatcher3, LegalOpTest > AuxMatcher2;
- typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClass, AuxMatcher2> AuxMatcher1;
- AuxMatcher1 d_cgm;
- static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
- Assert( pat.getKind() == kind::APPLY_CONSTRUCTOR,
- "For datatypes only constructor are accepted in pattern" );
- /** In reverse order of matcher sequence */
- AuxMatcher3 am3(pat,qe);
- /** Keep only the one that have the good operator */
- AuxMatcher2 am2(am3,LegalOpTest(pat.getOperator()));
- /** Iter on the equivalence class of the given term */
- datatypes::TheoryDatatypes* dt = static_cast<datatypes::TheoryDatatypes *>(qe->getTheoryEngine()->getTheory( theory::THEORY_DATATYPES ));
- eq::EqualityEngine* ee = static_cast<eq::EqualityEngine*>(dt->getEqualityEngine());
- CandidateGeneratorTheoryEeClass cdtDtEq(ee);
- /* Create a matcher from the candidate generator */
- AuxMatcher1 am1(cdtDtEq,am2);
- return am1;
- }
- Node d_pat;
-public:
- DatatypesMatcher( Node pat, QuantifiersEngine* qe ):
- d_cgm(createCgm(pat, qe)),
- d_pat(pat) {}
-
- void resetInstantiationRound( QuantifiersEngine* qe ){
- d_cgm.resetInstantiationRound(qe);
- };
- bool reset( TNode t, InstMatch& m, QuantifiersEngine* qe ){
- Debug("matching") << "datatypes: " << t << " matches " << d_pat << std::endl;
- return d_cgm.reset(t, m, qe);
- }
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- return d_cgm.getNextMatch(m, qe);
- }
-};
-
-class ArrayMatcher: public Matcher{
- /* The matcher */
- typedef ApplyMatcher AuxMatcher3;
- typedef TestMatcher< AuxMatcher3, LegalKindTest > AuxMatcher2;
- typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClass, AuxMatcher2> AuxMatcher1;
- AuxMatcher1 d_cgm;
- static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
- Assert( pat.getKind() == kind::SELECT || pat.getKind() == kind::STORE );
- /** In reverse order of matcher sequence */
- AuxMatcher3 am3(pat,qe);
- /** Keep only the one that have the good operator */
- AuxMatcher2 am2(am3, LegalKindTest(pat.getKind()));
- /** Iter on the equivalence class of the given term */
- arrays::TheoryArrays* ar = static_cast<arrays::TheoryArrays *>(qe->getTheoryEngine()->getTheory( theory::THEORY_ARRAY ));
- eq::EqualityEngine* ee =
- static_cast<eq::EqualityEngine*>(ar->getEqualityEngine());
- CandidateGeneratorTheoryEeClass cdtUfEq(ee);
- /* Create a matcher from the candidate generator */
- AuxMatcher1 am1(cdtUfEq,am2);
- return am1;
- }
- size_t d_num_var;
- Node d_pat;
-public:
- ArrayMatcher( Node pat, QuantifiersEngine* qe ):
- d_cgm(createCgm(pat, qe)),d_num_var(numFreeVar(pat)),
- d_pat(pat) {}
-
- void resetInstantiationRound( QuantifiersEngine* qe ){
- d_cgm.resetInstantiationRound(qe);
- };
- bool reset( TNode t, InstMatch& m, QuantifiersEngine* qe ){
- // size_t m_size = m.d_map.size();
- // if(m_size == d_num_var){
- // uf::EqualityEngine<uf::TheoryUF::NotifyClass>* ee = (static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF )))->getEqualityEngine();
- // std::cout << "!";
- // return ee->areEqual(m.subst(d_pat),t);
- // }else{
- // std::cout << m.d_map.size() << std::endl;
- return d_cgm.reset(t, m, qe);
- // }
- }
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- return d_cgm.getNextMatch(m, qe);
- }
-};
-
-class AllOpMatcher: public PatMatcher{
- /* The matcher */
- typedef ApplyMatcher AuxMatcher3;
- typedef TestMatcher< AuxMatcher3, LegalTest > AuxMatcher2;
- typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryUfOp, AuxMatcher2> AuxMatcher1;
- AuxMatcher1 d_cgm;
- static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
- Assert( pat.hasOperator() );
- /** In reverse order of matcher sequence */
- AuxMatcher3 am3(pat,qe);
- /** Keep only the one that have the good operator */
- AuxMatcher2 am2(am3,LegalTest());
- /** Iter on the equivalence class of the given term */
- TermDb* tdb = qe->getTermDatabase();
- CandidateGeneratorTheoryUfOp cdtUfEq(pat.getOperator(),tdb);
- /* Create a matcher from the candidate generator */
- AuxMatcher1 am1(cdtUfEq,am2);
- return am1;
- }
- size_t d_num_var;
- Node d_pat;
-public:
- AllOpMatcher( TNode pat, QuantifiersEngine* qe ):
- d_cgm(createCgm(pat, qe)), d_num_var(numFreeVar(pat)),
- d_pat(pat) {}
-
- void resetInstantiationRound( QuantifiersEngine* qe ){
- d_cgm.resetInstantiationRound(qe);
- };
- bool reset( InstMatch& m, QuantifiersEngine* qe ){
- // std::cout << m.d_map.size() << "/" << d_num_var << std::endl;
- return d_cgm.reset(Node::null(), m, qe);
- }
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- return d_cgm.getNextMatch(m, qe);
- }
-};
-
-template <bool classes> /** true classes | false class */
-class GenericCandidateGeneratorClasses: public CandidateGenerator{
-private:
- CandidateGenerator* d_cg;
- QuantifiersEngine* d_qe;
-
-public:
- void mkCandidateGenerator(){
- if(classes)
- d_cg = d_qe->getRRCanGenClasses();
- else
- d_cg = d_qe->getRRCanGenClass();
- }
-
- GenericCandidateGeneratorClasses(QuantifiersEngine* qe):
- d_qe(qe) {
- mkCandidateGenerator();
- }
- ~GenericCandidateGeneratorClasses(){
- delete(d_cg);
- }
- const GenericCandidateGeneratorClasses & operator =(const GenericCandidateGeneratorClasses & m){
- mkCandidateGenerator();
- return m;
- };
- GenericCandidateGeneratorClasses(const GenericCandidateGeneratorClasses & m):
- d_qe(m.d_qe){
- mkCandidateGenerator();
- }
- void resetInstantiationRound(){
- d_cg->resetInstantiationRound();
- };
- void reset( TNode eqc ){
- Assert( !classes || eqc.isNull() );
- d_cg->reset(eqc);
- }; //* the argument is not used
- TNode getNextCandidate(){
- return d_cg->getNextCandidate();
- };
-}; /* MetaCandidateGeneratorClasses */
-
-
-class GenericMatcher: public Matcher{
- /* The matcher */
- typedef ApplyMatcher AuxMatcher3;
- typedef TestMatcher< AuxMatcher3, LegalOpTest > AuxMatcher2;
- typedef CandidateGeneratorMatcher< GenericCandidateGeneratorClasses<false>, AuxMatcher2> AuxMatcher1;
- AuxMatcher1 d_cgm;
- static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
- /** In reverse order of matcher sequence */
- AuxMatcher3 am3(pat,qe);
- /** Keep only the one that have the good operator */
- AuxMatcher2 am2(am3,LegalOpTest(pat.getOperator()));
- /** Iter on the equivalence class of the given term */
- GenericCandidateGeneratorClasses<false> cdtG(qe);
- /* Create a matcher from the candidate generator */
- AuxMatcher1 am1(cdtG,am2);
- return am1;
- }
- Node d_pat;
-public:
- GenericMatcher( Node pat, QuantifiersEngine* qe ):
- d_cgm(createCgm(pat, qe)),
- d_pat(pat) {}
-
- void resetInstantiationRound( QuantifiersEngine* qe ){
- d_cgm.resetInstantiationRound(qe);
- };
- bool reset( TNode t, InstMatch& m, QuantifiersEngine* qe ){
- return d_cgm.reset(t, m, qe);
- }
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- return d_cgm.getNextMatch(m, qe);
- }
-};
-
-
-class GenericPatMatcher: public PatMatcher{
- /* The matcher */
- typedef ApplyMatcher AuxMatcher3;
- typedef TestMatcher< AuxMatcher3, LegalOpTest > AuxMatcher2;
- typedef CandidateGeneratorMatcher< GenericCandidateGeneratorClasses<true>, AuxMatcher2> AuxMatcher1;
- AuxMatcher1 d_cgm;
- static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
- /** In reverse order of matcher sequence */
- AuxMatcher3 am3(pat,qe);
- /** Keep only the one that have the good operator */
- AuxMatcher2 am2(am3,LegalOpTest(pat.getOperator()));
- /** Iter on the equivalence class of the given term */
- GenericCandidateGeneratorClasses<true> cdtG(qe);
- /* Create a matcher from the candidate generator */
- AuxMatcher1 am1(cdtG,am2);
- return am1;
- }
- Node d_pat;
-public:
- GenericPatMatcher( Node pat, QuantifiersEngine* qe ):
- d_cgm(createCgm(pat, qe)),
- d_pat(pat) {}
-
- void resetInstantiationRound( QuantifiersEngine* qe ){
- d_cgm.resetInstantiationRound(qe);
- };
- bool reset( InstMatch& m, QuantifiersEngine* qe ){
- return d_cgm.reset(Node::null(), m, qe);
- }
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- return d_cgm.getNextMatch(m, qe);
- }
-};
-
-class MetaCandidateGeneratorClasses: public CandidateGenerator{
-private:
- CandidateGenerator* d_cg;
- TypeNode d_ty;
- TheoryEngine* d_te;
-
-public:
- CandidateGenerator* mkCandidateGenerator(TypeNode ty, TheoryEngine* te){
- Debug("inst-match-gen") << "MetaCandidateGenerator for type: " << ty
- << " Theory : " << Theory::theoryOf(ty) << std::endl;
- if( Theory::theoryOf(ty) == theory::THEORY_DATATYPES ){
- // datatypes::TheoryDatatypes* dt = static_cast<datatypes::TheoryDatatypes *>(te->getTheory( theory::THEORY_DATATYPES ));
- // return new datatypes::rrinst::CandidateGeneratorTheoryClasses(dt);
- Unimplemented("MetaCandidateGeneratorClasses for THEORY_DATATYPES");
- }else if ( Theory::theoryOf(ty) == theory::THEORY_ARRAY ){
- arrays::TheoryArrays* ar = static_cast<arrays::TheoryArrays *>(te->getTheory( theory::THEORY_ARRAY ));
- eq::EqualityEngine* ee =
- static_cast<eq::EqualityEngine*>(ar->getEqualityEngine());
- return new CandidateGeneratorTheoryEeClasses(ee);
- } else {
- uf::TheoryUF* uf = static_cast<uf::TheoryUF*>(te->getTheory( theory::THEORY_UF ));
- eq::EqualityEngine* ee =
- static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
- return new CandidateGeneratorTheoryEeClasses(ee);
- }
- }
- MetaCandidateGeneratorClasses(TypeNode ty, TheoryEngine* te):
- d_ty(ty), d_te(te) {
- d_cg = mkCandidateGenerator(ty,te);
- }
- ~MetaCandidateGeneratorClasses(){
- delete(d_cg);
- }
- const MetaCandidateGeneratorClasses & operator =(const MetaCandidateGeneratorClasses & m){
- d_cg = mkCandidateGenerator(m.d_ty, m.d_te);
- return m;
- };
- MetaCandidateGeneratorClasses(const MetaCandidateGeneratorClasses & m):
- d_ty(m.d_ty), d_te(m.d_te){
- d_cg = mkCandidateGenerator(m.d_ty, m.d_te);
- }
- void resetInstantiationRound(){
- d_cg->resetInstantiationRound();
- };
- void reset( TNode eqc ){
- d_cg->reset(eqc);
- }; //* the argument is not used
- TNode getNextCandidate(){
- return d_cg->getNextCandidate();
- };
-}; /* MetaCandidateGeneratorClasses */
-
-/** Match just a variable */
-class AllVarMatcher: public PatMatcher{
-private:
- /* generator */
- typedef VarMatcher AuxMatcher3;
- typedef TestMatcher< AuxMatcher3, LegalTypeTest > AuxMatcher2;
- typedef CandidateGeneratorMatcher< MetaCandidateGeneratorClasses, AuxMatcher2 > AuxMatcher1;
- AuxMatcher1 d_cgm;
- static inline AuxMatcher1 createCgm(TNode pat, QuantifiersEngine* qe){
- Assert( pat.getKind()==INST_CONSTANT );
- TypeNode ty = pat.getType();
- Debug("inst-match-gen") << "create AllVarMatcher for type: " << ty << std::endl;
- /** In reverse order of matcher sequence */
- /** Distribute it to all the pattern */
- AuxMatcher3 am3(pat,qe);
- /** Keep only the one that have the good type */
- AuxMatcher2 am2(am3,LegalTypeTest(ty));
- /** Generate one term by eq classes */
- MetaCandidateGeneratorClasses mcdt(ty,qe->getTheoryEngine());
- /* Create a matcher from the candidate generator */
- AuxMatcher1 am1(mcdt,am2);
- return am1;
- }
-public:
- AllVarMatcher( TNode pat, QuantifiersEngine* qe ):
- d_cgm(createCgm(pat, qe)){}
-
- void resetInstantiationRound( QuantifiersEngine* qe ){
- d_cgm.resetInstantiationRound(qe);
- };
- bool reset( InstMatch& m, QuantifiersEngine* qe ){
- return d_cgm.reset(Node::null(), m, qe); //cdtUfEq doesn't use it's argument for reset
- }
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- return d_cgm.getNextMatch(m, qe);
- }
-};
-
-/** Match all the pattern with the same term */
-class SplitMatcher: public Matcher{
-private:
- const size_t size;
- ApplyMatcher d_m; /** Use ApplyMatcher by creating a fake application */
-public:
- SplitMatcher(std::vector< Node > pats, QuantifiersEngine* qe):
- size(pats.size()),
- d_m(NodeManager::currentNM()->mkNode(kind::INST_PATTERN,pats), qe) {}
- void resetInstantiationRound( QuantifiersEngine* qe ){
- d_m.resetInstantiationRound(qe);
- };
- bool reset( TNode ex, InstMatch& m, QuantifiersEngine* qe ){
- NodeBuilder<> n(kind::INST_PATTERN);
- for(size_t i = 0; i < size; ++i) n << ex;
- Node nn = n;
- return d_m.reset(nn,m,qe);
- };
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- return getNextMatch(m, qe);
- }
-};
-
-
-/** Match uf term in a fixed equivalence class */
-class UfCstEqMatcher: public PatMatcher{
-private:
- /* equivalence class to match */
- Node d_cst;
- /* generator */
- OpMatcher d_cgm;
-public:
- UfCstEqMatcher( Node pat, Node cst, QuantifiersEngine* qe ):
- d_cst(cst),
- d_cgm(OpMatcher(pat,qe)) {};
- void resetInstantiationRound( QuantifiersEngine* qe ){
- d_cgm.resetInstantiationRound(qe);
- };
- bool reset( InstMatch& m, QuantifiersEngine* qe ){
- return d_cgm.reset(d_cst, m, qe);
- }
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- return d_cgm.getNextMatch(m, qe);
- }
-};
-
-/** Match equalities */
-class UfEqMatcher: public PatMatcher{
-private:
- /* generator */
- typedef SplitMatcher AuxMatcher3;
- typedef TestMatcher< AuxMatcher3, LegalTypeTest > AuxMatcher2;
- typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClasses, AuxMatcher2 > AuxMatcher1;
- AuxMatcher1 d_cgm;
- static inline AuxMatcher1 createCgm(std::vector<Node> & pat, QuantifiersEngine* qe){
- Assert( pat.size() > 0);
- TypeNode ty = pat[0].getType();
- for(size_t i = 1; i < pat.size(); ++i){
- Assert(pat[i].getType() == ty);
- }
- /** In reverse order of matcher sequence */
- /** Distribute it to all the pattern */
- AuxMatcher3 am3(pat,qe);
- /** Keep only the one that have the good type */
- AuxMatcher2 am2(am3,LegalTypeTest(ty));
- /** Generate one term by eq classes */
- uf::TheoryUF* uf = static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF ));
- eq::EqualityEngine* ee =
- static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
- CandidateGeneratorTheoryEeClasses cdtUfEq(ee);
- /* Create a matcher from the candidate generator */
- AuxMatcher1 am1(cdtUfEq,am2);
- return am1;
- }
-public:
- UfEqMatcher( std::vector<Node> & pat, QuantifiersEngine* qe ):
- d_cgm(createCgm(pat, qe)){}
-
- void resetInstantiationRound( QuantifiersEngine* qe ){
- d_cgm.resetInstantiationRound(qe);
- };
- bool reset( InstMatch& m, QuantifiersEngine* qe ){
- return d_cgm.reset(Node::null(), m, qe); //cdtUfEq doesn't use it's argument for reset
- }
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- return d_cgm.getNextMatch(m, qe);
- }
-};
-
-
-/** Match dis-equalities */
-class UfDeqMatcher: public PatMatcher{
-private:
- /* generator */
- typedef ApplyMatcher AuxMatcher3;
-
- class EqTest/* : public unary_function<Node,bool>*/ {
- TypeNode d_type;
- public:
- inline EqTest(TypeNode type): d_type(type){};
- inline bool operator() (Node n) {
- return
- CandidateGenerator::isLegalCandidate(n) &&
- n.getKind() == kind::EQUAL &&
- n[0].getType()==d_type;
- };
- };
- typedef TestMatcher< AuxMatcher3, EqTest > AuxMatcher2;
- typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClass, AuxMatcher2 > AuxMatcher1;
- AuxMatcher1 d_cgm;
- Node false_term;
- static inline AuxMatcher1 createCgm(Node pat, QuantifiersEngine* qe){
- Assert( pat.getKind() == kind::NOT);
- TNode eq = pat[0];
- Assert( eq.getKind() == kind::EQUAL);
- TypeNode ty = eq[0].getType();
- /** In reverse order of matcher sequence */
- /** Distribute it to all the pattern */
- AuxMatcher3 am3(eq,qe);
- /** Keep only the one that have the good type */
- AuxMatcher2 am2(am3,EqTest(ty));
- /** Will generate all the terms of the eq class of false */
- uf::TheoryUF* uf = static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF ));
- eq::EqualityEngine* ee =
- static_cast<eq::EqualityEngine*>(uf->getEqualityEngine());
- CandidateGeneratorTheoryEeClass cdtUfEq(ee);
- /* Create a matcher from the candidate generator */
- AuxMatcher1 am1(cdtUfEq,am2);
- return am1;
- }
-public:
- UfDeqMatcher( Node pat, QuantifiersEngine* qe ):
- d_cgm(createCgm(pat, qe)),
- false_term((static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF )))->getEqualityEngine()->
- getRepresentative(NodeManager::currentNM()->mkConst<bool>(false) )){};
- void resetInstantiationRound( QuantifiersEngine* qe ){
- d_cgm.resetInstantiationRound(qe);
- };
- bool reset( InstMatch& m, QuantifiersEngine* qe ){
- return d_cgm.reset(false_term, m, qe);
- }
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- return d_cgm.getNextMatch(m, qe);
- }
-};
-
-Matcher* mkMatcher( Node pat, QuantifiersEngine* qe ){
- Debug("inst-match-gen") << "mkMatcher: Pattern term is " << pat << std::endl;
-
- // if( pat.getKind() == kind::APPLY_UF){
- // return new OpMatcher(pat, qe);
- // } else if( pat.getKind() == kind::APPLY_CONSTRUCTOR ){
- // return new DatatypesMatcher(pat, qe);
- // } else if( pat.getKind() == kind::SELECT || pat.getKind() == kind::STORE ){
- // return new ArrayMatcher(pat, qe);
- if( pat.getKind() == kind::APPLY_UF ||
- pat.getKind() == kind::APPLY_CONSTRUCTOR ||
- pat.getKind() == kind::SELECT || pat.getKind() == kind::STORE ){
- return new GenericMatcher(pat, qe);
- } else { /* Arithmetic? */
- /** TODO: something simpler to see if the pattern is a good
- arithmetic pattern */
- std::map< Node, Node > d_arith_coeffs;
- if( !Trigger::getPatternArithmetic( pat.getAttribute(InstConstantAttribute()), pat, d_arith_coeffs ) ){
- Message() << "(?) Unknown matching pattern is " << pat << std::endl;
- Unimplemented("pattern not implemented");
- return new DumbMatcher();
- }else{
- Debug("matching-arith") << "Generated arithmetic pattern for " << pat << ": " << std::endl;
- for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
- Debug("matching-arith") << " " << it->first << " -> " << it->second << std::endl;
- }
- ArithMatcher am3 (pat, qe);
- TestMatcher<ArithMatcher, LegalTypeTest>
- am2(am3,LegalTypeTest(pat.getType()));
- /* generator */
- uf::TheoryUF* uf = static_cast<uf::TheoryUF*>(qe->getTheoryEngine()->getTheory( theory::THEORY_UF ));
- eq::EqualityEngine* ee =
- static_cast<eq::EqualityEngine*> (uf->getEqualityEngine());
- CandidateGeneratorTheoryEeClass cdtUfEq(ee);
- return new CandidateGeneratorMatcher< CandidateGeneratorTheoryEeClass,
- TestMatcher<ArithMatcher, LegalTypeTest> > (cdtUfEq,am2);
- }
- }
-};
-
-PatMatcher* mkPattern( Node pat, QuantifiersEngine* qe ){
- Debug("inst-match-gen") << "Pattern term is " << pat << std::endl;
- Assert( pat.hasAttribute(InstConstantAttribute()) );
-
- if( pat.getKind()==kind::NOT && pat[0].getKind() == kind::EQUAL){
- /* Difference */
- return new UfDeqMatcher(pat, qe);
- } else if (pat.getKind() == kind::EQUAL){
- if( !pat[0].hasAttribute(InstConstantAttribute() )){
- Assert(pat[1].hasAttribute(InstConstantAttribute()));
- return new UfCstEqMatcher(pat[1], pat[0], qe);
- }else if( !pat[1].hasAttribute(InstConstantAttribute() )){
- Assert(pat[0].hasAttribute(InstConstantAttribute()));
- return new UfCstEqMatcher(pat[0], pat[1], qe);
- }else{
- std::vector< Node > pats(pat.begin(),pat.end());
- return new UfEqMatcher(pats,qe);
- }
- } else if( Trigger::isAtomicTrigger( pat ) ){
- return new AllOpMatcher(pat, qe);
- // return new GenericPatMatcher(pat, qe);
- } else if( pat.getKind()==INST_CONSTANT ){
- // just a variable
- return new AllVarMatcher(pat, qe);
- } else { /* Arithmetic? */
- /** TODO: something simpler to see if the pattern is a good
- arithmetic pattern */
- std::map< Node, Node > d_arith_coeffs;
- if( !Trigger::getPatternArithmetic( pat.getAttribute(InstConstantAttribute()), pat, d_arith_coeffs ) ){
- Debug("inst-match-gen") << "(?) Unknown matching pattern is " << pat << std::endl;
- Message() << "(?) Unknown matching pattern is " << pat << std::endl;
- return new DumbPatMatcher();
- }else{
- Debug("matching-arith") << "Generated arithmetic pattern for " << pat << ": " << std::endl;
- for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
- Debug("matching-arith") << " " << it->first << " -> " << it->second << std::endl;
- }
- ArithMatcher am3 (pat, qe);
- TestMatcher<ArithMatcher, LegalTest>
- am2(am3,LegalTest());
- /* generator */
- TermDb* tdb = qe->getTermDatabase();
- CandidateGeneratorTheoryUfType cdtUfEq(pat.getType(),tdb);
- typedef CandidateGeneratorMatcher< CandidateGeneratorTheoryUfType,
- TestMatcher<ArithMatcher, LegalTest> > AuxMatcher1;
- return new PatOfMatcher<AuxMatcher1>(AuxMatcher1(cdtUfEq,am2));
- }
- }
-};
-
-ArithMatcher::ArithMatcher(Node pat, QuantifiersEngine* qe): d_pattern(pat){
-
- if(Trigger::getPatternArithmetic(pat.getAttribute(InstConstantAttribute()), pat, d_arith_coeffs ) )
- {
- Debug("inst-match-gen") << "(?) Unknown matching pattern is " << d_pattern << std::endl;
- Assert(false);
- }else{
- Debug("matching-arith") << "Generated arithmetic pattern for " << d_pattern << ": " << std::endl;
- for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
- Debug("matching-arith") << " " << it->first << " -> " << it->second << std::endl;
- }
- }
-
-};
-
-bool ArithMatcher::reset( TNode t, InstMatch& m, QuantifiersEngine* qe ){
- Debug("matching-arith") << "Matching " << t << " " << d_pattern << std::endl;
- d_binded.clear();
- if( !d_arith_coeffs.empty() ){
- NodeBuilder<> tb(kind::PLUS);
- Node ic = Node::null();
- for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
- Debug("matching-arith") << it->first << " -> " << it->second << std::endl;
- if( !it->first.isNull() ){
- if( m.find( it->first )==m.end() ){
- //see if we can choose this to set
- if( ic.isNull() && ( it->second.isNull() || !it->first.getType().isInteger() ) ){
- ic = it->first;
- }
- }else{
- Debug("matching-arith") << "already set " << m.get( it->first ) << std::endl;
- Node tm = m.get( it->first );
- if( !it->second.isNull() ){
- tm = NodeManager::currentNM()->mkNode( MULT, it->second, tm );
- }
- tb << tm;
- }
- }else{
- tb << it->second;
- }
- }
- if( !ic.isNull() ){
- Node tm;
- if( tb.getNumChildren()==0 ){
- tm = t;
- }else{
- tm = tb.getNumChildren()==1 ? tb.getChild( 0 ) : tb;
- tm = NodeManager::currentNM()->mkNode( MINUS, t, tm );
- }
- if( !d_arith_coeffs[ ic ].isNull() ){
- Assert( !ic.getType().isInteger() );
- Node coeff = NodeManager::currentNM()->mkConst( Rational(1) / d_arith_coeffs[ ic ].getConst<Rational>() );
- tm = NodeManager::currentNM()->mkNode( MULT, coeff, tm );
- }
- m.set( ic, Rewriter::rewrite( tm ));
- d_binded.push_back(ic);
- //set the rest to zeros
- for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
- if( !it->first.isNull() ){
- if( m.find( it->first )==m.end() ){
- m.set( it->first, NodeManager::currentNM()->mkConst( Rational(0) ));
- d_binded.push_back(ic);
- }
- }
- }
- Debug("matching-arith") << "Setting " << ic << " to " << tm << std::endl;
- return true;
- }else{
- m.erase(d_binded.begin(), d_binded.end());
- return false;
- }
- }else{
- m.erase(d_binded.begin(), d_binded.end());
- return false;
- }
-};
-
-bool ArithMatcher::getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- m.erase(d_binded.begin(), d_binded.end());
- return false;
-};
-
-
-class MultiPatsMatcher: public PatsMatcher{
-private:
- bool d_reset_done;
- std::vector< PatMatcher* > d_patterns;
- InstMatch d_im;
- bool reset( QuantifiersEngine* qe ){
- d_im.clear();
- d_reset_done = true;
-
- return getNextMatch(qe,true);
- };
-
- bool getNextMatch(QuantifiersEngine* qe, bool reset){
- const size_t max = d_patterns.size() - 1;
- size_t index = reset ? 0 : max;
- while(true){
- Debug("matching") << "MultiPatsMatcher::index " << index << "/"
- << max << (reset ? " reset_phase" : "") << std::endl;
- if(reset ?
- d_patterns[index]->reset( d_im, qe ) :
- d_patterns[index]->getNextMatch( d_im, qe )){
- if(index==max) return true;
- ++index;
- reset=true;
- }else{
- if(index==0) return false;
- --index;
- reset=false;
- };
- }
- }
-
-public:
- MultiPatsMatcher(std::vector< Node > & pats, QuantifiersEngine* qe):
- d_reset_done(false){
- Assert(pats.size() > 0);
- for( size_t i=0; i< pats.size(); i++ ){
- d_patterns.push_back(mkPattern(pats[i],qe));
- };
- };
- void resetInstantiationRound( QuantifiersEngine* qe ){
- for( size_t i=0; i< d_patterns.size(); i++ ){
- d_patterns[i]->resetInstantiationRound( qe );
- };
- d_reset_done = false;
- d_im.clear();
- };
- bool getNextMatch( QuantifiersEngine* qe ){
- Assert(d_patterns.size()>0);
- if(d_reset_done) return getNextMatch(qe,false);
- else return reset(qe);
- }
- const InstMatch& getInstMatch(){return d_im;};
-
- int addInstantiations( InstMatch& baseMatch, Node quant, QuantifiersEngine* qe);
-};
-
-enum EffiStep{
- ES_STOP,
- ES_GET_MONO_CANDIDATE,
- ES_GET_MULTI_CANDIDATE,
- ES_RESET1,
- ES_RESET2,
- ES_NEXT1,
- ES_NEXT2,
- ES_RESET_OTHER,
- ES_NEXT_OTHER,
-};
-static inline std::ostream& operator<<(std::ostream& out, const EffiStep& step) {
- switch(step){
- case ES_STOP: out << "STOP"; break;
- case ES_GET_MONO_CANDIDATE: out << "GET_MONO_CANDIDATE"; break;
- case ES_GET_MULTI_CANDIDATE: out << "GET_MULTI_CANDIDATE"; break;
- case ES_RESET1: out << "RESET1"; break;
- case ES_RESET2: out << "RESET2"; break;
- case ES_NEXT1: out << "NEXT1"; break;
- case ES_NEXT2: out << "NEXT2"; break;
- case ES_RESET_OTHER: out << "RESET_OTHER"; break;
- case ES_NEXT_OTHER: out << "NEXT_OTHER"; break;
- }
- return out;
-}
-
-
-int MultiPatsMatcher::addInstantiations( InstMatch& baseMatch, Node quant, QuantifiersEngine* qe){
- //now, try to add instantiation for each match produced
- int addedLemmas = 0;
- resetInstantiationRound( qe );
- d_im.add( baseMatch );
- while( getNextMatch( qe ) ){
- InstMatch im_copy = getInstMatch();
- //m.makeInternal( d_quantEngine->getEqualityQuery() );
- if( qe->addInstantiation( quant, im_copy ) ){
- addedLemmas++;
- }
- }
- //return number of lemmas added
- return addedLemmas;
-}
-
-PatsMatcher* mkPatterns( std::vector< Node > pat, QuantifiersEngine* qe ){
- return new MultiPatsMatcher( pat, qe);
-}
-
-class MultiEfficientPatsMatcher: public PatsMatcher{
-private:
- bool d_phase_mono;
- bool d_phase_new_term;
- std::vector< PatMatcher* > d_patterns;
- std::vector< Matcher* > d_direct_patterns;
- InstMatch d_im;
- uf::EfficientHandler d_eh;
- uf::EfficientHandler::MultiCandidate d_mc;
- InstMatchTrie2Pairs<true> d_cache;
- std::vector<Node> d_pats;
- // bool indexDone( size_t i){
- // return i == d_c.first.second ||
- // ( i == d_c.second.second && d_c.second.first.empty());
- // }
-
-
-
- static const EffiStep ES_START = ES_GET_MONO_CANDIDATE;
- EffiStep d_step;
-
- //return true if it becomes bigger than d_patterns.size() - 1
- bool incrIndex(size_t & index){
- if(index == d_patterns.size() - 1) return true;
- ++index;
- if(index == d_mc.first.second
- || (!d_phase_mono && index == d_mc.second.second))
- return incrIndex(index);
- else return false;
- }
-
- //return true if it becomes smaller than 0
- bool decrIndex(size_t & index){
- if(index == 0) return true;
- --index;
- if(index == d_mc.first.second
- || (!d_phase_mono && index == d_mc.second.second))
- return decrIndex(index);
- else return false;
- }
-
- bool resetOther( QuantifiersEngine* qe ){
- return getNextMatchOther(qe,true);
- };
-
-
- bool getNextMatchOther(QuantifiersEngine* qe, bool reset){
- size_t index = reset ? 0 : d_patterns.size();
- if(!reset && decrIndex(index)) return false;
- if( reset &&
- (index == d_mc.first.second
- || (!d_phase_mono && index == d_mc.second.second))
- && incrIndex(index)) return true;
- while(true){
- Debug("matching") << "MultiEfficientPatsMatcher::index " << index << "/"
- << d_patterns.size() - 1 << std::endl;
- if(reset ?
- d_patterns[index]->reset( d_im, qe ) :
- d_patterns[index]->getNextMatch( d_im, qe )){
- if(incrIndex(index)) return true;
- reset=true;
- }else{
- if(decrIndex(index)) return false;
- reset=false;
- };
- }
- }
-
- inline EffiStep TestMonoCache(QuantifiersEngine* qe){
- if( //!d_phase_new_term ||
- d_pats.size() == 1) return ES_RESET_OTHER;
- if(d_cache.addInstMatch(d_mc.first.second,d_im)){
- Debug("inst-match::cache") << "Cache miss" << d_im << std::endl;
- ++qe->d_statistics.d_mono_candidates_cache_miss;
- return ES_RESET_OTHER;
- } else {
- Debug("inst-match::cache") << "Cache hit" << d_im << std::endl;
- ++qe->d_statistics.d_mono_candidates_cache_hit;
- return ES_NEXT1;
- }
- // ++qe->d_statistics.d_mono_candidates_cache_miss;
- // return ES_RESET_OTHER;
- }
-
- inline EffiStep TestMultiCache(QuantifiersEngine* qe){
- if(d_cache.addInstMatch(d_mc.first.second,d_mc.second.second,d_im)){
- ++qe->d_statistics.d_multi_candidates_cache_miss;
- return ES_RESET_OTHER;
- } else {
- ++qe->d_statistics.d_multi_candidates_cache_hit;
- return ES_NEXT2;
- }
- }
-
-
-public:
-
- bool getNextMatch( QuantifiersEngine* qe ){
- Assert( d_step == ES_START || d_step == ES_NEXT_OTHER || d_step == ES_STOP );
- while(true){
- Debug("matching") << "d_step=" << d_step << " "
- << "d_im=" << d_im << std::endl;
- switch(d_step){
- case ES_GET_MONO_CANDIDATE:
- Assert(d_im.empty());
- if(d_phase_new_term ? d_eh.getNextMonoCandidate(d_mc.first) : d_eh.getNextMonoCandidateNewTerm(d_mc.first)){
- if(d_phase_new_term) ++qe->d_statistics.d_num_mono_candidates_new_term;
- else ++qe->d_statistics.d_num_mono_candidates;
- d_phase_mono = true;
- d_step = ES_RESET1;
- } else if (!d_phase_new_term){
- d_phase_new_term = true;
- d_step = ES_GET_MONO_CANDIDATE;
- } else {
- d_phase_new_term = false;
- d_step = ES_GET_MULTI_CANDIDATE;
- }
- break;
- case ES_GET_MULTI_CANDIDATE:
- Assert(d_im.empty());
- if(d_eh.getNextMultiCandidate(d_mc)){
- ++qe->d_statistics.d_num_multi_candidates;
- d_phase_mono = false;
- d_step = ES_RESET1;
- } else d_step = ES_STOP;
- break;
- case ES_RESET1:
- if(d_direct_patterns[d_mc.first.second]->reset(d_mc.first.first,d_im,qe))
- d_step = d_phase_mono ? TestMonoCache(qe) : ES_RESET2;
- else d_step = d_phase_mono ? ES_GET_MONO_CANDIDATE : ES_GET_MULTI_CANDIDATE;
- break;
- case ES_RESET2:
- Assert(!d_phase_mono);
- if(d_direct_patterns[d_mc.second.second]->reset(d_mc.second.first,d_im,qe))
- d_step = TestMultiCache(qe);
- else d_step = ES_NEXT1;
- break;
- case ES_NEXT1:
- if(d_direct_patterns[d_mc.first.second]->getNextMatch(d_im,qe))
- d_step = d_phase_mono ? TestMonoCache(qe) : ES_RESET2;
- else d_step = d_phase_mono ? ES_GET_MONO_CANDIDATE : ES_GET_MULTI_CANDIDATE;
- break;
- case ES_NEXT2:
- if(d_direct_patterns[d_mc.second.second]->getNextMatch(d_im,qe))
- d_step = TestMultiCache(qe);
- else d_step = ES_NEXT1;
- break;
- case ES_RESET_OTHER:
- if(resetOther(qe)){
- d_step = ES_NEXT_OTHER;
- return true;
- } else d_step = d_phase_mono ? ES_NEXT1 : ES_NEXT2;
- break;
- case ES_NEXT_OTHER:
- {
- if(!getNextMatchOther(qe,false)){
- d_step = d_phase_mono ? ES_NEXT1 : ES_NEXT2;
- }else{
- d_step = ES_NEXT_OTHER;
- return true;
- }
- }
- break;
- case ES_STOP:
- Assert(d_im.empty());
- return false;
- }
- }
- }
-
- MultiEfficientPatsMatcher(std::vector< Node > & pats, QuantifiersEngine* qe):
- d_eh(qe->getTheoryEngine()->getSatContext()),
- d_cache(qe->getTheoryEngine()->getSatContext(),qe,pats.size()),
- d_pats(pats), d_step(ES_START) {
- Assert(pats.size() > 0);
- for( size_t i=0; i< pats.size(); i++ ){
- d_patterns.push_back(mkPattern(pats[i],qe));
- if(pats[i].getKind()==kind::INST_CONSTANT){
- d_direct_patterns.push_back(new VarMatcher(pats[i],qe));
- } else if( pats[i].getKind() == kind::NOT && pats[i][0].getKind() == kind::EQUAL){
- d_direct_patterns.push_back(new ApplyMatcher(pats[i][0],qe));
- } else {
- d_direct_patterns.push_back(new ApplyMatcher(pats[i],qe));
- }
- };
- Theory* th_uf = qe->getTheoryEngine()->getTheory( theory::THEORY_UF );
- uf::InstantiatorTheoryUf* ith = (uf::InstantiatorTheoryUf*)th_uf->getInstantiator();
- ith->registerEfficientHandler(d_eh, pats);
- };
- void resetInstantiationRound( QuantifiersEngine* qe ){
- Assert(d_step == ES_START || d_step == ES_STOP);
- for( size_t i=0; i< d_patterns.size(); i++ ){
- d_patterns[i]->resetInstantiationRound( qe );
- d_direct_patterns[i]->resetInstantiationRound( qe );
- };
- d_step = ES_START;
- d_phase_new_term = false;
- Assert(d_im.empty());
- };
-
- const InstMatch& getInstMatch(){return d_im;};
-
- int addInstantiations( InstMatch& baseMatch, Node quant, QuantifiersEngine* qe);
-};
-
-int MultiEfficientPatsMatcher::addInstantiations( InstMatch& baseMatch, Node quant, QuantifiersEngine* qe){
- //now, try to add instantiation for each match produced
- int addedLemmas = 0;
- Assert(baseMatch.empty());
- resetInstantiationRound( qe );
- while( getNextMatch( qe ) ){
- InstMatch im_copy = getInstMatch();
- //m.makeInternal( d_quantEngine->getEqualityQuery() );
- if( qe->addInstantiation( quant, im_copy ) ){
- addedLemmas++;
- }
- }
- //return number of lemmas added
- return addedLemmas;
-};
-
-PatsMatcher* mkPatternsEfficient( std::vector< Node > pat, QuantifiersEngine* qe ){
- return new MultiEfficientPatsMatcher( pat, qe);
-}
-
-} /* CVC4::theory::rrinst */
-} /* CVC4::theory */
-} /* CVC4 */
+++ /dev/null
-/********************* */
-/*! \file rr_inst_match.h
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: bobot
- ** Minor contributors (to current version): mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief inst match class
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__RR_INST_MATCH_H
-#define __CVC4__RR_INST_MATCH_H
-
-#include "theory/theory.h"
-#include "util/hash.h"
-#include "util/ntuple.h"
-
-#include <ext/hash_set>
-#include <iostream>
-#include <map>
-
-#include "theory/uf/equality_engine.h"
-#include "theory/uf/theory_uf.h"
-#include "context/cdlist.h"
-
-#include "theory/inst_match.h"
-#include "expr/node_manager.h"
-#include "expr/node_builder.h"
-
-#include "theory/quantifiers/options.h"
-#include "theory/rewriterules/options.h"
-
-//#define USE_EFFICIENT_E_MATCHING
-
-namespace CVC4 {
-namespace theory {
-
-namespace rrinst{
-
-class CandidateGenerator
-{
-public:
- CandidateGenerator(){}
- virtual ~CandidateGenerator(){};
-
- /** Get candidates functions. These set up a context to get all match candidates.
- cg->reset( eqc );
- do{
- Node cand = cg->getNextCandidate();
- //.......
- }while( !cand.isNull() );
-
- eqc is the equivalence class you are searching in
- */
- virtual void reset( TNode eqc ) = 0;
- virtual TNode getNextCandidate() = 0;
- /** call this at the beginning of each instantiation round */
- virtual void resetInstantiationRound() = 0;
-public:
- /** legal candidate */
- static inline bool isLegalCandidate( TNode n ){
- return !n.getAttribute(NoMatchAttribute()) &&
- ( !options::cbqi() || !n.hasAttribute(InstConstantAttribute())) &&
- ( !options::efficientEMatching() || n.hasAttribute(AvailableInTermDb()) );
-}
-
-};
-
-
-inline std::ostream& operator<<(std::ostream& out, const InstMatch& m) {
- m.toStream(out);
- return out;
-}
-
-template<bool modEq = false> class InstMatchTrie2;
-template<bool modEq = false> class InstMatchTrie2Pairs;
-
-template<bool modEq = false>
-class InstMatchTrie2Gen
-{
- friend class InstMatchTrie2<modEq>;
- friend class InstMatchTrie2Pairs<modEq>;
-
-private:
-
- class Tree {
- public:
- typedef std::hash_map< Node, Tree *, NodeHashFunction > MLevel;
- MLevel e;
- const size_t level; //context level of creation
- Tree() CVC4_UNDEFINED;
- const Tree & operator =(const Tree & t){
- Assert(t.e.empty()); Assert(e.empty());
- Assert(t.level == level);
- return t;
- }
- Tree(size_t l): level(l) {};
- ~Tree(){
- for(typename MLevel::iterator i = e.begin(); i!=e.end(); ++i)
- delete(i->second);
- };
- };
-
-
- typedef std::pair<Tree *, TNode> Mod;
-
- class CleanUp{
- public:
- inline void operator()(Mod * m){
- typename Tree::MLevel::iterator i = m->first->e.find(m->second);
- Assert (i != m->first->e.end()); //should not have been already removed
- m->first->e.erase(i);
- };
- };
-
- EqualityQuery* d_eQ;
- CandidateGenerator * d_cG;
-
- context::Context* d_context;
- context::CDList<Mod, CleanUp, std::allocator<Mod> > d_mods;
-
-
- typedef std::map<Node, Node>::const_iterator mapIter;
-
- /** add the substitution given by the iterator*/
- void addSubTree( Tree * root, mapIter current, mapIter end, size_t currLevel);
- /** test if it exists match, modulo uf-equations if modEq is true if
- * return false the deepest point of divergence is put in [e] and
- * [diverge].
- */
- bool existsInstMatch( Tree * root,
- mapIter & current, mapIter & end,
- Tree * & e, mapIter & diverge) const;
-
- /** add match m in the trie root
- return true if it was never seen */
- bool addInstMatch( InstMatch& m, Tree * root);
-
-public:
- InstMatchTrie2Gen(context::Context* c, QuantifiersEngine* q);
- InstMatchTrie2Gen(const InstMatchTrie2Gen &) CVC4_UNDEFINED;
- const InstMatchTrie2Gen & operator =(const InstMatchTrie2Gen & e) CVC4_UNDEFINED;
-};
-
-template<bool modEq>
-class InstMatchTrie2
-{
- typename InstMatchTrie2Gen<modEq>::Tree d_data;
- InstMatchTrie2Gen<modEq> d_backtrack;
-public:
- InstMatchTrie2(context::Context* c, QuantifiersEngine* q): d_data(0),
- d_backtrack(c,q) {};
- InstMatchTrie2(const InstMatchTrie2 &) CVC4_UNDEFINED;
- const InstMatchTrie2 & operator =(const InstMatchTrie2 & e) CVC4_UNDEFINED;
- /** add match m in the trie,
- return true if it was never seen */
- inline bool addInstMatch( InstMatch& m){
- return d_backtrack.addInstMatch(m,&d_data);
- };
-
-};/* class InstMatchTrie2 */
-
-class Matcher
-{
-public:
- /** reset instantiation round (call this whenever equivalence classes have changed) */
- virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
- /** reset the term to match, return false if there is no such term */
- virtual bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe ) = 0;
- /** get the next match. If it return false once you shouldn't call
- getNextMatch again before doing a reset */
- virtual bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) = 0;
- /** If reset, or getNextMatch return false they remove from the
- InstMatch the binding that they have previously created */
-
- /** virtual Matcher in order to have definned behavior */
- virtual ~Matcher(){};
-};
-
-
-class ApplyMatcher: public Matcher{
-private:
- /** What to check first: constant and variable */
- std::vector< triple< TNode,size_t,EqualityQuery* > > d_constants;
- std::vector< triple< TNode,size_t,EqualityQuery* > > d_variables;
- /** children generators, only the sub-pattern which are
- neither a variable neither a constant appears */
- std::vector< triple< Matcher*, size_t, EqualityQuery* > > d_childrens;
- /** the variable that have been set by this matcher (during its own reset) */
- std::vector< TNode > d_binded; /* TNode because the variable are already in d_pattern */
- /** the representant of the argument of the term given by the last reset */
- std::vector< Node > d_reps;
-public:
- /** The pattern we are producing matches for */
- Node d_pattern;
-public:
- /** constructors */
- ApplyMatcher( Node pat, QuantifiersEngine* qe);
- /** destructor */
- ~ApplyMatcher(){/*TODO delete dandling pointers? */}
- /** reset instantiation round (call this whenever equivalence classes have changed) */
- void resetInstantiationRound( QuantifiersEngine* qe );
- /** reset the term to match */
- bool reset( TNode n, InstMatch& m, QuantifiersEngine* qe );
- /** get the next match. */
- bool getNextMatch(InstMatch& m, QuantifiersEngine* qe);
-private:
- bool getNextMatch(InstMatch& m, QuantifiersEngine* qe, bool reset);
-};
-
-
-/* Match literal so you don't choose the equivalence class( */
-class PatMatcher
-{
-public:
- /** reset instantiation round (call this whenever equivalence classes have changed) */
- virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
- /** reset the matcher, return false if there is no such term */
- virtual bool reset( InstMatch& m, QuantifiersEngine* qe ) = 0;
- /** get the next match. If it return false once you shouldn't call
- getNextMatch again before doing a reset */
- virtual bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) = 0;
- /** If reset, or getNextMatch return false they remove from the
- InstMatch the binding that they have previously created */
-};
-
-Matcher* mkMatcher( Node pat, QuantifiersEngine* qe );
-PatMatcher* mkPattern( Node pat, QuantifiersEngine* qe );
-
-/* Match literal so you don't choose the equivalence class( */
-class PatsMatcher
-{
-public:
- /** reset instantiation round (call this whenever equivalence classes have changed) */
- virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
- /** reset the matcher, return false if there is no such term */
- virtual bool getNextMatch( QuantifiersEngine* qe ) = 0;
- virtual const InstMatch& getInstMatch() = 0;
- /** Add directly the instantiation to quantifiers engine */
- virtual int addInstantiations( InstMatch& baseMatch, Node quant, QuantifiersEngine* qe) = 0;
-};
-
-PatsMatcher* mkPatterns( std::vector< Node > pat, QuantifiersEngine* qe );
-PatsMatcher* mkPatternsEfficient( std::vector< Node > pat, QuantifiersEngine* qe );
-
-/** return true if whatever Node is subsituted for the variables the
- given Node can't match the pattern */
-bool nonunifiable( TNode t, TNode pat, const std::vector<Node> & vars);
-
-class InstMatchGenerator;
-
-}/* CVC4::theory rrinst */
-
-}/* CVC4::theory namespace */
-
-}/* CVC4 namespace */
-
-#endif /* __CVC4__RR_INST_MATCH_H */
+++ /dev/null
-/********************* */
-/*! \file rr_inst_match_impl.h
- ** \verbatim
- ** Original author: bobot
- ** Major contributors: none
- ** Minor contributors (to current version): ajreynol, mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief inst match class
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__RR_INST_MATCH_IMPL_H
-#define __CVC4__RR_INST_MATCH_IMPL_H
-
-#include "theory/rr_inst_match.h"
-#include "theory/theory_engine.h"
-#include "theory/quantifiers_engine.h"
-#include "theory/rr_candidate_generator.h"
-#include "theory/uf/equality_engine.h"
-
-namespace CVC4 {
-namespace theory {
-namespace rrinst {
-
-template<bool modEq>
-InstMatchTrie2Gen<modEq>::InstMatchTrie2Gen(context::Context* c, QuantifiersEngine* qe):
- d_context(c), d_mods(c) {
- d_eQ = qe->getEqualityQuery();
- d_cG = qe->getRRCanGenClass();
-};
-
-/** add match m for quantifier f starting at index, take into account equalities q, return true if successful */
-template<bool modEq>
-void InstMatchTrie2Gen<modEq>::addSubTree( Tree * root, mapIter current, mapIter end, size_t currLevel ) {
- if( current == end ) return;
-
- Assert(root->e.find(current->second) == root->e.end());
- Tree * root2 = new Tree(currLevel);
- root->e.insert(std::make_pair(current->second, root2));
- addSubTree(root2, ++current, end, currLevel );
-}
-
-/** exists match */
-template<bool modEq>
-bool InstMatchTrie2Gen<modEq>::existsInstMatch(InstMatchTrie2Gen<modEq>::Tree * root,
- mapIter & current, mapIter & end,
- Tree * & e, mapIter & diverge) const{
- if( current == end ) {
- Debug("Trie2") << "Trie2 Bottom " << std::endl;
- --current;
- return true;
- }; //Already their
-
- if (current->first > diverge->first){
- // this point is the deepest point currently seen map are ordered
- e = root;
- diverge = current;
- };
-
- TNode n = current->second;
- typename InstMatchTrie2Gen<modEq>::Tree::MLevel::iterator it =
- root->e.find( n );
- if( it!=root->e.end() &&
- existsInstMatch( (*it).second, ++current, end, e, diverge) ){
- Debug("Trie2") << "Trie2 Directly here " << n << std::endl;
- --current;
- return true;
- }
- Assert( it==root->e.end() || e != root );
-
- // Even if n is in the trie others of the equivalence class
- // can also be in it since the equality can have appeared
- // after they have been added
- if( modEq && d_eQ->hasTerm( n ) ){
- //check modulo equality if any other instantiation match exists
- d_cG->reset( d_eQ->getRepresentative( n ) );
- for(TNode en = d_cG->getNextCandidate() ; !en.isNull() ;
- en = d_cG->getNextCandidate() ){
- if( en == n ) continue; // already tested
- typename InstMatchTrie2Gen<modEq>::Tree::MLevel::iterator itc =
- root->e.find( en );
- if( itc!=root->e.end() &&
- existsInstMatch( (*itc).second, ++current, end, e, diverge) ){
- Debug("Trie2") << "Trie2 Indirectly here by equality " << n << " = " << en << std::endl;
- --current;
- return true;
- }
- Assert( itc==root->e.end() || e != root );
- }
- }
- --current;
- return false;
-}
-
-template<bool modEq>
-bool InstMatchTrie2Gen<modEq>::
-addInstMatch( InstMatch& m, InstMatchTrie2Gen<modEq>::Tree* e ) {
- d_cG->resetInstantiationRound();
- mapIter begin = m.begin();
- mapIter end = m.end();
- mapIter diverge = begin;
- if( !existsInstMatch(e, begin, end, e, diverge ) ){
- Assert(!diverge->second.isNull());
- size_t currLevel = d_context->getLevel();
- addSubTree( e, diverge, end, currLevel );
- if(e->level != currLevel)
- //If same level that e, will be removed at the same time than e
- d_mods.push_back(std::make_pair(e,diverge->second));
- return true;
- }else{
- return false;
- }
-}
-
-}/* CVC4::theory::rrinst namespace */
-
-}/* CVC4::theory namespace */
-
-}/* CVC4 namespace */
-
-#endif /* __CVC4__RR_INST_MATCH_IMPL_H */
+++ /dev/null
-/********************* */
-/*! \file rr_trigger.cpp
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: mdeters
- ** Minor contributors (to current version): bobot
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Implementation of trigger class
- **/
-
-#include "theory/rr_trigger.h"
-#include "theory/theory_engine.h"
-#include "theory/quantifiers_engine.h"
-#include "theory/uf/theory_uf_instantiator.h"
-#include "theory/rr_candidate_generator.h"
-#include "theory/uf/equality_engine.h"
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::rrinst;
-
-//#define NESTED_PATTERN_SELECTION
-
-Trigger* Trigger::TrTrie::getTrigger2( std::vector< Node >& nodes ){
- if( nodes.empty() ){
- return d_tr;
- }else{
- Node n = nodes.back();
- nodes.pop_back();
- if( d_children.find( n )!=d_children.end() ){
- return d_children[n]->getTrigger2( nodes );
- }else{
- return NULL;
- }
- }
-}
-void Trigger::TrTrie::addTrigger2( std::vector< Node >& nodes, Trigger* t ){
- if( nodes.empty() ){
- d_tr = t;
- }else{
- Node n = nodes.back();
- nodes.pop_back();
- if( d_children.find( n )==d_children.end() ){
- d_children[n] = new TrTrie;
- }
- d_children[n]->addTrigger2( nodes, t );
- }
-}
-
-/** trigger static members */
-std::map< Node, std::vector< Node > > Trigger::d_var_contains;
-int Trigger::trCount = 0;
-Trigger::TrTrie Trigger::d_tr_trie;
-
-/** trigger class constructor */
-Trigger::Trigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool smartTriggers ) :
-d_quantEngine( qe ), d_f( f ){
- trCount++;
- d_nodes.insert( d_nodes.begin(), nodes.begin(), nodes.end() );
- Debug("trigger") << "Trigger for " << f << ": " << d_nodes << std::endl;
- if(matchOption == MATCH_GEN_DEFAULT) d_mg = mkPatterns( d_nodes, qe );
- else d_mg = mkPatternsEfficient( d_nodes, qe );
- if( d_nodes.size()==1 ){
- if( isSimpleTrigger( d_nodes[0] ) ){
- ++(qe->d_statistics.d_triggers);
- }else{
- ++(qe->d_statistics.d_simple_triggers);
- }
- }else{
- Debug("multi-trigger") << "Multi-trigger " << (*this) << std::endl;
- //std::cout << "Multi-trigger for " << f << " : " << std::endl;
- //std::cout << " " << (*this) << std::endl;
- ++(qe->d_statistics.d_multi_triggers);
- }
-}
-void Trigger::computeVarContains( Node n ) {
- if( d_var_contains.find( n )==d_var_contains.end() ){
- d_var_contains[n].clear();
- computeVarContains2( n, n );
- }
-}
-
-void Trigger::computeVarContains2( Node n, Node parent ){
- if( n.getKind()==INST_CONSTANT ){
- if( std::find( d_var_contains[parent].begin(), d_var_contains[parent].end(), n )==d_var_contains[parent].end() ){
- d_var_contains[parent].push_back( n );
- }
- }else{
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- computeVarContains2( n[i], parent );
- }
- }
-}
-
-void Trigger::resetInstantiationRound(){
- d_mg->resetInstantiationRound( d_quantEngine );
-}
-
-
-bool Trigger::getNextMatch(){
- bool retVal = d_mg->getNextMatch( d_quantEngine );
- //m.makeInternal( d_quantEngine->getEqualityQuery() );
- return retVal;
-}
-
-// bool Trigger::getMatch( Node t, InstMatch& m ){
-// //FIXME: this assumes d_mg is an inst match generator
-// return ((InstMatchGenerator*)d_mg)->getMatch( t, m, d_quantEngine );
-// }
-
-
-int Trigger::addInstantiations( InstMatch& baseMatch ){
- int addedLemmas = d_mg->addInstantiations( baseMatch,
- d_nodes[0].getAttribute(InstConstantAttribute()),
- d_quantEngine);
- if( addedLemmas>0 ){
- Debug("inst-trigger") << "Added " << addedLemmas << " lemmas, trigger was ";
- for( int i=0; i<(int)d_nodes.size(); i++ ){
- Debug("inst-trigger") << d_nodes[i] << " ";
- }
- Debug("inst-trigger") << std::endl;
- }
- return addedLemmas;
-}
-
-Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool keepAll, int trOption,
- bool smartTriggers ){
- std::vector< Node > trNodes;
- if( !keepAll ){
- //only take nodes that contribute variables to the trigger when added
- std::vector< Node > temp;
- temp.insert( temp.begin(), nodes.begin(), nodes.end() );
- std::map< Node, bool > vars;
- std::map< Node, std::vector< Node > > patterns;
- for( int i=0; i<(int)temp.size(); i++ ){
- bool foundVar = false;
- computeVarContains( temp[i] );
- for( int j=0; j<(int)d_var_contains[ temp[i] ].size(); j++ ){
- Node v = d_var_contains[ temp[i] ][j];
- if( v.getAttribute(InstConstantAttribute())==f ){
- if( vars.find( v )==vars.end() ){
- vars[ v ] = true;
- foundVar = true;
- }
- }
- }
- if( foundVar ){
- trNodes.push_back( temp[i] );
- for( int j=0; j<(int)d_var_contains[ temp[i] ].size(); j++ ){
- Node v = d_var_contains[ temp[i] ][j];
- patterns[ v ].push_back( temp[i] );
- }
- }
- }
- //now, minimalize the trigger
- for( int i=0; i<(int)trNodes.size(); i++ ){
- bool keepPattern = false;
- Node n = trNodes[i];
- for( int j=0; j<(int)d_var_contains[ n ].size(); j++ ){
- Node v = d_var_contains[ n ][j];
- if( patterns[v].size()==1 ){
- keepPattern = true;
- break;
- }
- }
- if( !keepPattern ){
- //remove from pattern vector
- for( int j=0; j<(int)d_var_contains[ n ].size(); j++ ){
- Node v = d_var_contains[ n ][j];
- for( int k=0; k<(int)patterns[v].size(); k++ ){
- if( patterns[v][k]==n ){
- patterns[v].erase( patterns[v].begin() + k, patterns[v].begin() + k + 1 );
- break;
- }
- }
- }
- //remove from trigger nodes
- trNodes.erase( trNodes.begin() + i, trNodes.begin() + i + 1 );
- i--;
- }
- }
- }else{
- trNodes.insert( trNodes.begin(), nodes.begin(), nodes.end() );
- }
-
- //check for duplicate?
- if( trOption==TR_MAKE_NEW ){
- //static int trNew = 0;
- //static int trOld = 0;
- //Trigger* t = d_tr_trie.getTrigger( trNodes );
- //if( t ){
- // trOld++;
- //}else{
- // trNew++;
- //}
- //if( (trNew+trOld)%100==0 ){
- // std::cout << "Trigger new old = " << trNew << " " << trOld << std::endl;
- //}
- }else{
- Trigger* t = d_tr_trie.getTrigger( trNodes );
- if( t ){
- if( trOption==TR_GET_OLD ){
- //just return old trigger
- return t;
- }else{
- return NULL;
- }
- }
- }
- Trigger* t = new Trigger( qe, f, trNodes, matchOption, smartTriggers );
- d_tr_trie.addTrigger( trNodes, t );
- return t;
-}
-Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, Node n, int matchOption, bool keepAll, int trOption, bool smartTriggers ){
- std::vector< Node > nodes;
- nodes.push_back( n );
- return mkTrigger( qe, f, nodes, matchOption, keepAll, trOption, smartTriggers );
-}
-
-bool Trigger::isUsableTrigger( std::vector< Node >& nodes, Node f ){
- for( int i=0; i<(int)nodes.size(); i++ ){
- if( !isUsableTrigger( nodes[i], f ) ){
- return false;
- }
- }
- return true;
-}
-
-bool Trigger::isUsable( Node n, Node f ){
- if( n.getAttribute(InstConstantAttribute())==f ){
- if( !isAtomicTrigger( n ) && n.getKind()!=INST_CONSTANT ){
- std::map< Node, Node > coeffs;
- return getPatternArithmetic( f, n, coeffs );
- }else{
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( !isUsable( n[i], f ) ){
- return false;
- }
- }
- return true;
- }
- }else{
- return true;
- }
-}
-
-bool Trigger::isSimpleTrigger( Node n ){
- if( isAtomicTrigger( n ) ){
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( n[i].getKind()!=INST_CONSTANT && n[i].hasAttribute(InstConstantAttribute()) ){
- return false;
- }
- }
- return true;
- }else{
- return false;
- }
-}
-
-/** filter all nodes that have instances */
-void Trigger::filterInstances( std::vector< Node >& nodes ){
- std::vector< bool > active;
- active.resize( nodes.size(), true );
- for( int i=0; i<(int)nodes.size(); i++ ){
- for( int j=i+1; j<(int)nodes.size(); j++ ){
- if( active[i] && active[j] ){
- int result = isInstanceOf( nodes[i], nodes[j] );
- if( result==1 ){
- active[j] = false;
- }else if( result==-1 ){
- active[i] = false;
- }
- }
- }
- }
- std::vector< Node > temp;
- for( int i=0; i<(int)nodes.size(); i++ ){
- if( active[i] ){
- temp.push_back( nodes[i] );
- }
- }
- nodes.clear();
- nodes.insert( nodes.begin(), temp.begin(), temp.end() );
-}
-
-
-bool Trigger::collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt ){
- if( patMap.find( n )==patMap.end() ){
- patMap[ n ] = false;
- if( tstrt==TS_MIN_TRIGGER ){
- if( n.getKind()==FORALL ){
-#ifdef NESTED_PATTERN_SELECTION
- //return collectPatTerms2( qe, f, qe->getOrCreateCounterexampleBody( n ), patMap, tstrt );
- return collectPatTerms2( qe, f, qe->getBoundBody( n ), patMap, tstrt );
-#else
- return false;
-#endif
- }else{
- bool retVal = false;
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( collectPatTerms2( qe, f, n[i], patMap, tstrt ) ){
- retVal = true;
- }
- }
- if( retVal ){
- return true;
- }else if( isUsableTrigger( n, f ) ){
- patMap[ n ] = true;
- return true;
- }else{
- return false;
- }
- }
- }else{
- bool retVal = false;
- if( isUsableTrigger( n, f ) ){
- patMap[ n ] = true;
- if( tstrt==TS_MAX_TRIGGER ){
- return true;
- }else{
- retVal = true;
- }
- }
- if( n.getKind()==FORALL ){
-#ifdef NESTED_PATTERN_SELECTION
- //if( collectPatTerms2( qe, f, qe->getOrCreateCounterexampleBody( n ), patMap, tstrt ) ){
- // retVal = true;
- //}
- if( collectPatTerms2( qe, f, qe->getBoundBody( n ), patMap, tstrt ) ){
- retVal = true;
- }
-#endif
- }else{
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( collectPatTerms2( qe, f, n[i], patMap, tstrt ) ){
- retVal = true;
- }
- }
- }
- return retVal;
- }
- }else{
- return patMap[ n ];
- }
-}
-
-void Trigger::collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, bool filterInst ){
- std::map< Node, bool > patMap;
- if( filterInst ){
- //immediately do not consider any term t for which another term is an instance of t
- std::vector< Node > patTerms2;
- collectPatTerms( qe, f, n, patTerms2, TS_ALL, false );
- std::vector< Node > temp;
- temp.insert( temp.begin(), patTerms2.begin(), patTerms2.end() );
- filterInstances( temp );
- if( temp.size()!=patTerms2.size() ){
- Debug("trigger-filter-instance") << "Filtered an instance: " << std::endl;
- Debug("trigger-filter-instance") << "Old: ";
- for( int i=0; i<(int)patTerms2.size(); i++ ){
- Debug("trigger-filter-instance") << patTerms2[i] << " ";
- }
- Debug("trigger-filter-instance") << std::endl << "New: ";
- for( int i=0; i<(int)temp.size(); i++ ){
- Debug("trigger-filter-instance") << temp[i] << " ";
- }
- Debug("trigger-filter-instance") << std::endl;
- }
- if( tstrt==TS_ALL ){
- patTerms.insert( patTerms.begin(), temp.begin(), temp.end() );
- return;
- }else{
- //do not consider terms that have instances
- for( int i=0; i<(int)patTerms2.size(); i++ ){
- if( std::find( temp.begin(), temp.end(), patTerms2[i] )==temp.end() ){
- patMap[ patTerms2[i] ] = false;
- }
- }
- }
- }
- collectPatTerms2( qe, f, n, patMap, tstrt );
- for( std::map< Node, bool >::iterator it = patMap.begin(); it != patMap.end(); ++it ){
- if( it->second ){
- patTerms.push_back( it->first );
- }
- }
-}
-
-/** is n1 an instance of n2 or vice versa? */
-int Trigger::isInstanceOf( Node n1, Node n2 ){
- if( n1==n2 ){
- return 1;
- }else if( n1.getKind()==n2.getKind() ){
- if( n1.getKind()==APPLY_UF ){
- if( n1.getOperator()==n2.getOperator() ){
- int result = 0;
- for( int i=0; i<(int)n1.getNumChildren(); i++ ){
- if( n1[i]!=n2[i] ){
- int cResult = isInstanceOf( n1[i], n2[i] );
- if( cResult==0 ){
- return 0;
- }else if( cResult!=result ){
- if( result!=0 ){
- return 0;
- }else{
- result = cResult;
- }
- }
- }
- }
- return result;
- }
- }
- return 0;
- }else if( n2.getKind()==INST_CONSTANT ){
- computeVarContains( n1 );
- //if( std::find( d_var_contains[ n1 ].begin(), d_var_contains[ n1 ].end(), n2 )!=d_var_contains[ n1 ].end() ){
- // return 1;
- //}
- if( d_var_contains[ n1 ].size()==1 && d_var_contains[ n1 ][ 0 ]==n2 ){
- return 1;
- }
- }else if( n1.getKind()==INST_CONSTANT ){
- computeVarContains( n2 );
- //if( std::find( d_var_contains[ n2 ].begin(), d_var_contains[ n2 ].end(), n1 )!=d_var_contains[ n2 ].end() ){
- // return -1;
- //}
- if( d_var_contains[ n2 ].size()==1 && d_var_contains[ n2 ][ 0 ]==n1 ){
- return 1;
- }
- }
- return 0;
-}
-
-bool Trigger::isVariableSubsume( Node n1, Node n2 ){
- if( n1==n2 ){
- return true;
- }else{
- //std::cout << "is variable subsume ? " << n1 << " " << n2 << std::endl;
- computeVarContains( n1 );
- computeVarContains( n2 );
- for( int i=0; i<(int)d_var_contains[n2].size(); i++ ){
- if( std::find( d_var_contains[n1].begin(), d_var_contains[n1].end(), d_var_contains[n2][i] )==d_var_contains[n1].end() ){
- //std::cout << "no" << std::endl;
- return false;
- }
- }
- //std::cout << "yes" << std::endl;
- return true;
- }
-}
-
-void Trigger::getVarContains( Node f, std::vector< Node >& pats, std::map< Node, std::vector< Node > >& varContains ){
- for( int i=0; i<(int)pats.size(); i++ ){
- computeVarContains( pats[i] );
- varContains[ pats[i] ].clear();
- for( int j=0; j<(int)d_var_contains[pats[i]].size(); j++ ){
- if( d_var_contains[pats[i]][j].getAttribute(InstConstantAttribute())==f ){
- varContains[ pats[i] ].push_back( d_var_contains[pats[i]][j] );
- }
- }
- }
-}
-
-void Trigger::getVarContainsNode( Node f, Node n, std::vector< Node >& varContains ){
- computeVarContains( n );
- for( int j=0; j<(int)d_var_contains[n].size(); j++ ){
- if( d_var_contains[n][j].getAttribute(InstConstantAttribute())==f ){
- varContains.push_back( d_var_contains[n][j] );
- }
- }
-}
-
-bool Trigger::getPatternArithmetic( Node f, Node n, std::map< Node, Node >& coeffs ){
- if( n.getKind()==PLUS ){
- Assert( coeffs.empty() );
- NodeBuilder<> t(kind::PLUS);
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( n[i].hasAttribute(InstConstantAttribute()) ){
- if( n[i].getKind()==INST_CONSTANT ){
- if( n[i].getAttribute(InstConstantAttribute())==f ){
- coeffs[ n[i] ] = Node::null();
- }else{
- coeffs.clear();
- return false;
- }
- }else if( !getPatternArithmetic( f, n[i], coeffs ) ){
- coeffs.clear();
- return false;
- }
- }else{
- t << n[i];
- }
- }
- if( t.getNumChildren()==0 ){
- coeffs[ Node::null() ] = NodeManager::currentNM()->mkConst( Rational(0) );
- }else if( t.getNumChildren()==1 ){
- coeffs[ Node::null() ] = t.getChild( 0 );
- }else{
- coeffs[ Node::null() ] = t;
- }
- return true;
- }else if( n.getKind()==MULT ){
- if( n[0].getKind()==INST_CONSTANT && n[0].getAttribute(InstConstantAttribute())==f ){
- Assert( !n[1].hasAttribute(InstConstantAttribute()) );
- coeffs[ n[0] ] = n[1];
- return true;
- }else if( n[1].getKind()==INST_CONSTANT && n[1].getAttribute(InstConstantAttribute())==f ){
- Assert( !n[0].hasAttribute(InstConstantAttribute()) );
- coeffs[ n[1] ] = n[0];
- return true;
- }
- }
- return false;
-}
+++ /dev/null
-/********************* */
-/*! \file rr_trigger.h
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: bobot
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief trigger class
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__RR_TRIGGER_H
-#define __CVC4__RR_TRIGGER_H
-
-#include "theory/rr_inst_match.h"
-
-namespace CVC4 {
-namespace theory {
-namespace rrinst {
-
-//a collect of nodes representing a trigger
-class Trigger {
-public:
- static int trCount;
-private:
- /** computation of variable contains */
- static std::map< Node, std::vector< Node > > d_var_contains;
- static void computeVarContains( Node n );
- static void computeVarContains2( Node n, Node parent );
-private:
- /** the quantifiers engine */
- QuantifiersEngine* d_quantEngine;
- /** the quantifier this trigger is for */
- Node d_f;
- /** match generators */
- PatsMatcher * d_mg;
-private:
- /** a trie of triggers */
- class TrTrie
- {
- private:
- Trigger* getTrigger2( std::vector< Node >& nodes );
- void addTrigger2( std::vector< Node >& nodes, Trigger* t );
- public:
- TrTrie() : d_tr( NULL ){}
- Trigger* d_tr;
- std::map< Node, TrTrie* > d_children;
- Trigger* getTrigger( std::vector< Node >& nodes ){
- std::vector< Node > temp;
- temp.insert( temp.begin(), nodes.begin(), nodes.end() );
- std::sort( temp.begin(), temp.end() );
- return getTrigger2( temp );
- }
- void addTrigger( std::vector< Node >& nodes, Trigger* t ){
- std::vector< Node > temp;
- temp.insert( temp.begin(), nodes.begin(), nodes.end() );
- std::sort( temp.begin(), temp.end() );
- return addTrigger2( temp, t );
- }
- };
- /** all triggers will be stored in this trie */
- static TrTrie d_tr_trie;
-private:
- /** trigger constructor */
- Trigger( QuantifiersEngine* ie, Node f, std::vector< Node >& nodes, int matchOption = 0, bool smartTriggers = false );
-public:
- ~Trigger(){}
-public:
- std::vector< Node > d_nodes;
-public:
- void debugPrint( const char* c );
- PatsMatcher* getGenerator() { return d_mg; }
-public:
- /** reset instantiation round (call this whenever equivalence classes have changed) */
- void resetInstantiationRound();
- /** get next match. must call reset( eqc ) once before this function. */
- bool getNextMatch();
- const InstMatch & getInstMatch(){return d_mg->getInstMatch();};
- /** return whether this is a multi-trigger */
- bool isMultiTrigger() { return d_nodes.size()>1; }
-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);
- /** mkTrigger method
- ie : quantifier engine;
- f : forall something ....
- nodes : (multi-)trigger
- matchOption : which policy to use for creating matches (one of InstMatchGenerator::MATCH_GEN_* )
- keepAll: don't remove unneeded patterns;
- trOption : policy for dealing with triggers that already existed (see below)
- */
- enum {
- //options for producing matches
- MATCH_GEN_DEFAULT = 0,
- MATCH_GEN_EFFICIENT_E_MATCH, //generate matches via Efficient E
- };
- enum{
- TR_MAKE_NEW, //make new trigger even if it already may exist
- TR_GET_OLD, //return a previous trigger if it had already been created
- TR_RETURN_NULL //return null if a duplicate is found
- };
- static Trigger* mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes,
- int matchOption = 0, bool keepAll = true, int trOption = TR_MAKE_NEW,
- bool smartTriggers = false );
- static Trigger* mkTrigger( QuantifiersEngine* qe, Node f, Node n,
- int matchOption = 0, bool keepAll = true, int trOption = TR_MAKE_NEW,
- bool smartTriggers = false );
-private:
- /** is subterm of trigger usable */
- static bool isUsable( Node n, Node f );
- /** collect all APPLY_UF pattern terms for f in n */
- static bool collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt );
-public:
- //different strategies for choosing trigger terms
- enum {
- TS_MAX_TRIGGER = 0,
- TS_MIN_TRIGGER,
- TS_ALL,
- };
- static void collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, bool filterInst = false );
-public:
- /** is usable trigger */
- static inline bool isUsableTrigger( TNode n, TNode f ){
- //return n.getAttribute(InstConstantAttribute())==f && n.getKind()==APPLY_UF;
- return n.getAttribute(InstConstantAttribute())==f && isAtomicTrigger( n ) && isUsable( n, f );
- }
- static inline bool isAtomicTrigger( TNode n ){
- return
- n.getKind()==kind::APPLY_UF ||
- n.getKind()==kind::SELECT ||
- n.getKind()==kind::STORE;
- }
- static bool isUsableTrigger( std::vector< Node >& nodes, Node f );
- static bool isSimpleTrigger( Node n );
- /** filter all nodes that have instances */
- static void filterInstances( std::vector< Node >& nodes );
- /** -1: n1 is an instance of n2, 1: n1 is an instance of n2 */
- static int isInstanceOf( Node n1, Node n2 );
- /** variables subsume, return true if n1 contains all free variables in n2 */
- static bool isVariableSubsume( Node n1, Node n2 );
- /** get var contains */
- static void getVarContains( Node f, std::vector< Node >& pats, std::map< Node, std::vector< Node > >& varContains );
- static void getVarContainsNode( Node f, Node n, std::vector< Node >& varContains );
- /** get pattern arithmetic */
- static bool getPatternArithmetic( Node f, Node n, std::map< Node, Node >& coeffs );
-
- inline void toStream(std::ostream& out) const {
- out << "TRIGGER( ";
- for( int i=0; i<(int)d_nodes.size(); i++ ){
- if( i>0 ){ out << ", "; }
- out << d_nodes[i];
- }
- out << " )";
- }
-};
-
-inline std::ostream& operator<<(std::ostream& out, const Trigger & tr) {
- tr.toStream(out);
- return out;
-}
-
-}/* CVC4::theory::rrinst namespace */
-
-}/* CVC4::theory namespace */
-
-}/* CVC4 namespace */
-
-#endif /* __CVC4__RR_TRIGGER_H */
#include "theory/theory.h"
#include "util/Assert.h"
#include "theory/quantifiers_engine.h"
-#include "theory/instantiator_default.h"
+#include "theory/quantifiers/instantiator_default.h"
#include <vector>
+++ /dev/null
-/********************* */
-/*! \file trigger.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 trigger class
- **/
-
-#include "theory/trigger.h"
-#include "theory/theory_engine.h"
-#include "theory/quantifiers_engine.h"
-#include "theory/uf/theory_uf_instantiator.h"
-#include "theory/candidate_generator.h"
-#include "theory/uf/equality_engine.h"
-#include "theory/quantifiers/options.h"
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::inst;
-
-//#define NESTED_PATTERN_SELECTION
-
-Trigger* Trigger::TrTrie::getTrigger2( std::vector< Node >& nodes ){
- if( nodes.empty() ){
- return d_tr;
- }else{
- Node n = nodes.back();
- nodes.pop_back();
- if( d_children.find( n )!=d_children.end() ){
- return d_children[n]->getTrigger2( nodes );
- }else{
- return NULL;
- }
- }
-}
-void Trigger::TrTrie::addTrigger2( std::vector< Node >& nodes, Trigger* t ){
- if( nodes.empty() ){
- d_tr = t;
- }else{
- Node n = nodes.back();
- nodes.pop_back();
- if( d_children.find( n )==d_children.end() ){
- d_children[n] = new TrTrie;
- }
- d_children[n]->addTrigger2( nodes, t );
- }
-}
-
-/** trigger static members */
-std::map< TNode, std::vector< TNode > > Trigger::d_var_contains;
-Trigger::TrTrie Trigger::d_tr_trie;
-
-/** trigger class constructor */
-Trigger::Trigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool smartTriggers ) :
-d_quantEngine( qe ), d_f( f ){
- d_nodes.insert( d_nodes.begin(), nodes.begin(), nodes.end() );
- if( smartTriggers ){
- if( d_nodes.size()==1 ){
- if( isSimpleTrigger( d_nodes[0] ) ){
- d_mg = new InstMatchGeneratorSimple( f, d_nodes[0] );
- }else{
- d_mg = new InstMatchGenerator( d_nodes[0], qe, matchOption );
- }
- }else{
- d_mg = new InstMatchGeneratorMulti( f, d_nodes, qe, matchOption );
- }
- }else{
- d_mg = new InstMatchGenerator( d_nodes, qe, matchOption );
- }
- Debug("trigger") << "Trigger for " << f << ": " << std::endl;
- for( int i=0; i<(int)d_nodes.size(); i++ ){
- Debug("trigger") << " " << d_nodes[i] << std::endl;
- }
- Debug("trigger") << std::endl;
- if( d_nodes.size()==1 ){
- if( isSimpleTrigger( d_nodes[0] ) ){
- ++(qe->d_statistics.d_triggers);
- }else{
- ++(qe->d_statistics.d_simple_triggers);
- }
- }else{
- Debug("multi-trigger") << "Multi-trigger " << (*this) << std::endl;
- //Notice() << "Multi-trigger for " << f << " : " << std::endl;
- //Notice() << " " << (*this) << std::endl;
- ++(qe->d_statistics.d_multi_triggers);
- }
- //Notice() << "Trigger : " << (*this) << " for " << f << std::endl;
- if( options::eagerInstQuant() ){
- Theory* th_uf = qe->getTheoryEngine()->getTheory( theory::THEORY_UF );
- uf::InstantiatorTheoryUf* ith = (uf::InstantiatorTheoryUf*)th_uf->getInstantiator();
- for( int i=0; i<(int)d_nodes.size(); i++ ){
- ith->registerTrigger( this, d_nodes[i].getOperator() );
- }
- }
-}
-void Trigger::computeVarContains( Node n ) {
- if( d_var_contains.find( n )==d_var_contains.end() ){
- d_var_contains[n].clear();
- computeVarContains2( n, n );
- }
-}
-
-void Trigger::computeVarContains2( Node n, Node parent ){
- if( n.getKind()==INST_CONSTANT ){
- if( std::find( d_var_contains[parent].begin(), d_var_contains[parent].end(), n )==d_var_contains[parent].end() ){
- d_var_contains[parent].push_back( n );
- }
- }else{
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- computeVarContains2( n[i], parent );
- }
- }
-}
-
-void Trigger::resetInstantiationRound(){
- d_mg->resetInstantiationRound( d_quantEngine );
-}
-
-void Trigger::reset( Node eqc ){
- d_mg->reset( eqc, d_quantEngine );
-}
-
-bool Trigger::getNextMatch( InstMatch& m ){
- bool retVal = d_mg->getNextMatch( m, d_quantEngine );
- //m.makeInternal( d_quantEngine->getEqualityQuery() );
- return retVal;
-}
-
-bool Trigger::getMatch( Node t, InstMatch& m ){
- //FIXME: this assumes d_mg is an inst match generator
- return ((InstMatchGenerator*)d_mg)->getMatch( t, m, d_quantEngine );
-}
-
-int Trigger::addTerm( Node t ){
- return d_mg->addTerm( d_f, t, d_quantEngine );
-}
-
-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++ ){
- Debug("inst-trigger") << d_nodes[i] << " ";
- }
- Debug("inst-trigger") << std::endl;
- }
- return addedLemmas;
-}
-
-Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool keepAll, int trOption,
- bool smartTriggers ){
- std::vector< Node > trNodes;
- if( !keepAll ){
- //only take nodes that contribute variables to the trigger when added
- std::vector< Node > temp;
- temp.insert( temp.begin(), nodes.begin(), nodes.end() );
- std::map< Node, bool > vars;
- std::map< Node, std::vector< Node > > patterns;
- for( int i=0; i<(int)temp.size(); i++ ){
- bool foundVar = false;
- computeVarContains( temp[i] );
- for( int j=0; j<(int)d_var_contains[ temp[i] ].size(); j++ ){
- Node v = d_var_contains[ temp[i] ][j];
- if( v.getAttribute(InstConstantAttribute())==f ){
- if( vars.find( v )==vars.end() ){
- vars[ v ] = true;
- foundVar = true;
- }
- }
- }
- if( foundVar ){
- trNodes.push_back( temp[i] );
- for( int j=0; j<(int)d_var_contains[ temp[i] ].size(); j++ ){
- Node v = d_var_contains[ temp[i] ][j];
- patterns[ v ].push_back( temp[i] );
- }
- }
- }
- //now, minimalize the trigger
- for( int i=0; i<(int)trNodes.size(); i++ ){
- bool keepPattern = false;
- Node n = trNodes[i];
- for( int j=0; j<(int)d_var_contains[ n ].size(); j++ ){
- Node v = d_var_contains[ n ][j];
- if( patterns[v].size()==1 ){
- keepPattern = true;
- break;
- }
- }
- if( !keepPattern ){
- //remove from pattern vector
- for( int j=0; j<(int)d_var_contains[ n ].size(); j++ ){
- Node v = d_var_contains[ n ][j];
- for( int k=0; k<(int)patterns[v].size(); k++ ){
- if( patterns[v][k]==n ){
- patterns[v].erase( patterns[v].begin() + k, patterns[v].begin() + k + 1 );
- break;
- }
- }
- }
- //remove from trigger nodes
- trNodes.erase( trNodes.begin() + i, trNodes.begin() + i + 1 );
- i--;
- }
- }
- }else{
- trNodes.insert( trNodes.begin(), nodes.begin(), nodes.end() );
- }
-
- //check for duplicate?
- if( trOption==TR_MAKE_NEW ){
- //static int trNew = 0;
- //static int trOld = 0;
- //Trigger* t = d_tr_trie.getTrigger( trNodes );
- //if( t ){
- // trOld++;
- //}else{
- // trNew++;
- //}
- //if( (trNew+trOld)%100==0 ){
- // Notice() << "Trigger new old = " << trNew << " " << trOld << std::endl;
- //}
- }else{
- Trigger* t = d_tr_trie.getTrigger( trNodes );
- if( t ){
- if( trOption==TR_GET_OLD ){
- //just return old trigger
- return t;
- }else{
- return NULL;
- }
- }
- }
- Trigger* t = new Trigger( qe, f, trNodes, matchOption, smartTriggers );
- d_tr_trie.addTrigger( trNodes, t );
- return t;
-}
-Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, Node n, int matchOption, bool keepAll, int trOption, bool smartTriggers ){
- std::vector< Node > nodes;
- nodes.push_back( n );
- return mkTrigger( qe, f, nodes, matchOption, keepAll, trOption, smartTriggers );
-}
-
-bool Trigger::isUsableTrigger( std::vector< Node >& nodes, Node f ){
- for( int i=0; i<(int)nodes.size(); i++ ){
- if( !isUsableTrigger( nodes[i], f ) ){
- return false;
- }
- }
- return true;
-}
-
-bool Trigger::isUsable( Node n, Node f ){
- if( n.getAttribute(InstConstantAttribute())==f ){
- if( !isAtomicTrigger( n ) && n.getKind()!=INST_CONSTANT ){
- std::map< Node, Node > coeffs;
- return getPatternArithmetic( f, n, coeffs );
- }else{
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( !isUsable( n[i], f ) ){
- return false;
- }
- }
- return true;
- }
- }else{
- return true;
- }
-}
-
-bool Trigger::isUsableTrigger( Node n, Node f ){
- //return n.getAttribute(InstConstantAttribute())==f && n.getKind()==APPLY_UF;
- return n.getAttribute(InstConstantAttribute())==f && isAtomicTrigger( n ) && isUsable( n, f );
-}
-
-bool Trigger::isAtomicTrigger( Node n ){
- return n.getKind()==APPLY_UF || n.getKind()==SELECT || n.getKind()==STORE ||
- n.getKind()==APPLY_CONSTRUCTOR || n.getKind()==APPLY_SELECTOR || n.getKind()==APPLY_TESTER;
-}
-bool Trigger::isSimpleTrigger( Node n ){
- if( isAtomicTrigger( n ) ){
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( n[i].getKind()!=INST_CONSTANT && n[i].hasAttribute(InstConstantAttribute()) ){
- return false;
- }
- }
- return true;
- }else{
- return false;
- }
-}
-
-/** filter all nodes that have instances */
-void Trigger::filterInstances( std::vector< Node >& nodes ){
- std::vector< bool > active;
- active.resize( nodes.size(), true );
- for( int i=0; i<(int)nodes.size(); i++ ){
- for( int j=i+1; j<(int)nodes.size(); j++ ){
- if( active[i] && active[j] ){
- int result = isInstanceOf( nodes[i], nodes[j] );
- if( result==1 ){
- active[j] = false;
- }else if( result==-1 ){
- active[i] = false;
- }
- }
- }
- }
- std::vector< Node > temp;
- for( int i=0; i<(int)nodes.size(); i++ ){
- if( active[i] ){
- temp.push_back( nodes[i] );
- }
- }
- nodes.clear();
- nodes.insert( nodes.begin(), temp.begin(), temp.end() );
-}
-
-
-bool Trigger::collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt ){
- if( patMap.find( n )==patMap.end() ){
- patMap[ n ] = false;
- if( tstrt==TS_MIN_TRIGGER ){
- if( n.getKind()==FORALL ){
-#ifdef NESTED_PATTERN_SELECTION
- //return collectPatTerms2( qe, f, qe->getOrCreateCounterexampleBody( n ), patMap, tstrt );
- return collectPatTerms2( qe, f, qe->getBoundBody( n ), patMap, tstrt );
-#else
- return false;
-#endif
- }else{
- bool retVal = false;
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( collectPatTerms2( qe, f, n[i], patMap, tstrt ) ){
- retVal = true;
- }
- }
- if( retVal ){
- return true;
- }else if( isUsableTrigger( n, f ) ){
- patMap[ n ] = true;
- return true;
- }else{
- return false;
- }
- }
- }else{
- bool retVal = false;
- if( isUsableTrigger( n, f ) ){
- patMap[ n ] = true;
- if( tstrt==TS_MAX_TRIGGER ){
- return true;
- }else{
- retVal = true;
- }
- }
- if( n.getKind()==FORALL ){
-#ifdef NESTED_PATTERN_SELECTION
- //if( collectPatTerms2( qe, f, qe->getOrCreateCounterexampleBody( n ), patMap, tstrt ) ){
- // retVal = true;
- //}
- if( collectPatTerms2( qe, f, qe->getBoundBody( n ), patMap, tstrt ) ){
- retVal = true;
- }
-#endif
- }else{
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( collectPatTerms2( qe, f, n[i], patMap, tstrt ) ){
- retVal = true;
- }
- }
- }
- return retVal;
- }
- }else{
- return patMap[ n ];
- }
-}
-
-void Trigger::collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, bool filterInst ){
- std::map< Node, bool > patMap;
- if( filterInst ){
- //immediately do not consider any term t for which another term is an instance of t
- std::vector< Node > patTerms2;
- collectPatTerms( qe, f, n, patTerms2, TS_ALL, false );
- std::vector< Node > temp;
- temp.insert( temp.begin(), patTerms2.begin(), patTerms2.end() );
- filterInstances( temp );
- if( temp.size()!=patTerms2.size() ){
- Debug("trigger-filter-instance") << "Filtered an instance: " << std::endl;
- Debug("trigger-filter-instance") << "Old: ";
- for( int i=0; i<(int)patTerms2.size(); i++ ){
- Debug("trigger-filter-instance") << patTerms2[i] << " ";
- }
- Debug("trigger-filter-instance") << std::endl << "New: ";
- for( int i=0; i<(int)temp.size(); i++ ){
- Debug("trigger-filter-instance") << temp[i] << " ";
- }
- Debug("trigger-filter-instance") << std::endl;
- }
- if( tstrt==TS_ALL ){
- patTerms.insert( patTerms.begin(), temp.begin(), temp.end() );
- return;
- }else{
- //do not consider terms that have instances
- for( int i=0; i<(int)patTerms2.size(); i++ ){
- if( std::find( temp.begin(), temp.end(), patTerms2[i] )==temp.end() ){
- patMap[ patTerms2[i] ] = false;
- }
- }
- }
- }
- collectPatTerms2( qe, f, n, patMap, tstrt );
- for( std::map< Node, bool >::iterator it = patMap.begin(); it != patMap.end(); ++it ){
- if( it->second ){
- patTerms.push_back( it->first );
- }
- }
-}
-
-/** is n1 an instance of n2 or vice versa? */
-int Trigger::isInstanceOf( Node n1, Node n2 ){
- if( n1==n2 ){
- return 1;
- }else if( n1.getKind()==n2.getKind() ){
- if( n1.getKind()==APPLY_UF ){
- if( n1.getOperator()==n2.getOperator() ){
- int result = 0;
- for( int i=0; i<(int)n1.getNumChildren(); i++ ){
- if( n1[i]!=n2[i] ){
- int cResult = isInstanceOf( n1[i], n2[i] );
- if( cResult==0 ){
- return 0;
- }else if( cResult!=result ){
- if( result!=0 ){
- return 0;
- }else{
- result = cResult;
- }
- }
- }
- }
- return result;
- }
- }
- return 0;
- }else if( n2.getKind()==INST_CONSTANT ){
- computeVarContains( n1 );
- //if( std::find( d_var_contains[ n1 ].begin(), d_var_contains[ n1 ].end(), n2 )!=d_var_contains[ n1 ].end() ){
- // return 1;
- //}
- if( d_var_contains[ n1 ].size()==1 && d_var_contains[ n1 ][ 0 ]==n2 ){
- return 1;
- }
- }else if( n1.getKind()==INST_CONSTANT ){
- computeVarContains( n2 );
- //if( std::find( d_var_contains[ n2 ].begin(), d_var_contains[ n2 ].end(), n1 )!=d_var_contains[ n2 ].end() ){
- // return -1;
- //}
- if( d_var_contains[ n2 ].size()==1 && d_var_contains[ n2 ][ 0 ]==n1 ){
- return 1;
- }
- }
- return 0;
-}
-
-bool Trigger::isVariableSubsume( Node n1, Node n2 ){
- if( n1==n2 ){
- return true;
- }else{
- //Notice() << "is variable subsume ? " << n1 << " " << n2 << std::endl;
- computeVarContains( n1 );
- computeVarContains( n2 );
- for( int i=0; i<(int)d_var_contains[n2].size(); i++ ){
- if( std::find( d_var_contains[n1].begin(), d_var_contains[n1].end(), d_var_contains[n2][i] )==d_var_contains[n1].end() ){
- //Notice() << "no" << std::endl;
- return false;
- }
- }
- //Notice() << "yes" << std::endl;
- return true;
- }
-}
-
-void Trigger::getVarContains( Node f, std::vector< Node >& pats, std::map< Node, std::vector< Node > >& varContains ){
- for( int i=0; i<(int)pats.size(); i++ ){
- computeVarContains( pats[i] );
- varContains[ pats[i] ].clear();
- for( int j=0; j<(int)d_var_contains[pats[i]].size(); j++ ){
- if( d_var_contains[pats[i]][j].getAttribute(InstConstantAttribute())==f ){
- varContains[ pats[i] ].push_back( d_var_contains[pats[i]][j] );
- }
- }
- }
-}
-
-void Trigger::getVarContainsNode( Node f, Node n, std::vector< Node >& varContains ){
- computeVarContains( n );
- for( int j=0; j<(int)d_var_contains[n].size(); j++ ){
- if( d_var_contains[n][j].getAttribute(InstConstantAttribute())==f ){
- varContains.push_back( d_var_contains[n][j] );
- }
- }
-}
-
-bool Trigger::getPatternArithmetic( Node f, Node n, std::map< Node, Node >& coeffs ){
- if( n.getKind()==PLUS ){
- Assert( coeffs.empty() );
- NodeBuilder<> t(kind::PLUS);
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( n[i].hasAttribute(InstConstantAttribute()) ){
- if( n[i].getKind()==INST_CONSTANT ){
- if( n[i].getAttribute(InstConstantAttribute())==f ){
- coeffs[ n[i] ] = Node::null();
- }else{
- coeffs.clear();
- return false;
- }
- }else if( !getPatternArithmetic( f, n[i], coeffs ) ){
- coeffs.clear();
- return false;
- }
- }else{
- t << n[i];
- }
- }
- if( t.getNumChildren()==0 ){
- coeffs[ Node::null() ] = NodeManager::currentNM()->mkConst( Rational(0) );
- }else if( t.getNumChildren()==1 ){
- coeffs[ Node::null() ] = t.getChild( 0 );
- }else{
- coeffs[ Node::null() ] = t;
- }
- return true;
- }else if( n.getKind()==MULT ){
- if( n[0].getKind()==INST_CONSTANT && n[0].getAttribute(InstConstantAttribute())==f ){
- Assert( !n[1].hasAttribute(InstConstantAttribute()) );
- coeffs[ n[0] ] = n[1];
- return true;
- }else if( n[1].getKind()==INST_CONSTANT && n[1].getAttribute(InstConstantAttribute())==f ){
- Assert( !n[0].hasAttribute(InstConstantAttribute()) );
- coeffs[ n[1] ] = n[0];
- return true;
- }
- }
- return false;
-}
+++ /dev/null
-/********************* */
-/*! \file trigger.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 trigger class
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__TRIGGER_H
-#define __CVC4__TRIGGER_H
-
-#include "theory/inst_match.h"
-
-namespace CVC4 {
-namespace theory {
-namespace inst {
-
-//a collect of nodes representing a trigger
-class Trigger {
-private:
- /** computation of variable contains */
- static std::map< TNode, std::vector< TNode > > d_var_contains;
- static void computeVarContains( Node n );
- static void computeVarContains2( Node n, Node parent );
-private:
- /** the quantifiers engine */
- QuantifiersEngine* d_quantEngine;
- /** the quantifier this trigger is for */
- Node d_f;
- /** match generators */
- IMGenerator* d_mg;
-private:
- /** a trie of triggers */
- class TrTrie {
- private:
- Trigger* getTrigger2( std::vector< Node >& nodes );
- void addTrigger2( std::vector< Node >& nodes, Trigger* t );
- public:
- TrTrie() : d_tr( NULL ){}
- Trigger* d_tr;
- std::map< TNode, TrTrie* > d_children;
- Trigger* getTrigger( std::vector< Node >& nodes ){
- std::vector< Node > temp;
- temp.insert( temp.begin(), nodes.begin(), nodes.end() );
- std::sort( temp.begin(), temp.end() );
- return getTrigger2( temp );
- }
- void addTrigger( std::vector< Node >& nodes, Trigger* t ){
- std::vector< Node > temp;
- temp.insert( temp.begin(), nodes.begin(), nodes.end() );
- std::sort( temp.begin(), temp.end() );
- return addTrigger2( temp, t );
- }
- };/* class Trigger::TrTrie */
- /** all triggers will be stored in this trie */
- static TrTrie d_tr_trie;
-private:
- /** trigger constructor */
- Trigger( QuantifiersEngine* ie, Node f, std::vector< Node >& nodes, int matchOption = 0, bool smartTriggers = false );
-public:
- ~Trigger(){}
-public:
- std::vector< Node > d_nodes;
-public:
- void debugPrint( const char* c );
- IMGenerator* getGenerator() { return d_mg; }
-public:
- /** reset instantiation round (call this whenever equivalence classes have changed) */
- void resetInstantiationRound();
- /** reset, eqc is the equivalence class to search in (search in any if eqc=null) */
- void reset( Node eqc );
- /** get next match. must call reset( eqc ) once before this function. */
- bool getNextMatch( InstMatch& m );
- /** get the match against ground term or formula t.
- the trigger and t should have the same shape.
- Currently the trigger should not be a multi-trigger.
- */
- bool getMatch( Node t, InstMatch& m);
- /** add ground term t, called when t is added to the TermDb */
- int addTerm( Node t );
- /** return true if whatever Node is subsituted for the variables the
- given Node can't match the pattern */
- bool nonunifiable( TNode t, const std::vector<Node> & vars){
- return d_mg->nonunifiable(t,vars);
- }
- /** return whether this is a multi-trigger */
- bool isMultiTrigger() { return d_nodes.size()>1; }
-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 );
- /** mkTrigger method
- ie : quantifier engine;
- f : forall something ....
- nodes : (multi-)trigger
- matchOption : which policy to use for creating matches (one of InstMatchGenerator::MATCH_GEN_* )
- keepAll: don't remove unneeded patterns;
- trOption : policy for dealing with triggers that already existed (see below)
- */
- enum{
- TR_MAKE_NEW, //make new trigger even if it already may exist
- TR_GET_OLD, //return a previous trigger if it had already been created
- TR_RETURN_NULL //return null if a duplicate is found
- };
- static Trigger* mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes,
- int matchOption = 0, bool keepAll = true, int trOption = TR_MAKE_NEW,
- bool smartTriggers = false );
- static Trigger* mkTrigger( QuantifiersEngine* qe, Node f, Node n,
- int matchOption = 0, bool keepAll = true, int trOption = TR_MAKE_NEW,
- bool smartTriggers = false );
-private:
- /** is subterm of trigger usable */
- static bool isUsable( Node n, Node f );
- /** collect all APPLY_UF pattern terms for f in n */
- static bool collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt );
-public:
- //different strategies for choosing trigger terms
- enum {
- TS_MAX_TRIGGER = 0,
- TS_MIN_TRIGGER,
- TS_ALL,
- };
- static void collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, bool filterInst = false );
-public:
- /** is usable trigger */
- static bool isUsableTrigger( std::vector< Node >& nodes, Node f );
- static bool isUsableTrigger( Node n, Node f );
- static bool isAtomicTrigger( Node n );
- static bool isSimpleTrigger( Node n );
- /** filter all nodes that have instances */
- static void filterInstances( std::vector< Node >& nodes );
- /** -1: n1 is an instance of n2, 1: n1 is an instance of n2 */
- static int isInstanceOf( Node n1, Node n2 );
- /** variables subsume, return true if n1 contains all free variables in n2 */
- static bool isVariableSubsume( Node n1, Node n2 );
- /** get var contains */
- static void getVarContains( Node f, std::vector< Node >& pats, std::map< Node, std::vector< Node > >& varContains );
- static void getVarContainsNode( Node f, Node n, std::vector< Node >& varContains );
- /** get pattern arithmetic */
- static bool getPatternArithmetic( Node f, Node n, std::map< Node, Node >& coeffs );
-
- inline void toStream(std::ostream& out) const {
- out << "TRIGGER( ";
- for( int i=0; i<(int)d_nodes.size(); i++ ){
- if( i>0 ){ out << ", "; }
- out << d_nodes[i];
- }
- out << " )";
- }
-};
-
-inline std::ostream& operator<<(std::ostream& out, const Trigger & tr) {
- tr.toStream(out);
- return out;
-}
-
-}/* CVC4::theory::inst namespace */
-
-}/* CVC4::theory namespace */
-
-}/* CVC4 namespace */
-
-#endif /* __CVC4__TRIGGER_H */
#define __CVC4__INST_STRATEGY_H
#include "theory/quantifiers_engine.h"
-#include "theory/trigger.h"
+#include "theory/quantifiers/trigger.h"
#include "context/context.h"
#include "context/context_mm.h"
#include "theory/uf/theory_uf_instantiator.h"
#include "theory/theory_engine.h"
#include "theory/uf/theory_uf.h"
-#include "theory/rr_candidate_generator.h"
+#include "theory/rewriterules/rr_candidate_generator.h"
#include "theory/uf/equality_engine.h"
#include "theory/quantifiers/options.h"
#include "theory/rewriterules/options.h"
#include "util/stats.h"
#include "theory/uf/theory_uf.h"
-#include "theory/trigger.h"
+#include "theory/quantifiers/trigger.h"
#include "util/ntuple.h"
#include "context/cdqueue.h"