From 2c09bb19994bc1baa97e30642a0281692c181a4b Mon Sep 17 00:00:00 2001 From: ajreynol Date: Wed, 21 Jan 2015 15:44:27 +0100 Subject: [PATCH] Avoid redundant constant arguments for SygusNormalForm. Refactor. --- src/theory/datatypes/datatypes_sygus.cpp | 334 ++++++++++++++++------- src/theory/datatypes/datatypes_sygus.h | 35 ++- src/theory/datatypes/theory_datatypes.h | 29 -- 3 files changed, 255 insertions(+), 143 deletions(-) diff --git a/src/theory/datatypes/datatypes_sygus.cpp b/src/theory/datatypes/datatypes_sygus.cpp index af855e166..cad4aaa48 100644 --- a/src/theory/datatypes/datatypes_sygus.cpp +++ b/src/theory/datatypes/datatypes_sygus.cpp @@ -27,31 +27,161 @@ using namespace CVC4::context; using namespace CVC4::theory; using namespace CVC4::theory::datatypes; +bool SygusSplit::isRegistered( TypeNode tn ) { + return d_register.find( tn )!=d_register.end(); +} + +int SygusSplit::getKindArg( TypeNode tn, Kind k ) { + Assert( isRegistered( tn ) ); + std::map< TypeNode, std::map< Kind, int > >::iterator itt = d_kinds.find( tn ); + if( itt!=d_kinds.end() ){ + std::map< Kind, int >::iterator it = itt->second.find( k ); + if( it!=itt->second.end() ){ + return it->second; + } + } + return -1; +} + +int SygusSplit::getConstArg( TypeNode tn, Node n ){ + Assert( isRegistered( tn ) ); + std::map< TypeNode, std::map< Node, int > >::iterator itt = d_consts.find( tn ); + if( itt!=d_consts.end() ){ + std::map< Node, int >::iterator it = itt->second.find( n ); + if( it!=itt->second.end() ){ + return it->second; + } + } + return -1; +} + +bool SygusSplit::hasKind( TypeNode tn, Kind k ) { + return getKindArg( tn, k )!=-1; +} +bool SygusSplit::hasConst( TypeNode tn, Node n ) { + return getConstArg( tn, n )!=-1; +} + +bool SygusSplit::isKindArg( TypeNode tn, int i ) { + Assert( isRegistered( tn ) ); + std::map< TypeNode, std::map< int, Kind > >::iterator itt = d_arg_kind.find( tn ); + if( itt!=d_arg_kind.end() ){ + return itt->second.find( i )!=itt->second.end(); + }else{ + return false; + } +} + +bool SygusSplit::isConstArg( TypeNode tn, int i ) { + Assert( isRegistered( tn ) ); + std::map< TypeNode, std::map< int, Node > >::iterator itt = d_arg_const.find( tn ); + if( itt!=d_arg_const.end() ){ + return itt->second.find( i )!=itt->second.end(); + }else{ + return false; + } +} + void SygusSplit::getSygusSplits( Node n, const Datatype& dt, std::vector< Node >& splits ) { Assert( dt.isSygus() ); Trace("sygus-split") << "Get sygus splits " << n << std::endl; - TypeNode typ, ptyp; - std::map< int, Kind > arg_kind, parg_kind; - std::map< Kind, int > kinds, pkinds; - std::map< int, Node > arg_const, parg_const; - std::map< Node, int > consts, pconsts; //get the kinds for child datatype - Trace("sygus-split") << "Operations for child : " << std::endl; - getSygusKinds( dt, arg_kind, kinds, arg_const, consts ); - typ = TypeNode::fromType(dt.getSygusType()); - - //compute the redundant operators TypeNode tnn = n.getType(); - if( d_sygus_nred.find( tnn )==d_sygus_nred.end() ){ + registerSygusType( tnn, dt ); + + //get parent information, if possible + int csIndex = -1; + int sIndex = -1; + if( n.getKind()==APPLY_SELECTOR_TOTAL ){ + Node op = n.getOperator(); + Expr selectorExpr = op.toExpr(); + const Datatype& pdt = Datatype::datatypeOf(selectorExpr); + Assert( pdt.isSygus() ); + csIndex = Datatype::cindexOf(selectorExpr); + sIndex = Datatype::indexOf(selectorExpr); + TypeNode tnnp = n[0].getType(); + //register the constructors that are redundant children of argument sIndex of constructor index csIndex of dt + registerSygusTypeConstructorArg( tnn, dt, tnnp, pdt, csIndex, sIndex ); + + + //relationships between arguments + /* + if( isKindArg( tnnp, csIndex ) ){ + Kind parentKind = d_arg_kind[tnnp][csIndex]; + if( isComm( parentKind ) ){ + //if commutative, normalize based on term ordering (the constructor index of left arg must be less than or equal to the right arg) + Trace("sygus-split-debug") << "Commutative operator : " << parentKind << std::endl; + if( pdt[csIndex].getNumArgs()==2 ){ + TypeNode tn1 = TypeNode::fromType( ((SelectorType)pdt[csIndex][0].getType()).getRangeType() ); + TypeNode tn2 = TypeNode::fromType( ((SelectorType)pdt[csIndex][1].getType()).getRangeType() ); + if( tn1==tn2 ){ + if( sIndex==1 ){ + registerSygusTypeConstructorArg( tnn, dt, tnnp, pdt, csIndex, 0 ); + } + for( unsigned i=1; i lem_c; + for( unsigned j=0; j::iterator it = arg_kind.find( i ); - if( it!=arg_kind.end() ){ + std::map< int, Kind >::iterator it = d_arg_kind[tn].find( i ); + if( it!=d_arg_kind[tn].end() ){ Kind dk; if( isAntisymmetric( it->second, dk ) ){ - std::map< Kind, int >::iterator ita = kinds.find( dk ); - if( ita!=kinds.end() ){ + std::map< Kind, int >::iterator ita = d_kinds[tn].find( dk ); + if( ita!=d_kinds[tn].end() ){ Trace("sygus-split-debug") << "Possible redundant operator : " << it->second << " with " << dk << std::endl; //check for type mismatches bool success = true; @@ -67,89 +197,49 @@ void SygusSplit::getSygusSplits( Node n, const Datatype& dt, std::vector< Node > } } if( success ){ - Trace("sygus-split") << "* Sygus norm " << dt.getName() << " : do not consider any " << arg_kind[i] << " terms." << std::endl; + Trace("sygus-split") << "* Sygus norm " << dt.getName() << " : do not consider any " << d_arg_kind[tn][i] << " terms." << std::endl; nred = false; } } } } - d_sygus_nred[tnn].push_back( nred ); + d_sygus_nred[tn].push_back( nred ); } } +} - - //get parent information, if possible - Node op; - int csIndex; - int sIndex; - if( n.getKind()==APPLY_SELECTOR_TOTAL ){ - op = n.getOperator(); - Expr selectorExpr = op.toExpr(); - const Datatype& pdt = Datatype::datatypeOf(selectorExpr); - Assert( pdt.isSygus() ); - csIndex = Datatype::cindexOf(selectorExpr); - sIndex = Datatype::indexOf(selectorExpr); - - std::map< int, std::vector< bool > >::iterator it = d_sygus_pc_nred[op].find( sIndex ); - if( it==d_sygus_pc_nred[op].end() ){ - Trace("sygus-split") << " Constructor, selector index : " << csIndex << " " << sIndex << std::endl; - - Trace("sygus-split") << "Operations for parent : " << std::endl; - getSygusKinds( pdt, parg_kind, pkinds, parg_const, pconsts ); - ptyp = TypeNode::fromType(pdt.getSygusType()); - bool parentKind = parg_kind.find( csIndex )!=parg_kind.end(); - for( unsigned i=0; i >::iterator it = d_sygus_pc_nred[tnn][csIndex].find( sIndex ); + if( it==d_sygus_pc_nred[tnn][csIndex].end() ){ + registerSygusType( tnnp, pdt ); + Trace("sygus-split") << "Register type constructor arg " << dt.getName() << " " << csIndex << " " << sIndex << std::endl; + //get parent kind + bool hasParentKind = false; + Kind parentKind; + if( isKindArg( tnnp, csIndex ) ){ + hasParentKind = true; + parentKind = d_arg_kind[tnnp][csIndex]; + } + for( unsigned i=0; i& arg_kind, std::map< Kind, int >& kinds, - std::map< int, Node >& arg_const, std::map< Node, int >& consts ) { - for( unsigned i=0; isecond; } } -bool SygusSplit::considerSygusSplitKind( const Datatype& dt, const Datatype& pdt, Kind k, Kind parent, int arg, - std::map< Kind, int >& kinds, std::map< Kind, int >& pkinds, - std::map< Node, int >& consts, std::map< Node, int >& pconsts ) { - Assert( kinds.find( k )!=kinds.end() ); - Assert( pkinds.find( parent )!=pkinds.end() ); +bool SygusSplit::considerSygusSplitKind( const Datatype& dt, const Datatype& pdt, TypeNode tn, TypeNode tnp, Kind k, Kind parent, int arg ) { + Assert( hasKind( tn, k ) ); + Assert( hasKind( tnp, parent ) ); Trace("sygus-split") << "Consider sygus split kind " << k << ", parent = " << parent << ", arg = " << arg << "?" << std::endl; + int c = getKindArg( tnp, parent ); if( k==parent ){ //check for associativity if( isAssoc( k ) ){ //if the operator is associative, then a repeated occurrence should only occur in the leftmost argument position - int firstArg = -1; - int c = pkinds[k]; - for( unsigned i=0; imkNode( parent, c ); + cr = Rewriter::rewrite( cr ); + Trace("sygus-split-debug") << " " << parent << " applied to " << c << " rewrites to " << cr << std::endl; + if( hasConst( tnp, cr ) ){ + return false; + } + } + return true; } + +int SygusSplit::getFirstArgOccurrence( const DatatypeConstructor& c, const Datatype& dt ) { + for( unsigned i=0; i > d_sygus_nred; - std::map< Node, std::map< int, std::vector< bool > > > d_sygus_pc_nred; + std::map< TypeNode, std::map< int, std::map< int, std::vector< bool > > > > d_sygus_pc_nred; + //information for builtin types std::map< TypeNode, std::map< int, Node > > d_type_value; std::map< TypeNode, Node > d_type_max_value; + //information for sygus types + std::map< TypeNode, bool > d_register; + std::map< TypeNode, std::map< int, Kind > > d_arg_kind; + std::map< TypeNode, std::map< Kind, int > > d_kinds; + std::map< TypeNode, std::map< int, Node > > d_arg_const; + std::map< TypeNode, std::map< Node, int > > d_consts; private: + bool isRegistered( TypeNode tn ); + int getKindArg( TypeNode tn, Kind k ); + int getConstArg( TypeNode tn, Node n ); + bool hasKind( TypeNode tn, Kind k ); + bool hasConst( TypeNode tn, Node n ); + bool isKindArg( TypeNode tn, int i ); + bool isConstArg( TypeNode tn, int i ); +private: + /** register sygus type */ + void registerSygusType( TypeNode tn, const Datatype& dt ); + /** register sygus operator */ + void registerSygusTypeConstructorArg( TypeNode tnn, const Datatype& dt, TypeNode tnnp, const Datatype& pdt, int csIndex, int sIndex ); /** consider sygus split */ - bool considerSygusSplitKind( const Datatype& dt, const Datatype& pdt, Kind k, Kind parent, int arg, - std::map< Kind, int >& kinds, std::map< Kind, int >& pkinds, - std::map< Node, int >& consts, std::map< Node, int >& pconsts ); - bool considerSygusSplitConst( const Datatype& dt, const Datatype& pdt, Node c, Kind parent, int arg, - std::map< Kind, int >& kinds, std::map< Kind, int >& pkinds, - std::map< Node, int >& consts, std::map< Node, int >& pconsts ); - /** get sygus kinds */ - void getSygusKinds( const Datatype& dt, std::map< int, Kind >& arg_kind, std::map< Kind, int >& kinds, std::map< int, Node >& arg_const, std::map< Node, int >& consts ); + bool considerSygusSplitKind( const Datatype& dt, const Datatype& pdt, TypeNode tn, TypeNode tnp, Kind k, Kind parent, int arg ); + bool considerSygusSplitConst( const Datatype& dt, const Datatype& pdt, TypeNode tn, TypeNode tnp, Node c, Kind parent, int arg ); /** is assoc */ bool isAssoc( Kind k ); + /** is comm */ + bool isComm( Kind k ); /** isAntisymmetric */ bool isAntisymmetric( Kind k, Kind& dk ); /** is idempotent arg */ @@ -56,6 +71,8 @@ private: Node getTypeValue( TypeNode tn, int val ); /** get value */ Node getTypeMaxValue( TypeNode tn ); + /** get first occurrence */ + int getFirstArgOccurrence( const DatatypeConstructor& c, const Datatype& dt ); public: /** get sygus splits */ void getSygusSplits( Node n, const Datatype& dt, std::vector< Node >& splits ); diff --git a/src/theory/datatypes/theory_datatypes.h b/src/theory/datatypes/theory_datatypes.h index 0421213a6..e5b9d32bb 100644 --- a/src/theory/datatypes/theory_datatypes.h +++ b/src/theory/datatypes/theory_datatypes.h @@ -288,35 +288,6 @@ private: public: /** get equality engine */ eq::EqualityEngine* getEqualityEngine() { return &d_equalityEngine; } - - -private: - /** sygus splits */ - std::map< TypeNode, std::vector< bool > > d_sygus_nred; - std::map< Node, std::map< int, std::vector< bool > > > d_sygus_pc_nred; - std::map< TypeNode, std::map< int, Node > > d_type_value; -private: - /** get sygus splits */ - void getSygusSplits( Node n, const Datatype& dt, std::vector< Node >& splits ); - /** consider sygus split */ - bool considerSygusSplitKind( const Datatype& dt, const Datatype& pdt, Kind k, Kind parent, int arg, - std::map< Kind, int >& kinds, std::map< Kind, int >& pkinds, - std::map< Node, int >& consts, std::map< Node, int >& pconsts ); - bool considerSygusSplitConst( const Datatype& dt, const Datatype& pdt, Node c, Kind parent, int arg, - std::map< Kind, int >& kinds, std::map< Kind, int >& pkinds, - std::map< Node, int >& consts, std::map< Node, int >& pconsts ); - /** get sygus kinds */ - void getSygusKinds( const Datatype& dt, std::map< int, Kind >& arg_kind, std::map< Kind, int >& kinds, std::map< int, Node >& arg_const, std::map< Node, int >& consts ); - /** is assoc */ - bool isAssoc( Kind k ); - /** isAntisymmetric */ - bool isAntisymmetric( Kind k, Kind& dk ); - /** is idempotent arg */ - bool isIdempotentArg( Node n, Kind ik, int arg ); - /** is singular arg */ - bool isSingularArg( Node n, Kind ik, int arg ); - /** get value */ - Node getTypeValue( TypeNode tn, int val, bool maxVal = false ); };/* class TheoryDatatypes */ }/* CVC4::theory::datatypes namespace */ -- 2.30.2