summaryrefslogtreecommitdiff
path: root/src/theory/quantifiers/quantifiers_rewriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/theory/quantifiers/quantifiers_rewriter.cpp')
-rw-r--r--src/theory/quantifiers/quantifiers_rewriter.cpp722
1 files changed, 722 insertions, 0 deletions
diff --git a/src/theory/quantifiers/quantifiers_rewriter.cpp b/src/theory/quantifiers/quantifiers_rewriter.cpp
new file mode 100644
index 000000000..0fba9d59e
--- /dev/null
+++ b/src/theory/quantifiers/quantifiers_rewriter.cpp
@@ -0,0 +1,722 @@
+/********************* */
+/*! \file theory_quantifiers_rewriter.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 QuantifiersRewriter class
+ **/
+
+#include "theory/quantifiers/quantifiers_rewriter.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+
+bool QuantifiersRewriter::isClause( Node n ){
+ if( isLiteral( n ) ){
+ return true;
+ }else if( n.getKind()==NOT ){
+ return isCube( n[0] );
+ }else if( n.getKind()==OR ){
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( !isClause( n[i] ) ){
+ return false;
+ }
+ }
+ return true;
+ }else if( n.getKind()==IMPLIES ){
+ return isCube( n[0] ) && isClause( n[1] );
+ }else{
+ return false;
+ }
+}
+
+bool QuantifiersRewriter::isLiteral( Node n ){
+ switch( n.getKind() ){
+ case NOT:
+ return isLiteral( n[0] );
+ break;
+ case OR:
+ case AND:
+ case IMPLIES:
+ case XOR:
+ case ITE:
+ case IFF:
+ return false;
+ break;
+ case EQUAL:
+ return n[0].getType()!=NodeManager::currentNM()->booleanType();
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+bool QuantifiersRewriter::isCube( Node n ){
+ if( isLiteral( n ) ){
+ return true;
+ }else if( n.getKind()==NOT ){
+ return isClause( n[0] );
+ }else if( n.getKind()==AND ){
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( !isCube( n[i] ) ){
+ return false;
+ }
+ }
+ return true;
+ }else{
+ return false;
+ }
+}
+
+void QuantifiersRewriter::addNodeToOrBuilder( Node n, NodeBuilder<>& t ){
+ if( n.getKind()==OR ){
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ t << n[i];
+ }
+ }else{
+ t << n;
+ }
+}
+
+void QuantifiersRewriter::computeArgs( std::map< Node, bool >& active, Node n ){
+ if( active.find( n )!=active.end() ){
+ active[n] = true;
+ }else{
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ computeArgs( active, n[i] );
+ }
+ }
+}
+
+void QuantifiersRewriter::computeArgs( std::vector< Node >& args, std::vector< Node >& activeArgs, Node n ){
+ std::map< Node, bool > active;
+ for( int i=0; i<(int)args.size(); i++ ){
+ active[ args[i] ] = false;
+ }
+ //Notice() << "For " << n << " : " << std::endl;
+ computeArgs( active, n );
+ activeArgs.clear();
+ for( std::map< Node, bool >::iterator it = active.begin(); it != active.end(); ++it ){
+ Node n = it->first;
+ //Notice() << " " << it->first << " is " << it->second << std::endl;
+ if( it->second ){ //only add bound variables that occur in body
+ activeArgs.push_back( it->first );
+ }
+ }
+}
+
+bool QuantifiersRewriter::hasArg( std::vector< Node >& args, Node n ){
+ if( std::find( args.begin(), args.end(), n )!=args.end() ){
+ return true;
+ }else{
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( hasArg( args, n[i] ) ){
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+void QuantifiersRewriter::setNestedQuantifiers( Node n, Node q ){
+ if( n.getKind()==FORALL || n.getKind()==EXISTS ){
+ Debug("quantifiers-rewrite-debug") << "Set nested quant attribute " << n << std::endl;
+ NestedQuantAttribute nqai;
+ n.setAttribute(nqai,q);
+ }
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ setNestedQuantifiers( n[i], q );
+ }
+}
+
+RewriteResponse QuantifiersRewriter::preRewrite(TNode in) {
+ Debug("quantifiers-rewrite-debug") << "pre-rewriting " << in << " " << in.hasAttribute(NestedQuantAttribute()) << std::endl;
+ if( in.getKind()==kind::EXISTS || in.getKind()==kind::FORALL ){
+ if( !in.hasAttribute(NestedQuantAttribute()) ){
+ setNestedQuantifiers( in[ 1 ], in );
+ }
+ std::vector< Node > args;
+ for( int i=0; i<(int)in[0].getNumChildren(); i++ ){
+ args.push_back( in[0][i] );
+ }
+ Node body = in[1];
+ bool doRewrite = false;
+ while( body.getNumChildren()>=2 && body.getKind()==in.getKind() ){
+ for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
+ args.push_back( body[0][i] );
+ }
+ body = body[1];
+ doRewrite = true;
+ }
+ if( doRewrite ){
+ std::vector< Node > children;
+ children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST,args) );
+ children.push_back( body );
+ if( in.getNumChildren()==3 ){
+ children.push_back( in[2] );
+ }
+ Node n = NodeManager::currentNM()->mkNode( in.getKind(), children );
+ if( in!=n ){
+ if( in.hasAttribute(NestedQuantAttribute()) ){
+ setNestedQuantifiers( n, in.getAttribute(NestedQuantAttribute()) );
+ }
+ Debug("quantifiers-pre-rewrite") << "*** pre-rewrite " << in << std::endl;
+ Debug("quantifiers-pre-rewrite") << " to " << std::endl;
+ Debug("quantifiers-pre-rewrite") << n << std::endl;
+ }
+ return RewriteResponse(REWRITE_DONE, n);
+ }
+ }
+ return RewriteResponse(REWRITE_DONE, in);
+}
+
+RewriteResponse QuantifiersRewriter::postRewrite(TNode in) {
+ Debug("quantifiers-rewrite-debug") << "post-rewriting " << in << " " << in.hasAttribute(NestedQuantAttribute()) << std::endl;
+ if( in.getKind()==kind::EXISTS || in.getKind()==kind::FORALL ){
+ //get the arguments
+ std::vector< Node > args;
+ for( int i=0; i<(int)in[0].getNumChildren(); i++ ){
+ args.push_back( in[0][i] );
+ }
+ //get the body
+ Node body = in[1];
+ if( in.getKind()==EXISTS ){
+ body = body.getKind()==NOT ? body[0] : body.notNode();
+ }
+ //get the instantiation pattern list
+ Node ipl;
+ if( in.getNumChildren()==3 ){
+ ipl = in[2];
+ }
+ bool isNested = in.hasAttribute(NestedQuantAttribute());
+ //compute miniscoping first
+ Node n = body;//computeNNF( body ); TODO: compute NNF here (current bad idea since arithmetic rewrites equalities)
+ if( body!=n ){
+ Notice() << "NNF " << body << " -> " << n << std::endl;
+ }
+ n = computeMiniscoping( args, n, ipl, isNested );
+ if( in.getKind()==kind::EXISTS ){
+ n = n.getKind()==NOT ? n[0] : n.notNode();
+ }
+ //compute other rewrite options for each produced quantifier
+ n = rewriteQuants( n, isNested, true );
+ //print if changed
+ if( in!=n ){
+ if( in.hasAttribute(NestedQuantAttribute()) ){
+ setNestedQuantifiers( n, in.getAttribute(NestedQuantAttribute()) );
+ }
+ Debug("quantifiers-rewrite") << "*** rewrite " << in << std::endl;
+ Debug("quantifiers-rewrite") << " to " << std::endl;
+ Debug("quantifiers-rewrite") << n << std::endl;
+ if( in.hasAttribute(InstConstantAttribute()) ){
+ InstConstantAttribute ica;
+ n.setAttribute(ica,in.getAttribute(InstConstantAttribute()) );
+ }
+ }
+ return RewriteResponse(REWRITE_DONE, n );
+ }
+ return RewriteResponse(REWRITE_DONE, in);
+}
+
+Node QuantifiersRewriter::computeNNF( Node body ){
+ if( body.getKind()==NOT ){
+ if( body[0].getKind()==NOT ){
+ return computeNNF( body[0][0] );
+ }else if( isLiteral( body[0] ) ){
+ return body;
+ }else{
+ std::vector< Node > children;
+ Kind k = body[0].getKind();
+ if( body[0].getKind()==OR || body[0].getKind()==IMPLIES || body[0].getKind()==AND ){
+ for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
+ Node nn = body[0].getKind()==IMPLIES && i==0 ? body[0][i] : body[0][i].notNode();
+ children.push_back( computeNNF( nn ) );
+ }
+ k = body[0].getKind()==AND ? OR : AND;
+ }else if( body[0].getKind()==XOR || body[0].getKind()==IFF ){
+ for( int i=0; i<2; i++ ){
+ Node nn = i==0 ? body[0][i] : body[0][i].notNode();
+ children.push_back( computeNNF( nn ) );
+ }
+ }else if( body[0].getKind()==ITE ){
+ for( int i=0; i<3; i++ ){
+ Node nn = i==0 ? body[0][i] : body[0][i].notNode();
+ children.push_back( computeNNF( nn ) );
+ }
+ }else{
+ Notice() << "Unhandled Quantifiers NNF: " << body << std::endl;
+ return body;
+ }
+ return NodeManager::currentNM()->mkNode( k, children );
+ }
+ }else if( isLiteral( body ) ){
+ return body;
+ }else{
+ std::vector< Node > children;
+ bool childrenChanged = false;
+ for( int i=0; i<(int)body.getNumChildren(); i++ ){
+ Node nc = computeNNF( body[i] );
+ children.push_back( nc );
+ childrenChanged = childrenChanged || nc!=body[i];
+ }
+ if( childrenChanged ){
+ return NodeManager::currentNM()->mkNode( body.getKind(), children );
+ }else{
+ return body;
+ }
+ }
+}
+
+Node QuantifiersRewriter::computeVarElimination( Node body, std::vector< Node >& args, Node& ipl ){
+ //Notice() << "Compute var elimination for " << f << std::endl;
+ std::map< Node, bool > litPhaseReq;
+ QuantifiersEngine::computePhaseReqs( body, false, litPhaseReq );
+ std::vector< Node > vars;
+ std::vector< Node > subs;
+ for( std::map< Node, bool >::iterator it = litPhaseReq.begin(); it != litPhaseReq.end(); ++it ){
+ //Notice() << " " << it->first << " -> " << ( it->second ? "true" : "false" ) << std::endl;
+ if( it->first.getKind()==EQUAL ){
+ if( it->second ){
+ for( int i=0; i<2; i++ ){
+ int j = i==0 ? 1 : 0;
+ std::vector< Node >::iterator ita = std::find( args.begin(), args.end(), it->first[i] );
+ if( ita!=args.end() ){
+ std::vector< Node > temp;
+ temp.push_back( it->first[i] );
+ if( !hasArg( temp, it->first[j] ) ){
+ vars.push_back( it->first[i] );
+ subs.push_back( it->first[j] );
+ args.erase( ita );
+ break;
+ }
+ }
+ }
+ if( !vars.empty() ){
+ break;
+ }
+ }
+ }
+ }
+ if( !vars.empty() ){
+ //Notice() << "VE " << vars.size() << "/" << n[0].getNumChildren() << std::endl;
+ //remake with eliminated nodes
+ body = body.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ body = Rewriter::rewrite( body );
+ if( !ipl.isNull() ){
+ ipl = ipl.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ }
+ }
+ return body;
+}
+
+Node QuantifiersRewriter::computeClause( Node n ){
+ Assert( isClause( n ) );
+ if( isLiteral( n ) ){
+ return n;
+ }else{
+ NodeBuilder<> t(OR);
+ if( n.getKind()==NOT ){
+ if( n[0].getKind()==NOT ){
+ return computeClause( n[0][0] );
+ }else{
+ //De-Morgan's law
+ Assert( n[0].getKind()==AND );
+ for( int i=0; i<(int)n[0].getNumChildren(); i++ ){
+ Node nn = computeClause( n[0][i].notNode() );
+ addNodeToOrBuilder( nn, t );
+ }
+ }
+ }else{
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ Node nc = ( ( i==0 && n.getKind()==IMPLIES ) ? n[i].notNode() : n[i] );
+ Node nn = computeClause( nc );
+ addNodeToOrBuilder( nn, t );
+ }
+ }
+ return t.constructNode();
+ }
+}
+
+Node QuantifiersRewriter::computeCNF( Node n, std::vector< Node >& args, NodeBuilder<>& defs, bool forcePred ){
+ if( isLiteral( n ) ){
+ return n;
+ }else if( !forcePred && isClause( n ) ){
+ return computeClause( n );
+ }else{
+ Kind k = ( n.getKind()==IMPLIES ? OR : ( n.getKind()==XOR ? IFF : n.getKind() ) );
+ NodeBuilder<> t(k);
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ Node nc = ( i==0 && ( n.getKind()==IMPLIES || n.getKind()==XOR ) ) ? n[i].notNode() : n[i];
+ Node ncnf = computeCNF( nc, args, defs, k!=OR );
+ if( k==OR ){
+ addNodeToOrBuilder( ncnf, t );
+ }else{
+ t << ncnf;
+ }
+ }
+ if( !forcePred && k==OR ){
+ return t.constructNode();
+ }else{
+ //compute the free variables
+ Node nt = t;
+ std::vector< Node > activeArgs;
+ computeArgs( args, activeArgs, nt );
+ std::vector< TypeNode > argTypes;
+ for( int i=0; i<(int)activeArgs.size(); i++ ){
+ argTypes.push_back( activeArgs[i].getType() );
+ }
+ //create the predicate
+ Assert( argTypes.size()>0 );
+ TypeNode typ = NodeManager::currentNM()->mkFunctionType( argTypes, NodeManager::currentNM()->booleanType() );
+ std::stringstream ss;
+ ss << "cnf_" << n.getKind() << "_" << n.getId();
+ Node op = NodeManager::currentNM()->mkVar( ss.str(), typ );
+ std::vector< Node > predArgs;
+ predArgs.push_back( op );
+ predArgs.insert( predArgs.end(), activeArgs.begin(), activeArgs.end() );
+ Node pred = NodeManager::currentNM()->mkNode( APPLY_UF, predArgs );
+ Debug("quantifiers-rewrite-cnf-debug") << "Made predicate " << pred << " for " << nt << std::endl;
+ //create the bound var list
+ Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, activeArgs );
+ //now, look at the structure of nt
+ if( nt.getKind()==NOT ){
+ //case for NOT
+ for( int i=0; i<2; i++ ){
+ NodeBuilder<> tt(OR);
+ tt << ( i==0 ? nt[0].notNode() : nt[0] );
+ tt << ( i==0 ? pred.notNode() : pred );
+ defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
+ }
+ }else if( nt.getKind()==OR ){
+ //case for OR
+ for( int i=0; i<(int)nt.getNumChildren(); i++ ){
+ NodeBuilder<> tt(OR);
+ tt << nt[i].notNode() << pred;
+ defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
+ }
+ NodeBuilder<> tt(OR);
+ for( int i=0; i<(int)nt.getNumChildren(); i++ ){
+ tt << nt[i];
+ }
+ tt << pred.notNode();
+ defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
+ }else if( nt.getKind()==AND ){
+ //case for AND
+ for( int i=0; i<(int)nt.getNumChildren(); i++ ){
+ NodeBuilder<> tt(OR);
+ tt << nt[i] << pred.notNode();
+ defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
+ }
+ NodeBuilder<> tt(OR);
+ for( int i=0; i<(int)nt.getNumChildren(); i++ ){
+ tt << nt[i].notNode();
+ }
+ tt << pred;
+ defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
+ }else if( nt.getKind()==IFF ){
+ //case for IFF
+ for( int i=0; i<4; i++ ){
+ NodeBuilder<> tt(OR);
+ tt << ( ( i==0 || i==3 ) ? nt[0].notNode() : nt[0] );
+ tt << ( ( i==1 || i==3 ) ? nt[1].notNode() : nt[1] );
+ tt << ( ( i==0 || i==1 ) ? pred.notNode() : pred );
+ defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
+ }
+ }else if( nt.getKind()==ITE ){
+ //case for ITE
+ for( int j=1; j<=2; j++ ){
+ for( int i=0; i<2; i++ ){
+ NodeBuilder<> tt(OR);
+ tt << ( ( j==1 ) ? nt[0].notNode() : nt[0] );
+ tt << ( ( i==1 ) ? nt[j].notNode() : nt[j] );
+ tt << ( ( i==0 ) ? pred.notNode() : pred );
+ defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
+ }
+ }
+ for( int i=0; i<2; i++ ){
+ NodeBuilder<> tt(OR);
+ tt << ( i==0 ? nt[1].notNode() : nt[1] );
+ tt << ( i==0 ? nt[2].notNode() : nt[2] );
+ tt << ( i==1 ? pred.notNode() : pred );
+ defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
+ }
+ }else{
+ Notice() << "Unhandled Quantifiers CNF: " << nt << std::endl;
+ }
+ return pred;
+ }
+ }
+}
+
+Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, bool pol, bool polReq ){
+ if( body.getKind()==FORALL ){
+ if( pol==polReq ){
+ std::vector< Node > terms;
+ std::vector< Node > subs;
+ if( polReq ){
+ //for doing prenexing of same-signed quantifiers
+ //must rename each variable that already exists
+ for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
+ //if( std::find( args.begin(), args.end(), body[0][i] )!=args.end() ){
+ terms.push_back( body[0][i] );
+ subs.push_back( NodeManager::currentNM()->mkVar( body[0][i].getType() ) );
+ }
+ args.insert( args.end(), subs.begin(), subs.end() );
+ }else{
+ std::vector< TypeNode > argTypes;
+ for( int i=0; i<(int)args.size(); i++ ){
+ argTypes.push_back( args[i].getType() );
+ }
+ //for doing pre-skolemization of opposite-signed quantifiers
+ for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
+ terms.push_back( body[0][i] );
+ //make the new function symbol
+ TypeNode typ = NodeManager::currentNM()->mkFunctionType( argTypes, body[0][i].getType() );
+ Node op = NodeManager::currentNM()->mkVar( typ );
+ std::vector< Node > funcArgs;
+ funcArgs.push_back( op );
+ funcArgs.insert( funcArgs.end(), args.begin(), args.end() );
+ subs.push_back( NodeManager::currentNM()->mkNode( APPLY_UF, funcArgs ) );
+ }
+ }
+ Node newBody = body[1];
+ newBody = newBody.substitute( terms.begin(), terms.end(), subs.begin(), subs.end() );
+ return newBody;
+ }else{
+ return body;
+ }
+ }else if( body.getKind()==ITE || body.getKind()==XOR || body.getKind()==IFF ){
+ return body;
+ }else{
+ Assert( body.getKind()!=EXISTS );
+ bool childrenChanged = false;
+ std::vector< Node > newChildren;
+ for( int i=0; i<(int)body.getNumChildren(); i++ ){
+ bool newPol = ( body.getKind()==NOT || ( body.getKind()==IMPLIES && i==0 ) ) ? !pol : pol;
+ Node n = computePrenex( body[i], args, newPol, polReq );
+ newChildren.push_back( n );
+ if( n!=body[i] ){
+ childrenChanged = true;
+ }
+ }
+ if( childrenChanged ){
+ if( body.getKind()==NOT && newChildren[0].getKind()==NOT ){
+ return newChildren[0][0];
+ }else{
+ return NodeManager::currentNM()->mkNode( body.getKind(), newChildren );
+ }
+ }else{
+ return body;
+ }
+ }
+}
+
+//general method for computing various rewrites
+Node QuantifiersRewriter::computeOperation( Node f, int computeOption ){
+ std::vector< Node > args;
+ for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
+ args.push_back( f[0][i] );
+ }
+ NodeBuilder<> defs(kind::AND);
+ Node n = f[1];
+ Node ipl;
+ if( f.getNumChildren()==3 ){
+ ipl = f[2];
+ }
+ if( computeOption==COMPUTE_NNF ){
+ n = computeNNF( n );
+ }else if( computeOption==COMPUTE_PRENEX || computeOption==COMPUTE_PRE_SKOLEM ){
+ n = computePrenex( n, args, true, computeOption==COMPUTE_PRENEX );
+ }else if( computeOption==COMPUTE_VAR_ELIMINATION ){
+ Node prev;
+ do{
+ prev = n;
+ n = computeVarElimination( n, args, ipl );
+ }while( prev!=n && !args.empty() );
+ }else if( computeOption==COMPUTE_CNF ){
+ //n = computeNNF( n );
+ n = computeCNF( n, args, defs, false );
+ ipl = Node::null();
+ }
+ if( f[1]==n && args.size()==long(f[0].getNumChildren()) ){
+ return f;
+ }else{
+ if( args.empty() ){
+ defs << n;
+ }else{
+ std::vector< Node > children;
+ children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, args ) );
+ children.push_back( n );
+ if( !ipl.isNull() ){
+ children.push_back( ipl );
+ }
+ defs << NodeManager::currentNM()->mkNode(kind::FORALL, children );
+ }
+ return defs.getNumChildren()==1 ? defs.getChild( 0 ) : defs.constructNode();
+ }
+}
+
+Node QuantifiersRewriter::mkForAll( std::vector< Node >& args, Node body, Node ipl ){
+ std::vector< Node > activeArgs;
+ computeArgs( args, activeArgs, body );
+ if( activeArgs.empty() ){
+ return body;
+ }else{
+ std::vector< Node > children;
+ children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, activeArgs ) );
+ children.push_back( body );
+ if( !ipl.isNull() ){
+ children.push_back( ipl );
+ }
+ return NodeManager::currentNM()->mkNode( kind::FORALL, children );
+ }
+}
+
+Node QuantifiersRewriter::computeMiniscoping( std::vector< Node >& args, Node body, Node ipl, bool isNested ){
+ //Notice() << "rewrite quant " << body << std::endl;
+ if( body.getKind()==FORALL ){
+ //combine arguments
+ std::vector< Node > newArgs;
+ for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
+ newArgs.push_back( body[0][i] );
+ }
+ newArgs.insert( newArgs.end(), args.begin(), args.end() );
+ return mkForAll( newArgs, body[ 1 ], ipl );
+ }else if( !isNested ){
+ if( body.getKind()==NOT ){
+ //push not downwards
+ if( body[0].getKind()==NOT ){
+ return computeMiniscoping( args, body[0][0], ipl );
+ }else if( body[0].getKind()==AND ){
+ if( doMiniscopingNoFreeVar() ){
+ NodeBuilder<> t(kind::OR);
+ for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
+ t << ( body[0][i].getKind()==NOT ? body[0][i][0] : body[0][i].notNode() );
+ }
+ return computeMiniscoping( args, t.constructNode(), ipl );
+ }
+ }else if( body[0].getKind()==OR || body[0].getKind()==IMPLIES ){
+ if( doMiniscopingAnd() ){
+ NodeBuilder<> t(kind::AND);
+ for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
+ Node trm = ( body[0].getKind()==IMPLIES && i==0 ) ? body[0][i] : ( body[0][i].getKind()==NOT ? body[0][i][0] : body[0][i].notNode() );
+ t << computeMiniscoping( args, trm, ipl );
+ }
+ return t.constructNode();
+ }
+ }
+ }else if( body.getKind()==AND ){
+ if( doMiniscopingAnd() ){
+ //break apart
+ NodeBuilder<> t(kind::AND);
+ for( int i=0; i<(int)body.getNumChildren(); i++ ){
+ t << computeMiniscoping( args, body[i], ipl );
+ }
+ Node retVal = t;
+ return retVal;
+ }
+ }else if( body.getKind()==OR || body.getKind()==IMPLIES ){
+ if( doMiniscopingNoFreeVar() ){
+ Node newBody = body;
+ NodeBuilder<> body_split(kind::OR);
+ NodeBuilder<> tb(kind::OR);
+ for( int i=0; i<(int)body.getNumChildren(); i++ ){
+ Node trm = ( body.getKind()==IMPLIES && i==0 ) ? ( body[i].getKind()==NOT ? body[i][0] : body[i].notNode() ) : body[i];
+ if( hasArg( args, body[i] ) ){
+ tb << trm;
+ }else{
+ body_split << trm;
+ }
+ }
+ if( tb.getNumChildren()==0 ){
+ return body_split;
+ }else if( body_split.getNumChildren()>0 ){
+ newBody = tb.getNumChildren()==1 ? tb.getChild( 0 ) : tb;
+ body_split << mkForAll( args, newBody, ipl );
+ return body_split.getNumChildren()==1 ? body_split.getChild( 0 ) : body_split;
+ }
+ }
+ }
+ }
+ return mkForAll( args, body, ipl );
+}
+
+Node QuantifiersRewriter::rewriteQuants( Node n, bool isNested, bool duringRewrite ){
+ if( n.getKind()==FORALL ){
+ return rewriteQuant( n, isNested, duringRewrite );
+ }else if( isLiteral( n ) ){
+ return n;
+ }else{
+ NodeBuilder<> tt(n.getKind());
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ tt << rewriteQuants( n[i], isNested, duringRewrite );
+ }
+ return tt.constructNode();
+ }
+}
+
+Node QuantifiersRewriter::rewriteQuant( Node n, bool isNested, bool duringRewrite ){
+ Node prev = n;
+ for( int op=0; op<COMPUTE_LAST; op++ ){
+ if( doOperation( n, isNested, op, duringRewrite ) ){
+ Node prev2 = n;
+ n = computeOperation( n, op );
+ if( prev2!=n ){
+ Debug("quantifiers-rewrite-op") << "Rewrite op " << op << ": rewrite " << prev2 << std::endl;
+ Debug("quantifiers-rewrite-op") << " to " << std::endl;
+ Debug("quantifiers-rewrite-op") << n << std::endl;
+ }
+ }
+ }
+ if( prev==n ){
+ return n;
+ }else{
+ //rewrite again until fix point is reached
+ return rewriteQuant( n, isNested, duringRewrite );
+ }
+}
+
+bool QuantifiersRewriter::doMiniscopingNoFreeVar(){
+ return Options::current()->miniscopeQuantFreeVar;
+}
+
+bool QuantifiersRewriter::doMiniscopingAnd(){
+ if( Options::current()->miniscopeQuant ){
+ return true;
+ }else{
+ if( Options::current()->cbqi ){
+ return true;
+ }else{
+ return false;
+ }
+ }
+}
+
+bool QuantifiersRewriter::doOperation( Node f, bool isNested, int computeOption, bool duringRewrite ){
+ if( computeOption==COMPUTE_NNF ){
+ return false;//TODO: compute NNF (current bad idea since arithmetic rewrites equalities)
+ }else if( computeOption==COMPUTE_PRE_SKOLEM ){
+ return Options::current()->preSkolemQuant && !duringRewrite;
+ }else if( computeOption==COMPUTE_PRENEX ){
+ return Options::current()->prenexQuant;
+ }else if( computeOption==COMPUTE_VAR_ELIMINATION ){
+ return Options::current()->varElimQuant;
+ }else if( computeOption==COMPUTE_CNF ){
+ return Options::current()->cnfQuant && !duringRewrite;// || Options::current()->finiteModelFind;
+ }else{
+ return false;
+ }
+}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback