/********************* */ /*! \file rep_set.cpp ** \verbatim ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS ** in the top-level source directory) and their institutional affiliations. ** All rights reserved. See the file COPYING in the top-level source ** directory for licensing information.\endverbatim ** ** \brief Implementation of representative set **/ #include "theory/rep_set.h" #include "theory/type_enumerator.h" #include "theory/quantifiers/bounded_integers.h" #include "theory/quantifiers/term_database.h" #include "theory/quantifiers/first_order_model.h" using namespace std; using namespace CVC4; using namespace CVC4::kind; using namespace CVC4::context; using namespace CVC4::theory; void RepSet::clear(){ d_type_reps.clear(); d_type_complete.clear(); d_tmap.clear(); d_values_to_terms.clear(); } bool RepSet::hasRep( TypeNode tn, Node n ) { std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.find( tn ); if( it==d_type_reps.end() ){ return false; }else{ return std::find( it->second.begin(), it->second.end(), n )!=it->second.end(); } } int RepSet::getNumRepresentatives( TypeNode tn ) const{ std::map< TypeNode, std::vector< Node > >::const_iterator it = d_type_reps.find( tn ); if( it!=d_type_reps.end() ){ return (int)it->second.size(); }else{ return 0; } } bool containsStoreAll( Node n, std::vector< Node >& cache ){ if( std::find( cache.begin(), cache.end(), n )==cache.end() ){ cache.push_back( n ); if( n.getKind()==STORE_ALL ){ return true; }else{ for( unsigned i=0; i cache; if( containsStoreAll( n, cache ) ){ return; } } Trace("rsi-debug") << "Add rep #" << d_type_reps[tn].size() << " for " << tn << " : " << n << std::endl; Assert( n.getType().isSubtypeOf( tn ) ); d_tmap[ n ] = (int)d_type_reps[tn].size(); d_type_reps[tn].push_back( n ); } int RepSet::getIndexFor( Node n ) const { std::map< Node, int >::const_iterator it = d_tmap.find( n ); if( it!=d_tmap.end() ){ return it->second; }else{ return -1; } } bool RepSet::complete( TypeNode t ){ std::map< TypeNode, bool >::iterator it = d_type_complete.find( t ); if( it==d_type_complete.end() ){ //remove all previous for( unsigned i=0; isecond; } } void RepSet::toStream(std::ostream& out){ for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){ if( !it->first.isFunction() && !it->first.isPredicate() ){ out << "(" << it->first << " " << it->second.size(); out << " ("; for( unsigned i=0; isecond.size(); i++ ){ if( i>0 ){ out << " "; } out << it->second[i]; } out << ")"; out << ")" << std::endl; } } } RepSetIterator::RepSetIterator( QuantifiersEngine * qe, RepSet* rs ) : d_qe(qe), d_rep_set( rs ){ d_incomplete = false; } int RepSetIterator::domainSize( int i ) { Assert(i>=0); int v = d_var_order[i]; return d_domain_elements[v].size(); } bool RepSetIterator::setQuantifier( Node f, RepBoundExt* rext ){ Trace("rsi") << "Make rsi for " << f << std::endl; Assert( d_types.empty() ); //store indicies for( size_t i=0; i() ); TypeNode tn = d_types[v]; Trace("rsi") << "Var #" << v << " is type " << tn << "..." << std::endl; if( tn.isSort() ){ //must ensure uninterpreted type is non-empty. if( !d_rep_set->hasType( tn ) ){ //FIXME: // terms in rep_set are now constants which mapped to terms through TheoryModel // thus, should introduce a constant and a term. for now, just a term. //Node c = d_qe->getTermDatabase()->getEnumerateTerm( tn, 0 ); Node var = d_qe->getModel()->getSomeDomainElement( tn ); Trace("mkVar") << "RepSetIterator:: Make variable " << var << " : " << tn << std::endl; d_rep_set->add( tn, var ); } } bool inc = true; //check if it is externally bound if( rext && rext->setBound( d_owner, v, tn, d_domain_elements[v] ) ){ d_enum_type.push_back( ENUM_DEFAULT ); inc = false; //builtin: check if it is bound by bounded integer module }else if( d_owner.getKind()==FORALL && d_qe && d_qe->getBoundedIntegers() ){ if( d_qe->getBoundedIntegers()->isBoundVar( d_owner, d_owner[0][v] ) ){ unsigned bvt = d_qe->getBoundedIntegers()->getBoundVarType( d_owner, d_owner[0][v] ); if( bvt!=quantifiers::BoundedIntegers::BOUND_FINITE ){ d_enum_type.push_back( ENUM_BOUND_INT ); inc = false; }else{ //will treat in default way } } } if( !tn.isSort() ){ if( inc ){ if( d_qe->getTermDatabase()->mayComplete( tn ) ){ Trace("rsi") << " do complete, since cardinality is small (" << tn.getCardinality() << ")..." << std::endl; d_rep_set->complete( tn ); //must have succeeded Assert( d_rep_set->hasType( tn ) ); }else{ Trace("rsi") << " variable cannot be bounded." << std::endl; Trace("fmf-incomplete") << "Incomplete because of quantification of type " << tn << std::endl; d_incomplete = true; } } } //if we have yet to determine the type of enumeration if( d_enum_type.size()<=v ){ if( d_rep_set->hasType( tn ) ){ d_enum_type.push_back( ENUM_DEFAULT ); for( unsigned j=0; jd_type_reps[tn].size(); j++ ){ //d_domain[v].push_back( j ); d_domain_elements[v].push_back( d_rep_set->d_type_reps[tn][j] ); } }else{ Assert( d_incomplete ); return false; } } } //must set a variable index order based on bounded integers if( d_owner.getKind()==FORALL && d_qe && d_qe->getBoundedIntegers() ){ Trace("bound-int-rsi") << "Calculating variable order..." << std::endl; std::vector< int > varOrder; for( unsigned i=0; igetBoundedIntegers()->getNumBoundVars( d_owner ); i++ ){ Node v = d_qe->getBoundedIntegers()->getBoundVar( d_owner, i ); Trace("bound-int-rsi") << " bound var #" << i << " is " << v << std::endl; varOrder.push_back( d_qe->getTermDatabase()->getVariableNum( d_owner, v ) ); } for( unsigned i=0; igetBoundedIntegers()->isBoundVar(d_owner, d_owner[0][i])) { varOrder.push_back(i); } } Trace("bound-int-rsi") << "Variable order : "; for( unsigned i=0; i indexOrder; indexOrder.resize(varOrder.size()); for( unsigned i=0; i& indexOrder ){ d_index_order.clear(); d_index_order.insert( d_index_order.begin(), indexOrder.begin(), indexOrder.end() ); //make the d_var_order mapping for( unsigned i=0; i=0 && d_index[i]>=(int)(domainSize(i)-1) ){ i--; if( i>=0){ Trace("rsi-debug") << "domain size of " << i << " is " << domainSize(i) << std::endl; } } if( i==-1 ){ d_index.clear(); return -1; }else{ Trace("rsi-debug") << "increment " << i << std::endl; d_index[i]++; return do_reset_increment( i ); } } int RepSetIterator::do_reset_increment( int i, bool initial ) { bool emptyDomain = false; for( unsigned ii=(i+1); ii