/********************* */ /*! \file quant_split.cpp ** \verbatim ** Top contributors (to current version): ** Andrew Reynolds, 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 dynamic quantifiers splitting **/ #include "theory/quantifiers/quant_split.h" #include "theory/quantifiers/term_database.h" #include "theory/quantifiers_engine.h" #include "theory/quantifiers/first_order_model.h" #include "options/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::quantifiers; QuantDSplit::QuantDSplit( QuantifiersEngine * qe, context::Context* c ) : QuantifiersModule( qe ), d_added_split( qe->getUserContext() ){ } /** pre register quantifier */ void QuantDSplit::preRegisterQuantifier( Node q ) { int max_index = -1; int max_score = -1; if( q.getNumChildren()==3 ){ return; } Trace("quant-dsplit-debug") << "Check split quantified formula : " << q << std::endl; for( unsigned i=0; imax_score ){ max_index = i; max_score = score; } } } } if( max_index!=-1 ){ Trace("quant-dsplit-debug") << "Will split at index " << max_index << "." << std::endl; d_quant_to_reduce[q] = max_index; d_quantEngine->setOwner( q, this ); } } /* whether this module needs to check this round */ bool QuantDSplit::needsCheck( Theory::Effort e ) { return e>=Theory::EFFORT_FULL && !d_quant_to_reduce.empty(); } /* Call during quantifier engine's check */ void QuantDSplit::check( Theory::Effort e, unsigned quant_e ) { //add lemmas ASAP (they are a reduction) if( quant_e==QuantifiersEngine::QEFFORT_CONFLICT ){ std::vector< Node > lemmas; for(std::map< Node, int >::iterator it = d_quant_to_reduce.begin(); it != d_quant_to_reduce.end(); ++it) { Node q = it->first; if( d_added_split.find( q )==d_added_split.end() ){ d_added_split.insert( q ); std::vector< Node > bvs; for( unsigned i=0; isecond ){ bvs.push_back( q[0][i] ); } } std::vector< Node > disj; disj.push_back( q.negate() ); TNode svar = q[0][it->second]; TypeNode tn = svar.getType(); if( tn.isDatatype() ){ std::vector< Node > cons; const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype(); for( unsigned j=0; j vars; for( unsigned k=0; kmkBoundVar( tns ); vars.push_back( v ); } std::vector< Node > bvs_cmb; bvs_cmb.insert( bvs_cmb.end(), bvs.begin(), bvs.end() ); bvs_cmb.insert( bvs_cmb.end(), vars.begin(), vars.end() ); vars.insert( vars.begin(), Node::fromExpr( dt[j].getConstructor() ) ); Node c = NodeManager::currentNM()->mkNode( kind::APPLY_CONSTRUCTOR, vars ); TNode ct = c; Node body = q[1].substitute( svar, ct ); if( !bvs_cmb.empty() ){ body = NodeManager::currentNM()->mkNode( kind::FORALL, NodeManager::currentNM()->mkNode( kind::BOUND_VAR_LIST, bvs_cmb ), body ); } cons.push_back( body ); } Node conc = cons.size()==1 ? cons[0] : NodeManager::currentNM()->mkNode( kind::AND, cons ); disj.push_back( conc ); }else{ Assert( false ); } lemmas.push_back( disj.size()==1 ? disj[0] : NodeManager::currentNM()->mkNode( kind::OR, disj ) ); } } //add lemmas to quantifiers engine for( unsigned i=0; iaddLemma( lemmas[i], false ); } d_quant_to_reduce.clear(); } }