/********************* */ /*! \file macros.cpp ** \verbatim ** Original author: Andrew Reynolds ** Major contributors: Morgan Deters ** Minor contributors (to current version): none ** This file is part of the CVC4 project. ** Copyright (c) 2009-2013 New York University and The University of Iowa ** See the file COPYING in the top-level source directory for licensing ** information.\endverbatim ** ** \brief Sort inference module ** ** This class implements quantifiers macro definitions. **/ #include #include "theory/quantifiers/macros.h" #include "theory/rewriter.h" using namespace CVC4; using namespace std; using namespace CVC4::theory; using namespace CVC4::theory::quantifiers; using namespace CVC4::kind; using namespace CVC4::context; bool QuantifierMacros::simplify( std::vector< Node >& assertions, bool doRewrite ){ //first, collect macro definitions for( size_t i=0; i args; for( size_t j=0; j > >::iterator it = d_macro_def_cases.begin(); it != d_macro_def_cases.end(); ++it ){ //create ite based on case definitions Node val; for( size_t i=0; isecond.size(); ++i ){ if( it->second[i].first.isNull() ){ Assert( i==0 ); val = it->second[i].second; }else{ //if value is null, must generate it if( val.isNull() ){ std::stringstream ss; ss << "mdo_" << it->first << "_$$"; Node op = NodeManager::currentNM()->mkSkolem( ss.str(), it->first.getType(), "op created during macro definitions" ); //will be defined in terms of fresh operator std::vector< Node > children; children.push_back( op ); children.insert( children.end(), d_macro_basis[ it->first ].begin(), d_macro_basis[ it->first ].end() ); val = NodeManager::currentNM()->mkNode( APPLY_UF, children ); } val = NodeManager::currentNM()->mkNode( ITE, it->second[i].first, it->second[i].second, val ); } } d_macro_defs[ it->first ] = val; Trace("macros-def") << "* " << val << " is a macro for " << it->first << std::endl; } //now simplify bodies for( std::map< Node, Node >::iterator it = d_macro_defs.begin(); it != d_macro_defs.end(); ++it ){ d_macro_defs[ it->first ] = Rewriter::rewrite( simplify( it->second ) ); } bool retVal = false; if( doRewrite && !d_macro_defs.empty() ){ //now, rewrite based on macro definitions for( size_t i=0; i& candidates ){ if( n.getKind()==APPLY_UF ){ candidates.push_back( n ); }else if( n.getKind()==PLUS ){ for( size_t i=0; i plus_children; //find monomial with n for( size_t j=0; jmkConst( Rational(1) ); }else if( lit[1][j].getKind()==MULT && lit[1][j][1]==n ){ Assert( coeff.isNull() ); Assert( lit[1][j][0].isConst() ); coeff = lit[1][j][0]; }else{ plus_children.push_back( lit[1][j] ); } } if( !coeff.isNull() ){ term = NodeManager::currentNM()->mkNode( PLUS, plus_children ); term = NodeManager::currentNM()->mkNode( MINUS, lit[0], term ); } } if( !coeff.isNull() ){ coeff = NodeManager::currentNM()->mkConst( Rational(1) / coeff.getConst() ); term = NodeManager::currentNM()->mkNode( MULT, coeff, term ); term = Rewriter::rewrite( term ); return term; } } } Trace("macros-debug") << "Cannot find for " << lit << " " << n << std::endl; return Node::null(); } bool QuantifierMacros::isConsistentDefinition( Node op, Node cond, Node def ){ if( d_macro_def_cases[op].empty() || ( cond.isNull() && !d_macro_def_cases[op][0].first.isNull() ) ){ return true; }else{ return false; } } bool QuantifierMacros::getFreeVariables( Node n, std::vector< Node >& v_quant, std::vector< Node >& vars, bool retOnly ){ if( std::find( v_quant.begin(), v_quant.end(), n )!=v_quant.end() ){ if( std::find( vars.begin(), vars.end(), n )==vars.end() ){ if( retOnly ){ return true; }else{ vars.push_back( n ); } } } for( size_t i=0; i& v_quant, std::map< Node, Node >& solved, std::vector< Node >& vars, std::vector< Node >& subs, bool reqComplete ){ bool success = true; for( size_t a=0; a& args, Node f ){ if( n.getKind()==NOT ){ process( n[0], !pol, args, f ); }else if( n.getKind()==AND || n.getKind()==OR || n.getKind()==IMPLIES ){ //bool favorPol = (n.getKind()==AND)==pol; //conditional? }else if( n.getKind()==ITE ){ //can not do anything }else{ //literal case if( isMacroLiteral( n, pol ) ){ std::vector< Node > candidates; for( size_t i=0; i fvs; getFreeVariables( m, args, fvs, false ); //get definition and condition Node n_def = solveInEquality( m, n ); //definition for the macro //definition must exist and not contain any free variables apart from fvs if( !n_def.isNull() && !getFreeVariables( n_def, args, fvs, true ) ){ Node n_cond; //condition when this definition holds //conditional must not contain any free variables apart from fvs if( n_cond.isNull() || !getFreeVariables( n_cond, args, fvs, true ) ){ Trace("macros") << m << " is possible macro in " << f << std::endl; //now we must rewrite candidates[i] to a term of form g( x1, ..., xn ) where // x1 ... xn are distinct variables if( d_macro_basis[op].empty() ){ for( size_t a=0; amkSkolem( ss.str(), m[a].getType(), "created during macro definition recognition" ); d_macro_basis[op].push_back( v ); } } std::vector< Node > eq; for( size_t a=0; a solved; //solve obvious cases first for( size_t a=0; a vars; std::vector< Node > subs; getSubstitution( fvs, solved, vars, subs, false ); for( size_t a=0; a conds; if( !n_cond.isNull() ){ //must apply substitution obtained from solving system of equations to original condition n_cond = n_cond.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() ); conds.push_back( n_cond ); } for( size_t a=0; amkNode( eq[a].getType().isBoolean() ? IFF : EQUAL, d_macro_basis[op][a], eq[a] ) ); } } //build the condition if( !conds.empty() ){ n_cond = conds.size()==1 ? conds[0] : NodeManager::currentNM()->mkNode( AND, conds ); } //apply the substitution to the n_def = n_def.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() ); //now see if definition is consistent with others if( isConsistentDefinition( op, n_cond, n_def ) ){ //must clear if it is a base definition if( n_cond.isNull() ){ d_macro_def_cases[ op ].clear(); } d_macro_def_cases[ op ].push_back( std::pair< Node, Node >( n_cond, n_def ) ); } } } } } } } } } Node QuantifierMacros::simplify( Node n ){ Trace("macros-debug") << "simplify " << n << std::endl; std::vector< Node > children; bool childChanged = false; for( size_t i=0; imkNode( n.getKind(), children ); }else{ return n; } }