From e908abc0e8a7a7d61a4d6e25821042a8e860e873 Mon Sep 17 00:00:00 2001 From: ajreynol Date: Wed, 21 Jan 2015 11:34:55 +0100 Subject: [PATCH] Initial work on sygusNormalForm. --- src/Makefile.am | 2 + src/parser/smt2/smt2.cpp | 2 - src/theory/datatypes/datatypes_sygus.cpp | 309 ++++++++++++++++++++++ src/theory/datatypes/datatypes_sygus.h | 69 +++++ src/theory/datatypes/theory_datatypes.cpp | 49 +--- src/theory/datatypes/theory_datatypes.h | 38 ++- src/theory/quantifiers/options | 2 - src/util/datatype.cpp | 4 + src/util/datatype.h | 3 + 9 files changed, 429 insertions(+), 49 deletions(-) create mode 100644 src/theory/datatypes/datatypes_sygus.cpp create mode 100644 src/theory/datatypes/datatypes_sygus.h diff --git a/src/Makefile.am b/src/Makefile.am index e66d590dc..c72e11809 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -235,6 +235,8 @@ libcvc4_la_SOURCES = \ theory/datatypes/theory_datatypes.h \ theory/datatypes/datatypes_rewriter.h \ theory/datatypes/theory_datatypes.cpp \ + theory/datatypes/datatypes_sygus.h \ + theory/datatypes/datatypes_sygus.cpp \ theory/sets/expr_patterns.h \ theory/sets/normal_form.h \ theory/sets/options_handlers.h \ diff --git a/src/parser/smt2/smt2.cpp b/src/parser/smt2/smt2.cpp index c6c3a896c..3db2e252d 100644 --- a/src/parser/smt2/smt2.cpp +++ b/src/parser/smt2/smt2.cpp @@ -526,8 +526,6 @@ void Smt2::includeFile(const std::string& filename) { void Smt2::mkSygusDatatype( CVC4::Datatype& dt, std::vector& ops, std::vector& cnames, std::vector< std::vector< CVC4::Type > >& cargs ) { - //minimize grammar goes here - for( unsigned i=0; i& 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() ){ + for( unsigned i=0; i::iterator it = arg_kind.find( i ); + if( it!=arg_kind.end() ){ + Kind dk; + if( isAntisymmetric( it->second, dk ) ){ + std::map< Kind, int >::iterator ita = kinds.find( dk ); + if( ita!=kinds.end() ){ + Trace("sygus-split-debug") << "Possible redundant operator : " << it->second << " with " << dk << std::endl; + //check for type mismatches + bool success = true; + unsigned j = ita->second; + for( unsigned k=0; k<2; k++ ){ + unsigned ko = k==0 ? 1 : 0; + TypeNode tni = TypeNode::fromType( ((SelectorType)dt[i][k].getType()).getRangeType() ); + TypeNode tnj = TypeNode::fromType( ((SelectorType)dt[j][ko].getType()).getRangeType() ); + if( tni!=tnj ){ + Trace("sygus-split-debug") << "Argument types " << tni << " and " << tnj << " are not equal." << std::endl; + success = false; + break; + } + } + if( success ){ + Trace("sygus-split") << "* Sygus norm " << dt.getName() << " : do not consider any " << arg_kind[i] << " terms." << std::endl; + nred = false; + } + } + } + } + d_sygus_nred[tnn].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& arg_kind, std::map< Kind, int >& kinds, + std::map< int, Node >& arg_const, std::map< Node, int >& consts ) { + for( unsigned i=0; i::iterator it = d_type_value[tn].find( val ); + if( it==d_type_value[tn].end() ){ + Node n; + if( tn.isInteger() || tn.isReal() ){ + Rational c(val); + n = NodeManager::currentNM()->mkConst( c ); + }else if( tn.isBitVector() ){ + unsigned int uv = val; + BitVector bval(tn.getConst(), uv); + n = NodeManager::currentNM()->mkConst(bval); + }else if( tn.isBoolean() ){ + if( val==0 || val==1 ){ + n = NodeManager::currentNM()->mkConst( val==1 ); + } + } + d_type_value[tn][val] = n; + return n; + }else{ + return it->second; + } +} + +Node SygusSplit::getTypeMaxValue( TypeNode tn ) { + std::map< TypeNode, Node >::iterator it = d_type_max_value.find( tn ); + if( it==d_type_max_value.end() ){ + Node n; + if( tn.isBitVector() ){ + n = bv::utils::mkOnes(tn.getConst()); + } + d_type_max_value[tn] = n; + return n; + }else{ + return it->second; + } +} +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() ); + Trace("sygus-split") << "Consider sygus split kind " << k << ", parent = " << parent << ", arg = " << arg << "?" << std::endl; + 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; i +#include +#include "context/cdchunk_list.h" + +namespace CVC4 { +namespace theory { +namespace datatypes { + +class SygusSplit +{ +private: + 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; + std::map< TypeNode, Node > d_type_max_value; +private: + /** 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 ); + /** get value */ + Node getTypeMaxValue( TypeNode tn ); +public: + /** get sygus splits */ + void getSygusSplits( Node n, const Datatype& dt, std::vector< Node >& splits ); +}; + + +} +} +} + +#endif diff --git a/src/theory/datatypes/theory_datatypes.cpp b/src/theory/datatypes/theory_datatypes.cpp index 8db9435ed..bbc8837b9 100644 --- a/src/theory/datatypes/theory_datatypes.cpp +++ b/src/theory/datatypes/theory_datatypes.cpp @@ -28,6 +28,7 @@ #include "theory/quantifiers/options.h" #include "theory/datatypes/options.h" #include "theory/type_enumerator.h" +#include "theory/datatypes/datatypes_sygus.h" #include @@ -64,6 +65,12 @@ TheoryDatatypes::TheoryDatatypes(Context* c, UserContext* u, OutputChannel& out, d_true = NodeManager::currentNM()->mkConst( true ); d_dtfCounter = 0; + + if( options::sygusNormalForm() ){ + d_sygus_split = new SygusSplit; + }else{ + d_sygus_split = NULL; + } } TheoryDatatypes::~TheoryDatatypes() { @@ -238,8 +245,8 @@ void TheoryDatatypes::check(Effort e) { }else{ Trace("dt-split") << "*************Split for constructors on " << n << endl; std::vector< Node > children; - if( dt.isSygus() && options::sygusNormalForm() ){ - getSygusSplits( n, dt, children ); + if( dt.isSygus() && d_sygus_split ){ + d_sygus_split->getSygusSplits( n, dt, children ); }else{ for( unsigned i=0; imkNode( kind::OR, children ); + Trace("dt-split-debug") << "Split lemma is : " << lemma << std::endl; d_out->lemma( lemma ); } return; @@ -1915,40 +1923,3 @@ bool TheoryDatatypes::checkClashModEq( TNode n1, TNode n2, std::vector< Node >& } return false; } - -void TheoryDatatypes::getSygusSplits( Node n, const Datatype& dt, std::vector< Node >& splits ) { - Assert( dt.isSygus() ); - Trace("sygus-split") << "Get sygus splits " << n << std::endl; - if( n.getKind()==APPLY_SELECTOR_TOTAL ){ - Node op = n.getOperator(); - std::map< Node, std::vector< bool > >::iterator it = d_sygus_splits.find( op ); - if( it==d_sygus_splits.end() ){ - Expr selectorExpr = op.toExpr(); - int csIndex = Datatype::cindexOf(selectorExpr); - int sIndex = Datatype::indexOf(selectorExpr); - Trace("sygus-split") << " Constructor, selector index : " << csIndex << " " << sIndex << std::endl; - for( unsigned i=0; i