#
# get-authors
# Morgan Deters <mdeters@cs.nyu.edu> for CVC4
-# Copyright (c) 2009, 2010, 2011 The CVC4 Project
+# Copyright (c) 2009-2013 The CVC4 Project
#
# usage: get-authors [ files... ]
#
-# This script uses svn to get the original author
+# This script uses git to get the original author
#
+gituser="`git config user.name` <`git config user.email`>"
+
while [ $# -gt 0 ]; do
f=$1
shift
major_contributors=
minor_contributors=
total_lines=`wc -l "$f" | awk '{print$1}'`
- original_author=`svn log -q --incremental "$f" | tail -1 | awk '{print$3}'`
- svn blame "$f" | awk '{print$2}' | sort | uniq -c | sort -n |
+ original_author=`git log --pretty="format:%aN <%aE>" "$f" | tail -1`
+ git blame --incremental "$f" | gawk '/^[0-9a-f]+ [0-9]+ [0-9]+ [0-9]+$/ {nl=$4;} /^author / {$1=""; author=$0;} /^author-mail / {mail=$2} /^filename / {while(nl--) {print author,mail}}' | sed "s,Not Committed Yet <not.committed.yet>,$gituser," | sort | uniq -c | sort -n |
( while read lines author; do
pct=$((100*$lines/$total_lines))
if [ "$author" != "$original_author" ]; then
#
# update-copyright.pl
# Morgan Deters <mdeters@cs.nyu.edu> for CVC4
-# Copyright (c) 2009-2012 The CVC4 Project
+# Copyright (c) 2009-2013 The CVC4 Project
#
# usage: update-copyright [-m] [files/directories...]
# update-copyright [-h | --help]
# the CVC4 source tree, that means src/ in the CVC4 source tree.
#
# If -m is specified as the first argument, all files and directories
-# are scanned, but only ones modifed in the current working directory
-# are modified (i.e., those that have status M in "svn status").
+# are scanned, but only ones modified in the index or working tree
+# are modified (i.e., those that have at least one status M in
+# "git status -s").
#
# It ignores any file/directory not starting with [a-zA-Z]
-# (so, this includes . and .., vi swaps, .svn meta-info,
+# (so, this includes . and .., vi swaps, .git meta-info,
# .deps, etc.)
#
# It ignores any file not ending with one of:
# .c .cc .cpp .C .h .hh .hpp .H .y .yy .ypp .Y .l .ll .lpp .L .g
+# [ or those with ".in" also suffixed, e.g., .cpp.in ]
# (so, this includes emacs ~-backups, CVS detritus, etc.)
#
# It ignores any directory matching $excluded_directories
# Years of copyright for the template. E.g., the string
# "1985, 1987, 1992, 1997, 2008" or "2006-2009" or whatever.
-my $years = '2009-2012';
+my $years = '2009-2013';
my $standard_template = <<EOF;
- ** This file is part of the CVC4 prototype.
+ ** This file is part of the CVC4 project.
** Copyright (c) $years New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\\endverbatim
EOF
my $public_template = <<EOF;
- ** This file is part of the CVC4 prototype.
+ ** This file is part of the CVC4 project.
** Copyright (c) $years New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\\endverbatim
exit;
}
-# whether we ONLY process files with svn status "M"
+# whether we ONLY process files with git status "M"
my $modonly = 0;
if($#ARGV >= 0 && $ARGV[0] eq '-m') {
print <<EOF;
Warning: this script is dangerous. It will overwrite the header comments in your
source files to match the template in the script, attempting to retain file-specific
-comments, but this isn't guaranteed. You should run this in an svn working directory
-and run "svn diff" after to ensure everything was correctly rewritten.
+comments, but this isn't guaranteed. You should run this in a git working tree
+and run "git diff" after to ensure everything was correctly rewritten.
The directories in which to search for and change sources is:
$pwd/src
+ $pwd/examples
$pwd/test
Continue? y or n:
die 'aborting operation' if !( $_ eq 'y' || $_ eq 'yes' || $_ eq 'Y' || $_ eq 'YES' );
$searchdirs[0] = 'src';
- $searchdirs[1] = 'test';
+ $searchdirs[1] = 'examples';
+ $searchdirs[2] = 'test';
} else {
@searchdirs = @ARGV;
}
sub handleFile {
my ($srcdir, $file) = @_;
- return if !($file =~ /\.(c|cc|cpp|C|h|hh|hpp|H|y|yy|ypp|Y|l|ll|lpp|L|g|java)$/);
+ return if !($file =~ /\.(c|cc|cpp|C|h|hh|hpp|H|y|yy|ypp|Y|l|ll|lpp|L|g|java)(\.in)?$/);
return if ($srcdir.'/'.$file) =~ /$excluded_paths/;
- return if $modonly &&`svn status "$srcdir/$file" 2>/dev/null` !~ /^M/;
+ return if $modonly && `git status -s "$srcdir/$file" 2>/dev/null` !~ /^(M|.M)/;
print "$srcdir/$file...";
my $infile = $srcdir.'/'.$file;
my $outfile = $srcdir.'/#'.$file.'.tmp';
/********************* */
/*! \file theory_arrays_model.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** 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 MODEL for theory of arrays\r
- **/\r
-\r
-\r
-#include "cvc4_private.h"\r
-\r
-#ifndef __CVC4__THEORY_ARRAYS_MODEL_H\r
-#define __CVC4__THEORY_ARRAYS_MODEL_H\r
-\r
-#include "theory/quantifiers_engine.h"\r
-\r
-namespace CVC4 {\r
-namespace theory {\r
-\r
-class TheoryModel;\r
-\r
-namespace arrays {\r
-\r
-class ArrayModel{\r
-protected:\r
- /** the array this model is for */\r
- Node d_arr;\r
-public:\r
- ArrayModel(){}\r
- ArrayModel( Node arr, TheoryModel* m );\r
- ~ArrayModel() {}\r
-public:\r
- /** pre-defined values */\r
- std::map< Node, Node > d_values;\r
- /** base array */\r
- Node d_base_arr;\r
- /** get value, return arguments that the value depends on */\r
- Node getValue( TheoryModel* m, Node i );\r
- /** set value */\r
- void setValue( TheoryModel* m, Node i, Node e );\r
- /** set default */\r
- void setDefaultArray( Node arr );\r
-public:\r
- /** get array value */\r
- Node getArrayValue();\r
-};/* class ArrayModel */\r
-\r
-}\r
-}\r
-}\r
-\r
+ ** \brief MODEL for theory of arrays
+ **/
+
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY_ARRAYS_MODEL_H
+#define __CVC4__THEORY_ARRAYS_MODEL_H
+
+#include "theory/quantifiers_engine.h"
+
+namespace CVC4 {
+namespace theory {
+
+class TheoryModel;
+
+namespace arrays {
+
+class ArrayModel{
+protected:
+ /** the array this model is for */
+ Node d_arr;
+public:
+ ArrayModel(){}
+ ArrayModel( Node arr, TheoryModel* m );
+ ~ArrayModel() {}
+public:
+ /** pre-defined values */
+ std::map< Node, Node > d_values;
+ /** base array */
+ Node d_base_arr;
+ /** get value, return arguments that the value depends on */
+ Node getValue( TheoryModel* m, Node i );
+ /** set value */
+ void setValue( TheoryModel* m, Node i, Node e );
+ /** set default */
+ void setDefaultArray( Node arr );
+public:
+ /** get array value */
+ Node getArrayValue();
+};/* class ArrayModel */
+
+}
+}
+}
+
#endif
\ No newline at end of file
-/********************* */\r
-/*! \file inst_gen.cpp\r
- ** \verbatim\r
- ** Original author: ajreynol\r
- ** Major contributors: none\r
- ** Minor contributors (to current version): none\r
- ** This file is part of the CVC4 prototype.\r
- ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)\r
- ** Courant Institute of Mathematical Sciences\r
- ** New York University\r
- ** See the file COPYING in the top-level source directory for licensing\r
- ** information.\endverbatim\r
- **\r
- ** \brief Implementation of inst gen classes\r
- **/\r
-\r
-#include "theory/quantifiers/inst_gen.h"\r
-#include "theory/quantifiers/model_engine.h"\r
-#include "theory/quantifiers/model_builder.h"\r
-#include "theory/quantifiers/first_order_model.h"\r
-\r
-//#define CHILD_USE_CONSIDER\r
-\r
-using namespace std;\r
-using namespace CVC4;\r
-using namespace CVC4::kind;\r
-using namespace CVC4::context;\r
-using namespace CVC4::theory;\r
-using namespace CVC4::theory::quantifiers;\r
-\r
-\r
-\r
-InstGenProcess::InstGenProcess( Node n ) : d_node( n ){\r
- Assert( n.hasAttribute(InstConstantAttribute()) );\r
- int count = 0;\r
- for( size_t i=0; i<n.getNumChildren(); i++ ){\r
- if( n[i].getKind()!=INST_CONSTANT && n[i].hasAttribute(InstConstantAttribute()) ){\r
- d_children.push_back( InstGenProcess( n[i] ) );\r
- d_children_index.push_back( i );\r
- d_children_map[ i ] = count;\r
- count++;\r
- }\r
- }\r
-}\r
-\r
-void InstGenProcess::addMatchValue( QuantifiersEngine* qe, Node f, Node val, InstMatch& m ){\r
- if( !qe->existsInstantiation( f, m, true ) ){\r
- //make sure no duplicates are produced\r
- if( d_inst_trie[val].addInstMatch( qe, f, m, true ) ){\r
- d_match_values.push_back( val );\r
- d_matches.push_back( InstMatch( &m ) );\r
- qe->getModelEngine()->getModelBuilder()->d_instGenMatches++;\r
- }\r
- }\r
-}\r
-\r
-void InstGenProcess::calculateMatches( QuantifiersEngine* qe, Node f, std::vector< Node >& considerVal, bool useConsider ){\r
- Trace("inst-gen-cm") << "* Calculate matches " << d_node << std::endl;\r
- //whether we are doing a product or sum or matches\r
- bool doProduct = true;\r
- //get the model\r
- FirstOrderModel* fm = qe->getModel();\r
-\r
- //calculate terms we will consider\r
- std::vector< Node > considerTerms;\r
- std::vector< std::vector< Node > > newConsiderVal;\r
- std::vector< bool > newUseConsider;\r
- std::map< Node, InstMatch > considerTermsMatch[2];\r
- std::map< Node, bool > considerTermsSuccess[2];\r
- newConsiderVal.resize( d_children.size() );\r
- newUseConsider.resize( d_children.size(), useConsider );\r
- if( d_node.getKind()==APPLY_UF ){\r
- Node op = d_node.getOperator();\r
- if( useConsider ){\r
-#ifndef CHILD_USE_CONSIDER\r
- for( size_t i=0; i<newUseConsider.size(); i++ ){\r
- newUseConsider[i] = false;\r
- }\r
-#endif\r
- for( size_t i=0; i<considerVal.size(); i++ ){\r
- eq::EqClassIterator eqc( qe->getEqualityQuery()->getEngine()->getRepresentative( considerVal[i] ),\r
- qe->getEqualityQuery()->getEngine() );\r
- while( !eqc.isFinished() ){\r
- Node en = (*eqc);\r
- if( en.getKind()==APPLY_UF && en.getOperator()==op ){\r
- considerTerms.push_back( en );\r
- }\r
- ++eqc;\r
- }\r
- }\r
- }else{\r
- considerTerms.insert( considerTerms.begin(), fm->d_uf_terms[op].begin(), fm->d_uf_terms[op].end() );\r
- }\r
- //for each term we consider, calculate a current match\r
- for( size_t i=0; i<considerTerms.size(); i++ ){\r
- Node n = considerTerms[i];\r
- bool isSelected = qe->getModelEngine()->getModelBuilder()->isTermSelected( n );\r
- bool hadSuccess CVC4_UNUSED = false;\r
- for( int t=(isSelected ? 0 : 1); t<2; t++ ){\r
- if( t==0 || !n.getAttribute(NoMatchAttribute()) ){\r
- considerTermsMatch[t][n] = InstMatch();\r
- considerTermsSuccess[t][n] = true;\r
- for( size_t j=0; j<d_node.getNumChildren(); j++ ){\r
- if( d_children_map.find( j )==d_children_map.end() ){\r
- if( t!=0 || !n[j].getAttribute(ModelBasisAttribute()) ){\r
- if( d_node[j].getKind()==INST_CONSTANT ){\r
- if( !considerTermsMatch[t][n].setMatch( qe->getEqualityQuery(), d_node[j], n[j] ) ){\r
- Trace("inst-gen-cm") << "fail match: " << n[j] << " is not equal to ";\r
- Trace("inst-gen-cm") << considerTermsMatch[t][n].getValue( d_node[j] ) << std::endl;\r
- considerTermsSuccess[t][n] = false;\r
- break;\r
- }\r
- }else if( !qe->getEqualityQuery()->areEqual( d_node[j], n[j] ) ){\r
- Trace("inst-gen-cm") << "fail arg: " << n[j] << " is not equal to " << d_node[j] << std::endl;\r
- considerTermsSuccess[t][n] = false;\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- //if successful, store it\r
- if( considerTermsSuccess[t][n] ){\r
-#ifdef CHILD_USE_CONSIDER\r
- if( !hadSuccess ){\r
- hadSuccess = true;\r
- for( size_t k=0; k<d_children.size(); k++ ){\r
- if( newUseConsider[k] ){\r
- int childIndex = d_children_index[k];\r
- //determine if we are restricted or not\r
- if( t!=0 || !n[childIndex].getAttribute(ModelBasisAttribute()) ){\r
- Node r = qe->getModel()->getRepresentative( n[childIndex] );\r
- if( std::find( newConsiderVal[k].begin(), newConsiderVal[k].end(), r )==newConsiderVal[k].end() ){\r
- newConsiderVal[k].push_back( r );\r
- //check if we now need to consider the entire domain\r
- TypeNode tn = r.getType();\r
- if( qe->getModel()->d_rep_set.hasType( tn ) ){\r
- if( (int)newConsiderVal[k].size()>=qe->getModel()->d_rep_set.getNumRepresentatives( tn ) ){\r
- newConsiderVal[k].clear();\r
- newUseConsider[k] = false;\r
- }\r
- }\r
- }\r
- }else{\r
- //matching against selected term, will need to consider all values\r
- newConsiderVal[k].clear();\r
- newUseConsider[k] = false;\r
- }\r
- }\r
- }\r
- }\r
-#endif\r
- }\r
- }\r
- }\r
- }\r
- }else{\r
- //the interpretted case\r
- if( d_node.getType().isBoolean() ){\r
- if( useConsider ){\r
- //if( considerVal.size()!=1 ) { std::cout << "consider val = " << considerVal.size() << std::endl; }\r
- Assert( considerVal.size()==1 );\r
- bool reqPol = considerVal[0]==fm->d_true;\r
- Node ncv = considerVal[0];\r
- if( d_node.getKind()==NOT ){\r
- ncv = reqPol ? fm->d_false : fm->d_true;\r
- }\r
- if( d_node.getKind()==NOT || d_node.getKind()==AND || d_node.getKind()==OR ){\r
- for( size_t i=0; i<newConsiderVal.size(); i++ ){\r
- newConsiderVal[i].push_back( ncv );\r
- }\r
- //instead we will do a sum\r
- if( ( d_node.getKind()==AND && !reqPol ) || ( d_node.getKind()==OR && reqPol ) ){\r
- doProduct = false;\r
- }\r
- }else{\r
- //do not use consider\r
- for( size_t i=0; i<newUseConsider.size(); i++ ){\r
- newUseConsider[i] = false;\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- //calculate all matches for children\r
- for( int i=0; i<(int)d_children.size(); i++ ){\r
- d_children[i].calculateMatches( qe, f, newConsiderVal[i], newUseConsider[i] );\r
- if( doProduct && d_children[i].getNumMatches()==0 ){\r
- return;\r
- }\r
- }\r
- if( d_node.getKind()==APPLY_UF ){\r
- //if this is an uninterpreted function\r
- Node op = d_node.getOperator();\r
- //process all values\r
- for( size_t i=0; i<considerTerms.size(); i++ ){\r
- Node n = considerTerms[i];\r
- bool isSelected = qe->getModelEngine()->getModelBuilder()->isTermSelected( n );\r
- for( int t=(isSelected ? 0 : 1); t<2; t++ ){\r
- //do not consider ground case if it is already congruent to another ground term\r
- if( t==0 || !n.getAttribute(NoMatchAttribute()) ){\r
- Trace("inst-gen-cm") << "calculate for " << n << ", selected = " << (t==0) << std::endl;\r
- if( considerTermsSuccess[t][n] ){\r
- //try to find unifier for d_node = n\r
- calculateMatchesUninterpreted( qe, f, considerTermsMatch[t][n], n, 0, t==0 );\r
- }\r
- }\r
- }\r
- }\r
- }else{\r
- //if this is an interpreted function\r
- if( doProduct ){\r
- //combining children matches\r
- InstMatch curr;\r
- std::vector< Node > terms;\r
- calculateMatchesInterpreted( qe, f, curr, terms, 0 );\r
- }else{\r
- //summing children matches\r
- Assert( considerVal.size()==1 );\r
- for( int i=0; i<(int)d_children.size(); i++ ){\r
- for( int j=0; j<(int)d_children[ i ].getNumMatches(); j++ ){\r
- InstMatch m;\r
- if( d_children[ i ].getMatch( qe->getEqualityQuery(), j, m ) ){\r
- addMatchValue( qe, f, considerVal[0], m );\r
- }\r
- }\r
- }\r
- }\r
- }\r
- Trace("inst-gen-cm") << "done calculate matches" << std::endl;\r
- //can clear information used for finding duplicates\r
- d_inst_trie.clear();\r
-}\r
-\r
-bool InstGenProcess::getMatch( EqualityQuery* q, int i, InstMatch& m ){\r
- //FIXME: is this correct? (query may not be accurate)\r
- return m.merge( q, d_matches[i] );\r
-}\r
-\r
-void InstGenProcess::calculateMatchesUninterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, Node n, int childIndex, bool isSelected ){\r
- if( childIndex==(int)d_children.size() ){\r
- Node val = qe->getModel()->getRepresentative( n ); //FIXME: is this correct?\r
- Trace("inst-gen-cm") << " - u-match : " << val << std::endl;\r
- Trace("inst-gen-cm") << " : " << curr << std::endl;\r
- addMatchValue( qe, f, val, curr );\r
- }else{\r
- Trace("inst-gen-cm") << "Consider child index = " << childIndex << ", against ground term argument " << d_children_index[childIndex] << " ... " << n[d_children_index[childIndex]] << std::endl;\r
- bool sel = ( isSelected && n[d_children_index[childIndex]].getAttribute(ModelBasisAttribute()) );\r
- for( int i=0; i<(int)d_children[ childIndex ].getNumMatches(); i++ ){\r
- //FIXME: is this correct?\r
- if( sel || qe->getEqualityQuery()->areEqual( d_children[ childIndex ].getMatchValue( i ), n[d_children_index[childIndex]] ) ){\r
- InstMatch next( &curr );\r
- if( d_children[ childIndex ].getMatch( qe->getEqualityQuery(), i, next ) ){\r
- calculateMatchesUninterpreted( qe, f, next, n, childIndex+1, isSelected );\r
- }else{\r
- Trace("inst-gen-cm") << curr << " not equal to " << d_children[ childIndex ].d_matches[i] << std::endl;\r
- Trace("inst-gen-cm") << childIndex << " match " << i << " not equal subs." << std::endl;\r
- }\r
- }else{\r
- Trace("inst-gen-cm") << childIndex << " match " << i << " not equal value." << std::endl;\r
- }\r
- }\r
- }\r
-}\r
-\r
-void InstGenProcess::calculateMatchesInterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, std::vector< Node >& terms, int argIndex ){\r
- FirstOrderModel* fm = qe->getModel();\r
- if( argIndex==(int)d_node.getNumChildren() ){\r
- Node val;\r
- if( d_node.getNumChildren()==0 ){\r
- val = d_node;\r
- }else if( d_node.getKind()==EQUAL ){\r
- val = qe->getEqualityQuery()->areEqual( terms[0], terms[1] ) ? fm->d_true : fm->d_false;\r
- }else{\r
- val = NodeManager::currentNM()->mkNode( d_node.getKind(), terms );\r
- val = Rewriter::rewrite( val );\r
- }\r
- Trace("inst-gen-cm") << " - i-match : " << d_node << std::endl;\r
- Trace("inst-gen-cm") << " : " << val << std::endl;\r
- Trace("inst-gen-cm") << " : " << curr << std::endl;\r
- addMatchValue( qe, f, val, curr );\r
- }else{\r
- if( d_children_map.find( argIndex )==d_children_map.end() ){\r
- terms.push_back( fm->getRepresentative( d_node[argIndex] ) );\r
- calculateMatchesInterpreted( qe, f, curr, terms, argIndex+1 );\r
- terms.pop_back();\r
- }else{\r
- for( int i=0; i<(int)d_children[ d_children_map[argIndex] ].getNumMatches(); i++ ){\r
- InstMatch next( &curr );\r
- if( d_children[ d_children_map[argIndex] ].getMatch( qe->getEqualityQuery(), i, next ) ){\r
- terms.push_back( d_children[ d_children_map[argIndex] ].getMatchValue( i ) );\r
- calculateMatchesInterpreted( qe, f, next, terms, argIndex+1 );\r
- terms.pop_back();\r
- }\r
- }\r
- }\r
- }\r
-}\r
+/********************* */
+/*! \file inst_gen.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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 Implementation of inst gen classes
+ **/
+
+#include "theory/quantifiers/inst_gen.h"
+#include "theory/quantifiers/model_engine.h"
+#include "theory/quantifiers/model_builder.h"
+#include "theory/quantifiers/first_order_model.h"
+
+//#define CHILD_USE_CONSIDER
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+
+
+
+InstGenProcess::InstGenProcess( Node n ) : d_node( n ){
+ Assert( n.hasAttribute(InstConstantAttribute()) );
+ int count = 0;
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ if( n[i].getKind()!=INST_CONSTANT && n[i].hasAttribute(InstConstantAttribute()) ){
+ d_children.push_back( InstGenProcess( n[i] ) );
+ d_children_index.push_back( i );
+ d_children_map[ i ] = count;
+ count++;
+ }
+ }
+}
+
+void InstGenProcess::addMatchValue( QuantifiersEngine* qe, Node f, Node val, InstMatch& m ){
+ if( !qe->existsInstantiation( f, m, true ) ){
+ //make sure no duplicates are produced
+ if( d_inst_trie[val].addInstMatch( qe, f, m, true ) ){
+ d_match_values.push_back( val );
+ d_matches.push_back( InstMatch( &m ) );
+ qe->getModelEngine()->getModelBuilder()->d_instGenMatches++;
+ }
+ }
+}
+
+void InstGenProcess::calculateMatches( QuantifiersEngine* qe, Node f, std::vector< Node >& considerVal, bool useConsider ){
+ Trace("inst-gen-cm") << "* Calculate matches " << d_node << std::endl;
+ //whether we are doing a product or sum or matches
+ bool doProduct = true;
+ //get the model
+ FirstOrderModel* fm = qe->getModel();
+
+ //calculate terms we will consider
+ std::vector< Node > considerTerms;
+ std::vector< std::vector< Node > > newConsiderVal;
+ std::vector< bool > newUseConsider;
+ std::map< Node, InstMatch > considerTermsMatch[2];
+ std::map< Node, bool > considerTermsSuccess[2];
+ newConsiderVal.resize( d_children.size() );
+ newUseConsider.resize( d_children.size(), useConsider );
+ if( d_node.getKind()==APPLY_UF ){
+ Node op = d_node.getOperator();
+ if( useConsider ){
+#ifndef CHILD_USE_CONSIDER
+ for( size_t i=0; i<newUseConsider.size(); i++ ){
+ newUseConsider[i] = false;
+ }
+#endif
+ for( size_t i=0; i<considerVal.size(); i++ ){
+ eq::EqClassIterator eqc( qe->getEqualityQuery()->getEngine()->getRepresentative( considerVal[i] ),
+ qe->getEqualityQuery()->getEngine() );
+ while( !eqc.isFinished() ){
+ Node en = (*eqc);
+ if( en.getKind()==APPLY_UF && en.getOperator()==op ){
+ considerTerms.push_back( en );
+ }
+ ++eqc;
+ }
+ }
+ }else{
+ considerTerms.insert( considerTerms.begin(), fm->d_uf_terms[op].begin(), fm->d_uf_terms[op].end() );
+ }
+ //for each term we consider, calculate a current match
+ for( size_t i=0; i<considerTerms.size(); i++ ){
+ Node n = considerTerms[i];
+ bool isSelected = qe->getModelEngine()->getModelBuilder()->isTermSelected( n );
+ bool hadSuccess CVC4_UNUSED = false;
+ for( int t=(isSelected ? 0 : 1); t<2; t++ ){
+ if( t==0 || !n.getAttribute(NoMatchAttribute()) ){
+ considerTermsMatch[t][n] = InstMatch();
+ considerTermsSuccess[t][n] = true;
+ for( size_t j=0; j<d_node.getNumChildren(); j++ ){
+ if( d_children_map.find( j )==d_children_map.end() ){
+ if( t!=0 || !n[j].getAttribute(ModelBasisAttribute()) ){
+ if( d_node[j].getKind()==INST_CONSTANT ){
+ if( !considerTermsMatch[t][n].setMatch( qe->getEqualityQuery(), d_node[j], n[j] ) ){
+ Trace("inst-gen-cm") << "fail match: " << n[j] << " is not equal to ";
+ Trace("inst-gen-cm") << considerTermsMatch[t][n].getValue( d_node[j] ) << std::endl;
+ considerTermsSuccess[t][n] = false;
+ break;
+ }
+ }else if( !qe->getEqualityQuery()->areEqual( d_node[j], n[j] ) ){
+ Trace("inst-gen-cm") << "fail arg: " << n[j] << " is not equal to " << d_node[j] << std::endl;
+ considerTermsSuccess[t][n] = false;
+ break;
+ }
+ }
+ }
+ }
+ //if successful, store it
+ if( considerTermsSuccess[t][n] ){
+#ifdef CHILD_USE_CONSIDER
+ if( !hadSuccess ){
+ hadSuccess = true;
+ for( size_t k=0; k<d_children.size(); k++ ){
+ if( newUseConsider[k] ){
+ int childIndex = d_children_index[k];
+ //determine if we are restricted or not
+ if( t!=0 || !n[childIndex].getAttribute(ModelBasisAttribute()) ){
+ Node r = qe->getModel()->getRepresentative( n[childIndex] );
+ if( std::find( newConsiderVal[k].begin(), newConsiderVal[k].end(), r )==newConsiderVal[k].end() ){
+ newConsiderVal[k].push_back( r );
+ //check if we now need to consider the entire domain
+ TypeNode tn = r.getType();
+ if( qe->getModel()->d_rep_set.hasType( tn ) ){
+ if( (int)newConsiderVal[k].size()>=qe->getModel()->d_rep_set.getNumRepresentatives( tn ) ){
+ newConsiderVal[k].clear();
+ newUseConsider[k] = false;
+ }
+ }
+ }
+ }else{
+ //matching against selected term, will need to consider all values
+ newConsiderVal[k].clear();
+ newUseConsider[k] = false;
+ }
+ }
+ }
+ }
+#endif
+ }
+ }
+ }
+ }
+ }else{
+ //the interpretted case
+ if( d_node.getType().isBoolean() ){
+ if( useConsider ){
+ //if( considerVal.size()!=1 ) { std::cout << "consider val = " << considerVal.size() << std::endl; }
+ Assert( considerVal.size()==1 );
+ bool reqPol = considerVal[0]==fm->d_true;
+ Node ncv = considerVal[0];
+ if( d_node.getKind()==NOT ){
+ ncv = reqPol ? fm->d_false : fm->d_true;
+ }
+ if( d_node.getKind()==NOT || d_node.getKind()==AND || d_node.getKind()==OR ){
+ for( size_t i=0; i<newConsiderVal.size(); i++ ){
+ newConsiderVal[i].push_back( ncv );
+ }
+ //instead we will do a sum
+ if( ( d_node.getKind()==AND && !reqPol ) || ( d_node.getKind()==OR && reqPol ) ){
+ doProduct = false;
+ }
+ }else{
+ //do not use consider
+ for( size_t i=0; i<newUseConsider.size(); i++ ){
+ newUseConsider[i] = false;
+ }
+ }
+ }
+ }
+ }
+
+ //calculate all matches for children
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ d_children[i].calculateMatches( qe, f, newConsiderVal[i], newUseConsider[i] );
+ if( doProduct && d_children[i].getNumMatches()==0 ){
+ return;
+ }
+ }
+ if( d_node.getKind()==APPLY_UF ){
+ //if this is an uninterpreted function
+ Node op = d_node.getOperator();
+ //process all values
+ for( size_t i=0; i<considerTerms.size(); i++ ){
+ Node n = considerTerms[i];
+ bool isSelected = qe->getModelEngine()->getModelBuilder()->isTermSelected( n );
+ for( int t=(isSelected ? 0 : 1); t<2; t++ ){
+ //do not consider ground case if it is already congruent to another ground term
+ if( t==0 || !n.getAttribute(NoMatchAttribute()) ){
+ Trace("inst-gen-cm") << "calculate for " << n << ", selected = " << (t==0) << std::endl;
+ if( considerTermsSuccess[t][n] ){
+ //try to find unifier for d_node = n
+ calculateMatchesUninterpreted( qe, f, considerTermsMatch[t][n], n, 0, t==0 );
+ }
+ }
+ }
+ }
+ }else{
+ //if this is an interpreted function
+ if( doProduct ){
+ //combining children matches
+ InstMatch curr;
+ std::vector< Node > terms;
+ calculateMatchesInterpreted( qe, f, curr, terms, 0 );
+ }else{
+ //summing children matches
+ Assert( considerVal.size()==1 );
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ for( int j=0; j<(int)d_children[ i ].getNumMatches(); j++ ){
+ InstMatch m;
+ if( d_children[ i ].getMatch( qe->getEqualityQuery(), j, m ) ){
+ addMatchValue( qe, f, considerVal[0], m );
+ }
+ }
+ }
+ }
+ }
+ Trace("inst-gen-cm") << "done calculate matches" << std::endl;
+ //can clear information used for finding duplicates
+ d_inst_trie.clear();
+}
+
+bool InstGenProcess::getMatch( EqualityQuery* q, int i, InstMatch& m ){
+ //FIXME: is this correct? (query may not be accurate)
+ return m.merge( q, d_matches[i] );
+}
+
+void InstGenProcess::calculateMatchesUninterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, Node n, int childIndex, bool isSelected ){
+ if( childIndex==(int)d_children.size() ){
+ Node val = qe->getModel()->getRepresentative( n ); //FIXME: is this correct?
+ Trace("inst-gen-cm") << " - u-match : " << val << std::endl;
+ Trace("inst-gen-cm") << " : " << curr << std::endl;
+ addMatchValue( qe, f, val, curr );
+ }else{
+ Trace("inst-gen-cm") << "Consider child index = " << childIndex << ", against ground term argument " << d_children_index[childIndex] << " ... " << n[d_children_index[childIndex]] << std::endl;
+ bool sel = ( isSelected && n[d_children_index[childIndex]].getAttribute(ModelBasisAttribute()) );
+ for( int i=0; i<(int)d_children[ childIndex ].getNumMatches(); i++ ){
+ //FIXME: is this correct?
+ if( sel || qe->getEqualityQuery()->areEqual( d_children[ childIndex ].getMatchValue( i ), n[d_children_index[childIndex]] ) ){
+ InstMatch next( &curr );
+ if( d_children[ childIndex ].getMatch( qe->getEqualityQuery(), i, next ) ){
+ calculateMatchesUninterpreted( qe, f, next, n, childIndex+1, isSelected );
+ }else{
+ Trace("inst-gen-cm") << curr << " not equal to " << d_children[ childIndex ].d_matches[i] << std::endl;
+ Trace("inst-gen-cm") << childIndex << " match " << i << " not equal subs." << std::endl;
+ }
+ }else{
+ Trace("inst-gen-cm") << childIndex << " match " << i << " not equal value." << std::endl;
+ }
+ }
+ }
+}
+
+void InstGenProcess::calculateMatchesInterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, std::vector< Node >& terms, int argIndex ){
+ FirstOrderModel* fm = qe->getModel();
+ if( argIndex==(int)d_node.getNumChildren() ){
+ Node val;
+ if( d_node.getNumChildren()==0 ){
+ val = d_node;
+ }else if( d_node.getKind()==EQUAL ){
+ val = qe->getEqualityQuery()->areEqual( terms[0], terms[1] ) ? fm->d_true : fm->d_false;
+ }else{
+ val = NodeManager::currentNM()->mkNode( d_node.getKind(), terms );
+ val = Rewriter::rewrite( val );
+ }
+ Trace("inst-gen-cm") << " - i-match : " << d_node << std::endl;
+ Trace("inst-gen-cm") << " : " << val << std::endl;
+ Trace("inst-gen-cm") << " : " << curr << std::endl;
+ addMatchValue( qe, f, val, curr );
+ }else{
+ if( d_children_map.find( argIndex )==d_children_map.end() ){
+ terms.push_back( fm->getRepresentative( d_node[argIndex] ) );
+ calculateMatchesInterpreted( qe, f, curr, terms, argIndex+1 );
+ terms.pop_back();
+ }else{
+ for( int i=0; i<(int)d_children[ d_children_map[argIndex] ].getNumMatches(); i++ ){
+ InstMatch next( &curr );
+ if( d_children[ d_children_map[argIndex] ].getMatch( qe->getEqualityQuery(), i, next ) ){
+ terms.push_back( d_children[ d_children_map[argIndex] ].getMatchValue( i ) );
+ calculateMatchesInterpreted( qe, f, next, terms, argIndex+1 );
+ terms.pop_back();
+ }
+ }
+ }
+ }
+}
-/********************* */\r
-/*! \file inst_gen.h\r
- ** \verbatim\r
- ** Original author: ajreynol\r
- ** Major contributors: none\r
- ** Minor contributors (to current version): none\r
- ** This file is part of the CVC4 prototype.\r
- ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)\r
- ** Courant Institute of Mathematical Sciences\r
- ** New York University\r
- ** See the file COPYING in the top-level source directory for licensing\r
- ** information.\endverbatim\r
- **\r
- ** \brief Inst Gen classes\r
- **/\r
-\r
-#include "cvc4_private.h"\r
-\r
-#ifndef __CVC4__THEORY__QUANTIFIERS__INST_GEN_H\r
-#define __CVC4__THEORY__QUANTIFIERS__INST_GEN_H\r
-\r
-#include "theory/quantifiers_engine.h"\r
-#include "theory/quantifiers/inst_match.h"\r
-\r
-namespace CVC4 {\r
-namespace theory {\r
-namespace quantifiers {\r
-\r
-class InstGenProcess\r
-{\r
-private:\r
- //the node we are processing\r
- Node d_node;\r
- //the sub children for this node\r
- std::vector< InstGenProcess > d_children;\r
- std::vector< int > d_children_index;\r
- std::map< int, int > d_children_map;\r
- //the matches we have produced\r
- std::vector< InstMatch > d_matches;\r
- std::vector< Node > d_match_values;\r
- //add match value\r
- std::map< Node, inst::InstMatchTrie > d_inst_trie;\r
- void addMatchValue( QuantifiersEngine* qe, Node f, Node val, InstMatch& m );\r
-private:\r
- void calculateMatchesUninterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, Node n, int childIndex, bool isSelected );\r
- void calculateMatchesInterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, std::vector< Node >& terms, int argIndex );\r
-public:\r
- InstGenProcess( Node n );\r
- virtual ~InstGenProcess(){}\r
-\r
- void calculateMatches( QuantifiersEngine* qe, Node f, std::vector< Node >& considerVal, bool useConsider );\r
- int getNumMatches() { return d_matches.size(); }\r
- bool getMatch( EqualityQuery* q, int i, InstMatch& m );\r
- Node getMatchValue( int i ) { return d_match_values[i]; }\r
-};\r
-\r
-}\r
-}\r
-}\r
-\r
-#endif\r
+/********************* */
+/*! \file inst_gen.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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 Inst Gen classes
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANTIFIERS__INST_GEN_H
+#define __CVC4__THEORY__QUANTIFIERS__INST_GEN_H
+
+#include "theory/quantifiers_engine.h"
+#include "theory/quantifiers/inst_match.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+class InstGenProcess
+{
+private:
+ //the node we are processing
+ Node d_node;
+ //the sub children for this node
+ std::vector< InstGenProcess > d_children;
+ std::vector< int > d_children_index;
+ std::map< int, int > d_children_map;
+ //the matches we have produced
+ std::vector< InstMatch > d_matches;
+ std::vector< Node > d_match_values;
+ //add match value
+ std::map< Node, inst::InstMatchTrie > d_inst_trie;
+ void addMatchValue( QuantifiersEngine* qe, Node f, Node val, InstMatch& m );
+private:
+ void calculateMatchesUninterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, Node n, int childIndex, bool isSelected );
+ void calculateMatchesInterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, std::vector< Node >& terms, int argIndex );
+public:
+ InstGenProcess( Node n );
+ virtual ~InstGenProcess(){}
+
+ void calculateMatches( QuantifiersEngine* qe, Node f, std::vector< Node >& considerVal, bool useConsider );
+ int getNumMatches() { return d_matches.size(); }
+ bool getMatch( EqualityQuery* q, int i, InstMatch& m );
+ Node getMatchValue( int i ) { return d_match_values[i]; }
+};
+
+}
+}
+}
+
+#endif
-/********************* */\r
-/*! \file inst_match_generator.cpp\r
-** \verbatim\r
-** Original author: ajreynol\r
-** Major contributors: bobot\r
-** Minor contributors (to current version): barrett, mdeters\r
-** This file is part of the CVC4 prototype.\r
-** Copyright (c) 2009-2012 New York University and The University of Iowa\r
-** See the file COPYING in the top-level source directory for licensing\r
-** information.\endverbatim\r
-**\r
-** \brief Implementation of inst match generator class\r
-**/\r
-\r
-#include "theory/quantifiers/inst_match_generator.h"\r
-#include "theory/quantifiers/trigger.h"\r
-#include "theory/quantifiers/term_database.h"\r
-#include "theory/quantifiers/candidate_generator.h"\r
-#include "theory/quantifiers_engine.h"\r
-\r
-using namespace std;\r
-using namespace CVC4;\r
-using namespace CVC4::kind;\r
-using namespace CVC4::context;\r
-using namespace CVC4::theory;\r
-\r
-namespace CVC4 {\r
-namespace theory {\r
-namespace inst {\r
-\r
-\r
-InstMatchGenerator::InstMatchGenerator( Node pat, QuantifiersEngine* qe, int matchPolicy ) : d_matchPolicy( matchPolicy ){\r
- initializePattern( pat, qe );\r
-}\r
-\r
-InstMatchGenerator::InstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe, int matchPolicy ) : d_matchPolicy( matchPolicy ){\r
- if( pats.size()==1 ){\r
- initializePattern( pats[0], qe );\r
- }else{\r
- initializePatterns( pats, qe );\r
- }\r
-}\r
-\r
-void InstMatchGenerator::setActiveAdd(){\r
- d_active_add = true;\r
- if( !d_children.empty() ){\r
- d_children[d_children.size()-1]->setActiveAdd();\r
- }\r
-}\r
-\r
-void InstMatchGenerator::initializePatterns( std::vector< Node >& pats, QuantifiersEngine* qe ){\r
- int childMatchPolicy = d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ? 0 : d_matchPolicy;\r
- for( int i=0; i<(int)pats.size(); i++ ){\r
- d_children.push_back( new InstMatchGenerator( pats[i], qe, childMatchPolicy ) );\r
- }\r
- d_pattern = Node::null();\r
- d_match_pattern = Node::null();\r
- d_cg = NULL;\r
-}\r
-\r
-void InstMatchGenerator::initializePattern( Node pat, QuantifiersEngine* qe ){\r
- d_active_add = false;\r
- Debug("inst-match-gen") << "Pattern term is " << pat << std::endl;\r
- Assert( pat.hasAttribute(InstConstantAttribute()) );\r
- d_pattern = pat;\r
- d_match_pattern = pat;\r
- if( d_match_pattern.getKind()==NOT ){\r
- //we want to add the children of the NOT\r
- d_match_pattern = d_pattern[0];\r
- }\r
- if( d_match_pattern.getKind()==IFF || d_match_pattern.getKind()==EQUAL ){\r
- if( !d_match_pattern[0].hasAttribute(InstConstantAttribute()) ){\r
- Assert( d_match_pattern[1].hasAttribute(InstConstantAttribute()) );\r
- //swap sides\r
- d_pattern = NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), d_match_pattern[1], d_match_pattern[0] );\r
- d_pattern = pat.getKind()==NOT ? d_pattern.notNode() : d_pattern;\r
- if( pat.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching\r
- d_match_pattern = d_match_pattern[1];\r
- }else{\r
- d_match_pattern = d_pattern[0][0];\r
- }\r
- }else if( !d_match_pattern[1].hasAttribute(InstConstantAttribute()) ){\r
- Assert( d_match_pattern[0].hasAttribute(InstConstantAttribute()) );\r
- if( pat.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching\r
- d_match_pattern = d_match_pattern[0];\r
- }\r
- }\r
- }\r
- int childMatchPolicy = MATCH_GEN_DEFAULT;\r
- for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){\r
- if( d_match_pattern[i].hasAttribute(InstConstantAttribute()) ){\r
- if( d_match_pattern[i].getKind()!=INST_CONSTANT ){\r
- d_children.push_back( new InstMatchGenerator( d_match_pattern[i], qe, childMatchPolicy ) );\r
- d_children_index.push_back( i );\r
- }\r
- }\r
- }\r
-\r
- Debug("inst-match-gen") << "Pattern is " << d_pattern << ", match pattern is " << d_match_pattern << std::endl;\r
-\r
- //create candidate generator\r
- if( d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==IFF ){\r
- Assert( d_matchPolicy==MATCH_GEN_DEFAULT );\r
- //we will be producing candidates via literal matching heuristics\r
- if( d_pattern.getKind()!=NOT ){\r
- //candidates will be all equalities\r
- d_cg = new inst::CandidateGeneratorQELitEq( qe, d_match_pattern );\r
- }else{\r
- //candidates will be all disequalities\r
- d_cg = new inst::CandidateGeneratorQELitDeq( qe, d_match_pattern );\r
- }\r
- }else if( d_pattern.getKind()==EQUAL || d_pattern.getKind()==IFF || d_pattern.getKind()==NOT ){\r
- Assert( d_matchPolicy==MATCH_GEN_DEFAULT );\r
- if( d_pattern.getKind()==NOT ){\r
- Unimplemented("Disequal generator unimplemented");\r
- }else{\r
- Assert( Trigger::isAtomicTrigger( d_match_pattern ) );\r
- //we are matching only in a particular equivalence class\r
- d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );\r
- //store the equivalence class that we will call d_cg->reset( ... ) on\r
- d_eq_class = d_pattern[1];\r
- }\r
- }else if( Trigger::isAtomicTrigger( d_match_pattern ) ){\r
- //if( d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ){\r
- //Warning() << "Currently efficient e matching is not taken into account for quantifiers: " << d_pattern << std::endl;\r
- //}\r
- //we will be scanning lists trying to find d_match_pattern.getOperator()\r
- d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );\r
- }else{\r
- d_cg = new CandidateGeneratorQueue;\r
- if( !Trigger::getPatternArithmetic( d_match_pattern.getAttribute(InstConstantAttribute()), d_match_pattern, d_arith_coeffs ) ){\r
- Debug("inst-match-gen") << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;\r
- //Warning() << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;\r
- d_matchPolicy = MATCH_GEN_INTERNAL_ERROR;\r
- }else{\r
- Debug("matching-arith") << "Generated arithmetic pattern for " << d_match_pattern << ": " << std::endl;\r
- for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){\r
- Debug("matching-arith") << " " << it->first << " -> " << it->second << std::endl;\r
- }\r
- //we will treat this as match gen internal arithmetic\r
- d_matchPolicy = MATCH_GEN_INTERNAL_ARITHMETIC;\r
- }\r
- }\r
-}\r
-\r
-/** get match (not modulo equality) */\r
-bool InstMatchGenerator::getMatch( Node f, Node t, InstMatch& m, QuantifiersEngine* qe ){\r
- Debug("matching") << "Matching " << t << " against pattern " << d_match_pattern << " ("\r
- << m << ")" << ", " << d_children.size() << std::endl;\r
- Assert( !d_match_pattern.isNull() );\r
- if( qe->d_optMatchIgnoreModelBasis && t.getAttribute(ModelBasisAttribute()) ){\r
- return true;\r
- }else if( d_matchPolicy==MATCH_GEN_INTERNAL_ARITHMETIC ){\r
- return getMatchArithmetic( t, m, qe );\r
- }else if( d_matchPolicy==MATCH_GEN_INTERNAL_ERROR ){\r
- return false;\r
- }else{\r
- EqualityQuery* q = qe->getEqualityQuery();\r
- //add m to partial match vector\r
- std::vector< InstMatch > partial;\r
- partial.push_back( InstMatch( &m ) );\r
- //if t is null\r
- Assert( !t.isNull() );\r
- Assert( !t.hasAttribute(InstConstantAttribute()) );\r
- Assert( t.getKind()==d_match_pattern.getKind() );\r
- Assert( !Trigger::isAtomicTrigger( d_match_pattern ) || t.getOperator()==d_match_pattern.getOperator() );\r
- //first, check if ground arguments are not equal, or a match is in conflict\r
- for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){\r
- if( d_match_pattern[i].hasAttribute(InstConstantAttribute()) ){\r
- if( d_match_pattern[i].getKind()==INST_CONSTANT ){\r
- if( !partial[0].setMatch( q, d_match_pattern[i], t[i] ) ){\r
- //match is in conflict\r
- Debug("matching-debug") << "Match in conflict " << t[i] << " and "\r
- << d_match_pattern[i] << " because "\r
- << partial[0].get(d_match_pattern[i])\r
- << std::endl;\r
- Debug("matching-fail") << "Match fail: " << partial[0].get(d_match_pattern[i]) << " and " << t[i] << std::endl;\r
- return false;\r
- }\r
- }\r
- }else{\r
- if( !q->areEqual( d_match_pattern[i], t[i] ) ){\r
- Debug("matching-fail") << "Match fail arg: " << d_match_pattern[i] << " and " << t[i] << std::endl;\r
- //ground arguments are not equal\r
- return false;\r
- }\r
- }\r
- }\r
- //now, fit children into match\r
- //we will be requesting candidates for matching terms for each child\r
- std::vector< Node > reps;\r
- for( int i=0; i<(int)d_children.size(); i++ ){\r
- Node rep = q->getRepresentative( t[ d_children_index[i] ] );\r
- reps.push_back( rep );\r
- d_children[i]->d_cg->reset( rep );\r
- }\r
-\r
- //combine child matches\r
- int index = 0;\r
- while( index>=0 && index<(int)d_children.size() ){\r
- partial.push_back( InstMatch( &partial[index] ) );\r
- if( d_children[index]->getNextMatch2( f, partial[index+1], qe ) ){\r
- index++;\r
- }else{\r
- d_children[index]->d_cg->reset( reps[index] );\r
- partial.pop_back();\r
- if( !partial.empty() ){\r
- partial.pop_back();\r
- }\r
- index--;\r
- }\r
- }\r
- if( index>=0 ){\r
- if( d_children.empty() && d_active_add ){\r
- Trace("active-add") << "Active Adding instantiation " << partial.back() << std::endl;\r
- bool succ = qe->addInstantiation( f, partial.back() );\r
- Trace("active-add") << "Success = " << succ << std::endl;\r
- return succ;\r
- }else{\r
- m = partial.back();\r
- return true;\r
- }\r
- }else{\r
- return false;\r
- }\r
- }\r
-}\r
-\r
-bool InstMatchGenerator::getNextMatch2( Node f, InstMatch& m, QuantifiersEngine* qe, bool saveMatched ){\r
- bool success = false;\r
- Node t;\r
- do{\r
- //get the next candidate term t\r
- t = d_cg->getNextCandidate();\r
- //if t not null, try to fit it into match m\r
- if( !t.isNull() && t.getType()==d_match_pattern.getType() ){\r
- success = getMatch( f, t, m, qe );\r
- }\r
- }while( !success && !t.isNull() );\r
- if (saveMatched) m.d_matched = t;\r
- return success;\r
-}\r
-\r
-bool InstMatchGenerator::getMatchArithmetic( Node t, InstMatch& m, QuantifiersEngine* qe ){\r
- Debug("matching-arith") << "Matching " << t << " " << d_match_pattern << std::endl;\r
- if( !d_arith_coeffs.empty() ){\r
- NodeBuilder<> tb(kind::PLUS);\r
- Node ic = Node::null();\r
- for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){\r
- Debug("matching-arith") << it->first << " -> " << it->second << std::endl;\r
- if( !it->first.isNull() ){\r
- if( m.find( it->first )==m.end() ){\r
- //see if we can choose this to set\r
- if( ic.isNull() && ( it->second.isNull() || !it->first.getType().isInteger() ) ){\r
- ic = it->first;\r
- }\r
- }else{\r
- Debug("matching-arith") << "already set " << m.get( it->first ) << std::endl;\r
- Node tm = m.get( it->first );\r
- if( !it->second.isNull() ){\r
- tm = NodeManager::currentNM()->mkNode( MULT, it->second, tm );\r
- }\r
- tb << tm;\r
- }\r
- }else{\r
- tb << it->second;\r
- }\r
- }\r
- if( !ic.isNull() ){\r
- Node tm;\r
- if( tb.getNumChildren()==0 ){\r
- tm = t;\r
- }else{\r
- tm = tb.getNumChildren()==1 ? tb.getChild( 0 ) : tb;\r
- tm = NodeManager::currentNM()->mkNode( MINUS, t, tm );\r
- }\r
- if( !d_arith_coeffs[ ic ].isNull() ){\r
- Assert( !ic.getType().isInteger() );\r
- Node coeff = NodeManager::currentNM()->mkConst( Rational(1) / d_arith_coeffs[ ic ].getConst<Rational>() );\r
- tm = NodeManager::currentNM()->mkNode( MULT, coeff, tm );\r
- }\r
- m.set( ic, Rewriter::rewrite( tm ));\r
- //set the rest to zeros\r
- for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){\r
- if( !it->first.isNull() ){\r
- if( m.find( it->first )==m.end() ){\r
- m.set( it->first, NodeManager::currentNM()->mkConst( Rational(0) ) );\r
- }\r
- }\r
- }\r
- Debug("matching-arith") << "Setting " << ic << " to " << tm << std::endl;\r
- return true;\r
- }else{\r
- return false;\r
- }\r
- }else{\r
- return false;\r
- }\r
-}\r
-\r
-\r
-/** reset instantiation round */\r
-void InstMatchGenerator::resetInstantiationRound( QuantifiersEngine* qe ){\r
- if( d_match_pattern.isNull() ){\r
- for( int i=0; i<(int)d_children.size(); i++ ){\r
- d_children[i]->resetInstantiationRound( qe );\r
- }\r
- }else{\r
- if( d_cg ){\r
- d_cg->resetInstantiationRound();\r
- }\r
- }\r
-}\r
-\r
-void InstMatchGenerator::reset( Node eqc, QuantifiersEngine* qe ){\r
- if( d_match_pattern.isNull() ){\r
- for( int i=0; i<(int)d_children.size(); i++ ){\r
- d_children[i]->reset( eqc, qe );\r
- }\r
- d_partial.clear();\r
- }else{\r
- if( !d_eq_class.isNull() ){\r
- //we have a specific equivalence class in mind\r
- //we are producing matches for f(E) ~ t, where E is a non-ground vector of terms, and t is a ground term\r
- //just look in equivalence class of the RHS\r
- d_cg->reset( d_eq_class );\r
- }else{\r
- d_cg->reset( eqc );\r
- }\r
- }\r
-}\r
-\r
-bool InstMatchGenerator::getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ){\r
- m.d_matched = Node::null();\r
- if( d_match_pattern.isNull() ){\r
- int index = (int)d_partial.size();\r
- while( index>=0 && index<(int)d_children.size() ){\r
- if( index>0 ){\r
- d_partial.push_back( InstMatch( &d_partial[index-1] ) );\r
- }else{\r
- d_partial.push_back( InstMatch() );\r
- }\r
- if( d_children[index]->getNextMatch( f, d_partial[index], qe ) ){\r
- index++;\r
- }else{\r
- d_children[index]->reset( Node::null(), qe );\r
- d_partial.pop_back();\r
- if( !d_partial.empty() ){\r
- d_partial.pop_back();\r
- }\r
- index--;\r
- }\r
- }\r
- if( index>=0 ){\r
- m = d_partial.back();\r
- d_partial.pop_back();\r
- return true;\r
- }else{\r
- return false;\r
- }\r
- }else{\r
- bool res = getNextMatch2( f, m, qe, true );\r
- Assert(!res || !m.d_matched.isNull());\r
- return res;\r
- }\r
-}\r
-\r
-\r
-\r
-int InstMatchGenerator::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){\r
- //now, try to add instantiation for each match produced\r
- int addedLemmas = 0;\r
- InstMatch m;\r
- while( getNextMatch( f, m, qe ) ){\r
- //if( d_active_add ){\r
- // std::cout << "should not add at top level." << std::endl;\r
- //}\r
- if( !d_active_add ){\r
- //m.makeInternal( d_quantEngine->getEqualityQuery() );\r
- m.add( baseMatch );\r
- if( qe->addInstantiation( f, m ) ){\r
- addedLemmas++;\r
- if( qe->d_optInstLimitActive && qe->d_optInstLimit<=0 ){\r
- return addedLemmas;\r
- }\r
- }\r
- m.clear();\r
- }\r
- }\r
- //return number of lemmas added\r
- return addedLemmas;\r
-}\r
-\r
-int InstMatchGenerator::addTerm( Node f, Node t, QuantifiersEngine* qe ){\r
- Assert( options::eagerInstQuant() );\r
- if( !d_match_pattern.isNull() ){\r
- InstMatch m;\r
- if( getMatch( f, t, m, qe ) ){\r
- if( qe->addInstantiation( f, m ) ){\r
- return 1;\r
- }\r
- }\r
- }else{\r
- for( int i=0; i<(int)d_children.size(); i++ ){\r
- d_children[i]->addTerm( f, t, qe );\r
- }\r
- }\r
- return 0;\r
-}\r
-\r
-/** constructors */\r
-InstMatchGeneratorMulti::InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption ) :\r
-d_f( f ){\r
- Debug("smart-multi-trigger") << "Making smart multi-trigger for " << f << std::endl;\r
- std::map< Node, std::vector< Node > > var_contains;\r
- qe->getTermDatabase()->getVarContains( f, pats, var_contains );\r
- //convert to indicies\r
- for( std::map< Node, std::vector< Node > >::iterator it = var_contains.begin(); it != var_contains.end(); ++it ){\r
- Debug("smart-multi-trigger") << "Pattern " << it->first << " contains: ";\r
- for( int i=0; i<(int)it->second.size(); i++ ){\r
- Debug("smart-multi-trigger") << it->second[i] << " ";\r
- int index = it->second[i].getAttribute(InstVarNumAttribute());\r
- d_var_contains[ it->first ].push_back( index );\r
- d_var_to_node[ index ].push_back( it->first );\r
- }\r
- Debug("smart-multi-trigger") << std::endl;\r
- }\r
- for( int i=0; i<(int)pats.size(); i++ ){\r
- Node n = pats[i];\r
- //make the match generator\r
- d_children.push_back( new InstMatchGenerator( n, qe, matchOption ) );\r
- //compute unique/shared variables\r
- std::vector< int > unique_vars;\r
- std::map< int, bool > shared_vars;\r
- int numSharedVars = 0;\r
- for( int j=0; j<(int)d_var_contains[n].size(); j++ ){\r
- if( d_var_to_node[ d_var_contains[n][j] ].size()==1 ){\r
- Debug("smart-multi-trigger") << "Var " << d_var_contains[n][j] << " is unique to " << pats[i] << std::endl;\r
- unique_vars.push_back( d_var_contains[n][j] );\r
- }else{\r
- shared_vars[ d_var_contains[n][j] ] = true;\r
- numSharedVars++;\r
- }\r
- }\r
- //we use the latest shared variables, then unique variables\r
- std::vector< int > vars;\r
- int index = i==0 ? (int)(pats.size()-1) : (i-1);\r
- while( numSharedVars>0 && index!=i ){\r
- for( std::map< int, bool >::iterator it = shared_vars.begin(); it != shared_vars.end(); ++it ){\r
- if( it->second ){\r
- if( std::find( d_var_contains[ pats[index] ].begin(), d_var_contains[ pats[index] ].end(), it->first )!=\r
- d_var_contains[ pats[index] ].end() ){\r
- vars.push_back( it->first );\r
- shared_vars[ it->first ] = false;\r
- numSharedVars--;\r
- }\r
- }\r
- }\r
- index = index==0 ? (int)(pats.size()-1) : (index-1);\r
- }\r
- vars.insert( vars.end(), unique_vars.begin(), unique_vars.end() );\r
- Debug("smart-multi-trigger") << " Index[" << i << "]: ";\r
- for( int i=0; i<(int)vars.size(); i++ ){\r
- Debug("smart-multi-trigger") << vars[i] << " ";\r
- }\r
- Debug("smart-multi-trigger") << std::endl;\r
- //make ordered inst match trie\r
- InstMatchTrie::ImtIndexOrder* imtio = new InstMatchTrie::ImtIndexOrder;\r
- imtio->d_order.insert( imtio->d_order.begin(), vars.begin(), vars.end() );\r
- d_children_trie.push_back( InstMatchTrieOrdered( imtio ) );\r
- }\r
-\r
-}\r
-\r
-/** reset instantiation round (call this whenever equivalence classes have changed) */\r
-void InstMatchGeneratorMulti::resetInstantiationRound( QuantifiersEngine* qe ){\r
- for( int i=0; i<(int)d_children.size(); i++ ){\r
- d_children[i]->resetInstantiationRound( qe );\r
- }\r
-}\r
-\r
-/** reset, eqc is the equivalence class to search in (any if eqc=null) */\r
-void InstMatchGeneratorMulti::reset( Node eqc, QuantifiersEngine* qe ){\r
- for( int i=0; i<(int)d_children.size(); i++ ){\r
- d_children[i]->reset( eqc, qe );\r
- }\r
-}\r
-\r
-int InstMatchGeneratorMulti::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){\r
- int addedLemmas = 0;\r
- Debug("smart-multi-trigger") << "Process smart multi trigger" << std::endl;\r
- for( int i=0; i<(int)d_children.size(); i++ ){\r
- Debug("smart-multi-trigger") << "Calculate matches " << i << std::endl;\r
- std::vector< InstMatch > newMatches;\r
- InstMatch m;\r
- while( d_children[i]->getNextMatch( f, m, qe ) ){\r
- m.makeRepresentative( qe );\r
- newMatches.push_back( InstMatch( &m ) );\r
- m.clear();\r
- }\r
- for( int j=0; j<(int)newMatches.size(); j++ ){\r
- processNewMatch( qe, newMatches[j], i, addedLemmas );\r
- }\r
- }\r
- return addedLemmas;\r
-}\r
-\r
-void InstMatchGeneratorMulti::processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas ){\r
- //see if these produce new matches\r
- d_children_trie[fromChildIndex].addInstMatch( qe, d_f, m, true );\r
- //possibly only do the following if we know that new matches will be produced?\r
- //the issue is that instantiations are filtered in quantifiers engine, and so there is no guarentee that\r
- // we can safely skip the following lines, even when we have already produced this match.\r
- Debug("smart-multi-trigger") << "Child " << fromChildIndex << " produced match " << m << std::endl;\r
- //process new instantiations\r
- int childIndex = (fromChildIndex+1)%(int)d_children.size();\r
- std::vector< IndexedTrie > unique_var_tries;\r
- processNewInstantiations( qe, m, addedLemmas, d_children_trie[childIndex].getTrie(),\r
- unique_var_tries, 0, childIndex, fromChildIndex, true );\r
-}\r
-\r
-void InstMatchGeneratorMulti::processNewInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,\r
- std::vector< IndexedTrie >& unique_var_tries,\r
- int trieIndex, int childIndex, int endChildIndex, bool modEq ){\r
- if( childIndex==endChildIndex ){\r
- //now, process unique variables\r
- processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, 0 );\r
- }else if( trieIndex<(int)d_children_trie[childIndex].getOrdering()->d_order.size() ){\r
- int curr_index = d_children_trie[childIndex].getOrdering()->d_order[trieIndex];\r
- Node curr_ic = qe->getTermDatabase()->getInstantiationConstant( d_f, curr_index );\r
- if( m.find( curr_ic )==m.end() ){\r
- //if( d_var_to_node[ curr_index ].size()==1 ){ //FIXME\r
- // //unique variable(s), defer calculation\r
- // unique_var_tries.push_back( IndexedTrie( std::pair< int, int >( childIndex, trieIndex ), tr ) );\r
- // int newChildIndex = (childIndex+1)%(int)d_children.size();\r
- // processNewInstantiations( qe, m, d_children_trie[newChildIndex].getTrie(), unique_var_tries,\r
- // 0, newChildIndex, endChildIndex, modEq );\r
- //}else{\r
- //shared and non-set variable, add to InstMatch\r
- for( std::map< Node, InstMatchTrie >::iterator it = tr->d_data.begin(); it != tr->d_data.end(); ++it ){\r
- InstMatch mn( &m );\r
- mn.set( curr_ic, it->first);\r
- processNewInstantiations( qe, mn, addedLemmas, &(it->second), unique_var_tries,\r
- trieIndex+1, childIndex, endChildIndex, modEq );\r
- }\r
- //}\r
- }else{\r
- //shared and set variable, try to merge\r
- Node n = m.get( curr_ic );\r
- std::map< Node, InstMatchTrie >::iterator it = tr->d_data.find( n );\r
- if( it!=tr->d_data.end() ){\r
- processNewInstantiations( qe, m, addedLemmas, &(it->second), unique_var_tries,\r
- trieIndex+1, childIndex, endChildIndex, modEq );\r
- }\r
- if( modEq ){\r
- //check modulo equality for other possible instantiations\r
- if( qe->getEqualityQuery()->getEngine()->hasTerm( n ) ){\r
- eq::EqClassIterator eqc( qe->getEqualityQuery()->getEngine()->getRepresentative( n ),\r
- qe->getEqualityQuery()->getEngine() );\r
- while( !eqc.isFinished() ){\r
- Node en = (*eqc);\r
- if( en!=n ){\r
- std::map< Node, InstMatchTrie >::iterator itc = tr->d_data.find( en );\r
- if( itc!=tr->d_data.end() ){\r
- processNewInstantiations( qe, m, addedLemmas, &(itc->second), unique_var_tries,\r
- trieIndex+1, childIndex, endChildIndex, modEq );\r
- }\r
- }\r
- ++eqc;\r
- }\r
- }\r
- }\r
- }\r
- }else{\r
- int newChildIndex = (childIndex+1)%(int)d_children.size();\r
- processNewInstantiations( qe, m, addedLemmas, d_children_trie[newChildIndex].getTrie(), unique_var_tries,\r
- 0, newChildIndex, endChildIndex, modEq );\r
- }\r
-}\r
-\r
-void InstMatchGeneratorMulti::processNewInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,\r
- std::vector< IndexedTrie >& unique_var_tries,\r
- int uvtIndex, InstMatchTrie* tr, int trieIndex ){\r
- if( uvtIndex<(int)unique_var_tries.size() ){\r
- int childIndex = unique_var_tries[uvtIndex].first.first;\r
- if( !tr ){\r
- tr = unique_var_tries[uvtIndex].second;\r
- trieIndex = unique_var_tries[uvtIndex].first.second;\r
- }\r
- if( trieIndex<(int)d_children_trie[childIndex].getOrdering()->d_order.size() ){\r
- int curr_index = d_children_trie[childIndex].getOrdering()->d_order[trieIndex];\r
- Node curr_ic = qe->getTermDatabase()->getInstantiationConstant( d_f, curr_index );\r
- //unique non-set variable, add to InstMatch\r
- for( std::map< Node, InstMatchTrie >::iterator it = tr->d_data.begin(); it != tr->d_data.end(); ++it ){\r
- InstMatch mn( &m );\r
- mn.set( curr_ic, it->first);\r
- processNewInstantiations2( qe, mn, addedLemmas, unique_var_tries, uvtIndex, &(it->second), trieIndex+1 );\r
- }\r
- }else{\r
- processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, uvtIndex+1 );\r
- }\r
- }else{\r
- //m is an instantiation\r
- if( qe->addInstantiation( d_f, m ) ){\r
- addedLemmas++;\r
- Debug("smart-multi-trigger") << "-> Produced instantiation " << m << std::endl;\r
- }\r
- }\r
-}\r
-\r
-int InstMatchGeneratorMulti::addTerm( Node f, Node t, QuantifiersEngine* qe ){\r
- Assert( options::eagerInstQuant() );\r
- int addedLemmas = 0;\r
- for( int i=0; i<(int)d_children.size(); i++ ){\r
- if( ((InstMatchGenerator*)d_children[i])->d_match_pattern.getOperator()==t.getOperator() ){\r
- InstMatch m;\r
- //if it produces a match, then process it with the rest\r
- if( ((InstMatchGenerator*)d_children[i])->getMatch( f, t, m, qe ) ){\r
- processNewMatch( qe, m, i, addedLemmas );\r
- }\r
- }\r
- }\r
- return addedLemmas;\r
-}\r
-\r
-int InstMatchGeneratorSimple::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){\r
- InstMatch m;\r
- m.add( baseMatch );\r
- int addedLemmas = 0;\r
- if( d_match_pattern.getType()==NodeManager::currentNM()->booleanType() ){\r
- for( int i=0; i<2; i++ ){\r
- addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_pred_map_trie[i][ d_match_pattern.getOperator() ]) );\r
- }\r
- }else{\r
- addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_func_map_trie[ d_match_pattern.getOperator() ]) );\r
- }\r
- return addedLemmas;\r
-}\r
-\r
-void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex, quantifiers::TermArgTrie* tat ){\r
- if( argIndex==(int)d_match_pattern.getNumChildren() ){\r
- //m is an instantiation\r
- if( qe->addInstantiation( d_f, m ) ){\r
- addedLemmas++;\r
- Debug("simple-multi-trigger") << "-> Produced instantiation " << m << std::endl;\r
- }\r
- }else{\r
- if( d_match_pattern[argIndex].getKind()==INST_CONSTANT ){\r
- Node ic = d_match_pattern[argIndex];\r
- for( std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){\r
- Node t = it->first;\r
- if( ( m.get( ic ).isNull() || m.get( ic )==t ) && ic.getType()==t.getType() ){\r
- Node prev = m.get( ic );\r
- m.set( ic, t);\r
- addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );\r
- m.set( ic, prev);\r
- }\r
- }\r
- }else{\r
- Node r = qe->getEqualityQuery()->getRepresentative( d_match_pattern[argIndex] );\r
- std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.find( r );\r
- if( it!=tat->d_data.end() ){\r
- addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );\r
- }\r
- }\r
- }\r
-}\r
-\r
-int InstMatchGeneratorSimple::addTerm( Node f, Node t, QuantifiersEngine* qe ){\r
- Assert( options::eagerInstQuant() );\r
- InstMatch m;\r
- for( int i=0; i<(int)t.getNumChildren(); i++ ){\r
- if( d_match_pattern[i].getKind()==INST_CONSTANT ){\r
- m.set(d_match_pattern[i], t[i]);\r
- }else if( !qe->getEqualityQuery()->areEqual( d_match_pattern[i], t[i] ) ){\r
- return 0;\r
- }\r
- }\r
- return qe->addInstantiation( f, m ) ? 1 : 0;\r
-}\r
-\r
-}/* CVC4::theory::inst namespace */\r
-}/* CVC4::theory namespace */\r
-}/* CVC4 namespace */\r
+/********************* */
+/*! \file inst_match_generator.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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
+ **
+ ** [[ Add lengthier description here ]]
+ ** \todo document this file
+**/
+
+#include "theory/quantifiers/inst_match_generator.h"
+#include "theory/quantifiers/trigger.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/candidate_generator.h"
+#include "theory/quantifiers_engine.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+
+namespace CVC4 {
+namespace theory {
+namespace inst {
+
+
+InstMatchGenerator::InstMatchGenerator( Node pat, QuantifiersEngine* qe, int matchPolicy ) : d_matchPolicy( matchPolicy ){
+ initializePattern( pat, qe );
+}
+
+InstMatchGenerator::InstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe, int matchPolicy ) : d_matchPolicy( matchPolicy ){
+ if( pats.size()==1 ){
+ initializePattern( pats[0], qe );
+ }else{
+ initializePatterns( pats, qe );
+ }
+}
+
+void InstMatchGenerator::setActiveAdd(){
+ d_active_add = true;
+ if( !d_children.empty() ){
+ d_children[d_children.size()-1]->setActiveAdd();
+ }
+}
+
+void InstMatchGenerator::initializePatterns( std::vector< Node >& pats, QuantifiersEngine* qe ){
+ int childMatchPolicy = d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ? 0 : d_matchPolicy;
+ for( int i=0; i<(int)pats.size(); i++ ){
+ d_children.push_back( new InstMatchGenerator( pats[i], qe, childMatchPolicy ) );
+ }
+ d_pattern = Node::null();
+ d_match_pattern = Node::null();
+ d_cg = NULL;
+}
+
+void InstMatchGenerator::initializePattern( Node pat, QuantifiersEngine* qe ){
+ d_active_add = false;
+ Debug("inst-match-gen") << "Pattern term is " << pat << std::endl;
+ Assert( pat.hasAttribute(InstConstantAttribute()) );
+ d_pattern = pat;
+ d_match_pattern = pat;
+ if( d_match_pattern.getKind()==NOT ){
+ //we want to add the children of the NOT
+ d_match_pattern = d_pattern[0];
+ }
+ if( d_match_pattern.getKind()==IFF || d_match_pattern.getKind()==EQUAL ){
+ if( !d_match_pattern[0].hasAttribute(InstConstantAttribute()) ){
+ Assert( d_match_pattern[1].hasAttribute(InstConstantAttribute()) );
+ //swap sides
+ d_pattern = NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), d_match_pattern[1], d_match_pattern[0] );
+ d_pattern = pat.getKind()==NOT ? d_pattern.notNode() : d_pattern;
+ if( pat.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching
+ d_match_pattern = d_match_pattern[1];
+ }else{
+ d_match_pattern = d_pattern[0][0];
+ }
+ }else if( !d_match_pattern[1].hasAttribute(InstConstantAttribute()) ){
+ Assert( d_match_pattern[0].hasAttribute(InstConstantAttribute()) );
+ if( pat.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching
+ d_match_pattern = d_match_pattern[0];
+ }
+ }
+ }
+ int childMatchPolicy = MATCH_GEN_DEFAULT;
+ for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
+ if( d_match_pattern[i].hasAttribute(InstConstantAttribute()) ){
+ if( d_match_pattern[i].getKind()!=INST_CONSTANT ){
+ d_children.push_back( new InstMatchGenerator( d_match_pattern[i], qe, childMatchPolicy ) );
+ d_children_index.push_back( i );
+ }
+ }
+ }
+
+ Debug("inst-match-gen") << "Pattern is " << d_pattern << ", match pattern is " << d_match_pattern << std::endl;
+
+ //create candidate generator
+ if( d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==IFF ){
+ Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
+ //we will be producing candidates via literal matching heuristics
+ if( d_pattern.getKind()!=NOT ){
+ //candidates will be all equalities
+ d_cg = new inst::CandidateGeneratorQELitEq( qe, d_match_pattern );
+ }else{
+ //candidates will be all disequalities
+ d_cg = new inst::CandidateGeneratorQELitDeq( qe, d_match_pattern );
+ }
+ }else if( d_pattern.getKind()==EQUAL || d_pattern.getKind()==IFF || d_pattern.getKind()==NOT ){
+ Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
+ if( d_pattern.getKind()==NOT ){
+ Unimplemented("Disequal generator unimplemented");
+ }else{
+ Assert( Trigger::isAtomicTrigger( d_match_pattern ) );
+ //we are matching only in a particular equivalence class
+ d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
+ //store the equivalence class that we will call d_cg->reset( ... ) on
+ d_eq_class = d_pattern[1];
+ }
+ }else if( Trigger::isAtomicTrigger( d_match_pattern ) ){
+ //if( d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ){
+ //Warning() << "Currently efficient e matching is not taken into account for quantifiers: " << d_pattern << std::endl;
+ //}
+ //we will be scanning lists trying to find d_match_pattern.getOperator()
+ d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
+ }else{
+ d_cg = new CandidateGeneratorQueue;
+ if( !Trigger::getPatternArithmetic( d_match_pattern.getAttribute(InstConstantAttribute()), d_match_pattern, d_arith_coeffs ) ){
+ Debug("inst-match-gen") << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
+ //Warning() << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
+ d_matchPolicy = MATCH_GEN_INTERNAL_ERROR;
+ }else{
+ Debug("matching-arith") << "Generated arithmetic pattern for " << d_match_pattern << ": " << std::endl;
+ for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+ Debug("matching-arith") << " " << it->first << " -> " << it->second << std::endl;
+ }
+ //we will treat this as match gen internal arithmetic
+ d_matchPolicy = MATCH_GEN_INTERNAL_ARITHMETIC;
+ }
+ }
+}
+
+/** get match (not modulo equality) */
+bool InstMatchGenerator::getMatch( Node f, Node t, InstMatch& m, QuantifiersEngine* qe ){
+ Debug("matching") << "Matching " << t << " against pattern " << d_match_pattern << " ("
+ << m << ")" << ", " << d_children.size() << std::endl;
+ Assert( !d_match_pattern.isNull() );
+ if( qe->d_optMatchIgnoreModelBasis && t.getAttribute(ModelBasisAttribute()) ){
+ return true;
+ }else if( d_matchPolicy==MATCH_GEN_INTERNAL_ARITHMETIC ){
+ return getMatchArithmetic( t, m, qe );
+ }else if( d_matchPolicy==MATCH_GEN_INTERNAL_ERROR ){
+ return false;
+ }else{
+ EqualityQuery* q = qe->getEqualityQuery();
+ //add m to partial match vector
+ std::vector< InstMatch > partial;
+ partial.push_back( InstMatch( &m ) );
+ //if t is null
+ Assert( !t.isNull() );
+ Assert( !t.hasAttribute(InstConstantAttribute()) );
+ Assert( t.getKind()==d_match_pattern.getKind() );
+ Assert( !Trigger::isAtomicTrigger( d_match_pattern ) || t.getOperator()==d_match_pattern.getOperator() );
+ //first, check if ground arguments are not equal, or a match is in conflict
+ for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
+ if( d_match_pattern[i].hasAttribute(InstConstantAttribute()) ){
+ if( d_match_pattern[i].getKind()==INST_CONSTANT ){
+ if( !partial[0].setMatch( q, d_match_pattern[i], t[i] ) ){
+ //match is in conflict
+ Debug("matching-debug") << "Match in conflict " << t[i] << " and "
+ << d_match_pattern[i] << " because "
+ << partial[0].get(d_match_pattern[i])
+ << std::endl;
+ Debug("matching-fail") << "Match fail: " << partial[0].get(d_match_pattern[i]) << " and " << t[i] << std::endl;
+ return false;
+ }
+ }
+ }else{
+ if( !q->areEqual( d_match_pattern[i], t[i] ) ){
+ Debug("matching-fail") << "Match fail arg: " << d_match_pattern[i] << " and " << t[i] << std::endl;
+ //ground arguments are not equal
+ return false;
+ }
+ }
+ }
+ //now, fit children into match
+ //we will be requesting candidates for matching terms for each child
+ std::vector< Node > reps;
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ Node rep = q->getRepresentative( t[ d_children_index[i] ] );
+ reps.push_back( rep );
+ d_children[i]->d_cg->reset( rep );
+ }
+
+ //combine child matches
+ int index = 0;
+ while( index>=0 && index<(int)d_children.size() ){
+ partial.push_back( InstMatch( &partial[index] ) );
+ if( d_children[index]->getNextMatch2( f, partial[index+1], qe ) ){
+ index++;
+ }else{
+ d_children[index]->d_cg->reset( reps[index] );
+ partial.pop_back();
+ if( !partial.empty() ){
+ partial.pop_back();
+ }
+ index--;
+ }
+ }
+ if( index>=0 ){
+ if( d_children.empty() && d_active_add ){
+ Trace("active-add") << "Active Adding instantiation " << partial.back() << std::endl;
+ bool succ = qe->addInstantiation( f, partial.back() );
+ Trace("active-add") << "Success = " << succ << std::endl;
+ return succ;
+ }else{
+ m = partial.back();
+ return true;
+ }
+ }else{
+ return false;
+ }
+ }
+}
+
+bool InstMatchGenerator::getNextMatch2( Node f, InstMatch& m, QuantifiersEngine* qe, bool saveMatched ){
+ bool success = false;
+ Node t;
+ do{
+ //get the next candidate term t
+ t = d_cg->getNextCandidate();
+ //if t not null, try to fit it into match m
+ if( !t.isNull() && t.getType()==d_match_pattern.getType() ){
+ success = getMatch( f, t, m, qe );
+ }
+ }while( !success && !t.isNull() );
+ if (saveMatched) m.d_matched = t;
+ return success;
+}
+
+bool InstMatchGenerator::getMatchArithmetic( Node t, InstMatch& m, QuantifiersEngine* qe ){
+ Debug("matching-arith") << "Matching " << t << " " << d_match_pattern << std::endl;
+ if( !d_arith_coeffs.empty() ){
+ NodeBuilder<> tb(kind::PLUS);
+ Node ic = Node::null();
+ for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+ Debug("matching-arith") << it->first << " -> " << it->second << std::endl;
+ if( !it->first.isNull() ){
+ if( m.find( it->first )==m.end() ){
+ //see if we can choose this to set
+ if( ic.isNull() && ( it->second.isNull() || !it->first.getType().isInteger() ) ){
+ ic = it->first;
+ }
+ }else{
+ Debug("matching-arith") << "already set " << m.get( it->first ) << std::endl;
+ Node tm = m.get( it->first );
+ if( !it->second.isNull() ){
+ tm = NodeManager::currentNM()->mkNode( MULT, it->second, tm );
+ }
+ tb << tm;
+ }
+ }else{
+ tb << it->second;
+ }
+ }
+ if( !ic.isNull() ){
+ Node tm;
+ if( tb.getNumChildren()==0 ){
+ tm = t;
+ }else{
+ tm = tb.getNumChildren()==1 ? tb.getChild( 0 ) : tb;
+ tm = NodeManager::currentNM()->mkNode( MINUS, t, tm );
+ }
+ if( !d_arith_coeffs[ ic ].isNull() ){
+ Assert( !ic.getType().isInteger() );
+ Node coeff = NodeManager::currentNM()->mkConst( Rational(1) / d_arith_coeffs[ ic ].getConst<Rational>() );
+ tm = NodeManager::currentNM()->mkNode( MULT, coeff, tm );
+ }
+ m.set( ic, Rewriter::rewrite( tm ));
+ //set the rest to zeros
+ for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+ if( !it->first.isNull() ){
+ if( m.find( it->first )==m.end() ){
+ m.set( it->first, NodeManager::currentNM()->mkConst( Rational(0) ) );
+ }
+ }
+ }
+ Debug("matching-arith") << "Setting " << ic << " to " << tm << std::endl;
+ return true;
+ }else{
+ return false;
+ }
+ }else{
+ return false;
+ }
+}
+
+
+/** reset instantiation round */
+void InstMatchGenerator::resetInstantiationRound( QuantifiersEngine* qe ){
+ if( d_match_pattern.isNull() ){
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ d_children[i]->resetInstantiationRound( qe );
+ }
+ }else{
+ if( d_cg ){
+ d_cg->resetInstantiationRound();
+ }
+ }
+}
+
+void InstMatchGenerator::reset( Node eqc, QuantifiersEngine* qe ){
+ if( d_match_pattern.isNull() ){
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ d_children[i]->reset( eqc, qe );
+ }
+ d_partial.clear();
+ }else{
+ if( !d_eq_class.isNull() ){
+ //we have a specific equivalence class in mind
+ //we are producing matches for f(E) ~ t, where E is a non-ground vector of terms, and t is a ground term
+ //just look in equivalence class of the RHS
+ d_cg->reset( d_eq_class );
+ }else{
+ d_cg->reset( eqc );
+ }
+ }
+}
+
+bool InstMatchGenerator::getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ){
+ m.d_matched = Node::null();
+ if( d_match_pattern.isNull() ){
+ int index = (int)d_partial.size();
+ while( index>=0 && index<(int)d_children.size() ){
+ if( index>0 ){
+ d_partial.push_back( InstMatch( &d_partial[index-1] ) );
+ }else{
+ d_partial.push_back( InstMatch() );
+ }
+ if( d_children[index]->getNextMatch( f, d_partial[index], qe ) ){
+ index++;
+ }else{
+ d_children[index]->reset( Node::null(), qe );
+ d_partial.pop_back();
+ if( !d_partial.empty() ){
+ d_partial.pop_back();
+ }
+ index--;
+ }
+ }
+ if( index>=0 ){
+ m = d_partial.back();
+ d_partial.pop_back();
+ return true;
+ }else{
+ return false;
+ }
+ }else{
+ bool res = getNextMatch2( f, m, qe, true );
+ Assert(!res || !m.d_matched.isNull());
+ return res;
+ }
+}
+
+
+
+int InstMatchGenerator::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
+ //now, try to add instantiation for each match produced
+ int addedLemmas = 0;
+ InstMatch m;
+ while( getNextMatch( f, m, qe ) ){
+ //if( d_active_add ){
+ // std::cout << "should not add at top level." << std::endl;
+ //}
+ if( !d_active_add ){
+ //m.makeInternal( d_quantEngine->getEqualityQuery() );
+ m.add( baseMatch );
+ if( qe->addInstantiation( f, m ) ){
+ addedLemmas++;
+ if( qe->d_optInstLimitActive && qe->d_optInstLimit<=0 ){
+ return addedLemmas;
+ }
+ }
+ m.clear();
+ }
+ }
+ //return number of lemmas added
+ return addedLemmas;
+}
+
+int InstMatchGenerator::addTerm( Node f, Node t, QuantifiersEngine* qe ){
+ Assert( options::eagerInstQuant() );
+ if( !d_match_pattern.isNull() ){
+ InstMatch m;
+ if( getMatch( f, t, m, qe ) ){
+ if( qe->addInstantiation( f, m ) ){
+ return 1;
+ }
+ }
+ }else{
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ d_children[i]->addTerm( f, t, qe );
+ }
+ }
+ return 0;
+}
+
+/** constructors */
+InstMatchGeneratorMulti::InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption ) :
+d_f( f ){
+ Debug("smart-multi-trigger") << "Making smart multi-trigger for " << f << std::endl;
+ std::map< Node, std::vector< Node > > var_contains;
+ qe->getTermDatabase()->getVarContains( f, pats, var_contains );
+ //convert to indicies
+ for( std::map< Node, std::vector< Node > >::iterator it = var_contains.begin(); it != var_contains.end(); ++it ){
+ Debug("smart-multi-trigger") << "Pattern " << it->first << " contains: ";
+ for( int i=0; i<(int)it->second.size(); i++ ){
+ Debug("smart-multi-trigger") << it->second[i] << " ";
+ int index = it->second[i].getAttribute(InstVarNumAttribute());
+ d_var_contains[ it->first ].push_back( index );
+ d_var_to_node[ index ].push_back( it->first );
+ }
+ Debug("smart-multi-trigger") << std::endl;
+ }
+ for( int i=0; i<(int)pats.size(); i++ ){
+ Node n = pats[i];
+ //make the match generator
+ d_children.push_back( new InstMatchGenerator( n, qe, matchOption ) );
+ //compute unique/shared variables
+ std::vector< int > unique_vars;
+ std::map< int, bool > shared_vars;
+ int numSharedVars = 0;
+ for( int j=0; j<(int)d_var_contains[n].size(); j++ ){
+ if( d_var_to_node[ d_var_contains[n][j] ].size()==1 ){
+ Debug("smart-multi-trigger") << "Var " << d_var_contains[n][j] << " is unique to " << pats[i] << std::endl;
+ unique_vars.push_back( d_var_contains[n][j] );
+ }else{
+ shared_vars[ d_var_contains[n][j] ] = true;
+ numSharedVars++;
+ }
+ }
+ //we use the latest shared variables, then unique variables
+ std::vector< int > vars;
+ int index = i==0 ? (int)(pats.size()-1) : (i-1);
+ while( numSharedVars>0 && index!=i ){
+ for( std::map< int, bool >::iterator it = shared_vars.begin(); it != shared_vars.end(); ++it ){
+ if( it->second ){
+ if( std::find( d_var_contains[ pats[index] ].begin(), d_var_contains[ pats[index] ].end(), it->first )!=
+ d_var_contains[ pats[index] ].end() ){
+ vars.push_back( it->first );
+ shared_vars[ it->first ] = false;
+ numSharedVars--;
+ }
+ }
+ }
+ index = index==0 ? (int)(pats.size()-1) : (index-1);
+ }
+ vars.insert( vars.end(), unique_vars.begin(), unique_vars.end() );
+ Debug("smart-multi-trigger") << " Index[" << i << "]: ";
+ for( int i=0; i<(int)vars.size(); i++ ){
+ Debug("smart-multi-trigger") << vars[i] << " ";
+ }
+ Debug("smart-multi-trigger") << std::endl;
+ //make ordered inst match trie
+ InstMatchTrie::ImtIndexOrder* imtio = new InstMatchTrie::ImtIndexOrder;
+ imtio->d_order.insert( imtio->d_order.begin(), vars.begin(), vars.end() );
+ d_children_trie.push_back( InstMatchTrieOrdered( imtio ) );
+ }
+
+}
+
+/** reset instantiation round (call this whenever equivalence classes have changed) */
+void InstMatchGeneratorMulti::resetInstantiationRound( QuantifiersEngine* qe ){
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ d_children[i]->resetInstantiationRound( qe );
+ }
+}
+
+/** reset, eqc is the equivalence class to search in (any if eqc=null) */
+void InstMatchGeneratorMulti::reset( Node eqc, QuantifiersEngine* qe ){
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ d_children[i]->reset( eqc, qe );
+ }
+}
+
+int InstMatchGeneratorMulti::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
+ int addedLemmas = 0;
+ Debug("smart-multi-trigger") << "Process smart multi trigger" << std::endl;
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ Debug("smart-multi-trigger") << "Calculate matches " << i << std::endl;
+ std::vector< InstMatch > newMatches;
+ InstMatch m;
+ while( d_children[i]->getNextMatch( f, m, qe ) ){
+ m.makeRepresentative( qe );
+ newMatches.push_back( InstMatch( &m ) );
+ m.clear();
+ }
+ for( int j=0; j<(int)newMatches.size(); j++ ){
+ processNewMatch( qe, newMatches[j], i, addedLemmas );
+ }
+ }
+ return addedLemmas;
+}
+
+void InstMatchGeneratorMulti::processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas ){
+ //see if these produce new matches
+ d_children_trie[fromChildIndex].addInstMatch( qe, d_f, m, true );
+ //possibly only do the following if we know that new matches will be produced?
+ //the issue is that instantiations are filtered in quantifiers engine, and so there is no guarentee that
+ // we can safely skip the following lines, even when we have already produced this match.
+ Debug("smart-multi-trigger") << "Child " << fromChildIndex << " produced match " << m << std::endl;
+ //process new instantiations
+ int childIndex = (fromChildIndex+1)%(int)d_children.size();
+ std::vector< IndexedTrie > unique_var_tries;
+ processNewInstantiations( qe, m, addedLemmas, d_children_trie[childIndex].getTrie(),
+ unique_var_tries, 0, childIndex, fromChildIndex, true );
+}
+
+void InstMatchGeneratorMulti::processNewInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
+ std::vector< IndexedTrie >& unique_var_tries,
+ int trieIndex, int childIndex, int endChildIndex, bool modEq ){
+ if( childIndex==endChildIndex ){
+ //now, process unique variables
+ processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, 0 );
+ }else if( trieIndex<(int)d_children_trie[childIndex].getOrdering()->d_order.size() ){
+ int curr_index = d_children_trie[childIndex].getOrdering()->d_order[trieIndex];
+ Node curr_ic = qe->getTermDatabase()->getInstantiationConstant( d_f, curr_index );
+ if( m.find( curr_ic )==m.end() ){
+ //if( d_var_to_node[ curr_index ].size()==1 ){ //FIXME
+ // //unique variable(s), defer calculation
+ // unique_var_tries.push_back( IndexedTrie( std::pair< int, int >( childIndex, trieIndex ), tr ) );
+ // int newChildIndex = (childIndex+1)%(int)d_children.size();
+ // processNewInstantiations( qe, m, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
+ // 0, newChildIndex, endChildIndex, modEq );
+ //}else{
+ //shared and non-set variable, add to InstMatch
+ for( std::map< Node, InstMatchTrie >::iterator it = tr->d_data.begin(); it != tr->d_data.end(); ++it ){
+ InstMatch mn( &m );
+ mn.set( curr_ic, it->first);
+ processNewInstantiations( qe, mn, addedLemmas, &(it->second), unique_var_tries,
+ trieIndex+1, childIndex, endChildIndex, modEq );
+ }
+ //}
+ }else{
+ //shared and set variable, try to merge
+ Node n = m.get( curr_ic );
+ std::map< Node, InstMatchTrie >::iterator it = tr->d_data.find( n );
+ if( it!=tr->d_data.end() ){
+ processNewInstantiations( qe, m, addedLemmas, &(it->second), unique_var_tries,
+ trieIndex+1, childIndex, endChildIndex, modEq );
+ }
+ if( modEq ){
+ //check modulo equality for other possible instantiations
+ if( qe->getEqualityQuery()->getEngine()->hasTerm( n ) ){
+ eq::EqClassIterator eqc( qe->getEqualityQuery()->getEngine()->getRepresentative( n ),
+ qe->getEqualityQuery()->getEngine() );
+ while( !eqc.isFinished() ){
+ Node en = (*eqc);
+ if( en!=n ){
+ std::map< Node, InstMatchTrie >::iterator itc = tr->d_data.find( en );
+ if( itc!=tr->d_data.end() ){
+ processNewInstantiations( qe, m, addedLemmas, &(itc->second), unique_var_tries,
+ trieIndex+1, childIndex, endChildIndex, modEq );
+ }
+ }
+ ++eqc;
+ }
+ }
+ }
+ }
+ }else{
+ int newChildIndex = (childIndex+1)%(int)d_children.size();
+ processNewInstantiations( qe, m, addedLemmas, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
+ 0, newChildIndex, endChildIndex, modEq );
+ }
+}
+
+void InstMatchGeneratorMulti::processNewInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
+ std::vector< IndexedTrie >& unique_var_tries,
+ int uvtIndex, InstMatchTrie* tr, int trieIndex ){
+ if( uvtIndex<(int)unique_var_tries.size() ){
+ int childIndex = unique_var_tries[uvtIndex].first.first;
+ if( !tr ){
+ tr = unique_var_tries[uvtIndex].second;
+ trieIndex = unique_var_tries[uvtIndex].first.second;
+ }
+ if( trieIndex<(int)d_children_trie[childIndex].getOrdering()->d_order.size() ){
+ int curr_index = d_children_trie[childIndex].getOrdering()->d_order[trieIndex];
+ Node curr_ic = qe->getTermDatabase()->getInstantiationConstant( d_f, curr_index );
+ //unique non-set variable, add to InstMatch
+ for( std::map< Node, InstMatchTrie >::iterator it = tr->d_data.begin(); it != tr->d_data.end(); ++it ){
+ InstMatch mn( &m );
+ mn.set( curr_ic, it->first);
+ processNewInstantiations2( qe, mn, addedLemmas, unique_var_tries, uvtIndex, &(it->second), trieIndex+1 );
+ }
+ }else{
+ processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, uvtIndex+1 );
+ }
+ }else{
+ //m is an instantiation
+ if( qe->addInstantiation( d_f, m ) ){
+ addedLemmas++;
+ Debug("smart-multi-trigger") << "-> Produced instantiation " << m << std::endl;
+ }
+ }
+}
+
+int InstMatchGeneratorMulti::addTerm( Node f, Node t, QuantifiersEngine* qe ){
+ Assert( options::eagerInstQuant() );
+ int addedLemmas = 0;
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ if( ((InstMatchGenerator*)d_children[i])->d_match_pattern.getOperator()==t.getOperator() ){
+ InstMatch m;
+ //if it produces a match, then process it with the rest
+ if( ((InstMatchGenerator*)d_children[i])->getMatch( f, t, m, qe ) ){
+ processNewMatch( qe, m, i, addedLemmas );
+ }
+ }
+ }
+ return addedLemmas;
+}
+
+int InstMatchGeneratorSimple::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
+ InstMatch m;
+ m.add( baseMatch );
+ int addedLemmas = 0;
+ if( d_match_pattern.getType()==NodeManager::currentNM()->booleanType() ){
+ for( int i=0; i<2; i++ ){
+ addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_pred_map_trie[i][ d_match_pattern.getOperator() ]) );
+ }
+ }else{
+ addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_func_map_trie[ d_match_pattern.getOperator() ]) );
+ }
+ return addedLemmas;
+}
+
+void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex, quantifiers::TermArgTrie* tat ){
+ if( argIndex==(int)d_match_pattern.getNumChildren() ){
+ //m is an instantiation
+ if( qe->addInstantiation( d_f, m ) ){
+ addedLemmas++;
+ Debug("simple-multi-trigger") << "-> Produced instantiation " << m << std::endl;
+ }
+ }else{
+ if( d_match_pattern[argIndex].getKind()==INST_CONSTANT ){
+ Node ic = d_match_pattern[argIndex];
+ for( std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
+ Node t = it->first;
+ if( ( m.get( ic ).isNull() || m.get( ic )==t ) && ic.getType()==t.getType() ){
+ Node prev = m.get( ic );
+ m.set( ic, t);
+ addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
+ m.set( ic, prev);
+ }
+ }
+ }else{
+ Node r = qe->getEqualityQuery()->getRepresentative( d_match_pattern[argIndex] );
+ std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.find( r );
+ if( it!=tat->d_data.end() ){
+ addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
+ }
+ }
+ }
+}
+
+int InstMatchGeneratorSimple::addTerm( Node f, Node t, QuantifiersEngine* qe ){
+ Assert( options::eagerInstQuant() );
+ InstMatch m;
+ for( int i=0; i<(int)t.getNumChildren(); i++ ){
+ if( d_match_pattern[i].getKind()==INST_CONSTANT ){
+ m.set(d_match_pattern[i], t[i]);
+ }else if( !qe->getEqualityQuery()->areEqual( d_match_pattern[i], t[i] ) ){
+ return 0;
+ }
+ }
+ return qe->addInstantiation( f, m ) ? 1 : 0;
+}
+
+}/* CVC4::theory::inst namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
-/********************* */\r
-/*! \file inst_match_generator.h\r
- ** \verbatim\r
- ** Original author: ajreynol\r
- ** Major contributors: bobot\r
- ** Minor contributors (to current version): mdeters\r
- ** This file is part of the CVC4 prototype.\r
- ** Copyright (c) 2009-2012 New York University and The University of Iowa\r
- ** See the file COPYING in the top-level source directory for licensing\r
- ** information.\endverbatim\r
- **\r
- ** \brief inst match generator class\r
- **/\r
-\r
-#include "cvc4_private.h"\r
-\r
-#ifndef __CVC4__THEORY__QUANTIFIERS__INST_MATCH_GENERATOR_H\r
-#define __CVC4__THEORY__QUANTIFIERS__INST_MATCH_GENERATOR_H\r
-\r
-#include "theory/quantifiers/inst_match.h"\r
-#include <map>\r
-\r
-namespace CVC4 {\r
-namespace theory {\r
-\r
-class QuantifiersEngine;\r
-namespace quantifiers{\r
- class TermArgTrie;\r
-}\r
-\r
-namespace inst {\r
-\r
-/** base class for producing InstMatch objects */\r
-class IMGenerator {\r
-public:\r
- /** reset instantiation round (call this at beginning of instantiation round) */\r
- virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;\r
- /** reset, eqc is the equivalence class to search in (any if eqc=null) */\r
- virtual void reset( Node eqc, QuantifiersEngine* qe ) = 0;\r
- /** get the next match. must call reset( eqc ) before this function. */\r
- virtual bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ) = 0;\r
- /** add instantiations directly */\r
- virtual int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ) = 0;\r
- /** add ground term t, called when t is added to term db */\r
- virtual int addTerm( Node f, Node t, QuantifiersEngine* qe ) = 0;\r
- /** set active add */\r
- virtual void setActiveAdd() {}\r
-};/* class IMGenerator */\r
-\r
-class CandidateGenerator;\r
-\r
-class InstMatchGenerator : public IMGenerator {\r
-private:\r
- /** candidate generator */\r
- CandidateGenerator* d_cg;\r
- /** policy to use for matching */\r
- int d_matchPolicy;\r
- /** children generators */\r
- std::vector< InstMatchGenerator* > d_children;\r
- std::vector< int > d_children_index;\r
- /** partial vector */\r
- std::vector< InstMatch > d_partial;\r
- /** eq class */\r
- Node d_eq_class;\r
- /** for arithmetic matching */\r
- std::map< Node, Node > d_arith_coeffs;\r
- /** initialize pattern */\r
- void initializePatterns( std::vector< Node >& pats, QuantifiersEngine* qe );\r
- void initializePattern( Node pat, QuantifiersEngine* qe );\r
-public:\r
- enum {\r
- //options for producing matches\r
- MATCH_GEN_DEFAULT = 0,\r
- MATCH_GEN_EFFICIENT_E_MATCH, //generate matches via Efficient E-matching for SMT solvers\r
- //others (internally used)\r
- MATCH_GEN_INTERNAL_ARITHMETIC,\r
- MATCH_GEN_INTERNAL_ERROR,\r
- };\r
-private:\r
- /** get the next match. must call d_cg->reset( ... ) before using.\r
- only valid for use where !d_match_pattern.isNull().\r
- */\r
- bool getNextMatch2( Node f, InstMatch& m, QuantifiersEngine* qe, bool saveMatched = false );\r
- /** for arithmetic */\r
- bool getMatchArithmetic( Node t, InstMatch& m, QuantifiersEngine* qe );\r
-public:\r
- /** get the match against ground term or formula t.\r
- d_match_pattern and t should have the same shape.\r
- only valid for use where !d_match_pattern.isNull().\r
- */\r
- bool getMatch( Node f, Node t, InstMatch& m, QuantifiersEngine* qe );\r
-\r
- /** constructors */\r
- InstMatchGenerator( Node pat, QuantifiersEngine* qe, int matchOption = 0 );\r
- InstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption = 0 );\r
- /** destructor */\r
- ~InstMatchGenerator(){}\r
- /** The pattern we are producing matches for.\r
- If null, this is a multi trigger that is merging matches from d_children.\r
- */\r
- Node d_pattern;\r
- /** match pattern */\r
- Node d_match_pattern;\r
-public:\r
- /** reset instantiation round (call this whenever equivalence classes have changed) */\r
- void resetInstantiationRound( QuantifiersEngine* qe );\r
- /** reset, eqc is the equivalence class to search in (any if eqc=null) */\r
- void reset( Node eqc, QuantifiersEngine* qe );\r
- /** get the next match. must call reset( eqc ) before this function. */\r
- bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe );\r
- /** add instantiations */\r
- int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );\r
- /** add ground term t */\r
- int addTerm( Node f, Node t, QuantifiersEngine* qe );\r
-\r
- bool d_active_add;\r
- void setActiveAdd();\r
-};/* class InstMatchGenerator */\r
-\r
-/** smart multi-trigger implementation */\r
-class InstMatchGeneratorMulti : public IMGenerator {\r
-private:\r
- /** indexed trie */\r
- typedef std::pair< std::pair< int, int >, InstMatchTrie* > IndexedTrie;\r
- /** process new match */\r
- void processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas );\r
- /** process new instantiations */\r
- void processNewInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,\r
- std::vector< IndexedTrie >& unique_var_tries,\r
- int trieIndex, int childIndex, int endChildIndex, bool modEq );\r
- /** process new instantiations 2 */\r
- void processNewInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,\r
- std::vector< IndexedTrie >& unique_var_tries,\r
- int uvtIndex, InstMatchTrie* tr = NULL, int trieIndex = 0 );\r
-private:\r
- /** var contains (variable indices) for each pattern node */\r
- std::map< Node, std::vector< int > > d_var_contains;\r
- /** variable indices contained to pattern nodes */\r
- std::map< int, std::vector< Node > > d_var_to_node;\r
- /** quantifier to use */\r
- Node d_f;\r
- /** policy to use for matching */\r
- int d_matchPolicy;\r
- /** children generators */\r
- std::vector< InstMatchGenerator* > d_children;\r
- /** inst match tries for each child */\r
- std::vector< InstMatchTrieOrdered > d_children_trie;\r
- /** calculate matches */\r
- void calculateMatches( QuantifiersEngine* qe );\r
-public:\r
- /** constructors */\r
- InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption = 0 );\r
- /** destructor */\r
- ~InstMatchGeneratorMulti(){}\r
- /** reset instantiation round (call this whenever equivalence classes have changed) */\r
- void resetInstantiationRound( QuantifiersEngine* qe );\r
- /** reset, eqc is the equivalence class to search in (any if eqc=null) */\r
- void reset( Node eqc, QuantifiersEngine* qe );\r
- /** get the next match. must call reset( eqc ) before this function. (not implemented) */\r
- bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ) { return false; }\r
- /** add instantiations */\r
- int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );\r
- /** add ground term t */\r
- int addTerm( Node f, Node t, QuantifiersEngine* qe );\r
-};/* class InstMatchGeneratorMulti */\r
-\r
-/** smart (single)-trigger implementation */\r
-class InstMatchGeneratorSimple : public IMGenerator {\r
-private:\r
- /** quantifier for match term */\r
- Node d_f;\r
- /** match term */\r
- Node d_match_pattern;\r
- /** add instantiations */\r
- void addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex, quantifiers::TermArgTrie* tat );\r
-public:\r
- /** constructors */\r
- InstMatchGeneratorSimple( Node f, Node pat ) : d_f( f ), d_match_pattern( pat ){}\r
- /** destructor */\r
- ~InstMatchGeneratorSimple(){}\r
- /** reset instantiation round (call this whenever equivalence classes have changed) */\r
- void resetInstantiationRound( QuantifiersEngine* qe ) {}\r
- /** reset, eqc is the equivalence class to search in (any if eqc=null) */\r
- void reset( Node eqc, QuantifiersEngine* qe ) {}\r
- /** get the next match. must call reset( eqc ) before this function. (not implemented) */\r
- bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ) { return false; }\r
- /** add instantiations */\r
- int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );\r
- /** add ground term t, possibly add instantiations */\r
- int addTerm( Node f, Node t, QuantifiersEngine* qe );\r
-};/* class InstMatchGeneratorSimple */\r
-\r
-}\r
-}\r
-}\r
-\r
-#endif\r
+/********************* */
+/*! \file inst_match_generator.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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 inst match generator class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANTIFIERS__INST_MATCH_GENERATOR_H
+#define __CVC4__THEORY__QUANTIFIERS__INST_MATCH_GENERATOR_H
+
+#include "theory/quantifiers/inst_match.h"
+#include <map>
+
+namespace CVC4 {
+namespace theory {
+
+class QuantifiersEngine;
+namespace quantifiers{
+ class TermArgTrie;
+}
+
+namespace inst {
+
+/** base class for producing InstMatch objects */
+class IMGenerator {
+public:
+ /** reset instantiation round (call this at beginning of instantiation round) */
+ virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
+ /** reset, eqc is the equivalence class to search in (any if eqc=null) */
+ virtual void reset( Node eqc, QuantifiersEngine* qe ) = 0;
+ /** get the next match. must call reset( eqc ) before this function. */
+ virtual bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ) = 0;
+ /** add instantiations directly */
+ virtual int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ) = 0;
+ /** add ground term t, called when t is added to term db */
+ virtual int addTerm( Node f, Node t, QuantifiersEngine* qe ) = 0;
+ /** set active add */
+ virtual void setActiveAdd() {}
+};/* class IMGenerator */
+
+class CandidateGenerator;
+
+class InstMatchGenerator : public IMGenerator {
+private:
+ /** candidate generator */
+ CandidateGenerator* d_cg;
+ /** policy to use for matching */
+ int d_matchPolicy;
+ /** children generators */
+ std::vector< InstMatchGenerator* > d_children;
+ std::vector< int > d_children_index;
+ /** partial vector */
+ std::vector< InstMatch > d_partial;
+ /** eq class */
+ Node d_eq_class;
+ /** for arithmetic matching */
+ std::map< Node, Node > d_arith_coeffs;
+ /** initialize pattern */
+ void initializePatterns( std::vector< Node >& pats, QuantifiersEngine* qe );
+ void initializePattern( Node pat, QuantifiersEngine* qe );
+public:
+ enum {
+ //options for producing matches
+ MATCH_GEN_DEFAULT = 0,
+ MATCH_GEN_EFFICIENT_E_MATCH, //generate matches via Efficient E-matching for SMT solvers
+ //others (internally used)
+ MATCH_GEN_INTERNAL_ARITHMETIC,
+ MATCH_GEN_INTERNAL_ERROR,
+ };
+private:
+ /** get the next match. must call d_cg->reset( ... ) before using.
+ only valid for use where !d_match_pattern.isNull().
+ */
+ bool getNextMatch2( Node f, InstMatch& m, QuantifiersEngine* qe, bool saveMatched = false );
+ /** for arithmetic */
+ bool getMatchArithmetic( Node t, InstMatch& m, QuantifiersEngine* qe );
+public:
+ /** get the match against ground term or formula t.
+ d_match_pattern and t should have the same shape.
+ only valid for use where !d_match_pattern.isNull().
+ */
+ bool getMatch( Node f, Node t, InstMatch& m, QuantifiersEngine* qe );
+
+ /** constructors */
+ InstMatchGenerator( Node pat, QuantifiersEngine* qe, int matchOption = 0 );
+ InstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption = 0 );
+ /** destructor */
+ ~InstMatchGenerator(){}
+ /** The pattern we are producing matches for.
+ If null, this is a multi trigger that is merging matches from d_children.
+ */
+ Node d_pattern;
+ /** match pattern */
+ Node d_match_pattern;
+public:
+ /** reset instantiation round (call this whenever equivalence classes have changed) */
+ void resetInstantiationRound( QuantifiersEngine* qe );
+ /** reset, eqc is the equivalence class to search in (any if eqc=null) */
+ void reset( Node eqc, QuantifiersEngine* qe );
+ /** get the next match. must call reset( eqc ) before this function. */
+ bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe );
+ /** add instantiations */
+ int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
+ /** add ground term t */
+ int addTerm( Node f, Node t, QuantifiersEngine* qe );
+
+ bool d_active_add;
+ void setActiveAdd();
+};/* class InstMatchGenerator */
+
+/** smart multi-trigger implementation */
+class InstMatchGeneratorMulti : public IMGenerator {
+private:
+ /** indexed trie */
+ typedef std::pair< std::pair< int, int >, InstMatchTrie* > IndexedTrie;
+ /** process new match */
+ void processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas );
+ /** process new instantiations */
+ void processNewInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
+ std::vector< IndexedTrie >& unique_var_tries,
+ int trieIndex, int childIndex, int endChildIndex, bool modEq );
+ /** process new instantiations 2 */
+ void processNewInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
+ std::vector< IndexedTrie >& unique_var_tries,
+ int uvtIndex, InstMatchTrie* tr = NULL, int trieIndex = 0 );
+private:
+ /** var contains (variable indices) for each pattern node */
+ std::map< Node, std::vector< int > > d_var_contains;
+ /** variable indices contained to pattern nodes */
+ std::map< int, std::vector< Node > > d_var_to_node;
+ /** quantifier to use */
+ Node d_f;
+ /** policy to use for matching */
+ int d_matchPolicy;
+ /** children generators */
+ std::vector< InstMatchGenerator* > d_children;
+ /** inst match tries for each child */
+ std::vector< InstMatchTrieOrdered > d_children_trie;
+ /** calculate matches */
+ void calculateMatches( QuantifiersEngine* qe );
+public:
+ /** constructors */
+ InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption = 0 );
+ /** destructor */
+ ~InstMatchGeneratorMulti(){}
+ /** reset instantiation round (call this whenever equivalence classes have changed) */
+ void resetInstantiationRound( QuantifiersEngine* qe );
+ /** reset, eqc is the equivalence class to search in (any if eqc=null) */
+ void reset( Node eqc, QuantifiersEngine* qe );
+ /** get the next match. must call reset( eqc ) before this function. (not implemented) */
+ bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ) { return false; }
+ /** add instantiations */
+ int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
+ /** add ground term t */
+ int addTerm( Node f, Node t, QuantifiersEngine* qe );
+};/* class InstMatchGeneratorMulti */
+
+/** smart (single)-trigger implementation */
+class InstMatchGeneratorSimple : public IMGenerator {
+private:
+ /** quantifier for match term */
+ Node d_f;
+ /** match term */
+ Node d_match_pattern;
+ /** add instantiations */
+ void addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex, quantifiers::TermArgTrie* tat );
+public:
+ /** constructors */
+ InstMatchGeneratorSimple( Node f, Node pat ) : d_f( f ), d_match_pattern( pat ){}
+ /** destructor */
+ ~InstMatchGeneratorSimple(){}
+ /** reset instantiation round (call this whenever equivalence classes have changed) */
+ void resetInstantiationRound( QuantifiersEngine* qe ) {}
+ /** reset, eqc is the equivalence class to search in (any if eqc=null) */
+ void reset( Node eqc, QuantifiersEngine* qe ) {}
+ /** get the next match. must call reset( eqc ) before this function. (not implemented) */
+ bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ) { return false; }
+ /** add instantiations */
+ int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
+ /** add ground term t, possibly add instantiations */
+ int addTerm( Node f, Node t, QuantifiersEngine* qe );
+};/* class InstMatchGeneratorSimple */
+
+}
+}
+}
+
+#endif
-/********************* */\r
-/*! \file inst_strategy_cbqi.cpp\r
- ** \verbatim\r
- ** Original author: ajreynol\r
- ** Major contributors: none\r
- ** Minor contributors (to current version): bobot, mdeters\r
- ** This file is part of the CVC4 prototype.\r
- ** Copyright (c) 2009-2012 New York University and The University of Iowa\r
- ** See the file COPYING in the top-level source directory for licensing\r
- ** information.\endverbatim\r
- **\r
- ** \brief Implementation of cbqi instantiation strategies\r
- **/\r
-\r
-#include "theory/quantifiers/inst_strategy_cbqi.h"\r
-#include "theory/arith/theory_arith.h"\r
-#include "theory/theory_engine.h"\r
-#include "theory/quantifiers/options.h"\r
-#include "theory/quantifiers/term_database.h"\r
-\r
-using namespace std;\r
-using namespace CVC4;\r
-using namespace CVC4::kind;\r
-using namespace CVC4::context;\r
-using namespace CVC4::theory;\r
-using namespace CVC4::theory::quantifiers;\r
-using namespace CVC4::theory::arith;\r
-using namespace CVC4::theory::datatypes;\r
-\r
-#define ARITH_INSTANTIATOR_USE_MINUS_DELTA\r
-\r
-InstStrategySimplex::InstStrategySimplex( TheoryArith* th, QuantifiersEngine* ie ) :\r
- InstStrategy( ie ), d_th( th ), d_counter( 0 ){\r
- d_negOne = NodeManager::currentNM()->mkConst( Rational(-1) );\r
-}\r
-\r
-bool InstStrategySimplex::calculateShouldProcess( Node f ){\r
- //DO_THIS\r
- return false;\r
-}\r
-\r
-void InstStrategySimplex::processResetInstantiationRound( Theory::Effort effort ){\r
- Debug("quant-arith") << "Setting up simplex for instantiator... " << std::endl;\r
- d_instRows.clear();\r
- d_tableaux_term.clear();\r
- d_tableaux.clear();\r
- d_ceTableaux.clear();\r
- //search for instantiation rows in simplex tableaux\r
- ArithVarNodeMap& avnm = d_th->d_arithvarNodeMap;\r
- ArithVarNodeMap::var_iterator vi, vend;\r
- for(vi = avnm.var_begin(), vend = avnm.var_end(); vi != vend; ++vi ){\r
- ArithVar x = *vi;\r
- if( d_th->d_partialModel.hasEitherBound( x ) ){\r
- Node n = avnm.asNode(x);\r
- Node f;\r
- NodeBuilder<> t(kind::PLUS);\r
- if( n.getKind()==PLUS ){\r
- for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
- addTermToRow( x, n[i], f, t );\r
- }\r
- }else{\r
- addTermToRow( x, n, f, t );\r
- }\r
- if( f!=Node::null() ){\r
- d_instRows[f].push_back( x );\r
- //this theory has constraints from f\r
- Debug("quant-arith") << "Has constraints from " << f << std::endl;\r
- //set that we should process it\r
- d_quantActive[ f ] = true;\r
- //set tableaux term\r
- if( t.getNumChildren()==0 ){\r
- d_tableaux_term[x] = NodeManager::currentNM()->mkConst( Rational(0) );\r
- }else if( t.getNumChildren()==1 ){\r
- d_tableaux_term[x] = t.getChild( 0 );\r
- }else{\r
- d_tableaux_term[x] = t;\r
- }\r
- }\r
- }\r
- }\r
- //print debug\r
- debugPrint( "quant-arith-debug" );\r
- d_counter++;\r
-}\r
-\r
-int InstStrategySimplex::process( Node f, Theory::Effort effort, int e ){\r
- if( e<2 ){\r
- return STATUS_UNFINISHED;\r
- }else if( e==2 ){\r
- //Notice() << f << std::endl;\r
- //Notice() << "Num inst rows = " << d_th->d_instRows[f].size() << std::endl;\r
- //Notice() << "Num inst constants = " << d_quantEngine->getNumInstantiationConstants( f ) << std::endl;\r
- Debug("quant-arith-simplex") << "InstStrategySimplex check " << f << ", rows = " << d_instRows[f].size() << std::endl;\r
- for( int j=0; j<(int)d_instRows[f].size(); j++ ){\r
- ArithVar x = d_instRows[f][j];\r
- if( !d_ceTableaux[x].empty() ){\r
- Debug("quant-arith-simplex") << "Check row " << x << std::endl;\r
- //instantiation row will be A*e + B*t = beta,\r
- // where e is a vector of terms , and t is vector of ground terms.\r
- // Say one term in A*e is coeff*e_i, where e_i is an instantiation constant\r
- // We will construct the term ( beta - B*t)/coeff to use for e_i.\r
- InstMatch m;\r
- //By default, choose the first instantiation constant to be e_i.\r
- Node var = d_ceTableaux[x].begin()->first;\r
- if( var.getType().isInteger() ){\r
- std::map< Node, Node >::iterator it = d_ceTableaux[x].begin();\r
- //try to find coefficent that is +/- 1\r
- while( !var.isNull() && !d_ceTableaux[x][var].isNull() && d_ceTableaux[x][var]!=d_negOne ){\r
- ++it;\r
- if( it==d_ceTableaux[x].end() ){\r
- var = Node::null();\r
- }else{\r
- var = it->first;\r
- }\r
- }\r
- //otherwise, try one that divides all ground term coefficients? DO_THIS\r
- }\r
- if( !var.isNull() ){\r
- Debug("quant-arith-simplex") << "Instantiate with var " << var << std::endl;\r
- doInstantiation( f, d_tableaux_term[x], x, m, var );\r
- }else{\r
- Debug("quant-arith-simplex") << "Could not find var." << std::endl;\r
- }\r
- ////choose a new variable based on alternation strategy\r
- //int index = d_counter%(int)d_th->d_ceTableaux[x].size();\r
- //Node var;\r
- //for( std::map< Node, Node >::iterator it = d_th->d_ceTableaux[x].begin(); it != d_th->d_ceTableaux[x].end(); ++it ){\r
- // if( index==0 ){\r
- // var = it->first;\r
- // break;\r
- // }\r
- // index--;\r
- //}\r
- //d_th->doInstantiation( f, d_th->d_tableaux_term[x], x, &m, var );\r
- }\r
- }\r
- }\r
- return STATUS_UNKNOWN;\r
-}\r
-\r
-\r
-void InstStrategySimplex::addTermToRow( ArithVar x, Node n, Node& f, NodeBuilder<>& t ){\r
- if( n.getKind()==MULT ){\r
- if( n[1].hasAttribute(InstConstantAttribute()) ){\r
- f = n[1].getAttribute(InstConstantAttribute());\r
- if( n[1].getKind()==INST_CONSTANT ){\r
- d_ceTableaux[x][ n[1] ] = n[0];\r
- }else{\r
- d_tableaux_ce_term[x][ n[1] ] = n[0];\r
- }\r
- }else{\r
- d_tableaux[x][ n[1] ] = n[0];\r
- t << n;\r
- }\r
- }else{\r
- if( n.hasAttribute(InstConstantAttribute()) ){\r
- f = n.getAttribute(InstConstantAttribute());\r
- if( n.getKind()==INST_CONSTANT ){\r
- d_ceTableaux[x][ n ] = Node::null();\r
- }else{\r
- d_tableaux_ce_term[x][ n ] = NodeManager::currentNM()->mkConst( Rational(1) );\r
- }\r
- }else{\r
- d_tableaux[x][ n ] = NodeManager::currentNM()->mkConst( Rational(1) );\r
- t << n;\r
- }\r
- }\r
-}\r
-\r
-void InstStrategySimplex::debugPrint( const char* c ){\r
- const ArithVarNodeMap& avnm = d_th->d_arithvarNodeMap;\r
- ArithVarNodeMap::var_iterator vi, vend;\r
- for(vi = avnm.var_begin(), vend = avnm.var_end(); vi != vend; ++vi ){\r
- ArithVar x = *vi;\r
- Node n = avnm.asNode(x);\r
- //if( ((TheoryArith*)getTheory())->d_partialModel.hasEitherBound( x ) ){\r
- Debug(c) << x << " : " << n << ", bounds = ";\r
- if( d_th->d_partialModel.hasLowerBound( x ) ){\r
- Debug(c) << d_th->d_partialModel.getLowerBound( x );\r
- }else{\r
- Debug(c) << "-infty";\r
- }\r
- Debug(c) << " <= ";\r
- Debug(c) << d_th->d_partialModel.getAssignment( x );\r
- Debug(c) << " <= ";\r
- if( d_th->d_partialModel.hasUpperBound( x ) ){\r
- Debug(c) << d_th->d_partialModel.getUpperBound( x );\r
- }else{\r
- Debug(c) << "+infty";\r
- }\r
- Debug(c) << std::endl;\r
- //Debug(c) << " Term = " << d_tableaux_term[x] << std::endl;\r
- //Debug(c) << " ";\r
- //for( std::map< Node, Node >::iterator it2 = d_tableaux[x].begin(); it2 != d_tableaux[x].end(); ++it2 ){\r
- // Debug(c) << "( " << it2->first << ", " << it2->second << " ) ";\r
- //}\r
- //for( std::map< Node, Node >::iterator it2 = d_ceTableaux[x].begin(); it2 != d_ceTableaux[x].end(); ++it2 ){\r
- // Debug(c) << "(CE)( " << it2->first << ", " << it2->second << " ) ";\r
- //}\r
- //for( std::map< Node, Node >::iterator it2 = d_tableaux_ce_term[x].begin(); it2 != d_tableaux_ce_term[x].end(); ++it2 ){\r
- // Debug(c) << "(CE-term)( " << it2->first << ", " << it2->second << " ) ";\r
- //}\r
- //Debug(c) << std::endl;\r
- //}\r
- }\r
- Debug(c) << std::endl;\r
-\r
- for( int q=0; q<d_quantEngine->getNumQuantifiers(); q++ ){\r
- Node f = d_quantEngine->getQuantifier( q );\r
- Debug(c) << f << std::endl;\r
- Debug(c) << " Inst constants: ";\r
- for( int i=0; i<(int)d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){\r
- if( i>0 ){\r
- Debug( c ) << ", ";\r
- }\r
- Debug( c ) << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i );\r
- }\r
- Debug(c) << std::endl;\r
- Debug(c) << " Instantiation rows: ";\r
- for( int i=0; i<(int)d_instRows[f].size(); i++ ){\r
- if( i>0 ){\r
- Debug(c) << ", ";\r
- }\r
- Debug(c) << d_instRows[f][i];\r
- }\r
- Debug(c) << std::endl;\r
- }\r
-}\r
-\r
-//say instantiation row x for quantifier f is coeff*var + A*t[e] + term = beta,\r
-// where var is an instantiation constant from f,\r
-// t[e] is a vector of terms containing instantiation constants from f,\r
-// and term is a ground term (c1*t1 + ... + cn*tn).\r
-// We construct the term ( beta - term )/coeff to use as an instantiation for var.\r
-bool InstStrategySimplex::doInstantiation( Node f, Node term, ArithVar x, InstMatch& m, Node var ){\r
- //first try +delta\r
- if( doInstantiation2( f, term, x, m, var ) ){\r
- ++(d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_cbqi_arith);\r
- return true;\r
- }else{\r
-#ifdef ARITH_INSTANTIATOR_USE_MINUS_DELTA\r
- //otherwise try -delta\r
- if( doInstantiation2( f, term, x, m, var, true ) ){\r
- ++(d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_cbqi_arith_minus);\r
- return true;\r
- }else{\r
- return false;\r
- }\r
-#else\r
- return false;\r
-#endif\r
- }\r
-}\r
-\r
-bool InstStrategySimplex::doInstantiation2( Node f, Node term, ArithVar x, InstMatch& m, Node var, bool minus_delta ){\r
- // make term ( beta - term )/coeff\r
- Node beta = getTableauxValue( x, minus_delta );\r
- Node instVal = NodeManager::currentNM()->mkNode( MINUS, beta, term );\r
- if( !d_ceTableaux[x][var].isNull() ){\r
- if( var.getType().isInteger() ){\r
- Assert( d_ceTableaux[x][var]==NodeManager::currentNM()->mkConst( Rational(-1) ) );\r
- instVal = NodeManager::currentNM()->mkNode( MULT, d_ceTableaux[x][var], instVal );\r
- }else{\r
- Node coeff = NodeManager::currentNM()->mkConst( Rational(1) / d_ceTableaux[x][var].getConst<Rational>() );\r
- instVal = NodeManager::currentNM()->mkNode( MULT, coeff, instVal );\r
- }\r
- }\r
- instVal = Rewriter::rewrite( instVal );\r
- //use as instantiation value for var\r
- m.set(var, instVal);\r
- Debug("quant-arith") << "Add instantiation " << m << std::endl;\r
- return d_quantEngine->addInstantiation( f, m );\r
-}\r
-\r
-Node InstStrategySimplex::getTableauxValue( Node n, bool minus_delta ){\r
- if( d_th->d_arithvarNodeMap.hasArithVar(n) ){\r
- ArithVar v = d_th->d_arithvarNodeMap.asArithVar( n );\r
- return getTableauxValue( v, minus_delta );\r
- }else{\r
- return NodeManager::currentNM()->mkConst( Rational(0) );\r
- }\r
-}\r
-\r
-Node InstStrategySimplex::getTableauxValue( ArithVar v, bool minus_delta ){\r
- const Rational& delta = d_th->d_partialModel.getDelta();\r
- DeltaRational drv = d_th->d_partialModel.getAssignment( v );\r
- Rational qmodel = drv.substituteDelta( minus_delta ? -delta : delta );\r
- return mkRationalNode(qmodel);\r
-}\r
-\r
-\r
-InstStrategyDatatypesValue::InstStrategyDatatypesValue( TheoryDatatypes* th, QuantifiersEngine* qe ) :\r
- InstStrategy( qe ), d_th( th ){\r
-\r
-}\r
-\r
-bool InstStrategyDatatypesValue::calculateShouldProcess( Node f ){\r
- //DO_THIS\r
- return false;\r
-}\r
-\r
-void InstStrategyDatatypesValue::processResetInstantiationRound( Theory::Effort effort ){\r
-\r
-}\r
-\r
-int InstStrategyDatatypesValue::process( Node f, Theory::Effort effort, int e ){\r
- Debug("quant-datatypes") << "Datatypes: Try to solve (" << e << ") for " << f << "... " << std::endl;\r
- if( e<2 ){\r
- return InstStrategy::STATUS_UNFINISHED;\r
- }else if( e==2 ){\r
- InstMatch m;\r
- for( int j = 0; j<(int)d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); j++ ){\r
- Node i = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );\r
- if( i.getType().isDatatype() ){\r
- Node n = getValueFor( i );\r
- Debug("quant-datatypes-debug") << "Value for " << i << " is " << n << std::endl;\r
- m.set(i,n);\r
- }\r
- }\r
- //d_quantEngine->addInstantiation( f, m );\r
- }\r
- return InstStrategy::STATUS_UNKNOWN;\r
-}\r
-\r
-Node InstStrategyDatatypesValue::getValueFor( Node n ){\r
- //simply get the ground value for n in the current model, if it exists,\r
- // or return an arbitrary ground term otherwise\r
- if( !n.hasAttribute(InstConstantAttribute()) ){\r
- return n;\r
- }else{\r
- return n;\r
- }\r
- /* FIXME\r
-\r
- Debug("quant-datatypes-debug") << "get value for " << n << std::endl;\r
- if( !n.hasAttribute(InstConstantAttribute()) ){\r
- return n;\r
- }else{\r
- Assert( n.getType().isDatatype() );\r
- //check if in equivalence class with ground term\r
- Node rep = getRepresentative( n );\r
- Debug("quant-datatypes-debug") << "Rep is " << rep << std::endl;\r
- if( !rep.hasAttribute(InstConstantAttribute()) ){\r
- return rep;\r
- }else{\r
- if( !n.getType().isDatatype() ){\r
- return n.getType().mkGroundTerm();\r
- }else{\r
- if( n.getKind()==APPLY_CONSTRUCTOR ){\r
- std::vector< Node > children;\r
- children.push_back( n.getOperator() );\r
- for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
- children.push_back( getValueFor( n[i] ) );\r
- }\r
- return NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, children );\r
- }else{\r
- const Datatype& dt = ((DatatypeType)(n.getType()).toType()).getDatatype();\r
- TheoryDatatypes::EqLists* labels = &((TheoryDatatypes*)d_th)->d_labels;\r
- //otherwise, use which constructor the inst constant is current chosen to be\r
- if( labels->find( n )!=labels->end() ){\r
- TheoryDatatypes::EqList* lbl = (*labels->find( n )).second;\r
- int tIndex = -1;\r
- if( !lbl->empty() && (*lbl)[ lbl->size()-1 ].getKind()==APPLY_TESTER ){\r
- Debug("quant-datatypes-debug") << n << " tester is " << (*lbl)[ lbl->size()-1 ] << std::endl;\r
- tIndex = Datatype::indexOf((*lbl)[ lbl->size()-1 ].getOperator().toExpr());\r
- }else{\r
- Debug("quant-datatypes-debug") << "find possible tester choice" << std::endl;\r
- //must find a possible choice\r
- vector< bool > possibleCons;\r
- possibleCons.resize( dt.getNumConstructors(), true );\r
- for( TheoryDatatypes::EqList::const_iterator j = lbl->begin(); j != lbl->end(); j++ ) {\r
- Node leqn = (*j);\r
- possibleCons[ Datatype::indexOf( leqn[0].getOperator().toExpr() ) ] = false;\r
- }\r
- for( unsigned int j=0; j<possibleCons.size(); j++ ) {\r
- if( possibleCons[j] ){\r
- tIndex = j;\r
- break;\r
- }\r
- }\r
- }\r
- Assert( tIndex!=-1 );\r
- Node cons = Node::fromExpr( dt[ tIndex ].getConstructor() );\r
- Debug("quant-datatypes-debug") << n << " cons is " << cons << std::endl;\r
- std::vector< Node > children;\r
- children.push_back( cons );\r
- for( int i=0; i<(int)dt[ tIndex ].getNumArgs(); i++ ) {\r
- Node sn = NodeManager::currentNM()->mkNode( APPLY_SELECTOR, Node::fromExpr( dt[tIndex][i].getSelector() ), n );\r
- if( n.hasAttribute(InstConstantAttribute()) ){\r
- InstConstantAttribute ica;\r
- sn.setAttribute(ica,n.getAttribute(InstConstantAttribute()) );\r
- }\r
- Node snn = getValueFor( sn );\r
- children.push_back( snn );\r
- }\r
- return NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, children );\r
- }else{\r
- return n.getType().mkGroundTerm();\r
- }\r
- }\r
- }\r
- }\r
- }\r
- */\r
-}\r
+/********************* */
+/*! \file inst_strategy_cbqi.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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 Implementation of cbqi instantiation strategies
+ **/
+
+#include "theory/quantifiers/inst_strategy_cbqi.h"
+#include "theory/arith/theory_arith.h"
+#include "theory/theory_engine.h"
+#include "theory/quantifiers/options.h"
+#include "theory/quantifiers/term_database.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+using namespace CVC4::theory::arith;
+using namespace CVC4::theory::datatypes;
+
+#define ARITH_INSTANTIATOR_USE_MINUS_DELTA
+
+InstStrategySimplex::InstStrategySimplex( TheoryArith* th, QuantifiersEngine* ie ) :
+ InstStrategy( ie ), d_th( th ), d_counter( 0 ){
+ d_negOne = NodeManager::currentNM()->mkConst( Rational(-1) );
+}
+
+bool InstStrategySimplex::calculateShouldProcess( Node f ){
+ //DO_THIS
+ return false;
+}
+
+void InstStrategySimplex::processResetInstantiationRound( Theory::Effort effort ){
+ Debug("quant-arith") << "Setting up simplex for instantiator... " << std::endl;
+ d_instRows.clear();
+ d_tableaux_term.clear();
+ d_tableaux.clear();
+ d_ceTableaux.clear();
+ //search for instantiation rows in simplex tableaux
+ ArithVarNodeMap& avnm = d_th->d_arithvarNodeMap;
+ ArithVarNodeMap::var_iterator vi, vend;
+ for(vi = avnm.var_begin(), vend = avnm.var_end(); vi != vend; ++vi ){
+ ArithVar x = *vi;
+ if( d_th->d_partialModel.hasEitherBound( x ) ){
+ Node n = avnm.asNode(x);
+ Node f;
+ NodeBuilder<> t(kind::PLUS);
+ if( n.getKind()==PLUS ){
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ addTermToRow( x, n[i], f, t );
+ }
+ }else{
+ addTermToRow( x, n, f, t );
+ }
+ if( f!=Node::null() ){
+ d_instRows[f].push_back( x );
+ //this theory has constraints from f
+ Debug("quant-arith") << "Has constraints from " << f << std::endl;
+ //set that we should process it
+ d_quantActive[ f ] = true;
+ //set tableaux term
+ if( t.getNumChildren()==0 ){
+ d_tableaux_term[x] = NodeManager::currentNM()->mkConst( Rational(0) );
+ }else if( t.getNumChildren()==1 ){
+ d_tableaux_term[x] = t.getChild( 0 );
+ }else{
+ d_tableaux_term[x] = t;
+ }
+ }
+ }
+ }
+ //print debug
+ debugPrint( "quant-arith-debug" );
+ d_counter++;
+}
+
+int InstStrategySimplex::process( Node f, Theory::Effort effort, int e ){
+ if( e<2 ){
+ return STATUS_UNFINISHED;
+ }else if( e==2 ){
+ //Notice() << f << std::endl;
+ //Notice() << "Num inst rows = " << d_th->d_instRows[f].size() << std::endl;
+ //Notice() << "Num inst constants = " << d_quantEngine->getNumInstantiationConstants( f ) << std::endl;
+ Debug("quant-arith-simplex") << "InstStrategySimplex check " << f << ", rows = " << d_instRows[f].size() << std::endl;
+ for( int j=0; j<(int)d_instRows[f].size(); j++ ){
+ ArithVar x = d_instRows[f][j];
+ if( !d_ceTableaux[x].empty() ){
+ Debug("quant-arith-simplex") << "Check row " << x << std::endl;
+ //instantiation row will be A*e + B*t = beta,
+ // where e is a vector of terms , and t is vector of ground terms.
+ // Say one term in A*e is coeff*e_i, where e_i is an instantiation constant
+ // We will construct the term ( beta - B*t)/coeff to use for e_i.
+ InstMatch m;
+ //By default, choose the first instantiation constant to be e_i.
+ Node var = d_ceTableaux[x].begin()->first;
+ if( var.getType().isInteger() ){
+ std::map< Node, Node >::iterator it = d_ceTableaux[x].begin();
+ //try to find coefficent that is +/- 1
+ while( !var.isNull() && !d_ceTableaux[x][var].isNull() && d_ceTableaux[x][var]!=d_negOne ){
+ ++it;
+ if( it==d_ceTableaux[x].end() ){
+ var = Node::null();
+ }else{
+ var = it->first;
+ }
+ }
+ //otherwise, try one that divides all ground term coefficients? DO_THIS
+ }
+ if( !var.isNull() ){
+ Debug("quant-arith-simplex") << "Instantiate with var " << var << std::endl;
+ doInstantiation( f, d_tableaux_term[x], x, m, var );
+ }else{
+ Debug("quant-arith-simplex") << "Could not find var." << std::endl;
+ }
+ ////choose a new variable based on alternation strategy
+ //int index = d_counter%(int)d_th->d_ceTableaux[x].size();
+ //Node var;
+ //for( std::map< Node, Node >::iterator it = d_th->d_ceTableaux[x].begin(); it != d_th->d_ceTableaux[x].end(); ++it ){
+ // if( index==0 ){
+ // var = it->first;
+ // break;
+ // }
+ // index--;
+ //}
+ //d_th->doInstantiation( f, d_th->d_tableaux_term[x], x, &m, var );
+ }
+ }
+ }
+ return STATUS_UNKNOWN;
+}
+
+
+void InstStrategySimplex::addTermToRow( ArithVar x, Node n, Node& f, NodeBuilder<>& t ){
+ if( n.getKind()==MULT ){
+ if( n[1].hasAttribute(InstConstantAttribute()) ){
+ f = n[1].getAttribute(InstConstantAttribute());
+ if( n[1].getKind()==INST_CONSTANT ){
+ d_ceTableaux[x][ n[1] ] = n[0];
+ }else{
+ d_tableaux_ce_term[x][ n[1] ] = n[0];
+ }
+ }else{
+ d_tableaux[x][ n[1] ] = n[0];
+ t << n;
+ }
+ }else{
+ if( n.hasAttribute(InstConstantAttribute()) ){
+ f = n.getAttribute(InstConstantAttribute());
+ if( n.getKind()==INST_CONSTANT ){
+ d_ceTableaux[x][ n ] = Node::null();
+ }else{
+ d_tableaux_ce_term[x][ n ] = NodeManager::currentNM()->mkConst( Rational(1) );
+ }
+ }else{
+ d_tableaux[x][ n ] = NodeManager::currentNM()->mkConst( Rational(1) );
+ t << n;
+ }
+ }
+}
+
+void InstStrategySimplex::debugPrint( const char* c ){
+ const ArithVarNodeMap& avnm = d_th->d_arithvarNodeMap;
+ ArithVarNodeMap::var_iterator vi, vend;
+ for(vi = avnm.var_begin(), vend = avnm.var_end(); vi != vend; ++vi ){
+ ArithVar x = *vi;
+ Node n = avnm.asNode(x);
+ //if( ((TheoryArith*)getTheory())->d_partialModel.hasEitherBound( x ) ){
+ Debug(c) << x << " : " << n << ", bounds = ";
+ if( d_th->d_partialModel.hasLowerBound( x ) ){
+ Debug(c) << d_th->d_partialModel.getLowerBound( x );
+ }else{
+ Debug(c) << "-infty";
+ }
+ Debug(c) << " <= ";
+ Debug(c) << d_th->d_partialModel.getAssignment( x );
+ Debug(c) << " <= ";
+ if( d_th->d_partialModel.hasUpperBound( x ) ){
+ Debug(c) << d_th->d_partialModel.getUpperBound( x );
+ }else{
+ Debug(c) << "+infty";
+ }
+ Debug(c) << std::endl;
+ //Debug(c) << " Term = " << d_tableaux_term[x] << std::endl;
+ //Debug(c) << " ";
+ //for( std::map< Node, Node >::iterator it2 = d_tableaux[x].begin(); it2 != d_tableaux[x].end(); ++it2 ){
+ // Debug(c) << "( " << it2->first << ", " << it2->second << " ) ";
+ //}
+ //for( std::map< Node, Node >::iterator it2 = d_ceTableaux[x].begin(); it2 != d_ceTableaux[x].end(); ++it2 ){
+ // Debug(c) << "(CE)( " << it2->first << ", " << it2->second << " ) ";
+ //}
+ //for( std::map< Node, Node >::iterator it2 = d_tableaux_ce_term[x].begin(); it2 != d_tableaux_ce_term[x].end(); ++it2 ){
+ // Debug(c) << "(CE-term)( " << it2->first << ", " << it2->second << " ) ";
+ //}
+ //Debug(c) << std::endl;
+ //}
+ }
+ Debug(c) << std::endl;
+
+ for( int q=0; q<d_quantEngine->getNumQuantifiers(); q++ ){
+ Node f = d_quantEngine->getQuantifier( q );
+ Debug(c) << f << std::endl;
+ Debug(c) << " Inst constants: ";
+ for( int i=0; i<(int)d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
+ if( i>0 ){
+ Debug( c ) << ", ";
+ }
+ Debug( c ) << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i );
+ }
+ Debug(c) << std::endl;
+ Debug(c) << " Instantiation rows: ";
+ for( int i=0; i<(int)d_instRows[f].size(); i++ ){
+ if( i>0 ){
+ Debug(c) << ", ";
+ }
+ Debug(c) << d_instRows[f][i];
+ }
+ Debug(c) << std::endl;
+ }
+}
+
+//say instantiation row x for quantifier f is coeff*var + A*t[e] + term = beta,
+// where var is an instantiation constant from f,
+// t[e] is a vector of terms containing instantiation constants from f,
+// and term is a ground term (c1*t1 + ... + cn*tn).
+// We construct the term ( beta - term )/coeff to use as an instantiation for var.
+bool InstStrategySimplex::doInstantiation( Node f, Node term, ArithVar x, InstMatch& m, Node var ){
+ //first try +delta
+ if( doInstantiation2( f, term, x, m, var ) ){
+ ++(d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_cbqi_arith);
+ return true;
+ }else{
+#ifdef ARITH_INSTANTIATOR_USE_MINUS_DELTA
+ //otherwise try -delta
+ if( doInstantiation2( f, term, x, m, var, true ) ){
+ ++(d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_cbqi_arith_minus);
+ return true;
+ }else{
+ return false;
+ }
+#else
+ return false;
+#endif
+ }
+}
+
+bool InstStrategySimplex::doInstantiation2( Node f, Node term, ArithVar x, InstMatch& m, Node var, bool minus_delta ){
+ // make term ( beta - term )/coeff
+ Node beta = getTableauxValue( x, minus_delta );
+ Node instVal = NodeManager::currentNM()->mkNode( MINUS, beta, term );
+ if( !d_ceTableaux[x][var].isNull() ){
+ if( var.getType().isInteger() ){
+ Assert( d_ceTableaux[x][var]==NodeManager::currentNM()->mkConst( Rational(-1) ) );
+ instVal = NodeManager::currentNM()->mkNode( MULT, d_ceTableaux[x][var], instVal );
+ }else{
+ Node coeff = NodeManager::currentNM()->mkConst( Rational(1) / d_ceTableaux[x][var].getConst<Rational>() );
+ instVal = NodeManager::currentNM()->mkNode( MULT, coeff, instVal );
+ }
+ }
+ instVal = Rewriter::rewrite( instVal );
+ //use as instantiation value for var
+ m.set(var, instVal);
+ Debug("quant-arith") << "Add instantiation " << m << std::endl;
+ return d_quantEngine->addInstantiation( f, m );
+}
+
+Node InstStrategySimplex::getTableauxValue( Node n, bool minus_delta ){
+ if( d_th->d_arithvarNodeMap.hasArithVar(n) ){
+ ArithVar v = d_th->d_arithvarNodeMap.asArithVar( n );
+ return getTableauxValue( v, minus_delta );
+ }else{
+ return NodeManager::currentNM()->mkConst( Rational(0) );
+ }
+}
+
+Node InstStrategySimplex::getTableauxValue( ArithVar v, bool minus_delta ){
+ const Rational& delta = d_th->d_partialModel.getDelta();
+ DeltaRational drv = d_th->d_partialModel.getAssignment( v );
+ Rational qmodel = drv.substituteDelta( minus_delta ? -delta : delta );
+ return mkRationalNode(qmodel);
+}
+
+
+InstStrategyDatatypesValue::InstStrategyDatatypesValue( TheoryDatatypes* th, QuantifiersEngine* qe ) :
+ InstStrategy( qe ), d_th( th ){
+
+}
+
+bool InstStrategyDatatypesValue::calculateShouldProcess( Node f ){
+ //DO_THIS
+ return false;
+}
+
+void InstStrategyDatatypesValue::processResetInstantiationRound( Theory::Effort effort ){
+
+}
+
+int InstStrategyDatatypesValue::process( Node f, Theory::Effort effort, int e ){
+ Debug("quant-datatypes") << "Datatypes: Try to solve (" << e << ") for " << f << "... " << std::endl;
+ if( e<2 ){
+ return InstStrategy::STATUS_UNFINISHED;
+ }else if( e==2 ){
+ InstMatch m;
+ for( int j = 0; j<(int)d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); j++ ){
+ Node i = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );
+ if( i.getType().isDatatype() ){
+ Node n = getValueFor( i );
+ Debug("quant-datatypes-debug") << "Value for " << i << " is " << n << std::endl;
+ m.set(i,n);
+ }
+ }
+ //d_quantEngine->addInstantiation( f, m );
+ }
+ return InstStrategy::STATUS_UNKNOWN;
+}
+
+Node InstStrategyDatatypesValue::getValueFor( Node n ){
+ //simply get the ground value for n in the current model, if it exists,
+ // or return an arbitrary ground term otherwise
+ if( !n.hasAttribute(InstConstantAttribute()) ){
+ return n;
+ }else{
+ return n;
+ }
+ /* FIXME
+
+ Debug("quant-datatypes-debug") << "get value for " << n << std::endl;
+ if( !n.hasAttribute(InstConstantAttribute()) ){
+ return n;
+ }else{
+ Assert( n.getType().isDatatype() );
+ //check if in equivalence class with ground term
+ Node rep = getRepresentative( n );
+ Debug("quant-datatypes-debug") << "Rep is " << rep << std::endl;
+ if( !rep.hasAttribute(InstConstantAttribute()) ){
+ return rep;
+ }else{
+ if( !n.getType().isDatatype() ){
+ return n.getType().mkGroundTerm();
+ }else{
+ if( n.getKind()==APPLY_CONSTRUCTOR ){
+ std::vector< Node > children;
+ children.push_back( n.getOperator() );
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ children.push_back( getValueFor( n[i] ) );
+ }
+ return NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, children );
+ }else{
+ const Datatype& dt = ((DatatypeType)(n.getType()).toType()).getDatatype();
+ TheoryDatatypes::EqLists* labels = &((TheoryDatatypes*)d_th)->d_labels;
+ //otherwise, use which constructor the inst constant is current chosen to be
+ if( labels->find( n )!=labels->end() ){
+ TheoryDatatypes::EqList* lbl = (*labels->find( n )).second;
+ int tIndex = -1;
+ if( !lbl->empty() && (*lbl)[ lbl->size()-1 ].getKind()==APPLY_TESTER ){
+ Debug("quant-datatypes-debug") << n << " tester is " << (*lbl)[ lbl->size()-1 ] << std::endl;
+ tIndex = Datatype::indexOf((*lbl)[ lbl->size()-1 ].getOperator().toExpr());
+ }else{
+ Debug("quant-datatypes-debug") << "find possible tester choice" << std::endl;
+ //must find a possible choice
+ vector< bool > possibleCons;
+ possibleCons.resize( dt.getNumConstructors(), true );
+ for( TheoryDatatypes::EqList::const_iterator j = lbl->begin(); j != lbl->end(); j++ ) {
+ Node leqn = (*j);
+ possibleCons[ Datatype::indexOf( leqn[0].getOperator().toExpr() ) ] = false;
+ }
+ for( unsigned int j=0; j<possibleCons.size(); j++ ) {
+ if( possibleCons[j] ){
+ tIndex = j;
+ break;
+ }
+ }
+ }
+ Assert( tIndex!=-1 );
+ Node cons = Node::fromExpr( dt[ tIndex ].getConstructor() );
+ Debug("quant-datatypes-debug") << n << " cons is " << cons << std::endl;
+ std::vector< Node > children;
+ children.push_back( cons );
+ for( int i=0; i<(int)dt[ tIndex ].getNumArgs(); i++ ) {
+ Node sn = NodeManager::currentNM()->mkNode( APPLY_SELECTOR, Node::fromExpr( dt[tIndex][i].getSelector() ), n );
+ if( n.hasAttribute(InstConstantAttribute()) ){
+ InstConstantAttribute ica;
+ sn.setAttribute(ica,n.getAttribute(InstConstantAttribute()) );
+ }
+ Node snn = getValueFor( sn );
+ children.push_back( snn );
+ }
+ return NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, children );
+ }else{
+ return n.getType().mkGroundTerm();
+ }
+ }
+ }
+ }
+ }
+ */
+}
-/********************* */\r
-/*! \file inst_strategy_cbqi.h\r
- ** \verbatim\r
- ** Original author: ajreynol\r
- ** Major contributors: none\r
- ** Minor contributors (to current version): mdeters\r
- ** This file is part of the CVC4 prototype.\r
- ** Copyright (c) 2009-2012 New York University and The University of Iowa\r
- ** See the file COPYING in the top-level source directory for licensing\r
- ** information.\endverbatim\r
- **\r
- ** \brief instantiator_arith_instantiator\r
- **/\r
-\r
-\r
-#include "cvc4_private.h"\r
-\r
-#ifndef __CVC4__INST_STRATEGT_CBQI_H\r
-#define __CVC4__INST_STRATEGT_CBQI_H\r
-\r
-#include "theory/quantifiers/instantiation_engine.h"\r
-#include "theory/arith/arithvar_node_map.h"\r
-\r
-#include "util/statistics_registry.h"\r
-\r
-namespace CVC4 {\r
-namespace theory {\r
-\r
-namespace arith {\r
- class TheoryArith;\r
-}\r
-\r
-namespace datatypes {\r
- class TheoryDatatypes;\r
-}\r
-\r
-namespace quantifiers {\r
-\r
-\r
-class InstStrategySimplex : public InstStrategy{\r
-protected:\r
- /** calculate if we should process this quantifier */\r
- bool calculateShouldProcess( Node f );\r
-private:\r
- /** reference to theory arithmetic */\r
- arith::TheoryArith* d_th;\r
- /** delta */\r
- std::map< TypeNode, Node > d_deltas;\r
- /** for each quantifier, simplex rows */\r
- std::map< Node, std::vector< arith::ArithVar > > d_instRows;\r
- /** tableaux */\r
- std::map< arith::ArithVar, Node > d_tableaux_term;\r
- std::map< arith::ArithVar, std::map< Node, Node > > d_tableaux_ce_term;\r
- std::map< arith::ArithVar, std::map< Node, Node > > d_tableaux;\r
- /** ce tableaux */\r
- std::map< arith::ArithVar, std::map< Node, Node > > d_ceTableaux;\r
- /** get value */\r
- Node getTableauxValue( Node n, bool minus_delta = false );\r
- Node getTableauxValue( arith::ArithVar v, bool minus_delta = false );\r
- /** do instantiation */\r
- bool doInstantiation( Node f, Node term, arith::ArithVar x, InstMatch& m, Node var );\r
- bool doInstantiation2( Node f, Node term, arith::ArithVar x, InstMatch& m, Node var, bool minus_delta = false );\r
- /** add term to row */\r
- void addTermToRow( arith::ArithVar x, Node n, Node& f, NodeBuilder<>& t );\r
- /** print debug */\r
- void debugPrint( const char* c );\r
-private:\r
- /** */\r
- int d_counter;\r
- /** negative one */\r
- Node d_negOne;\r
- /** process functions */\r
- void processResetInstantiationRound( Theory::Effort effort );\r
- int process( Node f, Theory::Effort effort, int e );\r
-public:\r
- InstStrategySimplex( arith::TheoryArith* th, QuantifiersEngine* ie );\r
- ~InstStrategySimplex(){}\r
- /** identify */\r
- std::string identify() const { return std::string("Simplex"); }\r
-};\r
-\r
-\r
-class InstStrategyDatatypesValue : public InstStrategy\r
-{\r
-protected:\r
- /** calculate if we should process this quantifier */\r
- bool calculateShouldProcess( Node f );\r
-private:\r
- /** reference to theory datatypes */\r
- datatypes::TheoryDatatypes* d_th;\r
- /** get value function */\r
- Node getValueFor( Node n );\r
-public:\r
- //constructor\r
- InstStrategyDatatypesValue( datatypes::TheoryDatatypes* th, QuantifiersEngine* qe );\r
- ~InstStrategyDatatypesValue(){}\r
- /** reset instantiation */\r
- void processResetInstantiationRound( Theory::Effort effort );\r
- /** process method, returns a status */\r
- int process( Node f, Theory::Effort effort, int e );\r
- /** identify */\r
- std::string identify() const { return std::string("InstStrategyDatatypesValue"); }\r
-\r
-};/* class InstStrategy */\r
-\r
-}\r
-}\r
-}\r
-\r
+/********************* */
+/*! \file inst_strategy_cbqi.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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 instantiator_arith_instantiator
+ **/
+
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__INST_STRATEGT_CBQI_H
+#define __CVC4__INST_STRATEGT_CBQI_H
+
+#include "theory/quantifiers/instantiation_engine.h"
+#include "theory/arith/arithvar_node_map.h"
+
+#include "util/statistics_registry.h"
+
+namespace CVC4 {
+namespace theory {
+
+namespace arith {
+ class TheoryArith;
+}
+
+namespace datatypes {
+ class TheoryDatatypes;
+}
+
+namespace quantifiers {
+
+
+class InstStrategySimplex : public InstStrategy{
+protected:
+ /** calculate if we should process this quantifier */
+ bool calculateShouldProcess( Node f );
+private:
+ /** reference to theory arithmetic */
+ arith::TheoryArith* d_th;
+ /** delta */
+ std::map< TypeNode, Node > d_deltas;
+ /** for each quantifier, simplex rows */
+ std::map< Node, std::vector< arith::ArithVar > > d_instRows;
+ /** tableaux */
+ std::map< arith::ArithVar, Node > d_tableaux_term;
+ std::map< arith::ArithVar, std::map< Node, Node > > d_tableaux_ce_term;
+ std::map< arith::ArithVar, std::map< Node, Node > > d_tableaux;
+ /** ce tableaux */
+ std::map< arith::ArithVar, std::map< Node, Node > > d_ceTableaux;
+ /** get value */
+ Node getTableauxValue( Node n, bool minus_delta = false );
+ Node getTableauxValue( arith::ArithVar v, bool minus_delta = false );
+ /** do instantiation */
+ bool doInstantiation( Node f, Node term, arith::ArithVar x, InstMatch& m, Node var );
+ bool doInstantiation2( Node f, Node term, arith::ArithVar x, InstMatch& m, Node var, bool minus_delta = false );
+ /** add term to row */
+ void addTermToRow( arith::ArithVar x, Node n, Node& f, NodeBuilder<>& t );
+ /** print debug */
+ void debugPrint( const char* c );
+private:
+ /** */
+ int d_counter;
+ /** negative one */
+ Node d_negOne;
+ /** process functions */
+ void processResetInstantiationRound( Theory::Effort effort );
+ int process( Node f, Theory::Effort effort, int e );
+public:
+ InstStrategySimplex( arith::TheoryArith* th, QuantifiersEngine* ie );
+ ~InstStrategySimplex(){}
+ /** identify */
+ std::string identify() const { return std::string("Simplex"); }
+};
+
+
+class InstStrategyDatatypesValue : public InstStrategy
+{
+protected:
+ /** calculate if we should process this quantifier */
+ bool calculateShouldProcess( Node f );
+private:
+ /** reference to theory datatypes */
+ datatypes::TheoryDatatypes* d_th;
+ /** get value function */
+ Node getValueFor( Node n );
+public:
+ //constructor
+ InstStrategyDatatypesValue( datatypes::TheoryDatatypes* th, QuantifiersEngine* qe );
+ ~InstStrategyDatatypesValue(){}
+ /** reset instantiation */
+ void processResetInstantiationRound( Theory::Effort effort );
+ /** process method, returns a status */
+ int process( Node f, Theory::Effort effort, int e );
+ /** identify */
+ std::string identify() const { return std::string("InstStrategyDatatypesValue"); }
+
+};/* class InstStrategy */
+
+}
+}
+}
+
#endif
\ No newline at end of file
-/********************* */\r
-/*! \file inst_strategy_e_matching.cpp\r
- ** \verbatim\r
- ** Original author: ajreynol\r
- ** Major contributors: mdeters\r
- ** Minor contributors (to current version): bobot\r
- ** This file is part of the CVC4 prototype.\r
- ** Copyright (c) 2009-2012 New York University and The University of Iowa\r
- ** See the file COPYING in the top-level source directory for licensing\r
- ** information.\endverbatim\r
- **\r
- ** \brief Implementation of e matching instantiation strategies\r
- **/\r
-\r
-#include "theory/quantifiers/inst_strategy_e_matching.h"\r
-\r
-#include "theory/theory_engine.h"\r
-#include "theory/quantifiers/options.h"\r
-#include "theory/quantifiers/term_database.h"\r
-#include "theory/quantifiers/inst_match_generator.h"\r
-\r
-using namespace std;\r
-using namespace CVC4;\r
-using namespace CVC4::kind;\r
-using namespace CVC4::context;\r
-using namespace CVC4::theory;\r
-using namespace CVC4::theory::inst;\r
-using namespace CVC4::theory::quantifiers;\r
-\r
-//#define MULTI_TRIGGER_FULL_EFFORT_HALF\r
-#define MULTI_MULTI_TRIGGERS\r
-\r
-struct sortQuantifiersForSymbol {\r
- QuantifiersEngine* d_qe;\r
- bool operator() (Node i, Node j) {\r
- int nqfsi = d_qe->getQuantifierRelevance()->getNumQuantifiersForSymbol( i.getOperator() );\r
- int nqfsj = d_qe->getQuantifierRelevance()->getNumQuantifiersForSymbol( j.getOperator() );\r
- if( nqfsi<nqfsj ){\r
- return true;\r
- }else if( nqfsi>nqfsj ){\r
- return false;\r
- }else{\r
- return false;\r
- }\r
- }\r
-};\r
-\r
-void InstStrategyUserPatterns::processResetInstantiationRound( Theory::Effort effort ){\r
- //reset triggers\r
- for( std::map< Node, std::vector< Trigger* > >::iterator it = d_user_gen.begin(); it != d_user_gen.end(); ++it ){\r
- for( int i=0; i<(int)it->second.size(); i++ ){\r
- it->second[i]->resetInstantiationRound();\r
- it->second[i]->reset( Node::null() );\r
- }\r
- }\r
-}\r
-\r
-int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e ){\r
- if( e==0 ){\r
- return STATUS_UNFINISHED;\r
- }else if( e==1 ){\r
- d_counter[f]++;\r
- Debug("quant-uf-strategy") << "Try user-provided patterns..." << std::endl;\r
- //Notice() << "Try user-provided patterns..." << std::endl;\r
- for( int i=0; i<(int)d_user_gen[f].size(); i++ ){\r
- bool processTrigger = true;\r
- if( processTrigger ){\r
- //if( d_user_gen[f][i]->isMultiTrigger() )\r
- Trace("process-trigger") << " Process (user) " << (*d_user_gen[f][i]) << "..." << std::endl;\r
- InstMatch baseMatch;\r
- int numInst = d_user_gen[f][i]->addInstantiations( baseMatch );\r
- //if( d_user_gen[f][i]->isMultiTrigger() )\r
- Trace("process-trigger") << " Done, numInst = " << numInst << "." << std::endl;\r
- d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_user_patterns += numInst;\r
- if( d_user_gen[f][i]->isMultiTrigger() ){\r
- d_quantEngine->d_statistics.d_multi_trigger_instantiations += numInst;\r
- }\r
- //d_quantEngine->d_hasInstantiated[f] = true;\r
- }\r
- }\r
- Debug("quant-uf-strategy") << "done." << std::endl;\r
- //Notice() << "done" << std::endl;\r
- }\r
- return STATUS_UNKNOWN;\r
-}\r
-\r
-void InstStrategyUserPatterns::addUserPattern( Node f, Node pat ){\r
- //add to generators\r
- std::vector< Node > nodes;\r
- for( int i=0; i<(int)pat.getNumChildren(); i++ ){\r
- nodes.push_back( pat[i] );\r
- }\r
- if( Trigger::isUsableTrigger( nodes, f ) ){\r
- //extend to literal matching\r
- d_quantEngine->getPhaseReqTerms( f, nodes );\r
- //check match option\r
- int matchOption = options::efficientEMatching() ? InstMatchGenerator::MATCH_GEN_EFFICIENT_E_MATCH : 0;\r
- d_user_gen[f].push_back( Trigger::mkTrigger( d_quantEngine, f, nodes, matchOption, true, Trigger::TR_MAKE_NEW,\r
- options::smartTriggers() ) );\r
- }\r
-}\r
-/*\r
-InstStrategyUserPatterns::Statistics::Statistics():\r
- d_instantiations("InstStrategyUserPatterns::Instantiations", 0)\r
-{\r
- StatisticsRegistry::registerStat(&d_instantiations);\r
-}\r
-\r
-InstStrategyUserPatterns::Statistics::~Statistics(){\r
- StatisticsRegistry::unregisterStat(&d_instantiations);\r
-}\r
-*/\r
-\r
-void InstStrategyAutoGenTriggers::processResetInstantiationRound( Theory::Effort effort ){\r
- //reset triggers\r
- for( std::map< Node, std::map< Trigger*, bool > >::iterator it = d_auto_gen_trigger.begin(); it != d_auto_gen_trigger.end(); ++it ){\r
- for( std::map< Trigger*, bool >::iterator itt = it->second.begin(); itt != it->second.end(); ++itt ){\r
- itt->first->resetInstantiationRound();\r
- itt->first->reset( Node::null() );\r
- }\r
- }\r
- d_processed_trigger.clear();\r
-}\r
-\r
-int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e ){\r
- int peffort = f.getNumChildren()==3 ? 2 : 1;\r
- //int peffort = f.getNumChildren()==3 ? 2 : 1;\r
- //int peffort = 1;\r
- if( e<peffort ){\r
- return STATUS_UNFINISHED;\r
- }else{\r
- int status = STATUS_UNKNOWN;\r
- bool gen = false;\r
- if( e==peffort ){\r
- if( d_counter.find( f )==d_counter.end() ){\r
- d_counter[f] = 0;\r
- gen = true;\r
- }else{\r
- d_counter[f]++;\r
- gen = d_regenerate && d_counter[f]%d_regenerate_frequency==0;\r
- }\r
- }else{\r
- gen = true;\r
- }\r
- if( gen ){\r
- generateTriggers( f, effort, e, status );\r
- }\r
- Debug("quant-uf-strategy") << "Try auto-generated triggers... " << d_tr_strategy << " " << e << std::endl;\r
- //Notice() << "Try auto-generated triggers..." << std::endl;\r
- for( std::map< Trigger*, bool >::iterator itt = d_auto_gen_trigger[f].begin(); itt != d_auto_gen_trigger[f].end(); ++itt ){\r
- Trigger* tr = itt->first;\r
- if( tr ){\r
- bool processTrigger = itt->second;\r
- if( processTrigger && d_processed_trigger[f].find( tr )==d_processed_trigger[f].end() ){\r
- d_processed_trigger[f][tr] = true;\r
- //if( tr->isMultiTrigger() )\r
- Trace("process-trigger") << " Process " << (*tr) << "..." << std::endl;\r
- InstMatch baseMatch;\r
- int numInst = tr->addInstantiations( baseMatch );\r
- //if( tr->isMultiTrigger() )\r
- Trace("process-trigger") << " Done, numInst = " << numInst << "." << std::endl;\r
- if( d_tr_strategy==Trigger::TS_MIN_TRIGGER ){\r
- d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_auto_gen_min += numInst;\r
- }else{\r
- d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_auto_gen += numInst;\r
- }\r
- if( tr->isMultiTrigger() ){\r
- d_quantEngine->d_statistics.d_multi_trigger_instantiations += numInst;\r
- }\r
- //d_quantEngine->d_hasInstantiated[f] = true;\r
- }\r
- }\r
- }\r
- Debug("quant-uf-strategy") << "done." << std::endl;\r
- //Notice() << "done" << std::endl;\r
- return status;\r
- }\r
-}\r
-\r
-void InstStrategyAutoGenTriggers::generateTriggers( Node f, Theory::Effort effort, int e, int & status ){\r
- Trace("auto-gen-trigger-debug") << "Generate trigger for " << f << std::endl;\r
- if( d_patTerms[0].find( f )==d_patTerms[0].end() ){\r
- //determine all possible pattern terms based on trigger term selection strategy d_tr_strategy\r
- d_patTerms[0][f].clear();\r
- d_patTerms[1][f].clear();\r
- std::vector< Node > patTermsF;\r
- Trigger::collectPatTerms( d_quantEngine, f, d_quantEngine->getTermDatabase()->getInstConstantBody( f ), patTermsF, d_tr_strategy, true );\r
- Trace("auto-gen-trigger") << "Collected pat terms for " << d_quantEngine->getTermDatabase()->getInstConstantBody( f ) << std::endl;\r
- Trace("auto-gen-trigger") << " ";\r
- for( int i=0; i<(int)patTermsF.size(); i++ ){\r
- Trace("auto-gen-trigger") << patTermsF[i] << " ";\r
- }\r
- Trace("auto-gen-trigger") << std::endl;\r
- //extend to literal matching (if applicable)\r
- d_quantEngine->getPhaseReqTerms( f, patTermsF );\r
- //sort into single/multi triggers\r
- std::map< Node, std::vector< Node > > varContains;\r
- d_quantEngine->getTermDatabase()->getVarContains( f, patTermsF, varContains );\r
- for( std::map< Node, std::vector< Node > >::iterator it = varContains.begin(); it != varContains.end(); ++it ){\r
- if( it->second.size()==f[0].getNumChildren() ){\r
- d_patTerms[0][f].push_back( it->first );\r
- d_is_single_trigger[ it->first ] = true;\r
- }else{\r
- d_patTerms[1][f].push_back( it->first );\r
- d_is_single_trigger[ it->first ] = false;\r
- }\r
- }\r
- d_made_multi_trigger[f] = false;\r
- Trace("auto-gen-trigger") << "Single triggers for " << f << " : " << std::endl;\r
- Trace("auto-gen-trigger") << " ";\r
- for( int i=0; i<(int)d_patTerms[0][f].size(); i++ ){\r
- Trace("auto-gen-trigger") << d_patTerms[0][f][i] << " ";\r
- }\r
- Trace("auto-gen-trigger") << std::endl;\r
- Trace("auto-gen-trigger") << "Multi-trigger term pool for " << f << " : " << std::endl;\r
- Trace("auto-gen-trigger") << " ";\r
- for( int i=0; i<(int)d_patTerms[1][f].size(); i++ ){\r
- Trace("auto-gen-trigger") << d_patTerms[1][f][i] << " ";\r
- }\r
- Trace("auto-gen-trigger") << std::endl;\r
- }\r
-\r
- //populate candidate pattern term vector for the current trigger\r
- std::vector< Node > patTerms;\r
- //try to add single triggers first\r
- for( int i=0; i<(int)d_patTerms[0][f].size(); i++ ){\r
- if( !d_single_trigger_gen[d_patTerms[0][f][i]] ){\r
- patTerms.push_back( d_patTerms[0][f][i] );\r
- }\r
- }\r
- //if no single triggers exist, add multi trigger terms\r
- if( patTerms.empty() ){\r
- patTerms.insert( patTerms.begin(), d_patTerms[1][f].begin(), d_patTerms[1][f].end() );\r
- }\r
-\r
- if( !patTerms.empty() ){\r
- Trace("auto-gen-trigger") << "Generate trigger for " << f << std::endl;\r
- //sort terms based on relevance\r
- if( d_rlv_strategy==RELEVANCE_DEFAULT ){\r
- sortQuantifiersForSymbol sqfs;\r
- sqfs.d_qe = d_quantEngine;\r
- //sort based on # occurrences (this will cause Trigger to select rarer symbols)\r
- std::sort( patTerms.begin(), patTerms.end(), sqfs );\r
- Debug("relevant-trigger") << "Terms based on relevance: " << std::endl;\r
- for( int i=0; i<(int)patTerms.size(); i++ ){\r
- Debug("relevant-trigger") << " " << patTerms[i] << " (";\r
- Debug("relevant-trigger") << d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[i].getOperator() ) << ")" << std::endl;\r
- }\r
- //Notice() << "Terms based on relevance: " << std::endl;\r
- //for( int i=0; i<(int)patTerms.size(); i++ ){\r
- // Notice() << " " << patTerms[i] << " (";\r
- // Notice() << d_quantEngine->getNumQuantifiersForSymbol( patTerms[i].getOperator() ) << ")" << std::endl;\r
- //}\r
- }\r
- //now, generate the trigger...\r
- int matchOption = options::efficientEMatching() ? InstMatchGenerator::MATCH_GEN_EFFICIENT_E_MATCH : 0;\r
- Trigger* tr = NULL;\r
- if( d_is_single_trigger[ patTerms[0] ] ){\r
- tr = Trigger::mkTrigger( d_quantEngine, f, patTerms[0], matchOption, false, Trigger::TR_RETURN_NULL,\r
- options::smartTriggers() );\r
- d_single_trigger_gen[ patTerms[0] ] = true;\r
- }else{\r
- //only generate multi trigger if effort level > 5, or if no single triggers exist\r
- if( !d_patTerms[0][f].empty() ){\r
- if( e<=5 ){\r
- status = STATUS_UNFINISHED;\r
- return;\r
- }else{\r
- Trace("multi-trigger-debug") << "Resort to choosing multi-triggers..." << std::endl;\r
- }\r
- }\r
- //if we are re-generating triggers, shuffle based on some method\r
- if( d_made_multi_trigger[f] ){\r
-#ifndef MULTI_MULTI_TRIGGERS\r
- return;\r
-#endif\r
- std::random_shuffle( patTerms.begin(), patTerms.end() ); //shuffle randomly\r
- }else{\r
- d_made_multi_trigger[f] = true;\r
- }\r
- //will possibly want to get an old trigger\r
- tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, false, Trigger::TR_GET_OLD,\r
- options::smartTriggers() );\r
- }\r
- if( tr ){\r
- if( tr->isMultiTrigger() ){\r
- //disable all other multi triggers\r
- for( std::map< Trigger*, bool >::iterator it = d_auto_gen_trigger[f].begin(); it != d_auto_gen_trigger[f].end(); ++it ){\r
- if( it->first->isMultiTrigger() ){\r
- d_auto_gen_trigger[f][ it->first ] = false;\r
- }\r
- }\r
- }\r
- //making it during an instantiation round, so must reset\r
- if( d_auto_gen_trigger[f].find( tr )==d_auto_gen_trigger[f].end() ){\r
- tr->resetInstantiationRound();\r
- tr->reset( Node::null() );\r
- }\r
- d_auto_gen_trigger[f][tr] = true;\r
- //if we are generating additional triggers...\r
- if( d_generate_additional && d_is_single_trigger[ patTerms[0] ] ){\r
- int index = 0;\r
- if( index<(int)patTerms.size() ){\r
- //Notice() << "check add additional" << std::endl;\r
- //check if similar patterns exist, and if so, add them additionally\r
- int nqfs_curr = d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[0].getOperator() );\r
- index++;\r
- bool success = true;\r
- while( success && index<(int)patTerms.size() && d_is_single_trigger[ patTerms[index] ] ){\r
- success = false;\r
- if( d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[index].getOperator() )<=nqfs_curr ){\r
- d_single_trigger_gen[ patTerms[index] ] = true;\r
- Trigger* tr2 = Trigger::mkTrigger( d_quantEngine, f, patTerms[index], matchOption, false, Trigger::TR_RETURN_NULL,\r
- options::smartTriggers() );\r
- if( tr2 ){\r
- //Notice() << "Add additional trigger " << patTerms[index] << std::endl;\r
- tr2->resetInstantiationRound();\r
- tr2->reset( Node::null() );\r
- d_auto_gen_trigger[f][tr2] = true;\r
- }\r
- success = true;\r
- }\r
- index++;\r
- }\r
- //Notice() << "done check add additional" << std::endl;\r
- }\r
- }\r
- }\r
- }\r
-}\r
-/*\r
-InstStrategyAutoGenTriggers::Statistics::Statistics():\r
- d_instantiations("InstStrategyAutoGenTriggers::Instantiations", 0),\r
- d_instantiations_min("InstStrategyAutoGenTriggers::Instantiations_min", 0)\r
-{\r
- StatisticsRegistry::registerStat(&d_instantiations);\r
- StatisticsRegistry::registerStat(&d_instantiations_min);\r
-}\r
-\r
-InstStrategyAutoGenTriggers::Statistics::~Statistics(){\r
- StatisticsRegistry::unregisterStat(&d_instantiations);\r
- StatisticsRegistry::unregisterStat(&d_instantiations_min);\r
-}\r
-*/\r
-\r
-void InstStrategyFreeVariable::processResetInstantiationRound( Theory::Effort effort ){\r
-}\r
-\r
-int InstStrategyFreeVariable::process( Node f, Theory::Effort effort, int e ){\r
- if( e<5 ){\r
- return STATUS_UNFINISHED;\r
- }else{\r
- if( d_guessed.find( f )==d_guessed.end() ){\r
- d_guessed[f] = true;\r
- Debug("quant-uf-alg") << "Add guessed instantiation" << std::endl;\r
- InstMatch m;\r
- if( d_quantEngine->addInstantiation( f, m ) ){\r
- ++(d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_guess);\r
- //d_quantEngine->d_hasInstantiated[f] = true;\r
- }\r
- }\r
- return STATUS_UNKNOWN;\r
- }\r
-}\r
-/*\r
-InstStrategyFreeVariable::Statistics::Statistics():\r
- d_instantiations("InstStrategyGuess::Instantiations", 0)\r
-{\r
- StatisticsRegistry::registerStat(&d_instantiations);\r
-}\r
-\r
-InstStrategyFreeVariable::Statistics::~Statistics(){\r
- StatisticsRegistry::unregisterStat(&d_instantiations);\r
-}\r
-*/\r
+/********************* */
+/*! \file inst_strategy_e_matching.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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 Implementation of e matching instantiation strategies
+ **/
+
+#include "theory/quantifiers/inst_strategy_e_matching.h"
+
+#include "theory/theory_engine.h"
+#include "theory/quantifiers/options.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/inst_match_generator.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::inst;
+using namespace CVC4::theory::quantifiers;
+
+//#define MULTI_TRIGGER_FULL_EFFORT_HALF
+#define MULTI_MULTI_TRIGGERS
+
+struct sortQuantifiersForSymbol {
+ QuantifiersEngine* d_qe;
+ bool operator() (Node i, Node j) {
+ int nqfsi = d_qe->getQuantifierRelevance()->getNumQuantifiersForSymbol( i.getOperator() );
+ int nqfsj = d_qe->getQuantifierRelevance()->getNumQuantifiersForSymbol( j.getOperator() );
+ if( nqfsi<nqfsj ){
+ return true;
+ }else if( nqfsi>nqfsj ){
+ return false;
+ }else{
+ return false;
+ }
+ }
+};
+
+void InstStrategyUserPatterns::processResetInstantiationRound( Theory::Effort effort ){
+ //reset triggers
+ for( std::map< Node, std::vector< Trigger* > >::iterator it = d_user_gen.begin(); it != d_user_gen.end(); ++it ){
+ for( int i=0; i<(int)it->second.size(); i++ ){
+ it->second[i]->resetInstantiationRound();
+ it->second[i]->reset( Node::null() );
+ }
+ }
+}
+
+int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e ){
+ if( e==0 ){
+ return STATUS_UNFINISHED;
+ }else if( e==1 ){
+ d_counter[f]++;
+ Debug("quant-uf-strategy") << "Try user-provided patterns..." << std::endl;
+ //Notice() << "Try user-provided patterns..." << std::endl;
+ for( int i=0; i<(int)d_user_gen[f].size(); i++ ){
+ bool processTrigger = true;
+ if( processTrigger ){
+ //if( d_user_gen[f][i]->isMultiTrigger() )
+ Trace("process-trigger") << " Process (user) " << (*d_user_gen[f][i]) << "..." << std::endl;
+ InstMatch baseMatch;
+ int numInst = d_user_gen[f][i]->addInstantiations( baseMatch );
+ //if( d_user_gen[f][i]->isMultiTrigger() )
+ Trace("process-trigger") << " Done, numInst = " << numInst << "." << std::endl;
+ d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_user_patterns += numInst;
+ if( d_user_gen[f][i]->isMultiTrigger() ){
+ d_quantEngine->d_statistics.d_multi_trigger_instantiations += numInst;
+ }
+ //d_quantEngine->d_hasInstantiated[f] = true;
+ }
+ }
+ Debug("quant-uf-strategy") << "done." << std::endl;
+ //Notice() << "done" << std::endl;
+ }
+ return STATUS_UNKNOWN;
+}
+
+void InstStrategyUserPatterns::addUserPattern( Node f, Node pat ){
+ //add to generators
+ std::vector< Node > nodes;
+ for( int i=0; i<(int)pat.getNumChildren(); i++ ){
+ nodes.push_back( pat[i] );
+ }
+ if( Trigger::isUsableTrigger( nodes, f ) ){
+ //extend to literal matching
+ d_quantEngine->getPhaseReqTerms( f, nodes );
+ //check match option
+ int matchOption = options::efficientEMatching() ? InstMatchGenerator::MATCH_GEN_EFFICIENT_E_MATCH : 0;
+ d_user_gen[f].push_back( Trigger::mkTrigger( d_quantEngine, f, nodes, matchOption, true, Trigger::TR_MAKE_NEW,
+ options::smartTriggers() ) );
+ }
+}
+/*
+InstStrategyUserPatterns::Statistics::Statistics():
+ d_instantiations("InstStrategyUserPatterns::Instantiations", 0)
+{
+ StatisticsRegistry::registerStat(&d_instantiations);
+}
+
+InstStrategyUserPatterns::Statistics::~Statistics(){
+ StatisticsRegistry::unregisterStat(&d_instantiations);
+}
+*/
+
+void InstStrategyAutoGenTriggers::processResetInstantiationRound( Theory::Effort effort ){
+ //reset triggers
+ for( std::map< Node, std::map< Trigger*, bool > >::iterator it = d_auto_gen_trigger.begin(); it != d_auto_gen_trigger.end(); ++it ){
+ for( std::map< Trigger*, bool >::iterator itt = it->second.begin(); itt != it->second.end(); ++itt ){
+ itt->first->resetInstantiationRound();
+ itt->first->reset( Node::null() );
+ }
+ }
+ d_processed_trigger.clear();
+}
+
+int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e ){
+ int peffort = f.getNumChildren()==3 ? 2 : 1;
+ //int peffort = f.getNumChildren()==3 ? 2 : 1;
+ //int peffort = 1;
+ if( e<peffort ){
+ return STATUS_UNFINISHED;
+ }else{
+ int status = STATUS_UNKNOWN;
+ bool gen = false;
+ if( e==peffort ){
+ if( d_counter.find( f )==d_counter.end() ){
+ d_counter[f] = 0;
+ gen = true;
+ }else{
+ d_counter[f]++;
+ gen = d_regenerate && d_counter[f]%d_regenerate_frequency==0;
+ }
+ }else{
+ gen = true;
+ }
+ if( gen ){
+ generateTriggers( f, effort, e, status );
+ }
+ Debug("quant-uf-strategy") << "Try auto-generated triggers... " << d_tr_strategy << " " << e << std::endl;
+ //Notice() << "Try auto-generated triggers..." << std::endl;
+ for( std::map< Trigger*, bool >::iterator itt = d_auto_gen_trigger[f].begin(); itt != d_auto_gen_trigger[f].end(); ++itt ){
+ Trigger* tr = itt->first;
+ if( tr ){
+ bool processTrigger = itt->second;
+ if( processTrigger && d_processed_trigger[f].find( tr )==d_processed_trigger[f].end() ){
+ d_processed_trigger[f][tr] = true;
+ //if( tr->isMultiTrigger() )
+ Trace("process-trigger") << " Process " << (*tr) << "..." << std::endl;
+ InstMatch baseMatch;
+ int numInst = tr->addInstantiations( baseMatch );
+ //if( tr->isMultiTrigger() )
+ Trace("process-trigger") << " Done, numInst = " << numInst << "." << std::endl;
+ if( d_tr_strategy==Trigger::TS_MIN_TRIGGER ){
+ d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_auto_gen_min += numInst;
+ }else{
+ d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_auto_gen += numInst;
+ }
+ if( tr->isMultiTrigger() ){
+ d_quantEngine->d_statistics.d_multi_trigger_instantiations += numInst;
+ }
+ //d_quantEngine->d_hasInstantiated[f] = true;
+ }
+ }
+ }
+ Debug("quant-uf-strategy") << "done." << std::endl;
+ //Notice() << "done" << std::endl;
+ return status;
+ }
+}
+
+void InstStrategyAutoGenTriggers::generateTriggers( Node f, Theory::Effort effort, int e, int & status ){
+ Trace("auto-gen-trigger-debug") << "Generate trigger for " << f << std::endl;
+ if( d_patTerms[0].find( f )==d_patTerms[0].end() ){
+ //determine all possible pattern terms based on trigger term selection strategy d_tr_strategy
+ d_patTerms[0][f].clear();
+ d_patTerms[1][f].clear();
+ std::vector< Node > patTermsF;
+ Trigger::collectPatTerms( d_quantEngine, f, d_quantEngine->getTermDatabase()->getInstConstantBody( f ), patTermsF, d_tr_strategy, true );
+ Trace("auto-gen-trigger") << "Collected pat terms for " << d_quantEngine->getTermDatabase()->getInstConstantBody( f ) << std::endl;
+ Trace("auto-gen-trigger") << " ";
+ for( int i=0; i<(int)patTermsF.size(); i++ ){
+ Trace("auto-gen-trigger") << patTermsF[i] << " ";
+ }
+ Trace("auto-gen-trigger") << std::endl;
+ //extend to literal matching (if applicable)
+ d_quantEngine->getPhaseReqTerms( f, patTermsF );
+ //sort into single/multi triggers
+ std::map< Node, std::vector< Node > > varContains;
+ d_quantEngine->getTermDatabase()->getVarContains( f, patTermsF, varContains );
+ for( std::map< Node, std::vector< Node > >::iterator it = varContains.begin(); it != varContains.end(); ++it ){
+ if( it->second.size()==f[0].getNumChildren() ){
+ d_patTerms[0][f].push_back( it->first );
+ d_is_single_trigger[ it->first ] = true;
+ }else{
+ d_patTerms[1][f].push_back( it->first );
+ d_is_single_trigger[ it->first ] = false;
+ }
+ }
+ d_made_multi_trigger[f] = false;
+ Trace("auto-gen-trigger") << "Single triggers for " << f << " : " << std::endl;
+ Trace("auto-gen-trigger") << " ";
+ for( int i=0; i<(int)d_patTerms[0][f].size(); i++ ){
+ Trace("auto-gen-trigger") << d_patTerms[0][f][i] << " ";
+ }
+ Trace("auto-gen-trigger") << std::endl;
+ Trace("auto-gen-trigger") << "Multi-trigger term pool for " << f << " : " << std::endl;
+ Trace("auto-gen-trigger") << " ";
+ for( int i=0; i<(int)d_patTerms[1][f].size(); i++ ){
+ Trace("auto-gen-trigger") << d_patTerms[1][f][i] << " ";
+ }
+ Trace("auto-gen-trigger") << std::endl;
+ }
+
+ //populate candidate pattern term vector for the current trigger
+ std::vector< Node > patTerms;
+ //try to add single triggers first
+ for( int i=0; i<(int)d_patTerms[0][f].size(); i++ ){
+ if( !d_single_trigger_gen[d_patTerms[0][f][i]] ){
+ patTerms.push_back( d_patTerms[0][f][i] );
+ }
+ }
+ //if no single triggers exist, add multi trigger terms
+ if( patTerms.empty() ){
+ patTerms.insert( patTerms.begin(), d_patTerms[1][f].begin(), d_patTerms[1][f].end() );
+ }
+
+ if( !patTerms.empty() ){
+ Trace("auto-gen-trigger") << "Generate trigger for " << f << std::endl;
+ //sort terms based on relevance
+ if( d_rlv_strategy==RELEVANCE_DEFAULT ){
+ sortQuantifiersForSymbol sqfs;
+ sqfs.d_qe = d_quantEngine;
+ //sort based on # occurrences (this will cause Trigger to select rarer symbols)
+ std::sort( patTerms.begin(), patTerms.end(), sqfs );
+ Debug("relevant-trigger") << "Terms based on relevance: " << std::endl;
+ for( int i=0; i<(int)patTerms.size(); i++ ){
+ Debug("relevant-trigger") << " " << patTerms[i] << " (";
+ Debug("relevant-trigger") << d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[i].getOperator() ) << ")" << std::endl;
+ }
+ //Notice() << "Terms based on relevance: " << std::endl;
+ //for( int i=0; i<(int)patTerms.size(); i++ ){
+ // Notice() << " " << patTerms[i] << " (";
+ // Notice() << d_quantEngine->getNumQuantifiersForSymbol( patTerms[i].getOperator() ) << ")" << std::endl;
+ //}
+ }
+ //now, generate the trigger...
+ int matchOption = options::efficientEMatching() ? InstMatchGenerator::MATCH_GEN_EFFICIENT_E_MATCH : 0;
+ Trigger* tr = NULL;
+ if( d_is_single_trigger[ patTerms[0] ] ){
+ tr = Trigger::mkTrigger( d_quantEngine, f, patTerms[0], matchOption, false, Trigger::TR_RETURN_NULL,
+ options::smartTriggers() );
+ d_single_trigger_gen[ patTerms[0] ] = true;
+ }else{
+ //only generate multi trigger if effort level > 5, or if no single triggers exist
+ if( !d_patTerms[0][f].empty() ){
+ if( e<=5 ){
+ status = STATUS_UNFINISHED;
+ return;
+ }else{
+ Trace("multi-trigger-debug") << "Resort to choosing multi-triggers..." << std::endl;
+ }
+ }
+ //if we are re-generating triggers, shuffle based on some method
+ if( d_made_multi_trigger[f] ){
+#ifndef MULTI_MULTI_TRIGGERS
+ return;
+#endif
+ std::random_shuffle( patTerms.begin(), patTerms.end() ); //shuffle randomly
+ }else{
+ d_made_multi_trigger[f] = true;
+ }
+ //will possibly want to get an old trigger
+ tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, false, Trigger::TR_GET_OLD,
+ options::smartTriggers() );
+ }
+ if( tr ){
+ if( tr->isMultiTrigger() ){
+ //disable all other multi triggers
+ for( std::map< Trigger*, bool >::iterator it = d_auto_gen_trigger[f].begin(); it != d_auto_gen_trigger[f].end(); ++it ){
+ if( it->first->isMultiTrigger() ){
+ d_auto_gen_trigger[f][ it->first ] = false;
+ }
+ }
+ }
+ //making it during an instantiation round, so must reset
+ if( d_auto_gen_trigger[f].find( tr )==d_auto_gen_trigger[f].end() ){
+ tr->resetInstantiationRound();
+ tr->reset( Node::null() );
+ }
+ d_auto_gen_trigger[f][tr] = true;
+ //if we are generating additional triggers...
+ if( d_generate_additional && d_is_single_trigger[ patTerms[0] ] ){
+ int index = 0;
+ if( index<(int)patTerms.size() ){
+ //Notice() << "check add additional" << std::endl;
+ //check if similar patterns exist, and if so, add them additionally
+ int nqfs_curr = d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[0].getOperator() );
+ index++;
+ bool success = true;
+ while( success && index<(int)patTerms.size() && d_is_single_trigger[ patTerms[index] ] ){
+ success = false;
+ if( d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[index].getOperator() )<=nqfs_curr ){
+ d_single_trigger_gen[ patTerms[index] ] = true;
+ Trigger* tr2 = Trigger::mkTrigger( d_quantEngine, f, patTerms[index], matchOption, false, Trigger::TR_RETURN_NULL,
+ options::smartTriggers() );
+ if( tr2 ){
+ //Notice() << "Add additional trigger " << patTerms[index] << std::endl;
+ tr2->resetInstantiationRound();
+ tr2->reset( Node::null() );
+ d_auto_gen_trigger[f][tr2] = true;
+ }
+ success = true;
+ }
+ index++;
+ }
+ //Notice() << "done check add additional" << std::endl;
+ }
+ }
+ }
+ }
+}
+/*
+InstStrategyAutoGenTriggers::Statistics::Statistics():
+ d_instantiations("InstStrategyAutoGenTriggers::Instantiations", 0),
+ d_instantiations_min("InstStrategyAutoGenTriggers::Instantiations_min", 0)
+{
+ StatisticsRegistry::registerStat(&d_instantiations);
+ StatisticsRegistry::registerStat(&d_instantiations_min);
+}
+
+InstStrategyAutoGenTriggers::Statistics::~Statistics(){
+ StatisticsRegistry::unregisterStat(&d_instantiations);
+ StatisticsRegistry::unregisterStat(&d_instantiations_min);
+}
+*/
+
+void InstStrategyFreeVariable::processResetInstantiationRound( Theory::Effort effort ){
+}
+
+int InstStrategyFreeVariable::process( Node f, Theory::Effort effort, int e ){
+ if( e<5 ){
+ return STATUS_UNFINISHED;
+ }else{
+ if( d_guessed.find( f )==d_guessed.end() ){
+ d_guessed[f] = true;
+ Debug("quant-uf-alg") << "Add guessed instantiation" << std::endl;
+ InstMatch m;
+ if( d_quantEngine->addInstantiation( f, m ) ){
+ ++(d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_guess);
+ //d_quantEngine->d_hasInstantiated[f] = true;
+ }
+ }
+ return STATUS_UNKNOWN;
+ }
+}
+/*
+InstStrategyFreeVariable::Statistics::Statistics():
+ d_instantiations("InstStrategyGuess::Instantiations", 0)
+{
+ StatisticsRegistry::registerStat(&d_instantiations);
+}
+
+InstStrategyFreeVariable::Statistics::~Statistics(){
+ StatisticsRegistry::unregisterStat(&d_instantiations);
+}
+*/
-/********************* */\r
-/*! \file inst_strategy_e_matching.h\r
- ** \verbatim\r
- ** Original author: ajreynol\r
- ** Major contributors: none\r
- ** Minor contributors (to current version): bobot, mdeters\r
- ** This file is part of the CVC4 prototype.\r
- ** Copyright (c) 2009-2012 New York University and The University of Iowa\r
- ** See the file COPYING in the top-level source directory for licensing\r
- ** information.\endverbatim\r
- **\r
- ** \brief E matching instantiation strategies\r
- **/\r
-\r
-#include "cvc4_private.h"\r
-\r
-#ifndef __CVC4__INST_STRATEGY_E_MATCHING_H\r
-#define __CVC4__INST_STRATEGY_E_MATCHING_H\r
-\r
-#include "theory/quantifiers_engine.h"\r
-#include "theory/quantifiers/trigger.h"\r
-\r
-#include "context/context.h"\r
-#include "context/context_mm.h"\r
-\r
-#include "util/statistics_registry.h"\r
-#include "theory/quantifiers/instantiation_engine.h"\r
-\r
-namespace CVC4 {\r
-namespace theory {\r
-namespace quantifiers {\r
-\r
-//instantiation strategies\r
-\r
-class InstStrategyUserPatterns : public InstStrategy{\r
-private:\r
- /** explicitly provided patterns */\r
- std::map< Node, std::vector< inst::Trigger* > > d_user_gen;\r
- /** counter for quantifiers */\r
- std::map< Node, int > d_counter;\r
- /** process functions */\r
- void processResetInstantiationRound( Theory::Effort effort );\r
- int process( Node f, Theory::Effort effort, int e );\r
-public:\r
- InstStrategyUserPatterns( QuantifiersEngine* ie ) :\r
- InstStrategy( ie ){}\r
- ~InstStrategyUserPatterns(){}\r
-public:\r
- /** add pattern */\r
- void addUserPattern( Node f, Node pat );\r
- /** get num patterns */\r
- int getNumUserGenerators( Node f ) { return (int)d_user_gen[f].size(); }\r
- /** get user pattern */\r
- inst::Trigger* getUserGenerator( Node f, int i ) { return d_user_gen[f][ i ]; }\r
- /** identify */\r
- std::string identify() const { return std::string("UserPatterns"); }\r
-};/* class InstStrategyUserPatterns */\r
-\r
-class InstStrategyAutoGenTriggers : public InstStrategy{\r
-public:\r
- enum {\r
- RELEVANCE_NONE,\r
- RELEVANCE_DEFAULT,\r
- };\r
-private:\r
- /** trigger generation strategy */\r
- int d_tr_strategy;\r
- /** relevance strategy */\r
- int d_rlv_strategy;\r
- /** regeneration */\r
- bool d_regenerate;\r
- int d_regenerate_frequency;\r
- /** generate additional triggers */\r
- bool d_generate_additional;\r
- /** triggers for each quantifier */\r
- std::map< Node, std::map< inst::Trigger*, bool > > d_auto_gen_trigger;\r
- std::map< Node, int > d_counter;\r
- /** single, multi triggers for each quantifier */\r
- std::map< Node, std::vector< Node > > d_patTerms[2];\r
- std::map< Node, bool > d_is_single_trigger;\r
- std::map< Node, bool > d_single_trigger_gen;\r
- std::map< Node, bool > d_made_multi_trigger;\r
- //processed trigger this round\r
- std::map< Node, std::map< inst::Trigger*, bool > > d_processed_trigger;\r
-private:\r
- /** process functions */\r
- void processResetInstantiationRound( Theory::Effort effort );\r
- int process( Node f, Theory::Effort effort, int e );\r
- /** generate triggers */\r
- void generateTriggers( Node f, Theory::Effort effort, int e, int & status );\r
-public:\r
- /** tstrt is the type of triggers to use (maximum depth, minimum depth, or all)\r
- rstrt is the relevance setting for trigger (use only relevant triggers vs. use all)\r
- rgfr is the frequency at which triggers are generated */\r
- InstStrategyAutoGenTriggers( QuantifiersEngine* qe, int tstrt, int rstrt, int rgfr = -1 ) :\r
- InstStrategy( qe ), d_tr_strategy( tstrt ), d_rlv_strategy( rstrt ), d_generate_additional( false ){\r
- setRegenerateFrequency( rgfr );\r
- }\r
- ~InstStrategyAutoGenTriggers(){}\r
-public:\r
- /** get auto-generated trigger */\r
- inst::Trigger* getAutoGenTrigger( Node f );\r
- /** identify */\r
- std::string identify() const { return std::string("AutoGenTriggers"); }\r
- /** set regenerate frequency, if fr<0, turn off regenerate */\r
- void setRegenerateFrequency( int fr ){\r
- if( fr<0 ){\r
- d_regenerate = false;\r
- }else{\r
- d_regenerate_frequency = fr;\r
- d_regenerate = true;\r
- }\r
- }\r
- /** set generate additional */\r
- void setGenerateAdditional( bool val ) { d_generate_additional = val; }\r
-};/* class InstStrategyAutoGenTriggers */\r
-\r
-class InstStrategyFreeVariable : public InstStrategy{\r
-private:\r
- /** guessed instantiations */\r
- std::map< Node, bool > d_guessed;\r
- /** process functions */\r
- void processResetInstantiationRound( Theory::Effort effort );\r
- int process( Node f, Theory::Effort effort, int e );\r
-public:\r
- InstStrategyFreeVariable( QuantifiersEngine* qe ) :\r
- InstStrategy( qe ){}\r
- ~InstStrategyFreeVariable(){}\r
- /** identify */\r
- std::string identify() const { return std::string("FreeVariable"); }\r
-};/* class InstStrategyFreeVariable */\r
-\r
-}\r
-}/* CVC4::theory namespace */\r
-}/* CVC4 namespace */\r
-\r
-#endif\r
+/********************* */
+/*! \file inst_strategy_e_matching.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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 E matching instantiation strategies
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__INST_STRATEGY_E_MATCHING_H
+#define __CVC4__INST_STRATEGY_E_MATCHING_H
+
+#include "theory/quantifiers_engine.h"
+#include "theory/quantifiers/trigger.h"
+
+#include "context/context.h"
+#include "context/context_mm.h"
+
+#include "util/statistics_registry.h"
+#include "theory/quantifiers/instantiation_engine.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+//instantiation strategies
+
+class InstStrategyUserPatterns : public InstStrategy{
+private:
+ /** explicitly provided patterns */
+ std::map< Node, std::vector< inst::Trigger* > > d_user_gen;
+ /** counter for quantifiers */
+ std::map< Node, int > d_counter;
+ /** process functions */
+ void processResetInstantiationRound( Theory::Effort effort );
+ int process( Node f, Theory::Effort effort, int e );
+public:
+ InstStrategyUserPatterns( QuantifiersEngine* ie ) :
+ InstStrategy( ie ){}
+ ~InstStrategyUserPatterns(){}
+public:
+ /** add pattern */
+ void addUserPattern( Node f, Node pat );
+ /** get num patterns */
+ int getNumUserGenerators( Node f ) { return (int)d_user_gen[f].size(); }
+ /** get user pattern */
+ inst::Trigger* getUserGenerator( Node f, int i ) { return d_user_gen[f][ i ]; }
+ /** identify */
+ std::string identify() const { return std::string("UserPatterns"); }
+};/* class InstStrategyUserPatterns */
+
+class InstStrategyAutoGenTriggers : public InstStrategy{
+public:
+ enum {
+ RELEVANCE_NONE,
+ RELEVANCE_DEFAULT,
+ };
+private:
+ /** trigger generation strategy */
+ int d_tr_strategy;
+ /** relevance strategy */
+ int d_rlv_strategy;
+ /** regeneration */
+ bool d_regenerate;
+ int d_regenerate_frequency;
+ /** generate additional triggers */
+ bool d_generate_additional;
+ /** triggers for each quantifier */
+ std::map< Node, std::map< inst::Trigger*, bool > > d_auto_gen_trigger;
+ std::map< Node, int > d_counter;
+ /** single, multi triggers for each quantifier */
+ std::map< Node, std::vector< Node > > d_patTerms[2];
+ std::map< Node, bool > d_is_single_trigger;
+ std::map< Node, bool > d_single_trigger_gen;
+ std::map< Node, bool > d_made_multi_trigger;
+ //processed trigger this round
+ std::map< Node, std::map< inst::Trigger*, bool > > d_processed_trigger;
+private:
+ /** process functions */
+ void processResetInstantiationRound( Theory::Effort effort );
+ int process( Node f, Theory::Effort effort, int e );
+ /** generate triggers */
+ void generateTriggers( Node f, Theory::Effort effort, int e, int & status );
+public:
+ /** tstrt is the type of triggers to use (maximum depth, minimum depth, or all)
+ rstrt is the relevance setting for trigger (use only relevant triggers vs. use all)
+ rgfr is the frequency at which triggers are generated */
+ InstStrategyAutoGenTriggers( QuantifiersEngine* qe, int tstrt, int rstrt, int rgfr = -1 ) :
+ InstStrategy( qe ), d_tr_strategy( tstrt ), d_rlv_strategy( rstrt ), d_generate_additional( false ){
+ setRegenerateFrequency( rgfr );
+ }
+ ~InstStrategyAutoGenTriggers(){}
+public:
+ /** get auto-generated trigger */
+ inst::Trigger* getAutoGenTrigger( Node f );
+ /** identify */
+ std::string identify() const { return std::string("AutoGenTriggers"); }
+ /** set regenerate frequency, if fr<0, turn off regenerate */
+ void setRegenerateFrequency( int fr ){
+ if( fr<0 ){
+ d_regenerate = false;
+ }else{
+ d_regenerate_frequency = fr;
+ d_regenerate = true;
+ }
+ }
+ /** set generate additional */
+ void setGenerateAdditional( bool val ) { d_generate_additional = val; }
+};/* class InstStrategyAutoGenTriggers */
+
+class InstStrategyFreeVariable : public InstStrategy{
+private:
+ /** guessed instantiations */
+ std::map< Node, bool > d_guessed;
+ /** process functions */
+ void processResetInstantiationRound( Theory::Effort effort );
+ int process( Node f, Theory::Effort effort, int e );
+public:
+ InstStrategyFreeVariable( QuantifiersEngine* qe ) :
+ InstStrategy( qe ){}
+ ~InstStrategyFreeVariable(){}
+ /** identify */
+ std::string identify() const { return std::string("FreeVariable"); }
+};/* class InstStrategyFreeVariable */
+
+}
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
+
+#endif
-/********************* */\r
-/*! \file macros.cpp\r
- ** \verbatim\r
- ** Original author: ajreynol\r
- ** Major contributors: none\r
- ** Minor contributors (to current version): none\r
- ** This file is part of the CVC4 prototype.\r
- ** Copyright (c) 2009-2012 New York University and The University of Iowa\r
- ** See the file COPYING in the top-level source directory for licensing\r
- ** information.\endverbatim\r
- **\r
- ** \brief Sort inference module\r
- **\r
- ** This class implements quantifiers macro definitions.\r
- **/\r
-\r
-#include <vector>\r
-\r
-#include "theory/quantifiers/macros.h"\r
-#include "theory/rewriter.h"\r
-\r
-using namespace CVC4;\r
-using namespace std;\r
-using namespace CVC4::theory;\r
-using namespace CVC4::theory::quantifiers;\r
-using namespace CVC4::kind;\r
-using namespace CVC4::context;\r
-\r
-bool QuantifierMacros::simplify( std::vector< Node >& assertions, bool doRewrite ){\r
- //first, collect macro definitions\r
- for( size_t i=0; i<assertions.size(); i++ ){\r
- if( assertions[i].getKind()==FORALL ){\r
- std::vector< Node > args;\r
- for( size_t j=0; j<assertions[i][0].getNumChildren(); j++ ){\r
- args.push_back( assertions[i][0][j] );\r
- }\r
- //look at the body of the quantifier for macro definition\r
- process( assertions[i][1], true, args, assertions[i] );\r
- }\r
- }\r
- //create macro defs\r
- for( std::map< Node, std::vector< std::pair< Node, Node > > >::iterator it = d_macro_def_cases.begin();\r
- it != d_macro_def_cases.end(); ++it ){\r
- //create ite based on case definitions\r
- Node val;\r
- for( size_t i=0; i<it->second.size(); ++i ){\r
- if( it->second[i].first.isNull() ){\r
- Assert( i==0 );\r
- val = it->second[i].second;\r
- }else{\r
- //if value is null, must generate it\r
- if( val.isNull() ){\r
- std::stringstream ss;\r
- ss << "mdo_" << it->first << "_$$";\r
- Node op = NodeManager::currentNM()->mkSkolem( ss.str(), it->first.getType(), "op created during macro definitions" );\r
- //will be defined in terms of fresh operator\r
- std::vector< Node > children;\r
- children.push_back( op );\r
- children.insert( children.end(), d_macro_basis[ it->first ].begin(), d_macro_basis[ it->first ].end() );\r
- val = NodeManager::currentNM()->mkNode( APPLY_UF, children );\r
- }\r
- val = NodeManager::currentNM()->mkNode( ITE, it->second[i].first, it->second[i].second, val );\r
- }\r
- }\r
- d_macro_defs[ it->first ] = val;\r
- Trace("macros-def") << "* " << val << " is a macro for " << it->first << std::endl;\r
- }\r
- //now simplify bodies\r
- for( std::map< Node, Node >::iterator it = d_macro_defs.begin(); it != d_macro_defs.end(); ++it ){\r
- d_macro_defs[ it->first ] = Rewriter::rewrite( simplify( it->second ) );\r
- }\r
- bool retVal = false;\r
- if( doRewrite && !d_macro_defs.empty() ){\r
- //now, rewrite based on macro definitions\r
- for( size_t i=0; i<assertions.size(); i++ ){\r
- Node prev = assertions[i];\r
- assertions[i] = simplify( assertions[i] );\r
- if( prev!=assertions[i] ){\r
- assertions[i] = Rewriter::rewrite( assertions[i] );\r
- Trace("macros-rewrite") << "Rewrite " << prev << " to " << assertions[i] << std::endl;\r
- retVal = true;\r
- }\r
- }\r
- }\r
- return retVal;\r
-}\r
-\r
-bool QuantifierMacros::contains( Node n, Node n_s ){\r
- if( n==n_s ){\r
- return true;\r
- }else{\r
- for( size_t i=0; i<n.getNumChildren(); i++ ){\r
- if( contains( n[i], n_s ) ){\r
- return true;\r
- }\r
- }\r
- return false;\r
- }\r
-}\r
-\r
-bool QuantifierMacros::containsBadOp( Node n, Node n_op ){\r
- if( n!=n_op ){\r
- if( n.getKind()==APPLY_UF ){\r
- Node op = n.getOperator();\r
- if( op==n_op.getOperator() ){\r
- return true;\r
- }\r
- if( d_macro_def_cases.find( op )!=d_macro_def_cases.end() && !d_macro_def_cases[op].empty() ){\r
- return true;\r
- }\r
- }\r
- for( size_t i=0; i<n.getNumChildren(); i++ ){\r
- if( containsBadOp( n[i], n_op ) ){\r
- return true;\r
- }\r
- }\r
- }\r
- return false;\r
-}\r
-\r
-bool QuantifierMacros::isMacroLiteral( Node n, bool pol ){\r
- return pol && n.getKind()==EQUAL;//( n.getKind()==EQUAL || n.getKind()==IFF );\r
-}\r
-\r
-void QuantifierMacros::getMacroCandidates( Node n, std::vector< Node >& candidates ){\r
- if( n.getKind()==APPLY_UF ){\r
- candidates.push_back( n );\r
- }else if( n.getKind()==PLUS ){\r
- for( size_t i=0; i<n.getNumChildren(); i++ ){\r
- getMacroCandidates( n[i], candidates );\r
- }\r
- }else if( n.getKind()==MULT ){\r
- //if the LHS is a constant\r
- if( n.getNumChildren()==2 && n[0].isConst() ){\r
- getMacroCandidates( n[1], candidates );\r
- }\r
- }\r
-}\r
-\r
-Node QuantifierMacros::solveInEquality( Node n, Node lit ){\r
- if( lit.getKind()==IFF || lit.getKind()==EQUAL ){\r
- //return the opposite side of the equality if defined that way\r
- for( int i=0; i<2; i++ ){\r
- if( lit[i]==n ){\r
- return lit[ i==0 ? 1 : 0];\r
- }\r
- }\r
- //must solve for term n in the literal lit\r
- if( lit[0].getType().isInteger() || lit[0].getType().isReal() ){\r
- Node coeff;\r
- Node term;\r
- //could be solved for on LHS\r
- if( lit[0].getKind()==MULT && lit[0][1]==n ){\r
- Assert( lit[0][0].isConst() );\r
- term = lit[1];\r
- coeff = lit[0][0];\r
- }else{\r
- Assert( lit[1].getKind()==PLUS );\r
- std::vector< Node > plus_children;\r
- //find monomial with n\r
- for( size_t j=0; j<lit[1].getNumChildren(); j++ ){\r
- if( lit[1][j]==n ){\r
- Assert( coeff.isNull() );\r
- coeff = NodeManager::currentNM()->mkConst( Rational(1) );\r
- }else if( lit[1][j].getKind()==MULT && lit[1][j][1]==n ){\r
- Assert( coeff.isNull() );\r
- Assert( lit[1][j][0].isConst() );\r
- coeff = lit[1][j][0];\r
- }else{\r
- plus_children.push_back( lit[1][j] );\r
- }\r
- }\r
- if( !coeff.isNull() ){\r
- term = NodeManager::currentNM()->mkNode( PLUS, plus_children );\r
- term = NodeManager::currentNM()->mkNode( MINUS, lit[0], term );\r
- }\r
- }\r
- if( !coeff.isNull() ){\r
- coeff = NodeManager::currentNM()->mkConst( Rational(1) / coeff.getConst<Rational>() );\r
- term = NodeManager::currentNM()->mkNode( MULT, coeff, term );\r
- term = Rewriter::rewrite( term );\r
- return term;\r
- }\r
- }\r
- }\r
- Trace("macros-debug") << "Cannot find for " << lit << " " << n << std::endl;\r
- return Node::null();\r
-}\r
-\r
-bool QuantifierMacros::isConsistentDefinition( Node op, Node cond, Node def ){\r
- if( d_macro_def_cases[op].empty() || ( cond.isNull() && !d_macro_def_cases[op][0].first.isNull() ) ){\r
- return true;\r
- }else{\r
- return false;\r
- }\r
-}\r
-\r
-bool QuantifierMacros::getFreeVariables( Node n, std::vector< Node >& v_quant, std::vector< Node >& vars, bool retOnly ){\r
- if( std::find( v_quant.begin(), v_quant.end(), n )!=v_quant.end() ){\r
- if( std::find( vars.begin(), vars.end(), n )==vars.end() ){\r
- if( retOnly ){\r
- return true;\r
- }else{\r
- vars.push_back( n );\r
- }\r
- }\r
- }\r
- for( size_t i=0; i<n.getNumChildren(); i++ ){\r
- if( getFreeVariables( n[i], v_quant, vars, retOnly ) ){\r
- return true;\r
- }\r
- }\r
- return false;\r
-}\r
-\r
-bool QuantifierMacros::getSubstitution( std::vector< Node >& v_quant, std::map< Node, Node >& solved,\r
- std::vector< Node >& vars, std::vector< Node >& subs, bool reqComplete ){\r
- bool success = true;\r
- for( size_t a=0; a<v_quant.size(); a++ ){\r
- if( !solved[ v_quant[a] ].isNull() ){\r
- vars.push_back( v_quant[a] );\r
- subs.push_back( solved[ v_quant[a] ] );\r
- }else{\r
- if( reqComplete ){\r
- success = false;\r
- break;\r
- }\r
- }\r
- }\r
- return success;\r
-}\r
-\r
-void QuantifierMacros::process( Node n, bool pol, std::vector< Node >& args, Node f ){\r
- if( n.getKind()==NOT ){\r
- process( n[0], !pol, args, f );\r
- }else if( n.getKind()==AND || n.getKind()==OR || n.getKind()==IMPLIES ){\r
- //bool favorPol = (n.getKind()==AND)==pol;\r
- //conditional?\r
- }else if( n.getKind()==ITE ){\r
- //can not do anything\r
- }else{\r
- //literal case\r
- if( isMacroLiteral( n, pol ) ){\r
- std::vector< Node > candidates;\r
- for( size_t i=0; i<n.getNumChildren(); i++ ){\r
- getMacroCandidates( n[i], candidates );\r
- }\r
- for( size_t i=0; i<candidates.size(); i++ ){\r
- Node m = candidates[i];\r
- Node op = m.getOperator();\r
- if( !containsBadOp( n, m ) ){\r
- std::vector< Node > fvs;\r
- getFreeVariables( m, args, fvs, false );\r
- //get definition and condition\r
- Node n_def = solveInEquality( m, n ); //definition for the macro\r
- //definition must exist and not contain any free variables apart from fvs\r
- if( !n_def.isNull() && !getFreeVariables( n_def, args, fvs, true ) ){\r
- Node n_cond; //condition when this definition holds\r
- //conditional must not contain any free variables apart from fvs\r
- if( n_cond.isNull() || !getFreeVariables( n_cond, args, fvs, true ) ){\r
- Trace("macros") << m << " is possible macro in " << f << std::endl;\r
- //now we must rewrite candidates[i] to a term of form g( x1, ..., xn ) where\r
- // x1 ... xn are distinct variables\r
- if( d_macro_basis[op].empty() ){\r
- for( size_t a=0; a<m.getNumChildren(); a++ ){\r
- std::stringstream ss;\r
- ss << "mda_" << op << "_$$";\r
- Node v = NodeManager::currentNM()->mkSkolem( ss.str(), m[a].getType(), "created during macro definition recognition" );\r
- d_macro_basis[op].push_back( v );\r
- }\r
- }\r
- std::vector< Node > eq;\r
- for( size_t a=0; a<m.getNumChildren(); a++ ){\r
- eq.push_back( m[a] );\r
- }\r
- //solve system of equations "d_macro_basis[op] = m" for variables in fvs\r
- std::map< Node, Node > solved;\r
- //solve obvious cases first\r
- for( size_t a=0; a<eq.size(); a++ ){\r
- if( std::find( fvs.begin(), fvs.end(), eq[a] )!=fvs.end() ){\r
- if( solved[ eq[a] ].isNull() ){\r
- solved[ eq[a] ] = d_macro_basis[op][a];\r
- }\r
- }\r
- }\r
- //now, apply substitution for obvious cases\r
- std::vector< Node > vars;\r
- std::vector< Node > subs;\r
- getSubstitution( fvs, solved, vars, subs, false );\r
- for( size_t a=0; a<eq.size(); a++ ){\r
- eq[a] = eq[a].substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );\r
- }\r
-\r
- Trace("macros-eq") << "Solve system of equations : " << std::endl;\r
- for( size_t a=0; a<m.getNumChildren(); a++ ){\r
- if( d_macro_basis[op][a]!=eq[a] ){\r
- Trace("macros-eq") << " " << d_macro_basis[op][a] << " = " << eq[a] << std::endl;\r
- }\r
- }\r
- Trace("macros-eq") << " for ";\r
- for( size_t a=0; a<fvs.size(); a++ ){\r
- if( solved[ fvs[a] ].isNull() ){\r
- Trace("macros-eq") << fvs[a] << " ";\r
- }\r
- }\r
- Trace("macros-eq") << std::endl;\r
- //DO_THIS\r
-\r
-\r
- vars.clear();\r
- subs.clear();\r
- if( getSubstitution( fvs, solved, vars, subs, true ) ){\r
- //build condition\r
- std::vector< Node > conds;\r
- if( !n_cond.isNull() ){\r
- //must apply substitution obtained from solving system of equations to original condition\r
- n_cond = n_cond.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );\r
- conds.push_back( n_cond );\r
- }\r
- for( size_t a=0; a<eq.size(); a++ ){\r
- //collect conditions based on solving argument's system of equations\r
- if( d_macro_basis[op][a]!=eq[a] ){\r
- conds.push_back( NodeManager::currentNM()->mkNode( eq[a].getType().isBoolean() ? IFF : EQUAL, d_macro_basis[op][a], eq[a] ) );\r
- }\r
- }\r
- //build the condition\r
- if( !conds.empty() ){\r
- n_cond = conds.size()==1 ? conds[0] : NodeManager::currentNM()->mkNode( AND, conds );\r
- }\r
- //apply the substitution to the\r
- n_def = n_def.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );\r
- //now see if definition is consistent with others\r
- if( isConsistentDefinition( op, n_cond, n_def ) ){\r
- //must clear if it is a base definition\r
- if( n_cond.isNull() ){\r
- d_macro_def_cases[ op ].clear();\r
- }\r
- d_macro_def_cases[ op ].push_back( std::pair< Node, Node >( n_cond, n_def ) );\r
- }\r
- }\r
- }\r
- }\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-Node QuantifierMacros::simplify( Node n ){\r
- Trace("macros-debug") << "simplify " << n << std::endl;\r
- std::vector< Node > children;\r
- bool childChanged = false;\r
- for( size_t i=0; i<n.getNumChildren(); i++ ){\r
- Node nn = simplify( n[i] );\r
- children.push_back( nn );\r
- childChanged = childChanged || nn!=n[i];\r
- }\r
- if( n.getKind()==APPLY_UF ){\r
- Node op = n.getOperator();\r
- if( d_macro_defs.find( op )!=d_macro_defs.end() && !d_macro_defs[op].isNull() ){\r
- //do subsitutition\r
- Node ret = d_macro_defs[op];\r
- ret = ret.substitute( d_macro_basis[op].begin(), d_macro_basis[op].end(), children.begin(), children.end() );\r
- return ret;\r
- }\r
- }\r
- if( childChanged ){\r
- if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){\r
- children.insert( children.begin(), n.getOperator() );\r
- }\r
- return NodeManager::currentNM()->mkNode( n.getKind(), children );\r
- }else{\r
- return n;\r
- }\r
-}\r
+/********************* */
+/*! \file macros.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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 <vector>
+
+#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<assertions.size(); i++ ){
+ if( assertions[i].getKind()==FORALL ){
+ std::vector< Node > args;
+ for( size_t j=0; j<assertions[i][0].getNumChildren(); j++ ){
+ args.push_back( assertions[i][0][j] );
+ }
+ //look at the body of the quantifier for macro definition
+ process( assertions[i][1], true, args, assertions[i] );
+ }
+ }
+ //create macro defs
+ for( std::map< Node, std::vector< std::pair< Node, Node > > >::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; i<it->second.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<assertions.size(); i++ ){
+ Node prev = assertions[i];
+ assertions[i] = simplify( assertions[i] );
+ if( prev!=assertions[i] ){
+ assertions[i] = Rewriter::rewrite( assertions[i] );
+ Trace("macros-rewrite") << "Rewrite " << prev << " to " << assertions[i] << std::endl;
+ retVal = true;
+ }
+ }
+ }
+ return retVal;
+}
+
+bool QuantifierMacros::contains( Node n, Node n_s ){
+ if( n==n_s ){
+ return true;
+ }else{
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ if( contains( n[i], n_s ) ){
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+bool QuantifierMacros::containsBadOp( Node n, Node n_op ){
+ if( n!=n_op ){
+ if( n.getKind()==APPLY_UF ){
+ Node op = n.getOperator();
+ if( op==n_op.getOperator() ){
+ return true;
+ }
+ if( d_macro_def_cases.find( op )!=d_macro_def_cases.end() && !d_macro_def_cases[op].empty() ){
+ return true;
+ }
+ }
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ if( containsBadOp( n[i], n_op ) ){
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool QuantifierMacros::isMacroLiteral( Node n, bool pol ){
+ return pol && n.getKind()==EQUAL;//( n.getKind()==EQUAL || n.getKind()==IFF );
+}
+
+void QuantifierMacros::getMacroCandidates( Node n, std::vector< Node >& candidates ){
+ if( n.getKind()==APPLY_UF ){
+ candidates.push_back( n );
+ }else if( n.getKind()==PLUS ){
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ getMacroCandidates( n[i], candidates );
+ }
+ }else if( n.getKind()==MULT ){
+ //if the LHS is a constant
+ if( n.getNumChildren()==2 && n[0].isConst() ){
+ getMacroCandidates( n[1], candidates );
+ }
+ }
+}
+
+Node QuantifierMacros::solveInEquality( Node n, Node lit ){
+ if( lit.getKind()==IFF || lit.getKind()==EQUAL ){
+ //return the opposite side of the equality if defined that way
+ for( int i=0; i<2; i++ ){
+ if( lit[i]==n ){
+ return lit[ i==0 ? 1 : 0];
+ }
+ }
+ //must solve for term n in the literal lit
+ if( lit[0].getType().isInteger() || lit[0].getType().isReal() ){
+ Node coeff;
+ Node term;
+ //could be solved for on LHS
+ if( lit[0].getKind()==MULT && lit[0][1]==n ){
+ Assert( lit[0][0].isConst() );
+ term = lit[1];
+ coeff = lit[0][0];
+ }else{
+ Assert( lit[1].getKind()==PLUS );
+ std::vector< Node > plus_children;
+ //find monomial with n
+ for( size_t j=0; j<lit[1].getNumChildren(); j++ ){
+ if( lit[1][j]==n ){
+ Assert( coeff.isNull() );
+ coeff = NodeManager::currentNM()->mkConst( 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<Rational>() );
+ 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<n.getNumChildren(); i++ ){
+ if( getFreeVariables( n[i], v_quant, vars, retOnly ) ){
+ return true;
+ }
+ }
+ return false;
+}
+
+bool QuantifierMacros::getSubstitution( std::vector< Node >& 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<v_quant.size(); a++ ){
+ if( !solved[ v_quant[a] ].isNull() ){
+ vars.push_back( v_quant[a] );
+ subs.push_back( solved[ v_quant[a] ] );
+ }else{
+ if( reqComplete ){
+ success = false;
+ break;
+ }
+ }
+ }
+ return success;
+}
+
+void QuantifierMacros::process( Node n, bool pol, std::vector< Node >& 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<n.getNumChildren(); i++ ){
+ getMacroCandidates( n[i], candidates );
+ }
+ for( size_t i=0; i<candidates.size(); i++ ){
+ Node m = candidates[i];
+ Node op = m.getOperator();
+ if( !containsBadOp( n, m ) ){
+ std::vector< Node > 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; a<m.getNumChildren(); a++ ){
+ std::stringstream ss;
+ ss << "mda_" << op << "_$$";
+ Node v = NodeManager::currentNM()->mkSkolem( 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<m.getNumChildren(); a++ ){
+ eq.push_back( m[a] );
+ }
+ //solve system of equations "d_macro_basis[op] = m" for variables in fvs
+ std::map< Node, Node > solved;
+ //solve obvious cases first
+ for( size_t a=0; a<eq.size(); a++ ){
+ if( std::find( fvs.begin(), fvs.end(), eq[a] )!=fvs.end() ){
+ if( solved[ eq[a] ].isNull() ){
+ solved[ eq[a] ] = d_macro_basis[op][a];
+ }
+ }
+ }
+ //now, apply substitution for obvious cases
+ std::vector< Node > vars;
+ std::vector< Node > subs;
+ getSubstitution( fvs, solved, vars, subs, false );
+ for( size_t a=0; a<eq.size(); a++ ){
+ eq[a] = eq[a].substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ }
+
+ Trace("macros-eq") << "Solve system of equations : " << std::endl;
+ for( size_t a=0; a<m.getNumChildren(); a++ ){
+ if( d_macro_basis[op][a]!=eq[a] ){
+ Trace("macros-eq") << " " << d_macro_basis[op][a] << " = " << eq[a] << std::endl;
+ }
+ }
+ Trace("macros-eq") << " for ";
+ for( size_t a=0; a<fvs.size(); a++ ){
+ if( solved[ fvs[a] ].isNull() ){
+ Trace("macros-eq") << fvs[a] << " ";
+ }
+ }
+ Trace("macros-eq") << std::endl;
+ //DO_THIS
+
+
+ vars.clear();
+ subs.clear();
+ if( getSubstitution( fvs, solved, vars, subs, true ) ){
+ //build condition
+ std::vector< Node > 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; a<eq.size(); a++ ){
+ //collect conditions based on solving argument's system of equations
+ if( d_macro_basis[op][a]!=eq[a] ){
+ conds.push_back( NodeManager::currentNM()->mkNode( 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; i<n.getNumChildren(); i++ ){
+ Node nn = simplify( n[i] );
+ children.push_back( nn );
+ childChanged = childChanged || nn!=n[i];
+ }
+ if( n.getKind()==APPLY_UF ){
+ Node op = n.getOperator();
+ if( d_macro_defs.find( op )!=d_macro_defs.end() && !d_macro_defs[op].isNull() ){
+ //do subsitutition
+ Node ret = d_macro_defs[op];
+ ret = ret.substitute( d_macro_basis[op].begin(), d_macro_basis[op].end(), children.begin(), children.end() );
+ return ret;
+ }
+ }
+ if( childChanged ){
+ if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ children.insert( children.begin(), n.getOperator() );
+ }
+ return NodeManager::currentNM()->mkNode( n.getKind(), children );
+ }else{
+ return n;
+ }
+}
-/********************* */\r
-/*! \file macros.h\r
- ** \verbatim\r
- ** Original author: ajreynol\r
- ** Major contributors: none\r
- ** Minor contributors (to current version): none\r
- ** This file is part of the CVC4 prototype.\r
- ** Copyright (c) 2009-2012 New York University and The University of Iowa\r
- ** See the file COPYING in the top-level source directory for licensing\r
- ** information.\endverbatim\r
- **\r
- ** \brief Pre-process step for detecting quantifier macro definitions\r
- **/\r
-\r
-#include "cvc4_private.h"\r
-\r
-#ifndef __CVC4__QUANTIFIERS_MACROS_H\r
-#define __CVC4__QUANTIFIERS_MACROS_H\r
-\r
-#include <iostream>\r
-#include <string>\r
-#include <vector>\r
-#include <map>\r
-#include "expr/node.h"\r
-#include "expr/type_node.h"\r
-\r
-namespace CVC4 {\r
-namespace theory {\r
-namespace quantifiers {\r
-\r
-class QuantifierMacros{\r
-private:\r
- void process( Node n, bool pol, std::vector< Node >& args, Node f );\r
- bool contains( Node n, Node n_s );\r
- bool containsBadOp( Node n, Node n_op );\r
- bool isMacroLiteral( Node n, bool pol );\r
- void getMacroCandidates( Node n, std::vector< Node >& candidates );\r
- Node solveInEquality( Node n, Node lit );\r
- bool isConsistentDefinition( Node op, Node cond, Node def );\r
- bool getFreeVariables( Node n, std::vector< Node >& v_quant, std::vector< Node >& vars, bool retOnly );\r
- bool getSubstitution( std::vector< Node >& v_quant, std::map< Node, Node >& solved,\r
- std::vector< Node >& vars, std::vector< Node >& subs, bool reqComplete );\r
- //map from operators to macro basis terms\r
- std::map< Node, std::vector< Node > > d_macro_basis;\r
- //map from operators to map from conditions to definition cases\r
- std::map< Node, std::vector< std::pair< Node, Node > > > d_macro_def_cases;\r
- //map from operators to macro definition\r
- std::map< Node, Node > d_macro_defs;\r
-private:\r
- Node simplify( Node n );\r
-public:\r
- QuantifierMacros(){}\r
- ~QuantifierMacros(){}\r
-\r
- bool simplify( std::vector< Node >& assertions, bool doRewrite = false );\r
-};\r
-\r
-}\r
-}\r
-}\r
-\r
-#endif\r
+/********************* */
+/*! \file macros.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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 Pre-process step for detecting quantifier macro definitions
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__QUANTIFIERS_MACROS_H
+#define __CVC4__QUANTIFIERS_MACROS_H
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <map>
+#include "expr/node.h"
+#include "expr/type_node.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+class QuantifierMacros{
+private:
+ void process( Node n, bool pol, std::vector< Node >& args, Node f );
+ bool contains( Node n, Node n_s );
+ bool containsBadOp( Node n, Node n_op );
+ bool isMacroLiteral( Node n, bool pol );
+ void getMacroCandidates( Node n, std::vector< Node >& candidates );
+ Node solveInEquality( Node n, Node lit );
+ bool isConsistentDefinition( Node op, Node cond, Node def );
+ bool getFreeVariables( Node n, std::vector< Node >& v_quant, std::vector< Node >& vars, bool retOnly );
+ bool getSubstitution( std::vector< Node >& v_quant, std::map< Node, Node >& solved,
+ std::vector< Node >& vars, std::vector< Node >& subs, bool reqComplete );
+ //map from operators to macro basis terms
+ std::map< Node, std::vector< Node > > d_macro_basis;
+ //map from operators to map from conditions to definition cases
+ std::map< Node, std::vector< std::pair< Node, Node > > > d_macro_def_cases;
+ //map from operators to macro definition
+ std::map< Node, Node > d_macro_defs;
+private:
+ Node simplify( Node n );
+public:
+ QuantifierMacros(){}
+ ~QuantifierMacros(){}
+
+ bool simplify( std::vector< Node >& assertions, bool doRewrite = false );
+};
+
+}
+}
+}
+
+#endif
-/********************* */\r
-/*! \file quant_util.cpp\r
- ** \verbatim\r
- ** Original author: ajreynol\r
- ** Major contributors: bobot, mdeters\r
- ** Minor contributors (to current version): none\r
- ** This file is part of the CVC4 prototype.\r
- ** Copyright (c) 2009-2012 New York University and The University of Iowa\r
- ** See the file COPYING in the top-level source directory for licensing\r
- ** information.\endverbatim\r
- **\r
- ** \brief Implementation of quantifier utilities\r
- **/\r
-\r
-#include "theory/quantifiers/quant_util.h"\r
-#include "theory/quantifiers/inst_match.h"\r
-#include "theory/quantifiers/term_database.h"\r
-\r
-using namespace std;\r
-using namespace CVC4;\r
-using namespace CVC4::kind;\r
-using namespace CVC4::context;\r
-using namespace CVC4::theory;\r
-\r
-void QuantRelevance::registerQuantifier( Node f ){\r
- //compute symbols in f\r
- std::vector< Node > syms;\r
- computeSymbols( f[1], syms );\r
- d_syms[f].insert( d_syms[f].begin(), syms.begin(), syms.end() );\r
- //set initial relevance\r
- int minRelevance = -1;\r
- for( int i=0; i<(int)syms.size(); i++ ){\r
- d_syms_quants[ syms[i] ].push_back( f );\r
- int r = getRelevance( syms[i] );\r
- if( r!=-1 && ( minRelevance==-1 || r<minRelevance ) ){\r
- minRelevance = r;\r
- }\r
- }\r
- if( minRelevance!=-1 ){\r
- setRelevance( f, minRelevance+1 );\r
- }\r
-}\r
-\r
-\r
-/** compute symbols */\r
-void QuantRelevance::computeSymbols( Node n, std::vector< Node >& syms ){\r
- if( n.getKind()==APPLY_UF ){\r
- Node op = n.getOperator();\r
- if( std::find( syms.begin(), syms.end(), op )==syms.end() ){\r
- syms.push_back( op );\r
- }\r
- }\r
- if( n.getKind()!=FORALL ){\r
- for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
- computeSymbols( n[i], syms );\r
- }\r
- }\r
-}\r
-\r
-/** set relevance */\r
-void QuantRelevance::setRelevance( Node s, int r ){\r
- if( d_computeRel ){\r
- int rOld = getRelevance( s );\r
- if( rOld==-1 || r<rOld ){\r
- d_relevance[s] = r;\r
- if( s.getKind()==FORALL ){\r
- for( int i=0; i<(int)d_syms[s].size(); i++ ){\r
- setRelevance( d_syms[s][i], r );\r
- }\r
- }else{\r
- for( int i=0; i<(int)d_syms_quants[s].size(); i++ ){\r
- setRelevance( d_syms_quants[s][i], r+1 );\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-\r
-QuantPhaseReq::QuantPhaseReq( Node n, bool computeEq ){\r
- std::map< Node, int > phaseReqs2;\r
- computePhaseReqs( n, false, phaseReqs2 );\r
- for( std::map< Node, int >::iterator it = phaseReqs2.begin(); it != phaseReqs2.end(); ++it ){\r
- if( it->second==1 ){\r
- d_phase_reqs[ it->first ] = true;\r
- }else if( it->second==-1 ){\r
- d_phase_reqs[ it->first ] = false;\r
- }\r
- }\r
- Debug("inst-engine-phase-req") << "Phase requirements for " << n << ":" << std::endl;\r
- //now, compute if any patterns are equality required\r
- if( computeEq ){\r
- for( std::map< Node, bool >::iterator it = d_phase_reqs.begin(); it != d_phase_reqs.end(); ++it ){\r
- Debug("inst-engine-phase-req") << " " << it->first << " -> " << it->second << std::endl;\r
- if( it->first.getKind()==EQUAL ){\r
- if( it->first[0].hasAttribute(InstConstantAttribute()) ){\r
- if( !it->first[1].hasAttribute(InstConstantAttribute()) ){\r
- d_phase_reqs_equality_term[ it->first[0] ] = it->first[1];\r
- d_phase_reqs_equality[ it->first[0] ] = it->second;\r
- Debug("inst-engine-phase-req") << " " << it->first[0] << ( it->second ? " == " : " != " ) << it->first[1] << std::endl;\r
- }\r
- }else if( it->first[1].hasAttribute(InstConstantAttribute()) ){\r
- d_phase_reqs_equality_term[ it->first[1] ] = it->first[0];\r
- d_phase_reqs_equality[ it->first[1] ] = it->second;\r
- Debug("inst-engine-phase-req") << " " << it->first[1] << ( it->second ? " == " : " != " ) << it->first[0] << std::endl;\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-void QuantPhaseReq::computePhaseReqs( Node n, bool polarity, std::map< Node, int >& phaseReqs ){\r
- bool newReqPol = false;\r
- bool newPolarity;\r
- if( n.getKind()==NOT ){\r
- newReqPol = true;\r
- newPolarity = !polarity;\r
- }else if( n.getKind()==OR || n.getKind()==IMPLIES ){\r
- if( !polarity ){\r
- newReqPol = true;\r
- newPolarity = false;\r
- }\r
- }else if( n.getKind()==AND ){\r
- if( polarity ){\r
- newReqPol = true;\r
- newPolarity = true;\r
- }\r
- }else{\r
- int val = polarity ? 1 : -1;\r
- if( phaseReqs.find( n )==phaseReqs.end() ){\r
- phaseReqs[n] = val;\r
- }else if( val!=phaseReqs[n] ){\r
- phaseReqs[n] = 0;\r
- }\r
- }\r
- if( newReqPol ){\r
- for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
- if( n.getKind()==IMPLIES && i==0 ){\r
- computePhaseReqs( n[i], !newPolarity, phaseReqs );\r
- }else{\r
- computePhaseReqs( n[i], newPolarity, phaseReqs );\r
- }\r
- }\r
- }\r
-}\r
+/********************* */
+/*! \file quant_util.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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 Implementation of quantifier utilities
+ **/
+
+#include "theory/quantifiers/quant_util.h"
+#include "theory/quantifiers/inst_match.h"
+#include "theory/quantifiers/term_database.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+
+void QuantRelevance::registerQuantifier( Node f ){
+ //compute symbols in f
+ std::vector< Node > syms;
+ computeSymbols( f[1], syms );
+ d_syms[f].insert( d_syms[f].begin(), syms.begin(), syms.end() );
+ //set initial relevance
+ int minRelevance = -1;
+ for( int i=0; i<(int)syms.size(); i++ ){
+ d_syms_quants[ syms[i] ].push_back( f );
+ int r = getRelevance( syms[i] );
+ if( r!=-1 && ( minRelevance==-1 || r<minRelevance ) ){
+ minRelevance = r;
+ }
+ }
+ if( minRelevance!=-1 ){
+ setRelevance( f, minRelevance+1 );
+ }
+}
+
+
+/** compute symbols */
+void QuantRelevance::computeSymbols( Node n, std::vector< Node >& syms ){
+ if( n.getKind()==APPLY_UF ){
+ Node op = n.getOperator();
+ if( std::find( syms.begin(), syms.end(), op )==syms.end() ){
+ syms.push_back( op );
+ }
+ }
+ if( n.getKind()!=FORALL ){
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ computeSymbols( n[i], syms );
+ }
+ }
+}
+
+/** set relevance */
+void QuantRelevance::setRelevance( Node s, int r ){
+ if( d_computeRel ){
+ int rOld = getRelevance( s );
+ if( rOld==-1 || r<rOld ){
+ d_relevance[s] = r;
+ if( s.getKind()==FORALL ){
+ for( int i=0; i<(int)d_syms[s].size(); i++ ){
+ setRelevance( d_syms[s][i], r );
+ }
+ }else{
+ for( int i=0; i<(int)d_syms_quants[s].size(); i++ ){
+ setRelevance( d_syms_quants[s][i], r+1 );
+ }
+ }
+ }
+ }
+}
+
+
+QuantPhaseReq::QuantPhaseReq( Node n, bool computeEq ){
+ std::map< Node, int > phaseReqs2;
+ computePhaseReqs( n, false, phaseReqs2 );
+ for( std::map< Node, int >::iterator it = phaseReqs2.begin(); it != phaseReqs2.end(); ++it ){
+ if( it->second==1 ){
+ d_phase_reqs[ it->first ] = true;
+ }else if( it->second==-1 ){
+ d_phase_reqs[ it->first ] = false;
+ }
+ }
+ Debug("inst-engine-phase-req") << "Phase requirements for " << n << ":" << std::endl;
+ //now, compute if any patterns are equality required
+ if( computeEq ){
+ for( std::map< Node, bool >::iterator it = d_phase_reqs.begin(); it != d_phase_reqs.end(); ++it ){
+ Debug("inst-engine-phase-req") << " " << it->first << " -> " << it->second << std::endl;
+ if( it->first.getKind()==EQUAL ){
+ if( it->first[0].hasAttribute(InstConstantAttribute()) ){
+ if( !it->first[1].hasAttribute(InstConstantAttribute()) ){
+ d_phase_reqs_equality_term[ it->first[0] ] = it->first[1];
+ d_phase_reqs_equality[ it->first[0] ] = it->second;
+ Debug("inst-engine-phase-req") << " " << it->first[0] << ( it->second ? " == " : " != " ) << it->first[1] << std::endl;
+ }
+ }else if( it->first[1].hasAttribute(InstConstantAttribute()) ){
+ d_phase_reqs_equality_term[ it->first[1] ] = it->first[0];
+ d_phase_reqs_equality[ it->first[1] ] = it->second;
+ Debug("inst-engine-phase-req") << " " << it->first[1] << ( it->second ? " == " : " != " ) << it->first[0] << std::endl;
+ }
+ }
+ }
+ }
+}
+
+void QuantPhaseReq::computePhaseReqs( Node n, bool polarity, std::map< Node, int >& phaseReqs ){
+ bool newReqPol = false;
+ bool newPolarity;
+ if( n.getKind()==NOT ){
+ newReqPol = true;
+ newPolarity = !polarity;
+ }else if( n.getKind()==OR || n.getKind()==IMPLIES ){
+ if( !polarity ){
+ newReqPol = true;
+ newPolarity = false;
+ }
+ }else if( n.getKind()==AND ){
+ if( polarity ){
+ newReqPol = true;
+ newPolarity = true;
+ }
+ }else{
+ int val = polarity ? 1 : -1;
+ if( phaseReqs.find( n )==phaseReqs.end() ){
+ phaseReqs[n] = val;
+ }else if( val!=phaseReqs[n] ){
+ phaseReqs[n] = 0;
+ }
+ }
+ if( newReqPol ){
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( n.getKind()==IMPLIES && i==0 ){
+ computePhaseReqs( n[i], !newPolarity, phaseReqs );
+ }else{
+ computePhaseReqs( n[i], newPolarity, phaseReqs );
+ }
+ }
+ }
+}
-/********************* */\r
-/*! \file quant_util.h\r
- ** \verbatim\r
- ** Original author: ajreynol\r
- ** Major contributors: none\r
- ** Minor contributors (to current version): mdeters, bobot\r
- ** This file is part of the CVC4 prototype.\r
- ** Copyright (c) 2009-2012 New York University and The University of Iowa\r
- ** See the file COPYING in the top-level source directory for licensing\r
- ** information.\endverbatim\r
- **\r
- ** \brief quantifier util\r
- **/\r
-\r
-#include "cvc4_private.h"\r
-\r
-#ifndef __CVC4__THEORY__QUANT_UTIL_H\r
-#define __CVC4__THEORY__QUANT_UTIL_H\r
-\r
-#include "theory/theory.h"\r
-#include "theory/uf/equality_engine.h"\r
-\r
-#include <ext/hash_set>\r
-#include <iostream>\r
-#include <map>\r
-\r
-namespace CVC4 {\r
-namespace theory {\r
-\r
-\r
-class QuantRelevance\r
-{\r
-private:\r
- /** for computing relavance */\r
- bool d_computeRel;\r
- /** map from quantifiers to symbols they contain */\r
- std::map< Node, std::vector< Node > > d_syms;\r
- /** map from symbols to quantifiers */\r
- std::map< Node, std::vector< Node > > d_syms_quants;\r
- /** relevance for quantifiers and symbols */\r
- std::map< Node, int > d_relevance;\r
- /** compute symbols */\r
- void computeSymbols( Node n, std::vector< Node >& syms );\r
-public:\r
- QuantRelevance( bool cr ) : d_computeRel( cr ){}\r
- ~QuantRelevance(){}\r
- /** register quantifier */\r
- void registerQuantifier( Node f );\r
- /** set relevance */\r
- void setRelevance( Node s, int r );\r
- /** get relevance */\r
- int getRelevance( Node s ) { return d_relevance.find( s )==d_relevance.end() ? -1 : d_relevance[s]; }\r
- /** get number of quantifiers for symbol s */\r
- int getNumQuantifiersForSymbol( Node s ) { return (int)d_syms_quants[s].size(); }\r
-};\r
-\r
-class QuantPhaseReq\r
-{\r
-private:\r
- /** helper functions compute phase requirements */\r
- void computePhaseReqs( Node n, bool polarity, std::map< Node, int >& phaseReqs );\r
-public:\r
- QuantPhaseReq( Node n, bool computeEq = false );\r
- ~QuantPhaseReq(){}\r
- /** is phase required */\r
- bool isPhaseReq( Node lit ) { return d_phase_reqs.find( lit )!=d_phase_reqs.end(); }\r
- /** get phase requirement */\r
- bool getPhaseReq( Node lit ) { return d_phase_reqs.find( lit )==d_phase_reqs.end() ? false : d_phase_reqs[ lit ]; }\r
- /** phase requirements for each quantifier for each instantiation literal */\r
- std::map< Node, bool > d_phase_reqs;\r
- std::map< Node, bool > d_phase_reqs_equality;\r
- std::map< Node, Node > d_phase_reqs_equality_term;\r
-};\r
-\r
-\r
-class EqualityQuery {\r
-public:\r
- EqualityQuery(){}\r
- virtual ~EqualityQuery(){};\r
- /** reset */\r
- virtual void reset() = 0;\r
- /** contains term */\r
- virtual bool hasTerm( Node a ) = 0;\r
- /** get the representative of the equivalence class of a */\r
- virtual Node getRepresentative( Node a ) = 0;\r
- /** returns true if a and b are equal in the current context */\r
- virtual bool areEqual( Node a, Node b ) = 0;\r
- /** returns true is a and b are disequal in the current context */\r
- virtual bool areDisequal( Node a, Node b ) = 0;\r
- /** get the equality engine associated with this query */\r
- virtual eq::EqualityEngine* getEngine() = 0;\r
- /** get the equivalence class of a */\r
- virtual void getEquivalenceClass( Node a, std::vector< Node >& eqc ) = 0;\r
-};/* class EqualityQuery */\r
-\r
-}\r
-}\r
-\r
-#endif\r
+/********************* */
+/*! \file quant_util.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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 quantifier util
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANT_UTIL_H
+#define __CVC4__THEORY__QUANT_UTIL_H
+
+#include "theory/theory.h"
+#include "theory/uf/equality_engine.h"
+
+#include <ext/hash_set>
+#include <iostream>
+#include <map>
+
+namespace CVC4 {
+namespace theory {
+
+
+class QuantRelevance
+{
+private:
+ /** for computing relavance */
+ bool d_computeRel;
+ /** map from quantifiers to symbols they contain */
+ std::map< Node, std::vector< Node > > d_syms;
+ /** map from symbols to quantifiers */
+ std::map< Node, std::vector< Node > > d_syms_quants;
+ /** relevance for quantifiers and symbols */
+ std::map< Node, int > d_relevance;
+ /** compute symbols */
+ void computeSymbols( Node n, std::vector< Node >& syms );
+public:
+ QuantRelevance( bool cr ) : d_computeRel( cr ){}
+ ~QuantRelevance(){}
+ /** register quantifier */
+ void registerQuantifier( Node f );
+ /** set relevance */
+ void setRelevance( Node s, int r );
+ /** get relevance */
+ int getRelevance( Node s ) { return d_relevance.find( s )==d_relevance.end() ? -1 : d_relevance[s]; }
+ /** get number of quantifiers for symbol s */
+ int getNumQuantifiersForSymbol( Node s ) { return (int)d_syms_quants[s].size(); }
+};
+
+class QuantPhaseReq
+{
+private:
+ /** helper functions compute phase requirements */
+ void computePhaseReqs( Node n, bool polarity, std::map< Node, int >& phaseReqs );
+public:
+ QuantPhaseReq( Node n, bool computeEq = false );
+ ~QuantPhaseReq(){}
+ /** is phase required */
+ bool isPhaseReq( Node lit ) { return d_phase_reqs.find( lit )!=d_phase_reqs.end(); }
+ /** get phase requirement */
+ bool getPhaseReq( Node lit ) { return d_phase_reqs.find( lit )==d_phase_reqs.end() ? false : d_phase_reqs[ lit ]; }
+ /** phase requirements for each quantifier for each instantiation literal */
+ std::map< Node, bool > d_phase_reqs;
+ std::map< Node, bool > d_phase_reqs_equality;
+ std::map< Node, Node > d_phase_reqs_equality_term;
+};
+
+
+class EqualityQuery {
+public:
+ EqualityQuery(){}
+ virtual ~EqualityQuery(){};
+ /** reset */
+ virtual void reset() = 0;
+ /** contains term */
+ virtual bool hasTerm( Node a ) = 0;
+ /** get the representative of the equivalence class of a */
+ virtual Node getRepresentative( Node a ) = 0;
+ /** returns true if a and b are equal in the current context */
+ virtual bool areEqual( Node a, Node b ) = 0;
+ /** returns true is a and b are disequal in the current context */
+ virtual bool areDisequal( Node a, Node b ) = 0;
+ /** get the equality engine associated with this query */
+ virtual eq::EqualityEngine* getEngine() = 0;
+ /** get the equivalence class of a */
+ virtual void getEquivalenceClass( Node a, std::vector< Node >& eqc ) = 0;
+};/* class EqualityQuery */
+
+}
+}
+
+#endif
/********************* */
/*! \file quantifiers_attributes.cpp
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** 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 Implementation of QuantifiersAttributes class\r
- **/\r
-\r
-#include "theory/quantifiers/quantifiers_attributes.h"\r
-#include "theory/quantifiers/options.h"\r
-\r
-using namespace std;\r
-using namespace CVC4;\r
-using namespace CVC4::kind;\r
-using namespace CVC4::context;\r
-using namespace CVC4::theory;\r
-using namespace CVC4::theory::quantifiers;\r
-\r
-void QuantifiersAttributes::setUserAttribute( const std::string& attr, Node n ){\r
- if( n.getKind()==FORALL ){\r
- if( attr=="axiom" ){\r
- Trace("quant-attr") << "Set axiom " << n << std::endl;\r
- AxiomAttribute aa;\r
- n.setAttribute( aa, true );\r
- }else if( attr=="conjecture" ){\r
- Trace("quant-attr") << "Set conjecture " << n << std::endl;\r
- ConjectureAttribute ca;\r
- n.setAttribute( ca, true );\r
- }\r
- }else{\r
- for( size_t i=0; i<n.getNumChildren(); i++ ){\r
- setUserAttribute( attr, n[i] );\r
- }\r
- }\r
-}\r
+ ** \brief Implementation of QuantifiersAttributes class
+ **/
+
+#include "theory/quantifiers/quantifiers_attributes.h"
+#include "theory/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;
+
+void QuantifiersAttributes::setUserAttribute( const std::string& attr, Node n ){
+ if( n.getKind()==FORALL ){
+ if( attr=="axiom" ){
+ Trace("quant-attr") << "Set axiom " << n << std::endl;
+ AxiomAttribute aa;
+ n.setAttribute( aa, true );
+ }else if( attr=="conjecture" ){
+ Trace("quant-attr") << "Set conjecture " << n << std::endl;
+ ConjectureAttribute ca;
+ n.setAttribute( ca, true );
+ }
+ }else{
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ setUserAttribute( attr, n[i] );
+ }
+ }
+}
/********************* */
/*! \file quantifiers_attributes.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** 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 Attributes for the theory quantifiers\r
- **\r
- ** Attributes for the theory quantifiers.\r
- **/\r
-\r
-#include "cvc4_private.h"\r
-\r
-#ifndef __CVC4__THEORY__QUANTIFIERS__QUANTIFIERS_REWRITER_H\r
-#define __CVC4__THEORY__QUANTIFIERS__QUANTIFIERS_REWRITER_H\r
-\r
-#include "theory/rewriter.h"\r
-#include "theory/quantifiers_engine.h"\r
-\r
-namespace CVC4 {\r
-namespace theory {\r
-namespace quantifiers {\r
-\r
-/** Attribute true for quantifiers that are axioms */\r
-struct AxiomAttributeId {};\r
-typedef expr::Attribute< AxiomAttributeId, bool > AxiomAttribute;\r
-\r
-/** Attribute true for quantifiers that are conjecture */\r
-struct ConjectureAttributeId {};\r
-typedef expr::Attribute< ConjectureAttributeId, bool > ConjectureAttribute;\r
-\r
-struct QuantifiersAttributes\r
-{\r
- /** set user attribute\r
- * This function will apply a custom set of attributes to all top-level universal\r
- * quantifiers contained in n\r
- */\r
- static void setUserAttribute( const std::string& attr, Node n );\r
-};\r
-\r
-\r
-}\r
-}\r
-}\r
-\r
-#endif\r
+ ** \brief Attributes for the theory quantifiers
+ **
+ ** Attributes for the theory quantifiers.
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANTIFIERS__QUANTIFIERS_REWRITER_H
+#define __CVC4__THEORY__QUANTIFIERS__QUANTIFIERS_REWRITER_H
+
+#include "theory/rewriter.h"
+#include "theory/quantifiers_engine.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+/** Attribute true for quantifiers that are axioms */
+struct AxiomAttributeId {};
+typedef expr::Attribute< AxiomAttributeId, bool > AxiomAttribute;
+
+/** Attribute true for quantifiers that are conjecture */
+struct ConjectureAttributeId {};
+typedef expr::Attribute< ConjectureAttributeId, bool > ConjectureAttribute;
+
+struct QuantifiersAttributes
+{
+ /** set user attribute
+ * This function will apply a custom set of attributes to all top-level universal
+ * quantifiers contained in n
+ */
+ static void setUserAttribute( const std::string& attr, Node n );
+};
+
+
+}
+}
+}
+
+#endif
/********************* */
/*! \file rep_set.cpp
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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 Implementation of representative set\r
- **/\r
-\r
-#include "theory/rep_set.h"\r
-#include "theory/type_enumerator.h"\r
-\r
-using namespace std;\r
-using namespace CVC4;\r
-using namespace CVC4::kind;\r
-using namespace CVC4::context;\r
-using namespace CVC4::theory;\r
-\r
-void RepSet::clear(){\r
- d_type_reps.clear();\r
- d_type_complete.clear();\r
- d_tmap.clear();\r
-}\r
-\r
-int RepSet::getNumRepresentatives( TypeNode tn ) const{\r
- std::map< TypeNode, std::vector< Node > >::const_iterator it = d_type_reps.find( tn );\r
- if( it!=d_type_reps.end() ){\r
- return (int)it->second.size();\r
- }else{\r
- return 0;\r
- }\r
-}\r
-\r
-void RepSet::add( Node n ){\r
- TypeNode t = n.getType();\r
- d_tmap[ n ] = (int)d_type_reps[t].size();\r
- d_type_reps[t].push_back( n );\r
-}\r
-\r
-int RepSet::getIndexFor( Node n ) const {\r
- std::map< Node, int >::const_iterator it = d_tmap.find( n );\r
- if( it!=d_tmap.end() ){\r
- return it->second;\r
- }else{\r
- return -1;\r
- }\r
-}\r
-\r
-void RepSet::complete( TypeNode t ){\r
- if( d_type_complete.find( t )==d_type_complete.end() ){\r
- d_type_complete[t] = true;\r
- TypeEnumerator te(t);\r
- while( !te.isFinished() ){\r
- Node n = *te;\r
- if( std::find( d_type_reps[t].begin(), d_type_reps[t].end(), n )==d_type_reps[t].end() ){\r
- add( n );\r
- }\r
- ++te;\r
- }\r
- for( size_t i=0; i<d_type_reps[t].size(); i++ ){\r
- Trace("reps-complete") << d_type_reps[t][i] << " ";\r
- }\r
- Trace("reps-complete") << std::endl;\r
- }\r
-}\r
-\r
-void RepSet::toStream(std::ostream& out){\r
-#if 0\r
- for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){\r
- out << it->first << " : " << std::endl;\r
- for( int i=0; i<(int)it->second.size(); i++ ){\r
- out << " " << i << ": " << it->second[i] << std::endl;\r
- }\r
- }\r
-#else\r
- for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){\r
- if( !it->first.isFunction() && !it->first.isPredicate() ){\r
- out << "(" << it->first << " " << it->second.size();\r
- out << " (";\r
- for( int i=0; i<(int)it->second.size(); i++ ){\r
- if( i>0 ){ out << " "; }\r
- out << it->second[i];\r
- }\r
- out << ")";\r
- out << ")" << std::endl;\r
- }\r
- }\r
-#endif\r
-}\r
-\r
-\r
-RepSetIterator::RepSetIterator( RepSet* rs ) : d_rep_set( rs ){\r
- d_incomplete = false;\r
-\r
-}\r
-\r
-bool RepSetIterator::setQuantifier( Node f ){\r
- Assert( d_types.empty() );\r
- //store indicies\r
- for( size_t i=0; i<f[0].getNumChildren(); i++ ){\r
- d_types.push_back( f[0][i].getType() );\r
- }\r
- return initialize();\r
-}\r
-\r
-bool RepSetIterator::setFunctionDomain( Node op ){\r
- Assert( d_types.empty() );\r
- TypeNode tn = op.getType();\r
- for( size_t i=0; i<tn.getNumChildren()-1; i++ ){\r
- d_types.push_back( tn[i] );\r
- }\r
- return initialize();\r
-}\r
-\r
-bool RepSetIterator::initialize(){\r
- for( size_t i=0; i<d_types.size(); i++ ){\r
- d_index.push_back( 0 );\r
- //store default index order\r
- d_index_order.push_back( i );\r
- d_var_order[i] = i;\r
- //store default domain\r
- d_domain.push_back( RepDomain() );\r
- TypeNode tn = d_types[i];\r
- if( tn.isSort() ){\r
- if( !d_rep_set->hasType( tn ) ){\r
- Node var = NodeManager::currentNM()->mkSkolem( "repSet_$$", tn, "is a variable created by the RepSetIterator" );\r
- Trace("mkVar") << "RepSetIterator:: Make variable " << var << " : " << tn << std::endl;\r
- d_rep_set->add( var );\r
- }\r
- }else if( tn.isInteger() || tn.isReal() ){\r
- Trace("fmf-incomplete") << "Incomplete because of infinite type " << tn << std::endl;\r
- d_incomplete = true;\r
- }else if( tn.isDatatype() ){\r
- const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();\r
- //if finite, then complete all values of the domain\r
- if( dt.isFinite() ){\r
- d_rep_set->complete( tn );\r
- //d_incomplete = true;\r
- }else{\r
- Trace("fmf-incomplete") << "Incomplete because of infinite datatype " << tn << std::endl;\r
- d_incomplete = true;\r
- }\r
- }else{\r
- Trace("fmf-incomplete") << "Incomplete because of unknown type " << tn << std::endl;\r
- d_incomplete = true;\r
- }\r
- if( d_rep_set->hasType( tn ) ){\r
- for( size_t j=0; j<d_rep_set->d_type_reps[tn].size(); j++ ){\r
- d_domain[i].push_back( j );\r
- }\r
- }else{\r
- return false;\r
- }\r
- }\r
- return true;\r
-}\r
-\r
-void RepSetIterator::setIndexOrder( std::vector< int >& indexOrder ){\r
- d_index_order.clear();\r
- d_index_order.insert( d_index_order.begin(), indexOrder.begin(), indexOrder.end() );\r
- //make the d_var_order mapping\r
- for( int i=0; i<(int)d_index_order.size(); i++ ){\r
- d_var_order[d_index_order[i]] = i;\r
- }\r
-}\r
-\r
-void RepSetIterator::setDomain( std::vector< RepDomain >& domain ){\r
- d_domain.clear();\r
- d_domain.insert( d_domain.begin(), domain.begin(), domain.end() );\r
- //we are done if a domain is empty\r
- for( int i=0; i<(int)d_domain.size(); i++ ){\r
- if( d_domain[i].empty() ){\r
- d_index.clear();\r
- }\r
- }\r
-}\r
-\r
-void RepSetIterator::increment2( int counter ){\r
- Assert( !isFinished() );\r
-#ifdef DISABLE_EVAL_SKIP_MULTIPLE\r
- counter = (int)d_index.size()-1;\r
-#endif\r
- //increment d_index\r
- while( counter>=0 && d_index[counter]==(int)(d_domain[counter].size()-1) ){\r
- counter--;\r
- }\r
- if( counter==-1 ){\r
- d_index.clear();\r
- }else{\r
- for( int i=(int)d_index.size()-1; i>counter; i-- ){\r
- d_index[i] = 0;\r
- }\r
- d_index[counter]++;\r
- }\r
-}\r
-\r
-void RepSetIterator::increment(){\r
- if( !isFinished() ){\r
- increment2( (int)d_index.size()-1 );\r
- }\r
-}\r
-\r
-bool RepSetIterator::isFinished(){\r
- return d_index.empty();\r
-}\r
-\r
-Node RepSetIterator::getTerm( int i ){\r
- TypeNode tn = d_types[d_index_order[i]];\r
- Assert( d_rep_set->d_type_reps.find( tn )!=d_rep_set->d_type_reps.end() );\r
- int index = d_index_order[i];\r
- return d_rep_set->d_type_reps[tn][d_domain[index][d_index[index]]];\r
-}\r
-\r
-void RepSetIterator::debugPrint( const char* c ){\r
- for( int i=0; i<(int)d_index.size(); i++ ){\r
- Debug( c ) << i << " : " << d_index[i] << " : " << getTerm( i ) << std::endl;\r
- }\r
-}\r
-\r
-void RepSetIterator::debugPrintSmall( const char* c ){\r
- Debug( c ) << "RI: ";\r
- for( int i=0; i<(int)d_index.size(); i++ ){\r
- Debug( c ) << d_index[i] << ": " << getTerm( i ) << " ";\r
- }\r
- Debug( c ) << std::endl;\r
-}\r
+ ** \brief Implementation of representative set
+ **/
+
+#include "theory/rep_set.h"
+#include "theory/type_enumerator.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+
+void RepSet::clear(){
+ d_type_reps.clear();
+ d_type_complete.clear();
+ d_tmap.clear();
+}
+
+int RepSet::getNumRepresentatives( TypeNode tn ) const{
+ std::map< TypeNode, std::vector< Node > >::const_iterator it = d_type_reps.find( tn );
+ if( it!=d_type_reps.end() ){
+ return (int)it->second.size();
+ }else{
+ return 0;
+ }
+}
+
+void RepSet::add( Node n ){
+ TypeNode t = n.getType();
+ d_tmap[ n ] = (int)d_type_reps[t].size();
+ d_type_reps[t].push_back( n );
+}
+
+int RepSet::getIndexFor( Node n ) const {
+ std::map< Node, int >::const_iterator it = d_tmap.find( n );
+ if( it!=d_tmap.end() ){
+ return it->second;
+ }else{
+ return -1;
+ }
+}
+
+void RepSet::complete( TypeNode t ){
+ if( d_type_complete.find( t )==d_type_complete.end() ){
+ d_type_complete[t] = true;
+ TypeEnumerator te(t);
+ while( !te.isFinished() ){
+ Node n = *te;
+ if( std::find( d_type_reps[t].begin(), d_type_reps[t].end(), n )==d_type_reps[t].end() ){
+ add( n );
+ }
+ ++te;
+ }
+ for( size_t i=0; i<d_type_reps[t].size(); i++ ){
+ Trace("reps-complete") << d_type_reps[t][i] << " ";
+ }
+ Trace("reps-complete") << std::endl;
+ }
+}
+
+void RepSet::toStream(std::ostream& out){
+#if 0
+ for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){
+ out << it->first << " : " << std::endl;
+ for( int i=0; i<(int)it->second.size(); i++ ){
+ out << " " << i << ": " << it->second[i] << std::endl;
+ }
+ }
+#else
+ for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){
+ if( !it->first.isFunction() && !it->first.isPredicate() ){
+ out << "(" << it->first << " " << it->second.size();
+ out << " (";
+ for( int i=0; i<(int)it->second.size(); i++ ){
+ if( i>0 ){ out << " "; }
+ out << it->second[i];
+ }
+ out << ")";
+ out << ")" << std::endl;
+ }
+ }
+#endif
+}
+
+
+RepSetIterator::RepSetIterator( RepSet* rs ) : d_rep_set( rs ){
+ d_incomplete = false;
+
+}
+
+bool RepSetIterator::setQuantifier( Node f ){
+ Assert( d_types.empty() );
+ //store indicies
+ for( size_t i=0; i<f[0].getNumChildren(); i++ ){
+ d_types.push_back( f[0][i].getType() );
+ }
+ return initialize();
+}
+
+bool RepSetIterator::setFunctionDomain( Node op ){
+ Assert( d_types.empty() );
+ TypeNode tn = op.getType();
+ for( size_t i=0; i<tn.getNumChildren()-1; i++ ){
+ d_types.push_back( tn[i] );
+ }
+ return initialize();
+}
+
+bool RepSetIterator::initialize(){
+ for( size_t i=0; i<d_types.size(); i++ ){
+ d_index.push_back( 0 );
+ //store default index order
+ d_index_order.push_back( i );
+ d_var_order[i] = i;
+ //store default domain
+ d_domain.push_back( RepDomain() );
+ TypeNode tn = d_types[i];
+ if( tn.isSort() ){
+ if( !d_rep_set->hasType( tn ) ){
+ Node var = NodeManager::currentNM()->mkSkolem( "repSet_$$", tn, "is a variable created by the RepSetIterator" );
+ Trace("mkVar") << "RepSetIterator:: Make variable " << var << " : " << tn << std::endl;
+ d_rep_set->add( var );
+ }
+ }else if( tn.isInteger() || tn.isReal() ){
+ Trace("fmf-incomplete") << "Incomplete because of infinite type " << tn << std::endl;
+ d_incomplete = true;
+ }else if( tn.isDatatype() ){
+ const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ //if finite, then complete all values of the domain
+ if( dt.isFinite() ){
+ d_rep_set->complete( tn );
+ //d_incomplete = true;
+ }else{
+ Trace("fmf-incomplete") << "Incomplete because of infinite datatype " << tn << std::endl;
+ d_incomplete = true;
+ }
+ }else{
+ Trace("fmf-incomplete") << "Incomplete because of unknown type " << tn << std::endl;
+ d_incomplete = true;
+ }
+ if( d_rep_set->hasType( tn ) ){
+ for( size_t j=0; j<d_rep_set->d_type_reps[tn].size(); j++ ){
+ d_domain[i].push_back( j );
+ }
+ }else{
+ return false;
+ }
+ }
+ return true;
+}
+
+void RepSetIterator::setIndexOrder( std::vector< int >& indexOrder ){
+ d_index_order.clear();
+ d_index_order.insert( d_index_order.begin(), indexOrder.begin(), indexOrder.end() );
+ //make the d_var_order mapping
+ for( int i=0; i<(int)d_index_order.size(); i++ ){
+ d_var_order[d_index_order[i]] = i;
+ }
+}
+
+void RepSetIterator::setDomain( std::vector< RepDomain >& domain ){
+ d_domain.clear();
+ d_domain.insert( d_domain.begin(), domain.begin(), domain.end() );
+ //we are done if a domain is empty
+ for( int i=0; i<(int)d_domain.size(); i++ ){
+ if( d_domain[i].empty() ){
+ d_index.clear();
+ }
+ }
+}
+
+void RepSetIterator::increment2( int counter ){
+ Assert( !isFinished() );
+#ifdef DISABLE_EVAL_SKIP_MULTIPLE
+ counter = (int)d_index.size()-1;
+#endif
+ //increment d_index
+ while( counter>=0 && d_index[counter]==(int)(d_domain[counter].size()-1) ){
+ counter--;
+ }
+ if( counter==-1 ){
+ d_index.clear();
+ }else{
+ for( int i=(int)d_index.size()-1; i>counter; i-- ){
+ d_index[i] = 0;
+ }
+ d_index[counter]++;
+ }
+}
+
+void RepSetIterator::increment(){
+ if( !isFinished() ){
+ increment2( (int)d_index.size()-1 );
+ }
+}
+
+bool RepSetIterator::isFinished(){
+ return d_index.empty();
+}
+
+Node RepSetIterator::getTerm( int i ){
+ TypeNode tn = d_types[d_index_order[i]];
+ Assert( d_rep_set->d_type_reps.find( tn )!=d_rep_set->d_type_reps.end() );
+ int index = d_index_order[i];
+ return d_rep_set->d_type_reps[tn][d_domain[index][d_index[index]]];
+}
+
+void RepSetIterator::debugPrint( const char* c ){
+ for( int i=0; i<(int)d_index.size(); i++ ){
+ Debug( c ) << i << " : " << d_index[i] << " : " << getTerm( i ) << std::endl;
+ }
+}
+
+void RepSetIterator::debugPrintSmall( const char* c ){
+ Debug( c ) << "RI: ";
+ for( int i=0; i<(int)d_index.size(); i++ ){
+ Debug( c ) << d_index[i] << ": " << getTerm( i ) << " ";
+ }
+ Debug( c ) << std::endl;
+}
/********************* */
/*! \file rep_set.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** 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 Representative set class and utilities\r
- **/\r
-\r
-#include "cvc4_private.h"\r
-\r
-#ifndef __CVC4__REP_SET_H\r
-#define __CVC4__REP_SET_H\r
-\r
-#include "expr/node.h"\r
-#include <map>\r
-\r
-namespace CVC4 {\r
-namespace theory {\r
-\r
-/** this class stores a representative set */\r
-class RepSet {\r
-public:\r
- RepSet(){}\r
- ~RepSet(){}\r
- std::map< TypeNode, std::vector< Node > > d_type_reps;\r
- std::map< TypeNode, bool > d_type_complete;\r
- std::map< Node, int > d_tmap;\r
- /** clear the set */\r
- void clear();\r
- /** has type */\r
- bool hasType( TypeNode tn ) const { return d_type_reps.find( tn )!=d_type_reps.end(); }\r
- /** get cardinality for type */\r
- int getNumRepresentatives( TypeNode tn ) const;\r
- /** add representative for type */\r
- void add( Node n );\r
- /** returns index in d_type_reps for node n */\r
- int getIndexFor( Node n ) const;\r
- /** complete all values */\r
- void complete( TypeNode t );\r
- /** debug print */\r
- void toStream(std::ostream& out);\r
-};\r
-\r
-//representative domain\r
-typedef std::vector< int > RepDomain;\r
-\r
-/** this class iterates over a RepSet */\r
-class RepSetIterator {\r
-private:\r
- //initialize function\r
- bool initialize();\r
-public:\r
- RepSetIterator( RepSet* rs );\r
- ~RepSetIterator(){}\r
- //set that this iterator will be iterating over instantiations for a quantifier\r
- bool setQuantifier( Node f );\r
- //set that this iterator will be iterating over the domain of a function\r
- bool setFunctionDomain( Node op );\r
-public:\r
- //pointer to model\r
- RepSet* d_rep_set;\r
- //index we are considering\r
- std::vector< int > d_index;\r
- //types we are considering\r
- std::vector< TypeNode > d_types;\r
- //domain we are considering\r
- std::vector< RepDomain > d_domain;\r
- //are we only considering a strict subset of the domain of the quantifier?\r
- bool d_incomplete;\r
- //ordering for variables we are indexing over\r
- // for example, given reps = { a, b } and quantifier forall( x, y, z ) P( x, y, z ) with d_index_order = { 2, 0, 1 },\r
- // then we consider instantiations in this order:\r
- // a/x a/y a/z\r
- // a/x b/y a/z\r
- // b/x a/y a/z\r
- // b/x b/y a/z\r
- // ...\r
- std::vector< int > d_index_order;\r
- //variables to index they are considered at\r
- // for example, if d_index_order = { 2, 0, 1 }\r
- // then d_var_order = { 0 -> 1, 1 -> 2, 2 -> 0 }\r
- std::map< int, int > d_var_order;\r
-public:\r
- /** set index order */\r
- void setIndexOrder( std::vector< int >& indexOrder );\r
- /** set domain */\r
- void setDomain( std::vector< RepDomain >& domain );\r
- /** increment the iterator at index=counter */\r
- void increment2( int counter );\r
- /** increment the iterator */\r
- void increment();\r
- /** is the iterator finished? */\r
- bool isFinished();\r
- /** get the i_th term we are considering */\r
- Node getTerm( int i );\r
- /** get the number of terms we are considering */\r
- int getNumTerms() { return (int)d_index_order.size(); }\r
- /** debug print */\r
- void debugPrint( const char* c );\r
- void debugPrintSmall( const char* c );\r
-};\r
-\r
-}\r
-}\r
-\r
+ ** \brief Representative set class and utilities
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__REP_SET_H
+#define __CVC4__REP_SET_H
+
+#include "expr/node.h"
+#include <map>
+
+namespace CVC4 {
+namespace theory {
+
+/** this class stores a representative set */
+class RepSet {
+public:
+ RepSet(){}
+ ~RepSet(){}
+ std::map< TypeNode, std::vector< Node > > d_type_reps;
+ std::map< TypeNode, bool > d_type_complete;
+ std::map< Node, int > d_tmap;
+ /** clear the set */
+ void clear();
+ /** has type */
+ bool hasType( TypeNode tn ) const { return d_type_reps.find( tn )!=d_type_reps.end(); }
+ /** get cardinality for type */
+ int getNumRepresentatives( TypeNode tn ) const;
+ /** add representative for type */
+ void add( Node n );
+ /** returns index in d_type_reps for node n */
+ int getIndexFor( Node n ) const;
+ /** complete all values */
+ void complete( TypeNode t );
+ /** debug print */
+ void toStream(std::ostream& out);
+};
+
+//representative domain
+typedef std::vector< int > RepDomain;
+
+/** this class iterates over a RepSet */
+class RepSetIterator {
+private:
+ //initialize function
+ bool initialize();
+public:
+ RepSetIterator( RepSet* rs );
+ ~RepSetIterator(){}
+ //set that this iterator will be iterating over instantiations for a quantifier
+ bool setQuantifier( Node f );
+ //set that this iterator will be iterating over the domain of a function
+ bool setFunctionDomain( Node op );
+public:
+ //pointer to model
+ RepSet* d_rep_set;
+ //index we are considering
+ std::vector< int > d_index;
+ //types we are considering
+ std::vector< TypeNode > d_types;
+ //domain we are considering
+ std::vector< RepDomain > d_domain;
+ //are we only considering a strict subset of the domain of the quantifier?
+ bool d_incomplete;
+ //ordering for variables we are indexing over
+ // for example, given reps = { a, b } and quantifier forall( x, y, z ) P( x, y, z ) with d_index_order = { 2, 0, 1 },
+ // then we consider instantiations in this order:
+ // a/x a/y a/z
+ // a/x b/y a/z
+ // b/x a/y a/z
+ // b/x b/y a/z
+ // ...
+ std::vector< int > d_index_order;
+ //variables to index they are considered at
+ // for example, if d_index_order = { 2, 0, 1 }
+ // then d_var_order = { 0 -> 1, 1 -> 2, 2 -> 0 }
+ std::map< int, int > d_var_order;
+public:
+ /** set index order */
+ void setIndexOrder( std::vector< int >& indexOrder );
+ /** set domain */
+ void setDomain( std::vector< RepDomain >& domain );
+ /** increment the iterator at index=counter */
+ void increment2( int counter );
+ /** increment the iterator */
+ void increment();
+ /** is the iterator finished? */
+ bool isFinished();
+ /** get the i_th term we are considering */
+ Node getTerm( int i );
+ /** get the number of terms we are considering */
+ int getNumTerms() { return (int)d_index_order.size(); }
+ /** debug print */
+ void debugPrint( const char* c );
+ void debugPrintSmall( const char* c );
+};
+
+}
+}
+
#endif
\ No newline at end of file
-/********************* */\r
-/*! \file efficient_e_matching.cpp\r
- ** \verbatim\r
- ** Original author: ajreynol\r
- ** Major contributors: bobot\r
- ** Minor contributors (to current version): mdeters\r
- ** This file is part of the CVC4 prototype.\r
- ** Copyright (c) 2009-2012 New York University and The University of Iowa\r
- ** See the file COPYING in the top-level source directory for licensing\r
- ** information.\endverbatim\r
- **\r
- ** \brief Implementation of theory uf instantiator class\r
- **/\r
-\r
-#include "theory/rewriterules/efficient_e_matching.h"\r
-#include "theory/rewriterules/rr_candidate_generator.h"\r
-#include "theory/quantifiers/candidate_generator.h"\r
-#include "theory/quantifiers/options.h"\r
-#include "theory/rewriterules/options.h"\r
-#include "theory/quantifiers/term_database.h"\r
-\r
-#include "theory/theory_engine.h"\r
-\r
-using namespace std;\r
-using namespace CVC4;\r
-using namespace CVC4::kind;\r
-using namespace CVC4::context;\r
-using namespace CVC4::theory;\r
-using namespace CVC4::theory::inst;\r
-\r
-namespace CVC4 {\r
-namespace theory {\r
-\r
-inline std::ostream& operator<<(std::ostream& out, const EfficientEMatcher::Ips& ips) {\r
- return out;\r
-};\r
-\r
-EqClassInfo::EqClassInfo( context::Context* c ) : d_funs( c ), d_pfuns( c ), d_disequal( c ){\r
-\r
-}\r
-\r
-//set member\r
-void EqClassInfo::setMember( Node n, quantifiers::TermDb* db ){\r
- if( n.hasOperator() ){\r
- d_funs.insertAtContextLevelZero(n.getOperator(),true);\r
- }\r
- //add parent functions\r
- for( std::hash_map< Node, std::hash_map< int, std::vector< Node > >, NodeHashFunction >::iterator it = db->d_parents[n].begin();\r
- it != db->d_parents[n].end(); ++it ){\r
- //TODO Is it true to do it at level 0? That depend when SetMember is called\r
- // At worst it is a good overapproximation\r
- d_pfuns.insertAtContextLevelZero( it->first, true);\r
- }\r
-}\r
-\r
-//get has function\r
-bool EqClassInfo::hasFunction( Node op ){\r
- return d_funs.find( op )!=d_funs.end();\r
-}\r
-\r
-bool EqClassInfo::hasParent( Node op ){\r
- return d_pfuns.find( op )!=d_pfuns.end();\r
-}\r
-\r
-//merge with another eq class info\r
-void EqClassInfo::merge( EqClassInfo* eci ){\r
- for( BoolMap::iterator it = eci->d_funs.begin(); it != eci->d_funs.end(); it++ ) {\r
- d_funs[ (*it).first ] = true;\r
- }\r
- for( BoolMap::iterator it = eci->d_pfuns.begin(); it != eci->d_pfuns.end(); it++ ) {\r
- d_pfuns[ (*it).first ] = true;\r
- }\r
-}\r
-\r
-inline void outputEqClassInfo( const char* c, const EqClassInfo* eci){\r
- Debug(c) << " funs:";\r
- for( EqClassInfo::BoolMap::iterator it = eci->d_funs.begin(); it != eci->d_funs.end(); it++ ) {\r
- Debug(c) << (*it).first << ",";\r
- }\r
- Debug(c) << std::endl << "pfuns:";\r
- for( EqClassInfo::BoolMap::iterator it = eci->d_pfuns.begin(); it != eci->d_pfuns.end(); it++ ) {\r
- Debug(c) << (*it).first << ",";\r
- }\r
- Debug(c) << std::endl;\r
-}\r
-\r
-\r
-\r
-EfficientEMatcher::EfficientEMatcher( CVC4::theory::QuantifiersEngine* qe ) : d_quantEngine( qe )\r
-{\r
-\r
-}\r
-\r
-eq::EqualityEngine* EfficientEMatcher::getEqualityEngine(){\r
- //return ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->theoryOf( THEORY_UF ))->getEqualityEngine();\r
- return d_quantEngine->getMasterEqualityEngine();\r
-}\r
-\r
-/** new node */\r
-void EfficientEMatcher::newEqClass( TNode n ){\r
-\r
-}\r
-\r
-void EfficientEMatcher::newTerms(SetNode& s){\r
- static NoMatchAttribute rewrittenNodeAttribute;\r
- /* op -> nodes (if the set is empty, the op is not interesting) */\r
- std::hash_map< TNode, SetNode, TNodeHashFunction > h;\r
- /* types -> nodes (if the set is empty, the type is not interesting) */\r
- std::hash_map< TypeNode, SetNode, TypeNodeHashFunction > tyh;\r
- for(SetNode::iterator i=s.begin(), end=s.end(); i != end; ++i){\r
- if (i->getAttribute(rewrittenNodeAttribute)) continue; /* skip it */\r
- if( !d_cand_gens.empty() ){\r
- // op\r
- TNode op = i->getOperator();\r
- std::hash_map< TNode, SetNode, TNodeHashFunction >::iterator\r
- is = h.find(op);\r
- if(is == h.end()){\r
- std::pair<std::hash_map< TNode, SetNode, TNodeHashFunction >::iterator,bool>\r
- p = h.insert(make_pair(op,SetNode()));\r
- is = p.first;\r
- if(d_cand_gens.find(op) != d_cand_gens.end()){\r
- is->second.insert(*i);\r
- } /* else we have inserted an empty set */\r
- }else if(!is->second.empty()){\r
- is->second.insert(*i);\r
- }\r
- }\r
- if( !d_cand_gen_types.empty() ){\r
- //type\r
- TypeNode ty = i->getType();\r
- std::hash_map< TypeNode, SetNode, TypeNodeHashFunction >::iterator\r
- is = tyh.find(ty);\r
- if(is == tyh.end()){\r
- std::pair<std::hash_map< TypeNode, SetNode, TypeNodeHashFunction >::iterator,bool>\r
- p = tyh.insert(make_pair(ty,SetNode()));\r
- is = p.first;\r
- if(d_cand_gen_types.find(ty) != d_cand_gen_types.end()){\r
- is->second.insert(*i);\r
- } /* else we have inserted an empty set */\r
- }else if(!is->second.empty()){\r
- is->second.insert(*i);\r
- }\r
- }\r
- }\r
- //op\r
- for(std::hash_map< TNode, SetNode, TNodeHashFunction >::iterator i=h.begin(), end=h.end();\r
- i != end; ++i){\r
- //new term, add n to candidate generators\r
- if(i->second.empty()) continue;\r
- std::map< Node, NodeNewTermDispatcher >::iterator\r
- inpc = d_cand_gens.find(i->first);\r
- //we know that this op exists\r
- Assert(inpc != d_cand_gens.end());\r
- inpc->second.send(i->second);\r
- }\r
- //type\r
- for(std::hash_map< TypeNode, SetNode, TypeNodeHashFunction >::iterator i=tyh.begin(), end=tyh.end();\r
- i != end; ++i){\r
- //new term, add n to candidate generators\r
- if(i->second.empty()) continue;\r
- std::map< TypeNode, NodeNewTermDispatcher >::iterator\r
- inpc = d_cand_gen_types.find(i->first);\r
- //we know that this op exists\r
- Assert(inpc != d_cand_gen_types.end());\r
- inpc->second.send(i->second);\r
- }\r
-\r
-}\r
-\r
-\r
-/** merge */\r
-void EfficientEMatcher::merge( TNode a, TNode b ){\r
- if( options::efficientEMatching() ){\r
- //merge eqc_ops of b into a\r
- EqClassInfo* eci_a = getOrCreateEquivalenceClassInfo( a );\r
- EqClassInfo* eci_b = getOrCreateEquivalenceClassInfo( b );\r
-\r
- if( a.getKind()!=IFF && a.getKind()!=EQUAL && b.getKind()!=IFF && b.getKind()!=EQUAL ){\r
- Debug("efficient-e-match") << "Merging " << a << " with " << b << std::endl;\r
-\r
- //determine new candidates for instantiation\r
- computeCandidatesPcPairs( a, eci_a, b, eci_b );\r
- computeCandidatesPcPairs( b, eci_b, a, eci_a );\r
- computeCandidatesPpPairs( a, eci_a, b, eci_b );\r
- computeCandidatesPpPairs( b, eci_b, a, eci_a );\r
- }\r
- computeCandidatesConstants( a, eci_a, b, eci_b);\r
- computeCandidatesConstants( b, eci_b, a, eci_a);\r
-\r
- eci_a->merge( eci_b );\r
- }\r
-}\r
-\r
-/** assert terms are disequal */\r
-void EfficientEMatcher::assertDisequal( TNode a, TNode b, TNode reason ){\r
-\r
-}\r
-\r
-EqClassInfo* EfficientEMatcher::getEquivalenceClassInfo( Node n ) {\r
- return d_eqc_ops.find( n )==d_eqc_ops.end() ? NULL : d_eqc_ops[n];\r
-}\r
-EqClassInfo* EfficientEMatcher::getOrCreateEquivalenceClassInfo( Node n ){\r
- Assert( n==getEqualityEngine()->getRepresentative( n ) );\r
- if( d_eqc_ops.find( n )==d_eqc_ops.end() ){\r
- EqClassInfo* eci = new EqClassInfo( d_quantEngine->getSatContext() );\r
- eci->setMember( n, d_quantEngine->getTermDatabase() );\r
- d_eqc_ops[n] = eci;\r
- }\r
- return d_eqc_ops[n];\r
-}\r
-\r
-void EfficientEMatcher::computeCandidatesPcPairs( Node a, EqClassInfo* eci_a, Node b, EqClassInfo* eci_b ){\r
- Debug("efficient-e-match") << "Compute candidates for pc pairs..." << std::endl;\r
- Debug("efficient-e-match") << " Eq class = [";\r
- outputEqClass( "efficient-e-match", a);\r
- Debug("efficient-e-match") << "]" << std::endl;\r
- outputEqClassInfo("efficient-e-match",eci_a);\r
- for( EqClassInfo::BoolMap::iterator it = eci_a->d_funs.begin(); it != eci_a->d_funs.end(); it++ ) {\r
- //the child function: a member of eq_class( a ) has top symbol g, in other words g is in funs( a )\r
- Node g = (*it).first;\r
- Debug("efficient-e-match") << " Checking application " << g << std::endl;\r
- //look at all parent/child pairs\r
- for( std::map< Node, std::vector< std::pair< NodePcDispatcher*, Ips > > >::iterator itf = d_pc_pairs[g].begin();\r
- itf != d_pc_pairs[g].end(); ++itf ){\r
- //f/g is a parent/child pair\r
- Node f = itf->first;\r
- if( eci_b->hasParent( f ) ){\r
- //DO_THIS: determine if f in pfuns( b ), only do the follow if so\r
- Debug("efficient-e-match") << " Checking parent application " << f << std::endl;\r
- //scan through the list of inverted path strings/candidate generators\r
- for( std::vector< std::pair< NodePcDispatcher*, Ips > >::iterator cit = itf->second.begin();\r
- cit != itf->second.end(); ++cit ){\r
-#ifdef CVC4_DEBUG\r
- Debug("efficient-e-match") << " Checking pattern " << cit->first->pat << std::endl;\r
-#endif\r
- Debug("efficient-e-match") << " Check inverted path string for pattern ";\r
- outputIps( "efficient-e-match", cit->second );\r
- Debug("efficient-e-match") << std::endl;\r
-\r
- //collect all new relevant terms\r
- SetNode terms;\r
- terms.insert( b );\r
- collectTermsIps( cit->second, terms );\r
- if( terms.empty() ) continue;\r
- Debug("efficient-e-match") << " -> Added terms (" << terms.size() << "): ";\r
- for( SetNode::const_iterator t=terms.begin(), end=terms.end();\r
- t!=end; ++t ){\r
- Debug("efficient-e-match") << (*t) << " ";\r
- }\r
- Debug("efficient-e-match") << std::endl;\r
- //add them as candidates to the candidate generator\r
- cit->first->send(terms);\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-void EfficientEMatcher::computeCandidatesPpPairs( Node a, EqClassInfo* eci_a, Node b, EqClassInfo* eci_b ){\r
- Debug("efficient-e-match") << "Compute candidates for pp pairs..." << std::endl;\r
- for( std::map< Node, std::map< Node, std::vector< triple< NodePpDispatcher*, Ips, Ips > > > >::iterator it = d_pp_pairs.begin();\r
- it != d_pp_pairs.end(); ++it ){\r
- Node f = it->first;\r
- if( eci_a->hasParent( f ) ){\r
- Debug("efficient-e-match") << " Checking parent application " << f << std::endl;\r
- for( std::map< Node, std::vector< triple<NodePpDispatcher*, Ips, Ips> > >::iterator it2 = it->second.begin();\r
- it2 != it->second.end(); ++it2 ){\r
- Node g = it2->first;\r
- if( eci_b->hasParent( g ) ){\r
- Debug("efficient-e-match") << " Checking parent application " << g << std::endl;\r
- //if f in pfuns( a ) and g is in pfuns( b ), only do the follow if so\r
- for( std::vector< triple<NodePpDispatcher*, Ips, Ips> > ::iterator cit = it2->second.begin();\r
- cit != it2->second.end(); ++cit ){\r
-#ifdef CVC4_DEBUG\r
- Debug("efficient-e-match") << " Checking pattern " << cit->first->pat1 << " and " << cit->first->pat2 << std::endl;\r
-#endif\r
- Debug("efficient-e-match") << " Check inverted path string ";\r
- outputIps( "efficient-e-match", cit->second );\r
- SetNode a_terms;\r
- a_terms.insert( a );\r
- collectTermsIps( cit->second, a_terms );\r
- if( a_terms.empty() ) continue;\r
- Debug("efficient-e-match") << " And check inverted path string ";\r
- outputIps( "efficient-e-match", cit->third );\r
- SetNode b_terms;\r
- b_terms.insert( b );\r
- collectTermsIps( cit->third, b_terms );\r
- if( b_terms.empty() ) continue;\r
- //Start debug\r
- Debug("efficient-e-match") << " -> Possibly Added termsA (" << a_terms.size() << "): ";\r
- for( SetNode::const_iterator t=a_terms.begin(), end=a_terms.end();\r
- t!=end; ++t ){\r
- Debug("efficient-e-match") << (*t) << " ";\r
- }\r
- Debug("efficient-e-match") << std::endl;\r
- Debug("efficient-e-match") << " -> Possibly Added termsB (" << b_terms.size() << "): ";\r
- for( SetNode::const_iterator t=b_terms.begin(), end=b_terms.end();\r
- t!=end; ++t ){\r
- Debug("efficient-e-match") << (*t) << " ";\r
- }\r
- Debug("efficient-e-match") << std::endl;\r
- //End debug\r
-\r
- cit->first->send(a_terms,b_terms);\r
- }\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-\r
-void EfficientEMatcher::computeCandidatesConstants( Node a, EqClassInfo* eci_a, Node b, EqClassInfo* eci_b ){\r
- Debug("efficient-e-match") << "Compute candidates constants for cc pairs..." << std::endl;\r
- Debug("efficient-e-match") << " Eq class = [";\r
- outputEqClass( "efficient-e-match", a);\r
- Debug("efficient-e-match") << "]" << std::endl;\r
- outputEqClassInfo("efficient-e-match",eci_a);\r
- for( std::map< Node, std::map< Node, NodePcDispatcher* > >::iterator\r
- it = d_cc_pairs.begin(), end = d_cc_pairs.end();\r
- it != end; ++it ) {\r
- Debug("efficient-e-match") << " Checking application " << it->first << std::endl;\r
- if( !eci_b->hasFunction(it->first) ) continue;\r
- for( std::map< Node, NodePcDispatcher* >::iterator\r
- itc = it->second.begin(), end = it->second.end();\r
- itc != end; ++itc ) {\r
- //The constant\r
- Debug("efficient-e-match") << " Checking constant " << a << std::endl;\r
- if(getEqualityEngine()->getRepresentative(itc->first) != a) continue;\r
- SetNode s;\r
- eq::EqClassIterator eqc_iter( b, getEqualityEngine() );\r
- while( !eqc_iter.isFinished() ){\r
- Debug("efficient-e-match-debug") << "> look at " << (*eqc_iter)\r
- << std::endl;\r
- if( (*eqc_iter).hasOperator() && (*eqc_iter).getOperator() == it->first ) s.insert(*eqc_iter);\r
- eqc_iter++;\r
- }\r
-\r
- if( s.empty() ) continue;\r
- Debug("efficient-e-match") << " -> Added terms (" << s.size() << "): ";\r
- for( SetNode::const_iterator t=s.begin(), end=s.end();\r
- t!=end; ++t ){\r
- Debug("efficient-e-match") << (*t) << " ";\r
- }\r
- Debug("efficient-e-match") << std::endl;\r
- itc->second->send(s);\r
- }\r
- }\r
-}\r
-\r
-void EfficientEMatcher::collectTermsIps( Ips& ips, SetNode & terms ){\r
- Assert( ips.size() > 0);\r
- return collectTermsIps( ips, terms, ips.size() - 1);\r
-}\r
-\r
-void EfficientEMatcher::collectTermsIps( Ips& ips, SetNode& terms, int index ){\r
- if( !terms.empty() ){\r
- Debug("efficient-e-match-debug") << "> Process " << index << std::endl;\r
- Node f = ips[index].first;\r
- int arg = ips[index].second;\r
-\r
- //for each term in terms, determine if any term (modulo equality) has parent "f" from position "arg"\r
- bool addRep = ( index!=0 ); // We want to keep the top symbol for the last\r
- SetNode newTerms;\r
- for( SetNode::const_iterator t=terms.begin(), end=terms.end();\r
- t!=end; ++t ){\r
- collectParentsTermsIps( *t, f, arg, newTerms, addRep );\r
- }\r
- terms.swap(newTerms);\r
-\r
- Debug("efficient-e-match-debug") << "> Terms are now: ";\r
- for( SetNode::const_iterator t=terms.begin(), end=terms.end();\r
- t!=end; ++t ){\r
- Debug("efficient-e-match-debug") << *t << " ";\r
- }\r
- Debug("efficient-e-match-debug") << std::endl;\r
-\r
- if(index!=0) collectTermsIps( ips, terms, index-1 );\r
- }\r
-}\r
-\r
-bool EfficientEMatcher::collectParentsTermsIps( Node n, Node f, int arg, SetNode & terms, bool addRep, bool modEq ){ //modEq default true\r
- bool addedTerm = false;\r
-\r
- if( modEq && getEqualityEngine()->hasTerm( n )){\r
- Assert( getEqualityEngine()->getRepresentative( n )==n );\r
- //collect modulo equality\r
- //DO_THIS: this should (if necessary) compute a current set of (f, arg) parents for n and cache it\r
- eq::EqClassIterator eqc_iter( n, getEqualityEngine() );\r
- while( !eqc_iter.isFinished() ){\r
- Debug("efficient-e-match-debug") << "> look at " << (*eqc_iter)\r
- << std::endl;\r
- if( collectParentsTermsIps( (*eqc_iter), f, arg, terms, addRep, false ) ){\r
- //if only one argument, we know we can stop (since all others added will be congruent)\r
- if( f.getType().getNumChildren()==2 ){\r
- return true;\r
- }\r
- addedTerm = true;\r
- }\r
- eqc_iter++;\r
- }\r
- }else{\r
- quantifiers::TermDb* db = d_quantEngine->getTermDatabase();\r
- //see if parent f exists from argument arg\r
- const std::vector<Node> & parents = db->getParents(n,f,arg);\r
- for( size_t i=0; i<parents.size(); ++i ){\r
- TNode t = parents[i];\r
- if(!CandidateGenerator::isLegalCandidate(t)) continue;\r
- if( addRep ) t = getEqualityEngine()->getRepresentative( t );\r
- terms.insert(t);\r
- addedTerm = true;\r
- }\r
- }\r
- return addedTerm;\r
-}\r
-\r
-void EfficientEMatcher::registerPatternElementPairs2( Node pat, Ips& ips, PpIpsMap & pp_ips_map, NodePcDispatcher* npc ){\r
- Assert( pat.hasOperator() );\r
- //add information for possible pp-pair\r
- ips.push_back( std::pair< Node, int >( pat.getOperator(), 0 ) ); //0 is just a dumb value\r
-\r
- for( int i=0; i<(int)pat.getNumChildren(); i++ ){\r
- if( pat[i].getKind()==INST_CONSTANT ){\r
- ips.back().second = i;\r
- pp_ips_map[ pat[i] ].push_back( make_pair( pat.getOperator(), Ips( ips ) ) );\r
- }\r
- }\r
-\r
- for( int i=0; i<(int)pat.getNumChildren(); i++ ){\r
- if( pat[i].getKind()==APPLY_UF ){\r
- ips.back().second = i;\r
- registerPatternElementPairs2( pat[i], ips, pp_ips_map, npc );\r
- Debug("pattern-element-opt") << "Found pc-pair ( " << pat.getOperator() << ", " << pat[i].getOperator() << " )" << std::endl;\r
- Debug("pattern-element-opt") << " Path = ";\r
- outputIps( "pattern-element-opt", ips );\r
- Debug("pattern-element-opt") << std::endl;\r
- //pat.getOperator() and pat[i].getOperator() are a pc-pair\r
- d_pc_pairs[ pat[i].getOperator() ][ pat.getOperator() ]\r
- .push_back( make_pair(npc,Ips(ips)) );\r
- }\r
- }\r
- ips.pop_back();\r
-}\r
-\r
-void EfficientEMatcher::registerPatternElementPairs( Node pat, PpIpsMap & pp_ips_map,\r
- NodePcDispatcher* npc,\r
- NodePpDispatcher* npp){\r
- Ips ips;\r
- registerPatternElementPairs2( pat, ips, pp_ips_map, npc );\r
- for( PpIpsMap::iterator it = pp_ips_map.begin(); it != pp_ips_map.end(); ++it ){\r
- // for each variable construct all the pp-pair\r
- for( size_t j=0; j<it->second.size(); j++ ){\r
- for( size_t k=j+1; k<it->second.size(); k++ ){\r
- //found a pp-pair\r
- Debug("pattern-element-opt") << "Found pp-pair ( " << it->second[j].first << ", " << it->second[k].first << " )" << std::endl;\r
- Debug("pattern-element-opt") << " Paths = ";\r
- outputIps( "pattern-element-opt", it->second[j].second );\r
- Debug("pattern-element-opt") << " and ";\r
- outputIps( "pattern-element-opt", it->second[k].second );\r
- Debug("pattern-element-opt") << std::endl;\r
- d_pp_pairs[ it->second[j].first ][ it->second[k].first ]\r
- .push_back( make_triple( npp, it->second[j].second, it->second[k].second ));\r
- }\r
- }\r
- }\r
-};\r
-\r
-void findPpSite(Node pat, EfficientEMatcher::Ips& ips, EfficientEMatcher::PpIpsMap & pp_ips_map){\r
- Assert( pat.getKind()==APPLY_UF );\r
- //add information for possible pp-pair\r
-\r
- ips.push_back( make_pair( pat.getOperator(), 0) );\r
- for( size_t i=0; i<pat.getNumChildren(); i++ ){\r
- if( pat[i].getKind()==INST_CONSTANT ){\r
- ips.back().second = i;\r
- pp_ips_map[ pat[i] ].push_back( make_pair( pat.getOperator(), EfficientEMatcher::Ips( ips ) ) );\r
- }\r
- }\r
-\r
- for( size_t i=0; i<pat.getNumChildren(); i++ ){\r
- if( pat[i].getKind()==APPLY_UF ){\r
- ips.back().second = i;\r
- findPpSite( pat[i], ips, pp_ips_map );\r
- }\r
- }\r
- ips.pop_back();\r
-}\r
-\r
-void EfficientEMatcher::combineMultiPpIpsMap(PpIpsMap & pp_ips_map, MultiPpIpsMap & multi_pp_ips_map,\r
- EfficientHandler& eh, size_t index2,const std::vector<Node> & pats){\r
- hash_map<size_t,NodePpDispatcher*> npps;\r
- for( PpIpsMap::iterator it = pp_ips_map.begin(); it != pp_ips_map.end(); ++it ){\r
- MultiPpIpsMap::iterator mit = multi_pp_ips_map.find(it->first);\r
- if(mit == multi_pp_ips_map.end()) continue;\r
- // for each variable construct all the pp-pair\r
- // j the last pattern treated\r
- for( std::vector< std::pair< Node, Ips > >::iterator j=it->second.begin(), jend = it->second.end() ;\r
- j != jend; ++j){\r
- // k one of the previous one\r
- for( std::vector< triple< size_t, Node, Ips > >::iterator k=mit->second.begin(), kend = mit->second.end() ;\r
- k != kend; ++k){\r
- //found a pp-pair\r
- Debug("pattern-element-opt") << "Found multi-pp-pair ( " << j->first\r
- << ", " << k->second << " in "<< k->first\r
- << " )" << std::endl;\r
- Debug("pattern-element-opt") << " Paths = ";\r
- outputIps( "pattern-element-opt", j->second );\r
- Debug("pattern-element-opt") << " and ";\r
- outputIps( "pattern-element-opt", k->third );\r
- Debug("pattern-element-opt") << std::endl;\r
- NodePpDispatcher* dispatcher;\r
- hash_map<size_t,NodePpDispatcher*>::iterator inpp = npps.find(k->first);\r
- if( inpp != npps.end() ) dispatcher = inpp->second;\r
- else{\r
- dispatcher = new NodePpDispatcher();\r
-#ifdef CVC4_DEBUG\r
- dispatcher->pat1 = pats[index2];\r
- dispatcher->pat2 = pats[k->first];\r
-#endif\r
- dispatcher->addPpDispatcher(&eh,index2,k->first);\r
- };\r
- d_pp_pairs[ j->first ][ k->second ].push_back( make_triple( dispatcher, j->second, k->third ));\r
- }\r
- }\r
- }\r
-\r
- /** Put pp_ips_map to multi_pp_ips_map */\r
- for( PpIpsMap::iterator it = pp_ips_map.begin(); it != pp_ips_map.end(); ++it ){\r
- for( std::vector< std::pair< Node, Ips > >::iterator j=it->second.begin(), jend = it->second.end() ;\r
- j != jend; ++j){\r
- multi_pp_ips_map[it->first].push_back(make_triple(index2, j->first, j->second));\r
- }\r
- }\r
-\r
-}\r
-\r
-\r
-void EfficientEMatcher::registerEfficientHandler( EfficientHandler& handler,\r
- const std::vector< Node > & pats ){\r
- Assert(pats.size() > 0);\r
-\r
- MultiPpIpsMap multi_pp_ips_map;\r
- PpIpsMap pp_ips_map;\r
- //In a multi-pattern Pattern that is only a variable are specials,\r
- //if the variable appears in another pattern, it can be discarded.\r
- //Otherwise new term of this term can be candidate. So we stock them\r
- //here before adding them.\r
- std::vector< size_t > patVars;\r
-\r
- Debug("pattern-element-opt") << "Register patterns" << pats << std::endl;\r
- for(size_t i = 0; i < pats.size(); ++i){\r
- if( pats[i].getKind() == kind::INST_CONSTANT){\r
- patVars.push_back(i);\r
- continue;\r
- }\r
- //to complete\r
- if( pats[i].getKind() == kind::NOT && pats[i][0].getKind() == kind::EQUAL){\r
- Node cst = NodeManager::currentNM()->mkConst<bool>(false);\r
- TNode op = pats[i][0].getOperator();\r
- if(d_cc_pairs[op][cst] == NULL){\r
- d_cc_pairs[op][cst] = new NodePcDispatcher();\r
- }\r
- d_cc_pairs[op][cst]->addPcDispatcher(&handler,i);\r
- continue;\r
- }\r
- //end to complete\r
- Debug("pattern-element-opt") << " Register candidate generator..." << pats[i] << std::endl;\r
- /* Has the pattern already been seen */\r
- if( d_pat_cand_gens.find( pats[i] )==d_pat_cand_gens.end() ){\r
- NodePcDispatcher* npc = new NodePcDispatcher();\r
- NodePpDispatcher* npp = new NodePpDispatcher();\r
-#ifdef CVC4_DEBUG\r
- npc->pat = pats[i];\r
- npp->pat1 = pats[i];\r
- npp->pat2 = pats[i];\r
-#endif\r
- d_pat_cand_gens[pats[i]] = make_pair(npc,npp);\r
- registerPatternElementPairs( pats[i], pp_ips_map, npc, npp );\r
- }else{\r
- Ips ips;\r
- findPpSite(pats[i],ips,pp_ips_map);\r
- }\r
- //Has the top operator already been seen */\r
- TNode op = pats[i].getOperator();\r
- d_pat_cand_gens[pats[i]].first->addPcDispatcher(&handler,i);\r
- d_pat_cand_gens[pats[i]].second->addPpDispatcher(&handler,i,i);\r
- d_cand_gens[op].addNewTermDispatcher(&handler,i);\r
-\r
- combineMultiPpIpsMap(pp_ips_map,multi_pp_ips_map,handler,i,pats);\r
-\r
- pp_ips_map.clear();\r
- }\r
-\r
- for(size_t i = 0; i < patVars.size(); ++i){\r
- TNode var = pats[patVars[i]];\r
- Assert( var.getKind() == kind::INST_CONSTANT );\r
- if( multi_pp_ips_map.find(var) != multi_pp_ips_map.end() ){\r
- //The variable appear in another pattern, skip it\r
- continue;\r
- };\r
- d_cand_gen_types[var.getType()].addNewTermDispatcher(&handler,patVars[i]);\r
- }\r
-\r
- //take all terms from the uf term db and add to candidate generator\r
- if( pats[0].getKind() == kind::INST_CONSTANT ){\r
- TypeNode ty = pats[0].getType();\r
- rrinst::CandidateGenerator* cg = new GenericCandidateGeneratorClasses(d_quantEngine);\r
- cg->reset(Node::null());\r
- TNode c;\r
- SetNode ele;\r
- while( !(c = cg->getNextCandidate()).isNull() ){\r
- if( c.getType() == ty ) ele.insert(c);\r
- }\r
- if( !ele.empty() ){\r
- // for(std::vector<Node>::iterator i = db->d_op_map[op].begin(), end = db->d_op_map[op].end(); i != end; ++i){\r
- // if(CandidateGenerator::isLegalCandidate(*i)) ele.insert(*i);\r
- // }\r
- if(Debug.isOn("efficient-e-match-stats")){\r
- Debug("efficient-e-match-stats") << "pattern " << pats << " initialized with " << ele.size() << " terms"<< std::endl;\r
- }\r
- handler.addMonoCandidate(ele, 0);\r
- }\r
-\r
- } else if( pats[0].getKind() == kind::NOT && pats[0][0].getKind() == kind::EQUAL){\r
- Node cst = NodeManager::currentNM()->mkConst<bool>(false);\r
- TNode op = pats[0][0].getOperator();\r
- cst = getEqualityEngine()->getRepresentative(cst);\r
- SetNode ele;\r
- eq::EqClassIterator eqc_iter( cst, getEqualityEngine() );\r
- while( !eqc_iter.isFinished() ){\r
- Debug("efficient-e-match-debug") << "> look at " << (*eqc_iter)\r
- << std::endl;\r
- if( (*eqc_iter).hasOperator() && (*eqc_iter).getOperator() == op ) ele.insert(*eqc_iter);\r
- eqc_iter++;\r
- }\r
- if( !ele.empty() ){\r
- if(Debug.isOn("efficient-e-match-stats")){\r
- Debug("efficient-e-match-stats") << "pattern " << pats << " initialized with " << ele.size() << " terms"<< std::endl;\r
- }\r
- handler.addMonoCandidate(ele, 0);\r
- }\r
-\r
- } else {\r
- Node op = pats[0].getOperator();\r
- TermDb* db = d_quantEngine->getTermDatabase();\r
- if(db->d_op_map[op].begin() != db->d_op_map[op].end()){\r
- SetNode ele;\r
- // for(std::vector<Node>::iterator i = db->d_op_map[op].begin(), end = db->d_op_map[op].end(); i != end; ++i){\r
- // if(CandidateGenerator::isLegalCandidate(*i)) ele.insert(*i);\r
- // }\r
- ele.insert(db->d_op_map[op].begin(), db->d_op_map[op].end());\r
- if(Debug.isOn("efficient-e-match-stats")){\r
- Debug("efficient-e-match-stats") << "pattern " << pats << " initialized with " << ele.size() << " terms"<< std::endl;\r
- }\r
- handler.addMonoCandidate(ele, 0);\r
- }\r
- }\r
- Debug("efficient-e-match") << "Done." << std::endl;\r
-}\r
-\r
-void EfficientEMatcher::outputEqClass( const char* c, Node n ){\r
- if( getEqualityEngine()->hasTerm( n ) ){\r
- eq::EqClassIterator eqc_iter( getEqualityEngine()->getRepresentative( n ),\r
- getEqualityEngine() );\r
- bool firstTime = true;\r
- while( !eqc_iter.isFinished() ){\r
- if( !firstTime ){ Debug(c) << ", "; }\r
- Debug(c) << (*eqc_iter);\r
- firstTime = false;\r
- eqc_iter++;\r
- }\r
- }else{\r
- Debug(c) << n;\r
- }\r
-}\r
-\r
-void EfficientEMatcher::outputIps( const char* c, Ips& ips ){\r
- for( int i=0; i<(int)ips.size(); i++ ){\r
- if( i>0 ){ Debug( c ) << "."; }\r
- Debug( c ) << ips[i].first << "." << ips[i].second;\r
- }\r
-}\r
-\r
-\r
-} /* namespace theory */\r
-} /* namespace cvc4 */\r
+/********************* */
+/*! \file efficient_e_matching.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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 Implementation of theory uf instantiator class
+ **/
+
+#include "theory/rewriterules/efficient_e_matching.h"
+#include "theory/rewriterules/rr_candidate_generator.h"
+#include "theory/quantifiers/candidate_generator.h"
+#include "theory/quantifiers/options.h"
+#include "theory/rewriterules/options.h"
+#include "theory/quantifiers/term_database.h"
+
+#include "theory/theory_engine.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::inst;
+
+namespace CVC4 {
+namespace theory {
+
+inline std::ostream& operator<<(std::ostream& out, const EfficientEMatcher::Ips& ips) {
+ return out;
+};
+
+EqClassInfo::EqClassInfo( context::Context* c ) : d_funs( c ), d_pfuns( c ), d_disequal( c ){
+
+}
+
+//set member
+void EqClassInfo::setMember( Node n, quantifiers::TermDb* db ){
+ if( n.hasOperator() ){
+ d_funs.insertAtContextLevelZero(n.getOperator(),true);
+ }
+ //add parent functions
+ for( std::hash_map< Node, std::hash_map< int, std::vector< Node > >, NodeHashFunction >::iterator it = db->d_parents[n].begin();
+ it != db->d_parents[n].end(); ++it ){
+ //TODO Is it true to do it at level 0? That depend when SetMember is called
+ // At worst it is a good overapproximation
+ d_pfuns.insertAtContextLevelZero( it->first, true);
+ }
+}
+
+//get has function
+bool EqClassInfo::hasFunction( Node op ){
+ return d_funs.find( op )!=d_funs.end();
+}
+
+bool EqClassInfo::hasParent( Node op ){
+ return d_pfuns.find( op )!=d_pfuns.end();
+}
+
+//merge with another eq class info
+void EqClassInfo::merge( EqClassInfo* eci ){
+ for( BoolMap::iterator it = eci->d_funs.begin(); it != eci->d_funs.end(); it++ ) {
+ d_funs[ (*it).first ] = true;
+ }
+ for( BoolMap::iterator it = eci->d_pfuns.begin(); it != eci->d_pfuns.end(); it++ ) {
+ d_pfuns[ (*it).first ] = true;
+ }
+}
+
+inline void outputEqClassInfo( const char* c, const EqClassInfo* eci){
+ Debug(c) << " funs:";
+ for( EqClassInfo::BoolMap::iterator it = eci->d_funs.begin(); it != eci->d_funs.end(); it++ ) {
+ Debug(c) << (*it).first << ",";
+ }
+ Debug(c) << std::endl << "pfuns:";
+ for( EqClassInfo::BoolMap::iterator it = eci->d_pfuns.begin(); it != eci->d_pfuns.end(); it++ ) {
+ Debug(c) << (*it).first << ",";
+ }
+ Debug(c) << std::endl;
+}
+
+
+
+EfficientEMatcher::EfficientEMatcher( CVC4::theory::QuantifiersEngine* qe ) : d_quantEngine( qe )
+{
+
+}
+
+eq::EqualityEngine* EfficientEMatcher::getEqualityEngine(){
+ //return ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->theoryOf( THEORY_UF ))->getEqualityEngine();
+ return d_quantEngine->getMasterEqualityEngine();
+}
+
+/** new node */
+void EfficientEMatcher::newEqClass( TNode n ){
+
+}
+
+void EfficientEMatcher::newTerms(SetNode& s){
+ static NoMatchAttribute rewrittenNodeAttribute;
+ /* op -> nodes (if the set is empty, the op is not interesting) */
+ std::hash_map< TNode, SetNode, TNodeHashFunction > h;
+ /* types -> nodes (if the set is empty, the type is not interesting) */
+ std::hash_map< TypeNode, SetNode, TypeNodeHashFunction > tyh;
+ for(SetNode::iterator i=s.begin(), end=s.end(); i != end; ++i){
+ if (i->getAttribute(rewrittenNodeAttribute)) continue; /* skip it */
+ if( !d_cand_gens.empty() ){
+ // op
+ TNode op = i->getOperator();
+ std::hash_map< TNode, SetNode, TNodeHashFunction >::iterator
+ is = h.find(op);
+ if(is == h.end()){
+ std::pair<std::hash_map< TNode, SetNode, TNodeHashFunction >::iterator,bool>
+ p = h.insert(make_pair(op,SetNode()));
+ is = p.first;
+ if(d_cand_gens.find(op) != d_cand_gens.end()){
+ is->second.insert(*i);
+ } /* else we have inserted an empty set */
+ }else if(!is->second.empty()){
+ is->second.insert(*i);
+ }
+ }
+ if( !d_cand_gen_types.empty() ){
+ //type
+ TypeNode ty = i->getType();
+ std::hash_map< TypeNode, SetNode, TypeNodeHashFunction >::iterator
+ is = tyh.find(ty);
+ if(is == tyh.end()){
+ std::pair<std::hash_map< TypeNode, SetNode, TypeNodeHashFunction >::iterator,bool>
+ p = tyh.insert(make_pair(ty,SetNode()));
+ is = p.first;
+ if(d_cand_gen_types.find(ty) != d_cand_gen_types.end()){
+ is->second.insert(*i);
+ } /* else we have inserted an empty set */
+ }else if(!is->second.empty()){
+ is->second.insert(*i);
+ }
+ }
+ }
+ //op
+ for(std::hash_map< TNode, SetNode, TNodeHashFunction >::iterator i=h.begin(), end=h.end();
+ i != end; ++i){
+ //new term, add n to candidate generators
+ if(i->second.empty()) continue;
+ std::map< Node, NodeNewTermDispatcher >::iterator
+ inpc = d_cand_gens.find(i->first);
+ //we know that this op exists
+ Assert(inpc != d_cand_gens.end());
+ inpc->second.send(i->second);
+ }
+ //type
+ for(std::hash_map< TypeNode, SetNode, TypeNodeHashFunction >::iterator i=tyh.begin(), end=tyh.end();
+ i != end; ++i){
+ //new term, add n to candidate generators
+ if(i->second.empty()) continue;
+ std::map< TypeNode, NodeNewTermDispatcher >::iterator
+ inpc = d_cand_gen_types.find(i->first);
+ //we know that this op exists
+ Assert(inpc != d_cand_gen_types.end());
+ inpc->second.send(i->second);
+ }
+
+}
+
+
+/** merge */
+void EfficientEMatcher::merge( TNode a, TNode b ){
+ if( options::efficientEMatching() ){
+ //merge eqc_ops of b into a
+ EqClassInfo* eci_a = getOrCreateEquivalenceClassInfo( a );
+ EqClassInfo* eci_b = getOrCreateEquivalenceClassInfo( b );
+
+ if( a.getKind()!=IFF && a.getKind()!=EQUAL && b.getKind()!=IFF && b.getKind()!=EQUAL ){
+ Debug("efficient-e-match") << "Merging " << a << " with " << b << std::endl;
+
+ //determine new candidates for instantiation
+ computeCandidatesPcPairs( a, eci_a, b, eci_b );
+ computeCandidatesPcPairs( b, eci_b, a, eci_a );
+ computeCandidatesPpPairs( a, eci_a, b, eci_b );
+ computeCandidatesPpPairs( b, eci_b, a, eci_a );
+ }
+ computeCandidatesConstants( a, eci_a, b, eci_b);
+ computeCandidatesConstants( b, eci_b, a, eci_a);
+
+ eci_a->merge( eci_b );
+ }
+}
+
+/** assert terms are disequal */
+void EfficientEMatcher::assertDisequal( TNode a, TNode b, TNode reason ){
+
+}
+
+EqClassInfo* EfficientEMatcher::getEquivalenceClassInfo( Node n ) {
+ return d_eqc_ops.find( n )==d_eqc_ops.end() ? NULL : d_eqc_ops[n];
+}
+EqClassInfo* EfficientEMatcher::getOrCreateEquivalenceClassInfo( Node n ){
+ Assert( n==getEqualityEngine()->getRepresentative( n ) );
+ if( d_eqc_ops.find( n )==d_eqc_ops.end() ){
+ EqClassInfo* eci = new EqClassInfo( d_quantEngine->getSatContext() );
+ eci->setMember( n, d_quantEngine->getTermDatabase() );
+ d_eqc_ops[n] = eci;
+ }
+ return d_eqc_ops[n];
+}
+
+void EfficientEMatcher::computeCandidatesPcPairs( Node a, EqClassInfo* eci_a, Node b, EqClassInfo* eci_b ){
+ Debug("efficient-e-match") << "Compute candidates for pc pairs..." << std::endl;
+ Debug("efficient-e-match") << " Eq class = [";
+ outputEqClass( "efficient-e-match", a);
+ Debug("efficient-e-match") << "]" << std::endl;
+ outputEqClassInfo("efficient-e-match",eci_a);
+ for( EqClassInfo::BoolMap::iterator it = eci_a->d_funs.begin(); it != eci_a->d_funs.end(); it++ ) {
+ //the child function: a member of eq_class( a ) has top symbol g, in other words g is in funs( a )
+ Node g = (*it).first;
+ Debug("efficient-e-match") << " Checking application " << g << std::endl;
+ //look at all parent/child pairs
+ for( std::map< Node, std::vector< std::pair< NodePcDispatcher*, Ips > > >::iterator itf = d_pc_pairs[g].begin();
+ itf != d_pc_pairs[g].end(); ++itf ){
+ //f/g is a parent/child pair
+ Node f = itf->first;
+ if( eci_b->hasParent( f ) ){
+ //DO_THIS: determine if f in pfuns( b ), only do the follow if so
+ Debug("efficient-e-match") << " Checking parent application " << f << std::endl;
+ //scan through the list of inverted path strings/candidate generators
+ for( std::vector< std::pair< NodePcDispatcher*, Ips > >::iterator cit = itf->second.begin();
+ cit != itf->second.end(); ++cit ){
+#ifdef CVC4_DEBUG
+ Debug("efficient-e-match") << " Checking pattern " << cit->first->pat << std::endl;
+#endif
+ Debug("efficient-e-match") << " Check inverted path string for pattern ";
+ outputIps( "efficient-e-match", cit->second );
+ Debug("efficient-e-match") << std::endl;
+
+ //collect all new relevant terms
+ SetNode terms;
+ terms.insert( b );
+ collectTermsIps( cit->second, terms );
+ if( terms.empty() ) continue;
+ Debug("efficient-e-match") << " -> Added terms (" << terms.size() << "): ";
+ for( SetNode::const_iterator t=terms.begin(), end=terms.end();
+ t!=end; ++t ){
+ Debug("efficient-e-match") << (*t) << " ";
+ }
+ Debug("efficient-e-match") << std::endl;
+ //add them as candidates to the candidate generator
+ cit->first->send(terms);
+ }
+ }
+ }
+ }
+}
+
+void EfficientEMatcher::computeCandidatesPpPairs( Node a, EqClassInfo* eci_a, Node b, EqClassInfo* eci_b ){
+ Debug("efficient-e-match") << "Compute candidates for pp pairs..." << std::endl;
+ for( std::map< Node, std::map< Node, std::vector< triple< NodePpDispatcher*, Ips, Ips > > > >::iterator it = d_pp_pairs.begin();
+ it != d_pp_pairs.end(); ++it ){
+ Node f = it->first;
+ if( eci_a->hasParent( f ) ){
+ Debug("efficient-e-match") << " Checking parent application " << f << std::endl;
+ for( std::map< Node, std::vector< triple<NodePpDispatcher*, Ips, Ips> > >::iterator it2 = it->second.begin();
+ it2 != it->second.end(); ++it2 ){
+ Node g = it2->first;
+ if( eci_b->hasParent( g ) ){
+ Debug("efficient-e-match") << " Checking parent application " << g << std::endl;
+ //if f in pfuns( a ) and g is in pfuns( b ), only do the follow if so
+ for( std::vector< triple<NodePpDispatcher*, Ips, Ips> > ::iterator cit = it2->second.begin();
+ cit != it2->second.end(); ++cit ){
+#ifdef CVC4_DEBUG
+ Debug("efficient-e-match") << " Checking pattern " << cit->first->pat1 << " and " << cit->first->pat2 << std::endl;
+#endif
+ Debug("efficient-e-match") << " Check inverted path string ";
+ outputIps( "efficient-e-match", cit->second );
+ SetNode a_terms;
+ a_terms.insert( a );
+ collectTermsIps( cit->second, a_terms );
+ if( a_terms.empty() ) continue;
+ Debug("efficient-e-match") << " And check inverted path string ";
+ outputIps( "efficient-e-match", cit->third );
+ SetNode b_terms;
+ b_terms.insert( b );
+ collectTermsIps( cit->third, b_terms );
+ if( b_terms.empty() ) continue;
+ //Start debug
+ Debug("efficient-e-match") << " -> Possibly Added termsA (" << a_terms.size() << "): ";
+ for( SetNode::const_iterator t=a_terms.begin(), end=a_terms.end();
+ t!=end; ++t ){
+ Debug("efficient-e-match") << (*t) << " ";
+ }
+ Debug("efficient-e-match") << std::endl;
+ Debug("efficient-e-match") << " -> Possibly Added termsB (" << b_terms.size() << "): ";
+ for( SetNode::const_iterator t=b_terms.begin(), end=b_terms.end();
+ t!=end; ++t ){
+ Debug("efficient-e-match") << (*t) << " ";
+ }
+ Debug("efficient-e-match") << std::endl;
+ //End debug
+
+ cit->first->send(a_terms,b_terms);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void EfficientEMatcher::computeCandidatesConstants( Node a, EqClassInfo* eci_a, Node b, EqClassInfo* eci_b ){
+ Debug("efficient-e-match") << "Compute candidates constants for cc pairs..." << std::endl;
+ Debug("efficient-e-match") << " Eq class = [";
+ outputEqClass( "efficient-e-match", a);
+ Debug("efficient-e-match") << "]" << std::endl;
+ outputEqClassInfo("efficient-e-match",eci_a);
+ for( std::map< Node, std::map< Node, NodePcDispatcher* > >::iterator
+ it = d_cc_pairs.begin(), end = d_cc_pairs.end();
+ it != end; ++it ) {
+ Debug("efficient-e-match") << " Checking application " << it->first << std::endl;
+ if( !eci_b->hasFunction(it->first) ) continue;
+ for( std::map< Node, NodePcDispatcher* >::iterator
+ itc = it->second.begin(), end = it->second.end();
+ itc != end; ++itc ) {
+ //The constant
+ Debug("efficient-e-match") << " Checking constant " << a << std::endl;
+ if(getEqualityEngine()->getRepresentative(itc->first) != a) continue;
+ SetNode s;
+ eq::EqClassIterator eqc_iter( b, getEqualityEngine() );
+ while( !eqc_iter.isFinished() ){
+ Debug("efficient-e-match-debug") << "> look at " << (*eqc_iter)
+ << std::endl;
+ if( (*eqc_iter).hasOperator() && (*eqc_iter).getOperator() == it->first ) s.insert(*eqc_iter);
+ eqc_iter++;
+ }
+
+ if( s.empty() ) continue;
+ Debug("efficient-e-match") << " -> Added terms (" << s.size() << "): ";
+ for( SetNode::const_iterator t=s.begin(), end=s.end();
+ t!=end; ++t ){
+ Debug("efficient-e-match") << (*t) << " ";
+ }
+ Debug("efficient-e-match") << std::endl;
+ itc->second->send(s);
+ }
+ }
+}
+
+void EfficientEMatcher::collectTermsIps( Ips& ips, SetNode & terms ){
+ Assert( ips.size() > 0);
+ return collectTermsIps( ips, terms, ips.size() - 1);
+}
+
+void EfficientEMatcher::collectTermsIps( Ips& ips, SetNode& terms, int index ){
+ if( !terms.empty() ){
+ Debug("efficient-e-match-debug") << "> Process " << index << std::endl;
+ Node f = ips[index].first;
+ int arg = ips[index].second;
+
+ //for each term in terms, determine if any term (modulo equality) has parent "f" from position "arg"
+ bool addRep = ( index!=0 ); // We want to keep the top symbol for the last
+ SetNode newTerms;
+ for( SetNode::const_iterator t=terms.begin(), end=terms.end();
+ t!=end; ++t ){
+ collectParentsTermsIps( *t, f, arg, newTerms, addRep );
+ }
+ terms.swap(newTerms);
+
+ Debug("efficient-e-match-debug") << "> Terms are now: ";
+ for( SetNode::const_iterator t=terms.begin(), end=terms.end();
+ t!=end; ++t ){
+ Debug("efficient-e-match-debug") << *t << " ";
+ }
+ Debug("efficient-e-match-debug") << std::endl;
+
+ if(index!=0) collectTermsIps( ips, terms, index-1 );
+ }
+}
+
+bool EfficientEMatcher::collectParentsTermsIps( Node n, Node f, int arg, SetNode & terms, bool addRep, bool modEq ){ //modEq default true
+ bool addedTerm = false;
+
+ if( modEq && getEqualityEngine()->hasTerm( n )){
+ Assert( getEqualityEngine()->getRepresentative( n )==n );
+ //collect modulo equality
+ //DO_THIS: this should (if necessary) compute a current set of (f, arg) parents for n and cache it
+ eq::EqClassIterator eqc_iter( n, getEqualityEngine() );
+ while( !eqc_iter.isFinished() ){
+ Debug("efficient-e-match-debug") << "> look at " << (*eqc_iter)
+ << std::endl;
+ if( collectParentsTermsIps( (*eqc_iter), f, arg, terms, addRep, false ) ){
+ //if only one argument, we know we can stop (since all others added will be congruent)
+ if( f.getType().getNumChildren()==2 ){
+ return true;
+ }
+ addedTerm = true;
+ }
+ eqc_iter++;
+ }
+ }else{
+ quantifiers::TermDb* db = d_quantEngine->getTermDatabase();
+ //see if parent f exists from argument arg
+ const std::vector<Node> & parents = db->getParents(n,f,arg);
+ for( size_t i=0; i<parents.size(); ++i ){
+ TNode t = parents[i];
+ if(!CandidateGenerator::isLegalCandidate(t)) continue;
+ if( addRep ) t = getEqualityEngine()->getRepresentative( t );
+ terms.insert(t);
+ addedTerm = true;
+ }
+ }
+ return addedTerm;
+}
+
+void EfficientEMatcher::registerPatternElementPairs2( Node pat, Ips& ips, PpIpsMap & pp_ips_map, NodePcDispatcher* npc ){
+ Assert( pat.hasOperator() );
+ //add information for possible pp-pair
+ ips.push_back( std::pair< Node, int >( pat.getOperator(), 0 ) ); //0 is just a dumb value
+
+ for( int i=0; i<(int)pat.getNumChildren(); i++ ){
+ if( pat[i].getKind()==INST_CONSTANT ){
+ ips.back().second = i;
+ pp_ips_map[ pat[i] ].push_back( make_pair( pat.getOperator(), Ips( ips ) ) );
+ }
+ }
+
+ for( int i=0; i<(int)pat.getNumChildren(); i++ ){
+ if( pat[i].getKind()==APPLY_UF ){
+ ips.back().second = i;
+ registerPatternElementPairs2( pat[i], ips, pp_ips_map, npc );
+ Debug("pattern-element-opt") << "Found pc-pair ( " << pat.getOperator() << ", " << pat[i].getOperator() << " )" << std::endl;
+ Debug("pattern-element-opt") << " Path = ";
+ outputIps( "pattern-element-opt", ips );
+ Debug("pattern-element-opt") << std::endl;
+ //pat.getOperator() and pat[i].getOperator() are a pc-pair
+ d_pc_pairs[ pat[i].getOperator() ][ pat.getOperator() ]
+ .push_back( make_pair(npc,Ips(ips)) );
+ }
+ }
+ ips.pop_back();
+}
+
+void EfficientEMatcher::registerPatternElementPairs( Node pat, PpIpsMap & pp_ips_map,
+ NodePcDispatcher* npc,
+ NodePpDispatcher* npp){
+ Ips ips;
+ registerPatternElementPairs2( pat, ips, pp_ips_map, npc );
+ for( PpIpsMap::iterator it = pp_ips_map.begin(); it != pp_ips_map.end(); ++it ){
+ // for each variable construct all the pp-pair
+ for( size_t j=0; j<it->second.size(); j++ ){
+ for( size_t k=j+1; k<it->second.size(); k++ ){
+ //found a pp-pair
+ Debug("pattern-element-opt") << "Found pp-pair ( " << it->second[j].first << ", " << it->second[k].first << " )" << std::endl;
+ Debug("pattern-element-opt") << " Paths = ";
+ outputIps( "pattern-element-opt", it->second[j].second );
+ Debug("pattern-element-opt") << " and ";
+ outputIps( "pattern-element-opt", it->second[k].second );
+ Debug("pattern-element-opt") << std::endl;
+ d_pp_pairs[ it->second[j].first ][ it->second[k].first ]
+ .push_back( make_triple( npp, it->second[j].second, it->second[k].second ));
+ }
+ }
+ }
+};
+
+void findPpSite(Node pat, EfficientEMatcher::Ips& ips, EfficientEMatcher::PpIpsMap & pp_ips_map){
+ Assert( pat.getKind()==APPLY_UF );
+ //add information for possible pp-pair
+
+ ips.push_back( make_pair( pat.getOperator(), 0) );
+ for( size_t i=0; i<pat.getNumChildren(); i++ ){
+ if( pat[i].getKind()==INST_CONSTANT ){
+ ips.back().second = i;
+ pp_ips_map[ pat[i] ].push_back( make_pair( pat.getOperator(), EfficientEMatcher::Ips( ips ) ) );
+ }
+ }
+
+ for( size_t i=0; i<pat.getNumChildren(); i++ ){
+ if( pat[i].getKind()==APPLY_UF ){
+ ips.back().second = i;
+ findPpSite( pat[i], ips, pp_ips_map );
+ }
+ }
+ ips.pop_back();
+}
+
+void EfficientEMatcher::combineMultiPpIpsMap(PpIpsMap & pp_ips_map, MultiPpIpsMap & multi_pp_ips_map,
+ EfficientHandler& eh, size_t index2,const std::vector<Node> & pats){
+ hash_map<size_t,NodePpDispatcher*> npps;
+ for( PpIpsMap::iterator it = pp_ips_map.begin(); it != pp_ips_map.end(); ++it ){
+ MultiPpIpsMap::iterator mit = multi_pp_ips_map.find(it->first);
+ if(mit == multi_pp_ips_map.end()) continue;
+ // for each variable construct all the pp-pair
+ // j the last pattern treated
+ for( std::vector< std::pair< Node, Ips > >::iterator j=it->second.begin(), jend = it->second.end() ;
+ j != jend; ++j){
+ // k one of the previous one
+ for( std::vector< triple< size_t, Node, Ips > >::iterator k=mit->second.begin(), kend = mit->second.end() ;
+ k != kend; ++k){
+ //found a pp-pair
+ Debug("pattern-element-opt") << "Found multi-pp-pair ( " << j->first
+ << ", " << k->second << " in "<< k->first
+ << " )" << std::endl;
+ Debug("pattern-element-opt") << " Paths = ";
+ outputIps( "pattern-element-opt", j->second );
+ Debug("pattern-element-opt") << " and ";
+ outputIps( "pattern-element-opt", k->third );
+ Debug("pattern-element-opt") << std::endl;
+ NodePpDispatcher* dispatcher;
+ hash_map<size_t,NodePpDispatcher*>::iterator inpp = npps.find(k->first);
+ if( inpp != npps.end() ) dispatcher = inpp->second;
+ else{
+ dispatcher = new NodePpDispatcher();
+#ifdef CVC4_DEBUG
+ dispatcher->pat1 = pats[index2];
+ dispatcher->pat2 = pats[k->first];
+#endif
+ dispatcher->addPpDispatcher(&eh,index2,k->first);
+ };
+ d_pp_pairs[ j->first ][ k->second ].push_back( make_triple( dispatcher, j->second, k->third ));
+ }
+ }
+ }
+
+ /** Put pp_ips_map to multi_pp_ips_map */
+ for( PpIpsMap::iterator it = pp_ips_map.begin(); it != pp_ips_map.end(); ++it ){
+ for( std::vector< std::pair< Node, Ips > >::iterator j=it->second.begin(), jend = it->second.end() ;
+ j != jend; ++j){
+ multi_pp_ips_map[it->first].push_back(make_triple(index2, j->first, j->second));
+ }
+ }
+
+}
+
+
+void EfficientEMatcher::registerEfficientHandler( EfficientHandler& handler,
+ const std::vector< Node > & pats ){
+ Assert(pats.size() > 0);
+
+ MultiPpIpsMap multi_pp_ips_map;
+ PpIpsMap pp_ips_map;
+ //In a multi-pattern Pattern that is only a variable are specials,
+ //if the variable appears in another pattern, it can be discarded.
+ //Otherwise new term of this term can be candidate. So we stock them
+ //here before adding them.
+ std::vector< size_t > patVars;
+
+ Debug("pattern-element-opt") << "Register patterns" << pats << std::endl;
+ for(size_t i = 0; i < pats.size(); ++i){
+ if( pats[i].getKind() == kind::INST_CONSTANT){
+ patVars.push_back(i);
+ continue;
+ }
+ //to complete
+ if( pats[i].getKind() == kind::NOT && pats[i][0].getKind() == kind::EQUAL){
+ Node cst = NodeManager::currentNM()->mkConst<bool>(false);
+ TNode op = pats[i][0].getOperator();
+ if(d_cc_pairs[op][cst] == NULL){
+ d_cc_pairs[op][cst] = new NodePcDispatcher();
+ }
+ d_cc_pairs[op][cst]->addPcDispatcher(&handler,i);
+ continue;
+ }
+ //end to complete
+ Debug("pattern-element-opt") << " Register candidate generator..." << pats[i] << std::endl;
+ /* Has the pattern already been seen */
+ if( d_pat_cand_gens.find( pats[i] )==d_pat_cand_gens.end() ){
+ NodePcDispatcher* npc = new NodePcDispatcher();
+ NodePpDispatcher* npp = new NodePpDispatcher();
+#ifdef CVC4_DEBUG
+ npc->pat = pats[i];
+ npp->pat1 = pats[i];
+ npp->pat2 = pats[i];
+#endif
+ d_pat_cand_gens[pats[i]] = make_pair(npc,npp);
+ registerPatternElementPairs( pats[i], pp_ips_map, npc, npp );
+ }else{
+ Ips ips;
+ findPpSite(pats[i],ips,pp_ips_map);
+ }
+ //Has the top operator already been seen */
+ TNode op = pats[i].getOperator();
+ d_pat_cand_gens[pats[i]].first->addPcDispatcher(&handler,i);
+ d_pat_cand_gens[pats[i]].second->addPpDispatcher(&handler,i,i);
+ d_cand_gens[op].addNewTermDispatcher(&handler,i);
+
+ combineMultiPpIpsMap(pp_ips_map,multi_pp_ips_map,handler,i,pats);
+
+ pp_ips_map.clear();
+ }
+
+ for(size_t i = 0; i < patVars.size(); ++i){
+ TNode var = pats[patVars[i]];
+ Assert( var.getKind() == kind::INST_CONSTANT );
+ if( multi_pp_ips_map.find(var) != multi_pp_ips_map.end() ){
+ //The variable appear in another pattern, skip it
+ continue;
+ };
+ d_cand_gen_types[var.getType()].addNewTermDispatcher(&handler,patVars[i]);
+ }
+
+ //take all terms from the uf term db and add to candidate generator
+ if( pats[0].getKind() == kind::INST_CONSTANT ){
+ TypeNode ty = pats[0].getType();
+ rrinst::CandidateGenerator* cg = new GenericCandidateGeneratorClasses(d_quantEngine);
+ cg->reset(Node::null());
+ TNode c;
+ SetNode ele;
+ while( !(c = cg->getNextCandidate()).isNull() ){
+ if( c.getType() == ty ) ele.insert(c);
+ }
+ if( !ele.empty() ){
+ // for(std::vector<Node>::iterator i = db->d_op_map[op].begin(), end = db->d_op_map[op].end(); i != end; ++i){
+ // if(CandidateGenerator::isLegalCandidate(*i)) ele.insert(*i);
+ // }
+ if(Debug.isOn("efficient-e-match-stats")){
+ Debug("efficient-e-match-stats") << "pattern " << pats << " initialized with " << ele.size() << " terms"<< std::endl;
+ }
+ handler.addMonoCandidate(ele, 0);
+ }
+
+ } else if( pats[0].getKind() == kind::NOT && pats[0][0].getKind() == kind::EQUAL){
+ Node cst = NodeManager::currentNM()->mkConst<bool>(false);
+ TNode op = pats[0][0].getOperator();
+ cst = getEqualityEngine()->getRepresentative(cst);
+ SetNode ele;
+ eq::EqClassIterator eqc_iter( cst, getEqualityEngine() );
+ while( !eqc_iter.isFinished() ){
+ Debug("efficient-e-match-debug") << "> look at " << (*eqc_iter)
+ << std::endl;
+ if( (*eqc_iter).hasOperator() && (*eqc_iter).getOperator() == op ) ele.insert(*eqc_iter);
+ eqc_iter++;
+ }
+ if( !ele.empty() ){
+ if(Debug.isOn("efficient-e-match-stats")){
+ Debug("efficient-e-match-stats") << "pattern " << pats << " initialized with " << ele.size() << " terms"<< std::endl;
+ }
+ handler.addMonoCandidate(ele, 0);
+ }
+
+ } else {
+ Node op = pats[0].getOperator();
+ TermDb* db = d_quantEngine->getTermDatabase();
+ if(db->d_op_map[op].begin() != db->d_op_map[op].end()){
+ SetNode ele;
+ // for(std::vector<Node>::iterator i = db->d_op_map[op].begin(), end = db->d_op_map[op].end(); i != end; ++i){
+ // if(CandidateGenerator::isLegalCandidate(*i)) ele.insert(*i);
+ // }
+ ele.insert(db->d_op_map[op].begin(), db->d_op_map[op].end());
+ if(Debug.isOn("efficient-e-match-stats")){
+ Debug("efficient-e-match-stats") << "pattern " << pats << " initialized with " << ele.size() << " terms"<< std::endl;
+ }
+ handler.addMonoCandidate(ele, 0);
+ }
+ }
+ Debug("efficient-e-match") << "Done." << std::endl;
+}
+
+void EfficientEMatcher::outputEqClass( const char* c, Node n ){
+ if( getEqualityEngine()->hasTerm( n ) ){
+ eq::EqClassIterator eqc_iter( getEqualityEngine()->getRepresentative( n ),
+ getEqualityEngine() );
+ bool firstTime = true;
+ while( !eqc_iter.isFinished() ){
+ if( !firstTime ){ Debug(c) << ", "; }
+ Debug(c) << (*eqc_iter);
+ firstTime = false;
+ eqc_iter++;
+ }
+ }else{
+ Debug(c) << n;
+ }
+}
+
+void EfficientEMatcher::outputIps( const char* c, Ips& ips ){
+ for( int i=0; i<(int)ips.size(); i++ ){
+ if( i>0 ){ Debug( c ) << "."; }
+ Debug( c ) << ips[i].first << "." << ips[i].second;
+ }
+}
+
+
+} /* namespace theory */
+} /* namespace cvc4 */
-/********************* */\r
-/*! \file efficient_e_matching.h\r
- ** \verbatim\r
- ** Original author: ajreynol\r
- ** Major contributors: bobot\r
- ** Minor contributors (to current version): mdeters\r
- ** This file is part of the CVC4 prototype.\r
- ** Copyright (c) 2009-2012 New York University and The University of Iowa\r
- ** See the file COPYING in the top-level source directory for licensing\r
- ** information.\endverbatim\r
- **\r
- ** \brief efficient e-matching\r
- **/\r
-\r
-#include "cvc4_private.h"\r
-\r
-#ifndef __CVC4__EFFICIENT_E_MATCHING_H\r
-#define __CVC4__EFFICIENT_E_MATCHING_H\r
-\r
-#include "expr/node.h"\r
-#include "context/context.h"\r
-#include "context/context_mm.h"\r
-#include "context/cdchunk_list.h"\r
-\r
-#include "util/statistics_registry.h"\r
-#include "util/ntuple.h"\r
-#include "context/cdqueue.h"\r
-#include "context/cdo.h"\r
-\r
-#include "theory/uf/equality_engine.h"\r
-\r
-namespace CVC4 {\r
-namespace theory {\r
-\r
-class QuantifiersEngine;\r
-\r
-namespace quantifiers{\r
- class TermDb;\r
-}\r
-\r
-class EfficientEMatcher;\r
-class HandlerPcDispatcher;\r
-class HandlerPpDispatcher;\r
-\r
-typedef std::set<Node> SetNode;\r
-\r
-template<class T>\r
-class CleanUpPointer{\r
-public:\r
- inline void operator()(T** e){\r
- delete(*e);\r
- };\r
-};\r
-\r
-class EfficientHandler{\r
-public:\r
- typedef std::pair< Node, size_t > MonoCandidate;\r
- typedef std::pair< MonoCandidate, MonoCandidate > MultiCandidate;\r
- typedef std::pair< SetNode, size_t > MonoCandidates;\r
- typedef std::pair< MonoCandidates, MonoCandidates > MultiCandidates;\r
-private:\r
- /* Queue of candidates */\r
- typedef context::CDQueue< MonoCandidates *, CleanUpPointer<MonoCandidates> > MonoCandidatesQueue;\r
- typedef context::CDQueue< MultiCandidates *, CleanUpPointer<MultiCandidates> > MultiCandidatesQueue;\r
- MonoCandidatesQueue d_monoCandidates;\r
- typedef SetNode::iterator SetNodeIter;\r
- context::CDO<SetNodeIter> d_si;\r
- context::CDO<bool> d_mono_not_first;\r
-\r
- MonoCandidatesQueue d_monoCandidatesNewTerm;\r
- context::CDO<SetNodeIter> d_si_new_term;\r
- context::CDO<bool> d_mono_not_first_new_term;\r
-\r
-\r
- MultiCandidatesQueue d_multiCandidates;\r
- context::CDO<SetNodeIter> d_si1;\r
- context::CDO<SetNodeIter> d_si2;\r
- context::CDO<bool> d_multi_not_first;\r
-\r
-\r
- friend class EfficientEMatcher;\r
- friend class HandlerPcDispatcher;\r
- friend class HandlerPpDispatcher;\r
- friend class HandlerNewTermDispatcher;\r
-protected:\r
- void addMonoCandidate(SetNode & s, size_t index){\r
- Assert(!s.empty());\r
- d_monoCandidates.push(new MonoCandidates(s,index));\r
- }\r
- void addMonoCandidateNewTerm(SetNode & s, size_t index){\r
- Assert(!s.empty());\r
- d_monoCandidatesNewTerm.push(new MonoCandidates(s,index));\r
- }\r
- void addMultiCandidate(SetNode & s1, size_t index1, SetNode & s2, size_t index2){\r
- Assert(!s1.empty() && !s2.empty());\r
- d_multiCandidates.push(new MultiCandidates(MonoCandidates(s1,index1),\r
- MonoCandidates(s2,index2)));\r
- }\r
-public:\r
- EfficientHandler(context::Context * c):\r
- //false for d_mono_not_first beacause its the default constructor\r
- d_monoCandidates(c), d_si(c), d_mono_not_first(c,false),\r
- d_monoCandidatesNewTerm(c), d_si_new_term(c),\r
- d_mono_not_first_new_term(c,false),\r
- d_multiCandidates(c) , d_si1(c), d_si2(c), d_multi_not_first(c,false) {};\r
-\r
- bool getNextMonoCandidate(MonoCandidate & candidate){\r
- if(d_monoCandidates.empty()) return false;\r
- const MonoCandidates * front = d_monoCandidates.front();\r
- SetNodeIter si_tmp;\r
- if(!d_mono_not_first){\r
- Assert(front->first.begin() != front->first.end());\r
- d_mono_not_first = true;\r
- si_tmp=front->first.begin();\r
- }else{\r
- si_tmp = d_si;\r
- ++si_tmp;\r
- };\r
- if(si_tmp != front->first.end()){\r
- candidate.first = (*si_tmp);\r
- candidate.second = front->second;\r
- d_si = si_tmp;\r
- Debug("efficienthandler") << "Mono produces " << candidate.first << " for " << candidate.second << std::endl;\r
- return true;\r
- };\r
- d_monoCandidates.pop();\r
- d_mono_not_first = false;\r
- return getNextMonoCandidate(candidate);\r
- };\r
-\r
- bool getNextMonoCandidateNewTerm(MonoCandidate & candidate){\r
- if(d_monoCandidatesNewTerm.empty()) return false;\r
- const MonoCandidates * front = d_monoCandidatesNewTerm.front();\r
- SetNodeIter si_tmp;\r
- if(!d_mono_not_first_new_term){\r
- Assert(front->first.begin() != front->first.end());\r
- d_mono_not_first_new_term = true;\r
- si_tmp=front->first.begin();\r
- }else{\r
- si_tmp = d_si_new_term;\r
- ++si_tmp;\r
- };\r
- if(si_tmp != front->first.end()){\r
- candidate.first = (*si_tmp);\r
- candidate.second = front->second;\r
- d_si_new_term = si_tmp;\r
- Debug("efficienthandler") << "Mono produces " << candidate.first << " for " << candidate.second << std::endl;\r
- return true;\r
- };\r
- d_monoCandidatesNewTerm.pop();\r
- d_mono_not_first_new_term = false;\r
- return getNextMonoCandidateNewTerm(candidate);\r
- };\r
-\r
- bool getNextMultiCandidate(MultiCandidate & candidate){\r
- if(d_multiCandidates.empty()) return false;\r
- const MultiCandidates* front = d_multiCandidates.front();\r
- SetNodeIter si1_tmp;\r
- SetNodeIter si2_tmp;\r
- if(!d_multi_not_first){\r
- Assert(front->first.first.begin() != front->first.first.end());\r
- Assert(front->second.first.begin() != front->second.first.end());\r
- si1_tmp = front->first.first.begin();\r
- si2_tmp = front->second.first.begin();\r
- }else{\r
- si1_tmp = d_si1;\r
- si2_tmp = d_si2;\r
- ++si2_tmp;\r
- };\r
- if(si2_tmp != front->second.first.end()){\r
- candidate.first.first = *si1_tmp;\r
- candidate.first.second = front->first.second;\r
- candidate.second.first = *si2_tmp;\r
- candidate.second.second = front->second.second;\r
- if(!d_multi_not_first){d_si1 = si1_tmp; d_multi_not_first = true; };\r
- d_si2 = si2_tmp;\r
- Debug("efficienthandler") << "Multi1 produces "\r
- << candidate.first.first << " for "\r
- << candidate.first.second << " and "\r
- << candidate.second.first << " for "\r
- << candidate.second.second << " and "\r
- << std::endl;\r
- return true;\r
- }; // end of the second set\r
- si2_tmp = front->second.first.begin();\r
- ++si1_tmp;\r
- if(si1_tmp != front->first.first.end()){\r
- candidate.first.first = *si1_tmp;\r
- candidate.first.second = front->first.second;\r
- candidate.second.first = *si2_tmp;\r
- candidate.second.second = front->second.second;\r
- d_si1 = si1_tmp;\r
- d_si2 = si2_tmp;\r
- Debug("efficienthandler") << "Multi2 produces "\r
- << candidate.first.first << " for "\r
- << candidate.first.second << " and "\r
- << candidate.second.first << " for "\r
- << candidate.second.second << " and "\r
- << std::endl;\r
- return true;\r
- }; // end of the first set\r
- d_multiCandidates.pop();\r
- d_multi_not_first = false;\r
- return getNextMultiCandidate(candidate);\r
- }\r
-};\r
-\r
-class PcDispatcher{\r
-public:\r
- virtual ~PcDispatcher(){};\r
- /* Send the node to the dispatcher */\r
- virtual void send(SetNode & s) = 0;\r
-};\r
-\r
-\r
-class HandlerPcDispatcher: public PcDispatcher{\r
- EfficientHandler* d_handler;\r
- size_t d_index;\r
-public:\r
- HandlerPcDispatcher(EfficientHandler* handler, size_t index):\r
- d_handler(handler), d_index(index) {};\r
- void send(SetNode & s){\r
- d_handler->addMonoCandidate(s,d_index);\r
- }\r
-};\r
-\r
-\r
-/** All the dispatcher that correspond to this node */\r
-class NodePcDispatcher: public PcDispatcher{\r
-#ifdef CVC4_DEBUG\r
-public:\r
- Node pat;\r
-#endif/* CVC4_DEBUG*/\r
-private:\r
- std::vector<HandlerPcDispatcher> d_dis;\r
-public:\r
- void send(SetNode & s){\r
- Assert(!s.empty());\r
- for(std::vector<HandlerPcDispatcher>::iterator i = d_dis.begin(), end = d_dis.end();\r
- i != end; ++i){\r
- (*i).send(s);\r
- }\r
- }\r
- void addPcDispatcher(EfficientHandler* handler, size_t index){\r
- d_dis.push_back(HandlerPcDispatcher(handler,index));\r
- }\r
-};\r
-\r
-\r
-class HandlerNewTermDispatcher: public PcDispatcher{\r
- EfficientHandler* d_handler;\r
- size_t d_index;\r
-public:\r
- HandlerNewTermDispatcher(EfficientHandler* handler, size_t index):\r
- d_handler(handler), d_index(index) {};\r
- void send(SetNode & s){\r
- d_handler->addMonoCandidateNewTerm(s,d_index);\r
- }\r
-};\r
-\r
-/** All the dispatcher that correspond to this node */\r
-class NodeNewTermDispatcher: public PcDispatcher{\r
-#ifdef CVC4_DEBUG\r
-public:\r
- Node pat;\r
-#endif/* CVC4_DEBUG*/\r
-private:\r
- std::vector<HandlerNewTermDispatcher> d_dis;\r
-public:\r
- void send(SetNode & s){\r
- Assert(!s.empty());\r
- for(std::vector<HandlerNewTermDispatcher>::iterator i = d_dis.begin(), end = d_dis.end();\r
- i != end; ++i){\r
- (*i).send(s);\r
- }\r
- }\r
- void addNewTermDispatcher(EfficientHandler* handler, size_t index){\r
- d_dis.push_back(HandlerNewTermDispatcher(handler,index));\r
- }\r
-};\r
-\r
-class PpDispatcher{\r
-public:\r
- virtual ~PpDispatcher(){};\r
- /* Send the node to the dispatcher */\r
- virtual void send(SetNode & s1, SetNode & s2, SetNode & sinter) = 0;\r
-};\r
-\r
-\r
-class HandlerPpDispatcher: public PpDispatcher{\r
- EfficientHandler* d_handler;\r
- size_t d_index1;\r
- size_t d_index2;\r
-public:\r
- HandlerPpDispatcher(EfficientHandler* handler, size_t index1, size_t index2):\r
- d_handler(handler), d_index1(index1), d_index2(index2) {};\r
- void send(SetNode & s1, SetNode & s2, SetNode & sinter){\r
- if(d_index1 == d_index2){\r
- if(!sinter.empty())\r
- d_handler->addMonoCandidate(sinter,d_index1);\r
- }else{\r
- d_handler->addMultiCandidate(s1,d_index1,s2,d_index2);\r
- }\r
- }\r
-};\r
-\r
-\r
-/** All the dispatcher that correspond to this node */\r
-class NodePpDispatcher: public PpDispatcher{\r
-#ifdef CVC4_DEBUG\r
-public:\r
- Node pat1;\r
- Node pat2;\r
-#endif/* CVC4_DEBUG */\r
-private:\r
- std::vector<HandlerPpDispatcher> d_dis;\r
- void send(SetNode & s1, SetNode & s2, SetNode & inter){\r
- for(std::vector<HandlerPpDispatcher>::iterator i = d_dis.begin(), end = d_dis.end();\r
- i != end; ++i){\r
- (*i).send(s1,s2,inter);\r
- }\r
- }\r
-public:\r
- void send(SetNode & s1, SetNode & s2){\r
- // can be done in HandlerPpDispatcher lazily\r
- Assert(!s1.empty() && !s2.empty());\r
- SetNode inter;\r
- std::set_intersection( s1.begin(), s1.end(), s2.begin(), s2.end(),\r
- std::inserter( inter, inter.begin() ) );\r
- send(s1,s2,inter);\r
- }\r
- void addPpDispatcher(EfficientHandler* handler, size_t index1, size_t index2){\r
- d_dis.push_back(HandlerPpDispatcher(handler,index1,index2));\r
- }\r
-};\r
-\r
-//equivalence class info\r
-class EqClassInfo\r
-{\r
-public:\r
- typedef context::CDHashMap<Node, bool, NodeHashFunction> BoolMap;\r
- typedef context::CDChunkList<Node> NodeList;\r
-public:\r
- //a list of operators that occur as top symbols in this equivalence class\r
- // Efficient E-Matching for SMT Solvers: "funs"\r
- BoolMap d_funs;\r
- //a list of operators f for which a term of the form f( ... t ... ) exists\r
- // Efficient E-Matching for SMT Solvers: "pfuns"\r
- BoolMap d_pfuns;\r
- //a list of equivalence classes that are disequal\r
- BoolMap d_disequal;\r
-public:\r
- EqClassInfo( context::Context* c );\r
- ~EqClassInfo(){}\r
- //set member\r
- void setMember( Node n, quantifiers::TermDb* db );\r
- //has function "funs"\r
- bool hasFunction( Node op );\r
- //has parent "pfuns"\r
- bool hasParent( Node op );\r
- //merge with another eq class info\r
- void merge( EqClassInfo* eci );\r
-};\r
-\r
-class EfficientEMatcher{\r
-protected:\r
- /** reference to the quantifiers engine */\r
- QuantifiersEngine* d_quantEngine;\r
-public:\r
- EfficientEMatcher(CVC4::theory::QuantifiersEngine* qe);\r
- ~EfficientEMatcher() {\r
- for(std::map< Node, std::pair<NodePcDispatcher*, NodePpDispatcher*> >::iterator\r
- i = d_pat_cand_gens.begin(), end = d_pat_cand_gens.end();\r
- i != end; i++){\r
- delete(i->second.first);\r
- delete(i->second.second);\r
- }\r
- }\r
- /** get equality engine we are using */\r
- eq::EqualityEngine* getEqualityEngine();\r
-private:\r
- //information for each equivalence class\r
- std::map< Node, EqClassInfo* > d_eqc_ops;\r
-public:\r
- /** new node */\r
- void newEqClass( TNode n );\r
- /** merge */\r
- void merge( TNode a, TNode b );\r
- /** assert terms are disequal */\r
- void assertDisequal( TNode a, TNode b, TNode reason );\r
- /** get equivalence class info */\r
- EqClassInfo* getEquivalenceClassInfo( Node n );\r
- EqClassInfo* getOrCreateEquivalenceClassInfo( Node n );\r
- typedef std::vector< std::pair< Node, int > > Ips;\r
- typedef std::map< Node, std::vector< std::pair< Node, Ips > > > PpIpsMap;\r
- typedef std::map< Node, std::vector< triple< size_t, Node, Ips > > > MultiPpIpsMap;\r
-private:\r
- /** Parent/Child Pairs (for efficient E-matching)\r
- So, for example, if we have the pattern f( g( x ) ), then d_pc_pairs[g][f][f( g( x ) )] = { f.0 }.\r
- */\r
- std::map< Node, std::map< Node, std::vector< std::pair< NodePcDispatcher*, Ips > > > > d_pc_pairs;\r
- /** Parent/Parent Pairs (for efficient E-matching) */\r
- std::map< Node, std::map< Node, std::vector< triple< NodePpDispatcher*, Ips, Ips > > > > d_pp_pairs;\r
- /** Constants/Child Pairs\r
- So, for example, if we have the pattern f( x ) = c, then d_pc_pairs[f][c] = ..., pcdispatcher, ...\r
- */\r
- //TODO constant in pattern can use the same thing just add an Ips\r
- std::map< Node, std::map< Node, NodePcDispatcher* > > d_cc_pairs;\r
- /** list of all candidate generators for each operator */\r
- std::map< Node, NodeNewTermDispatcher > d_cand_gens;\r
- /** list of all candidate generators for each type */\r
- std::map< TypeNode, NodeNewTermDispatcher > d_cand_gen_types;\r
- /** map from patterns to candidate generators */\r
- std::map< Node, std::pair<NodePcDispatcher*, NodePpDispatcher*> > d_pat_cand_gens;\r
- /** helper functions */\r
- void registerPatternElementPairs2( Node pat, Ips& ips,\r
- PpIpsMap & pp_ips_map, NodePcDispatcher* npc);\r
- void registerPatternElementPairs( Node pat, PpIpsMap & pp_ips_map,\r
- NodePcDispatcher* npc, NodePpDispatcher* npp);\r
- /** find the pp-pair between pattern inside multi-pattern*/\r
- void combineMultiPpIpsMap(PpIpsMap & pp_ips_map, MultiPpIpsMap & multi_pp_ips_map,\r
- EfficientHandler& eh, size_t index2,\r
- const std::vector<Node> & pats); //pats for debug\r
- /** compute candidates for pc pairs */\r
- void computeCandidatesPcPairs( Node a, EqClassInfo*, Node b, EqClassInfo* );\r
- /** compute candidates for pp pairs */\r
- void computeCandidatesPpPairs( Node a, EqClassInfo*, Node b, EqClassInfo* );\r
- /** compute candidates for cc pairs */\r
- void computeCandidatesConstants( Node a, EqClassInfo*, Node b, EqClassInfo* );\r
- /** collect terms based on inverted path string */\r
- void collectTermsIps( Ips& ips, SetNode& terms, int index);\r
- bool collectParentsTermsIps( Node n, Node f, int arg, SetNode& terms, bool addRep, bool modEq = true );\r
-public:\r
- void collectTermsIps( Ips& ips, SetNode& terms);\r
-public:\r
- void registerEfficientHandler( EfficientHandler& eh, const std::vector<Node> & pat );\r
-public:\r
- void newTerms(SetNode& s);\r
-public:\r
- /** output eq class */\r
- void outputEqClass( const char* c, Node n );\r
- /** output inverted path string */\r
- void outputIps( const char* c, Ips& ips );\r
-};/* class EfficientEMatcher */\r
-\r
-\r
-}/* CVC4::theory namespace */\r
-}/* CVC4 namespace */\r
-\r
-#endif /* __CVC4__EFFICIENT_E_MATCHING_H */\r
+/********************* */
+/*! \file efficient_e_matching.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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 efficient e-matching
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__EFFICIENT_E_MATCHING_H
+#define __CVC4__EFFICIENT_E_MATCHING_H
+
+#include "expr/node.h"
+#include "context/context.h"
+#include "context/context_mm.h"
+#include "context/cdchunk_list.h"
+
+#include "util/statistics_registry.h"
+#include "util/ntuple.h"
+#include "context/cdqueue.h"
+#include "context/cdo.h"
+
+#include "theory/uf/equality_engine.h"
+
+namespace CVC4 {
+namespace theory {
+
+class QuantifiersEngine;
+
+namespace quantifiers{
+ class TermDb;
+}
+
+class EfficientEMatcher;
+class HandlerPcDispatcher;
+class HandlerPpDispatcher;
+
+typedef std::set<Node> SetNode;
+
+template<class T>
+class CleanUpPointer{
+public:
+ inline void operator()(T** e){
+ delete(*e);
+ };
+};
+
+class EfficientHandler{
+public:
+ typedef std::pair< Node, size_t > MonoCandidate;
+ typedef std::pair< MonoCandidate, MonoCandidate > MultiCandidate;
+ typedef std::pair< SetNode, size_t > MonoCandidates;
+ typedef std::pair< MonoCandidates, MonoCandidates > MultiCandidates;
+private:
+ /* Queue of candidates */
+ typedef context::CDQueue< MonoCandidates *, CleanUpPointer<MonoCandidates> > MonoCandidatesQueue;
+ typedef context::CDQueue< MultiCandidates *, CleanUpPointer<MultiCandidates> > MultiCandidatesQueue;
+ MonoCandidatesQueue d_monoCandidates;
+ typedef SetNode::iterator SetNodeIter;
+ context::CDO<SetNodeIter> d_si;
+ context::CDO<bool> d_mono_not_first;
+
+ MonoCandidatesQueue d_monoCandidatesNewTerm;
+ context::CDO<SetNodeIter> d_si_new_term;
+ context::CDO<bool> d_mono_not_first_new_term;
+
+
+ MultiCandidatesQueue d_multiCandidates;
+ context::CDO<SetNodeIter> d_si1;
+ context::CDO<SetNodeIter> d_si2;
+ context::CDO<bool> d_multi_not_first;
+
+
+ friend class EfficientEMatcher;
+ friend class HandlerPcDispatcher;
+ friend class HandlerPpDispatcher;
+ friend class HandlerNewTermDispatcher;
+protected:
+ void addMonoCandidate(SetNode & s, size_t index){
+ Assert(!s.empty());
+ d_monoCandidates.push(new MonoCandidates(s,index));
+ }
+ void addMonoCandidateNewTerm(SetNode & s, size_t index){
+ Assert(!s.empty());
+ d_monoCandidatesNewTerm.push(new MonoCandidates(s,index));
+ }
+ void addMultiCandidate(SetNode & s1, size_t index1, SetNode & s2, size_t index2){
+ Assert(!s1.empty() && !s2.empty());
+ d_multiCandidates.push(new MultiCandidates(MonoCandidates(s1,index1),
+ MonoCandidates(s2,index2)));
+ }
+public:
+ EfficientHandler(context::Context * c):
+ //false for d_mono_not_first beacause its the default constructor
+ d_monoCandidates(c), d_si(c), d_mono_not_first(c,false),
+ d_monoCandidatesNewTerm(c), d_si_new_term(c),
+ d_mono_not_first_new_term(c,false),
+ d_multiCandidates(c) , d_si1(c), d_si2(c), d_multi_not_first(c,false) {};
+
+ bool getNextMonoCandidate(MonoCandidate & candidate){
+ if(d_monoCandidates.empty()) return false;
+ const MonoCandidates * front = d_monoCandidates.front();
+ SetNodeIter si_tmp;
+ if(!d_mono_not_first){
+ Assert(front->first.begin() != front->first.end());
+ d_mono_not_first = true;
+ si_tmp=front->first.begin();
+ }else{
+ si_tmp = d_si;
+ ++si_tmp;
+ };
+ if(si_tmp != front->first.end()){
+ candidate.first = (*si_tmp);
+ candidate.second = front->second;
+ d_si = si_tmp;
+ Debug("efficienthandler") << "Mono produces " << candidate.first << " for " << candidate.second << std::endl;
+ return true;
+ };
+ d_monoCandidates.pop();
+ d_mono_not_first = false;
+ return getNextMonoCandidate(candidate);
+ };
+
+ bool getNextMonoCandidateNewTerm(MonoCandidate & candidate){
+ if(d_monoCandidatesNewTerm.empty()) return false;
+ const MonoCandidates * front = d_monoCandidatesNewTerm.front();
+ SetNodeIter si_tmp;
+ if(!d_mono_not_first_new_term){
+ Assert(front->first.begin() != front->first.end());
+ d_mono_not_first_new_term = true;
+ si_tmp=front->first.begin();
+ }else{
+ si_tmp = d_si_new_term;
+ ++si_tmp;
+ };
+ if(si_tmp != front->first.end()){
+ candidate.first = (*si_tmp);
+ candidate.second = front->second;
+ d_si_new_term = si_tmp;
+ Debug("efficienthandler") << "Mono produces " << candidate.first << " for " << candidate.second << std::endl;
+ return true;
+ };
+ d_monoCandidatesNewTerm.pop();
+ d_mono_not_first_new_term = false;
+ return getNextMonoCandidateNewTerm(candidate);
+ };
+
+ bool getNextMultiCandidate(MultiCandidate & candidate){
+ if(d_multiCandidates.empty()) return false;
+ const MultiCandidates* front = d_multiCandidates.front();
+ SetNodeIter si1_tmp;
+ SetNodeIter si2_tmp;
+ if(!d_multi_not_first){
+ Assert(front->first.first.begin() != front->first.first.end());
+ Assert(front->second.first.begin() != front->second.first.end());
+ si1_tmp = front->first.first.begin();
+ si2_tmp = front->second.first.begin();
+ }else{
+ si1_tmp = d_si1;
+ si2_tmp = d_si2;
+ ++si2_tmp;
+ };
+ if(si2_tmp != front->second.first.end()){
+ candidate.first.first = *si1_tmp;
+ candidate.first.second = front->first.second;
+ candidate.second.first = *si2_tmp;
+ candidate.second.second = front->second.second;
+ if(!d_multi_not_first){d_si1 = si1_tmp; d_multi_not_first = true; };
+ d_si2 = si2_tmp;
+ Debug("efficienthandler") << "Multi1 produces "
+ << candidate.first.first << " for "
+ << candidate.first.second << " and "
+ << candidate.second.first << " for "
+ << candidate.second.second << " and "
+ << std::endl;
+ return true;
+ }; // end of the second set
+ si2_tmp = front->second.first.begin();
+ ++si1_tmp;
+ if(si1_tmp != front->first.first.end()){
+ candidate.first.first = *si1_tmp;
+ candidate.first.second = front->first.second;
+ candidate.second.first = *si2_tmp;
+ candidate.second.second = front->second.second;
+ d_si1 = si1_tmp;
+ d_si2 = si2_tmp;
+ Debug("efficienthandler") << "Multi2 produces "
+ << candidate.first.first << " for "
+ << candidate.first.second << " and "
+ << candidate.second.first << " for "
+ << candidate.second.second << " and "
+ << std::endl;
+ return true;
+ }; // end of the first set
+ d_multiCandidates.pop();
+ d_multi_not_first = false;
+ return getNextMultiCandidate(candidate);
+ }
+};
+
+class PcDispatcher{
+public:
+ virtual ~PcDispatcher(){};
+ /* Send the node to the dispatcher */
+ virtual void send(SetNode & s) = 0;
+};
+
+
+class HandlerPcDispatcher: public PcDispatcher{
+ EfficientHandler* d_handler;
+ size_t d_index;
+public:
+ HandlerPcDispatcher(EfficientHandler* handler, size_t index):
+ d_handler(handler), d_index(index) {};
+ void send(SetNode & s){
+ d_handler->addMonoCandidate(s,d_index);
+ }
+};
+
+
+/** All the dispatcher that correspond to this node */
+class NodePcDispatcher: public PcDispatcher{
+#ifdef CVC4_DEBUG
+public:
+ Node pat;
+#endif/* CVC4_DEBUG*/
+private:
+ std::vector<HandlerPcDispatcher> d_dis;
+public:
+ void send(SetNode & s){
+ Assert(!s.empty());
+ for(std::vector<HandlerPcDispatcher>::iterator i = d_dis.begin(), end = d_dis.end();
+ i != end; ++i){
+ (*i).send(s);
+ }
+ }
+ void addPcDispatcher(EfficientHandler* handler, size_t index){
+ d_dis.push_back(HandlerPcDispatcher(handler,index));
+ }
+};
+
+
+class HandlerNewTermDispatcher: public PcDispatcher{
+ EfficientHandler* d_handler;
+ size_t d_index;
+public:
+ HandlerNewTermDispatcher(EfficientHandler* handler, size_t index):
+ d_handler(handler), d_index(index) {};
+ void send(SetNode & s){
+ d_handler->addMonoCandidateNewTerm(s,d_index);
+ }
+};
+
+/** All the dispatcher that correspond to this node */
+class NodeNewTermDispatcher: public PcDispatcher{
+#ifdef CVC4_DEBUG
+public:
+ Node pat;
+#endif/* CVC4_DEBUG*/
+private:
+ std::vector<HandlerNewTermDispatcher> d_dis;
+public:
+ void send(SetNode & s){
+ Assert(!s.empty());
+ for(std::vector<HandlerNewTermDispatcher>::iterator i = d_dis.begin(), end = d_dis.end();
+ i != end; ++i){
+ (*i).send(s);
+ }
+ }
+ void addNewTermDispatcher(EfficientHandler* handler, size_t index){
+ d_dis.push_back(HandlerNewTermDispatcher(handler,index));
+ }
+};
+
+class PpDispatcher{
+public:
+ virtual ~PpDispatcher(){};
+ /* Send the node to the dispatcher */
+ virtual void send(SetNode & s1, SetNode & s2, SetNode & sinter) = 0;
+};
+
+
+class HandlerPpDispatcher: public PpDispatcher{
+ EfficientHandler* d_handler;
+ size_t d_index1;
+ size_t d_index2;
+public:
+ HandlerPpDispatcher(EfficientHandler* handler, size_t index1, size_t index2):
+ d_handler(handler), d_index1(index1), d_index2(index2) {};
+ void send(SetNode & s1, SetNode & s2, SetNode & sinter){
+ if(d_index1 == d_index2){
+ if(!sinter.empty())
+ d_handler->addMonoCandidate(sinter,d_index1);
+ }else{
+ d_handler->addMultiCandidate(s1,d_index1,s2,d_index2);
+ }
+ }
+};
+
+
+/** All the dispatcher that correspond to this node */
+class NodePpDispatcher: public PpDispatcher{
+#ifdef CVC4_DEBUG
+public:
+ Node pat1;
+ Node pat2;
+#endif/* CVC4_DEBUG */
+private:
+ std::vector<HandlerPpDispatcher> d_dis;
+ void send(SetNode & s1, SetNode & s2, SetNode & inter){
+ for(std::vector<HandlerPpDispatcher>::iterator i = d_dis.begin(), end = d_dis.end();
+ i != end; ++i){
+ (*i).send(s1,s2,inter);
+ }
+ }
+public:
+ void send(SetNode & s1, SetNode & s2){
+ // can be done in HandlerPpDispatcher lazily
+ Assert(!s1.empty() && !s2.empty());
+ SetNode inter;
+ std::set_intersection( s1.begin(), s1.end(), s2.begin(), s2.end(),
+ std::inserter( inter, inter.begin() ) );
+ send(s1,s2,inter);
+ }
+ void addPpDispatcher(EfficientHandler* handler, size_t index1, size_t index2){
+ d_dis.push_back(HandlerPpDispatcher(handler,index1,index2));
+ }
+};
+
+//equivalence class info
+class EqClassInfo
+{
+public:
+ typedef context::CDHashMap<Node, bool, NodeHashFunction> BoolMap;
+ typedef context::CDChunkList<Node> NodeList;
+public:
+ //a list of operators that occur as top symbols in this equivalence class
+ // Efficient E-Matching for SMT Solvers: "funs"
+ BoolMap d_funs;
+ //a list of operators f for which a term of the form f( ... t ... ) exists
+ // Efficient E-Matching for SMT Solvers: "pfuns"
+ BoolMap d_pfuns;
+ //a list of equivalence classes that are disequal
+ BoolMap d_disequal;
+public:
+ EqClassInfo( context::Context* c );
+ ~EqClassInfo(){}
+ //set member
+ void setMember( Node n, quantifiers::TermDb* db );
+ //has function "funs"
+ bool hasFunction( Node op );
+ //has parent "pfuns"
+ bool hasParent( Node op );
+ //merge with another eq class info
+ void merge( EqClassInfo* eci );
+};
+
+class EfficientEMatcher{
+protected:
+ /** reference to the quantifiers engine */
+ QuantifiersEngine* d_quantEngine;
+public:
+ EfficientEMatcher(CVC4::theory::QuantifiersEngine* qe);
+ ~EfficientEMatcher() {
+ for(std::map< Node, std::pair<NodePcDispatcher*, NodePpDispatcher*> >::iterator
+ i = d_pat_cand_gens.begin(), end = d_pat_cand_gens.end();
+ i != end; i++){
+ delete(i->second.first);
+ delete(i->second.second);
+ }
+ }
+ /** get equality engine we are using */
+ eq::EqualityEngine* getEqualityEngine();
+private:
+ //information for each equivalence class
+ std::map< Node, EqClassInfo* > d_eqc_ops;
+public:
+ /** new node */
+ void newEqClass( TNode n );
+ /** merge */
+ void merge( TNode a, TNode b );
+ /** assert terms are disequal */
+ void assertDisequal( TNode a, TNode b, TNode reason );
+ /** get equivalence class info */
+ EqClassInfo* getEquivalenceClassInfo( Node n );
+ EqClassInfo* getOrCreateEquivalenceClassInfo( Node n );
+ typedef std::vector< std::pair< Node, int > > Ips;
+ typedef std::map< Node, std::vector< std::pair< Node, Ips > > > PpIpsMap;
+ typedef std::map< Node, std::vector< triple< size_t, Node, Ips > > > MultiPpIpsMap;
+private:
+ /** Parent/Child Pairs (for efficient E-matching)
+ So, for example, if we have the pattern f( g( x ) ), then d_pc_pairs[g][f][f( g( x ) )] = { f.0 }.
+ */
+ std::map< Node, std::map< Node, std::vector< std::pair< NodePcDispatcher*, Ips > > > > d_pc_pairs;
+ /** Parent/Parent Pairs (for efficient E-matching) */
+ std::map< Node, std::map< Node, std::vector< triple< NodePpDispatcher*, Ips, Ips > > > > d_pp_pairs;
+ /** Constants/Child Pairs
+ So, for example, if we have the pattern f( x ) = c, then d_pc_pairs[f][c] = ..., pcdispatcher, ...
+ */
+ //TODO constant in pattern can use the same thing just add an Ips
+ std::map< Node, std::map< Node, NodePcDispatcher* > > d_cc_pairs;
+ /** list of all candidate generators for each operator */
+ std::map< Node, NodeNewTermDispatcher > d_cand_gens;
+ /** list of all candidate generators for each type */
+ std::map< TypeNode, NodeNewTermDispatcher > d_cand_gen_types;
+ /** map from patterns to candidate generators */
+ std::map< Node, std::pair<NodePcDispatcher*, NodePpDispatcher*> > d_pat_cand_gens;
+ /** helper functions */
+ void registerPatternElementPairs2( Node pat, Ips& ips,
+ PpIpsMap & pp_ips_map, NodePcDispatcher* npc);
+ void registerPatternElementPairs( Node pat, PpIpsMap & pp_ips_map,
+ NodePcDispatcher* npc, NodePpDispatcher* npp);
+ /** find the pp-pair between pattern inside multi-pattern*/
+ void combineMultiPpIpsMap(PpIpsMap & pp_ips_map, MultiPpIpsMap & multi_pp_ips_map,
+ EfficientHandler& eh, size_t index2,
+ const std::vector<Node> & pats); //pats for debug
+ /** compute candidates for pc pairs */
+ void computeCandidatesPcPairs( Node a, EqClassInfo*, Node b, EqClassInfo* );
+ /** compute candidates for pp pairs */
+ void computeCandidatesPpPairs( Node a, EqClassInfo*, Node b, EqClassInfo* );
+ /** compute candidates for cc pairs */
+ void computeCandidatesConstants( Node a, EqClassInfo*, Node b, EqClassInfo* );
+ /** collect terms based on inverted path string */
+ void collectTermsIps( Ips& ips, SetNode& terms, int index);
+ bool collectParentsTermsIps( Node n, Node f, int arg, SetNode& terms, bool addRep, bool modEq = true );
+public:
+ void collectTermsIps( Ips& ips, SetNode& terms);
+public:
+ void registerEfficientHandler( EfficientHandler& eh, const std::vector<Node> & pat );
+public:
+ void newTerms(SetNode& s);
+public:
+ /** output eq class */
+ void outputEqClass( const char* c, Node n );
+ /** output inverted path string */
+ void outputIps( const char* c, Ips& ips );
+};/* class EfficientEMatcher */
+
+
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
+
+#endif /* __CVC4__EFFICIENT_E_MATCHING_H */
-/********************* */\r
-/*! \file sort_inference.cpp\r
- ** \verbatim\r
- ** Original author: ajreynol\r
- ** Major contributors: none\r
- ** Minor contributors (to current version): none\r
- ** This file is part of the CVC4 prototype.\r
- ** Copyright (c) 2009-2012 New York University and The University of Iowa\r
- ** See the file COPYING in the top-level source directory for licensing\r
- ** information.\endverbatim\r
- **\r
- ** \brief Sort inference module\r
- **\r
- ** This class implements sort inference, based on a simple algorithm:\r
- ** First, we assume all functions and predicates have distinct uninterpreted types.\r
- ** One pass is made through the input assertions, while a union-find data structure\r
- ** maintains necessary information regarding constraints on these types.\r
- **/\r
-\r
-#include <vector>\r
-\r
-#include "util/sort_inference.h"\r
-\r
-using namespace CVC4;\r
-using namespace std;\r
-\r
-namespace CVC4 {\r
-\r
-\r
-void SortInference::printSort( const char* c, int t ){\r
- int rt = getRepresentative( t );\r
- if( d_type_types.find( rt )!=d_type_types.end() ){\r
- Trace(c) << d_type_types[rt];\r
- }else{\r
- Trace(c) << "s_" << rt;\r
- }\r
-}\r
-\r
-void SortInference::simplify( std::vector< Node >& assertions, bool doRewrite ){\r
- //process all assertions\r
- for( unsigned i=0; i<assertions.size(); i++ ){\r
- Trace("sort-inference-debug") << "Process " << assertions[i] << std::endl;\r
- std::map< Node, Node > var_bound;\r
- process( assertions[i], var_bound );\r
- }\r
- //print debug\r
- if( Trace.isOn("sort-inference") ){\r
- for( std::map< Node, int >::iterator it = d_op_return_types.begin(); it != d_op_return_types.end(); ++it ){\r
- Trace("sort-inference") << it->first << " : ";\r
- if( !d_op_arg_types[ it->first ].empty() ){\r
- Trace("sort-inference") << "( ";\r
- for( size_t i=0; i<d_op_arg_types[ it->first ].size(); i++ ){\r
- printSort( "sort-inference", d_op_arg_types[ it->first ][i] );\r
- Trace("sort-inference") << " ";\r
- }\r
- Trace("sort-inference") << ") -> ";\r
- }\r
- printSort( "sort-inference", it->second );\r
- Trace("sort-inference") << std::endl;\r
- }\r
- for( std::map< Node, std::map< Node, int > >::iterator it = d_var_types.begin(); it != d_var_types.end(); ++it ){\r
- Trace("sort-inference") << "Quantified formula " << it->first << " : " << std::endl;\r
- for( std::map< Node, int >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){\r
- printSort( "sort-inference", it2->second );\r
- Trace("sort-inference") << std::endl;\r
- }\r
- Trace("sort-inference") << std::endl;\r
- }\r
- }\r
- if( doRewrite ){\r
- //simplify all assertions by introducing new symbols wherever necessary (NOTE: this is unsound for quantifiers)\r
- for( unsigned i=0; i<assertions.size(); i++ ){\r
- std::map< Node, Node > var_bound;\r
- assertions[i] = simplify( assertions[i], var_bound );\r
- Trace("sort-inference-rewrite") << " --> " << assertions[i] << std::endl;\r
- }\r
- //now, ensure constants are distinct\r
- for( std::map< TypeNode, std::map< Node, Node > >::iterator it = d_const_map.begin(); it != d_const_map.end(); ++it ){\r
- std::vector< Node > consts;\r
- for( std::map< Node, Node >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){\r
- consts.push_back( it2->second );\r
- }\r
- //add lemma enforcing introduced constants to be distinct?\r
- }\r
- }\r
-}\r
-\r
-int SortInference::getRepresentative( int t ){\r
- std::map< int, int >::iterator it = d_type_union_find.find( t );\r
- if( it!=d_type_union_find.end() ){\r
- if( it->second==t ){\r
- return t;\r
- }else{\r
- int rt = getRepresentative( it->second );\r
- d_type_union_find[t] = rt;\r
- return rt;\r
- }\r
- }else{\r
- return t;\r
- }\r
-}\r
-\r
-void SortInference::setEqual( int t1, int t2 ){\r
- if( t1!=t2 ){\r
- int rt1 = getRepresentative( t1 );\r
- int rt2 = getRepresentative( t2 );\r
- if( rt1!=rt2 ){\r
- Trace("sort-inference-debug") << "Set equal : ";\r
- printSort( "sort-inference-debug", rt1 );\r
- Trace("sort-inference-debug") << " ";\r
- printSort( "sort-inference-debug", rt2 );\r
- Trace("sort-inference-debug") << std::endl;\r
- //check if they must be a type\r
- std::map< int, TypeNode >::iterator it1 = d_type_types.find( rt1 );\r
- std::map< int, TypeNode >::iterator it2 = d_type_types.find( rt2 );\r
- if( it2!=d_type_types.end() ){\r
- if( it1==d_type_types.end() ){\r
- //swap sides\r
- int swap = rt1;\r
- rt1 = rt2;\r
- rt2 = swap;\r
- }else{\r
- Assert( rt1==rt2 );\r
- }\r
- }\r
- /*\r
- d_type_eq_class[rt1].insert( d_type_eq_class[rt1].end(), d_type_eq_class[rt2].begin(), d_type_eq_class[rt2].end() );\r
- d_type_eq_class[rt2].clear();\r
- Trace("sort-inference-debug") << "EqClass : { ";\r
- for( int i=0; i<(int)d_type_eq_class[rt1].size(); i++ ){\r
- Trace("sort-inference-debug") << d_type_eq_class[rt1][i] << ", ";\r
- }\r
- Trace("sort-inference-debug") << "}" << std::endl;\r
- */\r
- d_type_union_find[rt2] = rt1;\r
- }\r
- }\r
-}\r
-\r
-int SortInference::getIdForType( TypeNode tn ){\r
- //register the return type\r
- std::map< TypeNode, int >::iterator it = d_id_for_types.find( tn );\r
- if( it==d_id_for_types.end() ){\r
- int sc = sortCount;\r
- d_type_types[ sortCount ] = tn;\r
- d_id_for_types[ tn ] = sortCount;\r
- sortCount++;\r
- return sc;\r
- }else{\r
- return it->second;\r
- }\r
-}\r
-\r
-int SortInference::process( Node n, std::map< Node, Node >& var_bound ){\r
- Trace("sort-inference-debug") << "Process " << n << std::endl;\r
- //add to variable bindings\r
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){\r
- for( size_t i=0; i<n[0].getNumChildren(); i++ ){\r
- //TODO: try applying sort inference to quantified variables\r
- d_var_types[n][ n[0][i] ] = sortCount;\r
- sortCount++;\r
-\r
- //type of the quantified variable must be the same\r
- //d_var_types[n][ n[0][i] ] = getIdForType( n[0][i].getType() );\r
- var_bound[ n[0][i] ] = n;\r
- }\r
- }\r
-\r
- //process children\r
- std::vector< Node > children;\r
- std::vector< int > child_types;\r
- for( size_t i=0; i<n.getNumChildren(); i++ ){\r
- bool processChild = true;\r
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){\r
- processChild = i==1;\r
- }\r
- if( processChild ){\r
- children.push_back( n[i] );\r
- child_types.push_back( process( n[i], var_bound ) );\r
- }\r
- }\r
-\r
- //remove from variable bindings\r
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){\r
- //erase from variable bound\r
- for( size_t i=0; i<n[0].getNumChildren(); i++ ){\r
- var_bound.erase( n[0][i] );\r
- }\r
- }\r
-\r
- int retType;\r
- if( n.getKind()==kind::EQUAL ){\r
- //we only require that the left and right hand side must be equal\r
- setEqual( child_types[0], child_types[1] );\r
- retType = getIdForType( n.getType() );\r
- }else if( n.getKind()==kind::APPLY_UF ){\r
- Node op = n.getOperator();\r
- if( d_op_return_types.find( op )==d_op_return_types.end() ){\r
- //assign arbitrary sort for return type\r
- d_op_return_types[op] = sortCount;\r
- sortCount++;\r
- //d_type_eq_class[sortCount].push_back( op );\r
- //assign arbitrary sort for argument types\r
- for( size_t i=0; i<n.getNumChildren(); i++ ){\r
- d_op_arg_types[op].push_back( sortCount );\r
- sortCount++;\r
- }\r
- }\r
- for( size_t i=0; i<n.getNumChildren(); i++ ){\r
- //the argument of the operator must match the return type of the subterm\r
- setEqual( child_types[i], d_op_arg_types[op][i] );\r
- }\r
- //return type is the return type\r
- retType = d_op_return_types[op];\r
- }else{\r
- std::map< Node, Node >::iterator it = var_bound.find( n );\r
- if( it!=var_bound.end() ){\r
- Trace("sort-inference-debug") << n << " is a bound variable." << std::endl;\r
- //the return type was specified while binding\r
- retType = d_var_types[it->second][n];\r
- }else if( n.getKind() == kind::VARIABLE ){\r
- Trace("sort-inference-debug") << n << " is a variable." << std::endl;\r
- if( d_op_return_types.find( n )==d_op_return_types.end() ){\r
- //assign arbitrary sort\r
- d_op_return_types[n] = sortCount;\r
- sortCount++;\r
- //d_type_eq_class[sortCount].push_back( n );\r
- }\r
- retType = d_op_return_types[n];\r
- }else if( n.isConst() ){\r
- Trace("sort-inference-debug") << n << " is a constant." << std::endl;\r
- //can be any type we want\r
- retType = sortCount;\r
- sortCount++;\r
- }else{\r
- Trace("sort-inference-debug") << n << " is a interpreted symbol." << std::endl;\r
- //it is an interpretted term\r
- for( size_t i=0; i<children.size(); i++ ){\r
- Trace("sort-inference-debug") << children[i] << " forced to have " << children[i].getType() << std::endl;\r
- //must enforce the actual type of the operator on the children\r
- int ct = getIdForType( children[i].getType() );\r
- setEqual( child_types[i], ct );\r
- }\r
- //return type must be the actual return type\r
- retType = getIdForType( n.getType() );\r
- }\r
- }\r
- Trace("sort-inference-debug") << "Type( " << n << " ) = ";\r
- printSort("sort-inference-debug", retType );\r
- Trace("sort-inference-debug") << std::endl;\r
- return retType;\r
-}\r
-\r
-\r
-TypeNode SortInference::getOrCreateTypeForId( int t, TypeNode pref ){\r
- int rt = getRepresentative( t );\r
- if( d_type_types.find( rt )!=d_type_types.end() ){\r
- return d_type_types[rt];\r
- }else{\r
- TypeNode retType;\r
- //see if we can assign pref\r
- if( !pref.isNull() && d_id_for_types.find( pref )==d_id_for_types.end() ){\r
- retType = pref;\r
- }else{\r
- if( d_subtype_count.find( pref )==d_subtype_count.end() ){\r
- d_subtype_count[pref] = 0;\r
- }\r
- //must create new type\r
- std::stringstream ss;\r
- ss << "it_" << d_subtype_count[pref] << "_" << pref;\r
- d_subtype_count[pref]++;\r
- retType = NodeManager::currentNM()->mkSort( ss.str() );\r
- }\r
- d_id_for_types[ retType ] = rt;\r
- d_type_types[ rt ] = retType;\r
- return retType;\r
- }\r
-}\r
-\r
-TypeNode SortInference::getTypeForId( int t ){\r
- int rt = getRepresentative( t );\r
- if( d_type_types.find( rt )!=d_type_types.end() ){\r
- return d_type_types[rt];\r
- }else{\r
- return TypeNode::null();\r
- }\r
-}\r
-\r
-Node SortInference::getNewSymbol( Node old, TypeNode tn ){\r
- if( tn==old.getType() ){\r
- return old;\r
- }else if( old.isConst() ){\r
- //must make constant of type tn\r
- if( d_const_map[tn].find( old )==d_const_map[tn].end() ){\r
- std::stringstream ss;\r
- ss << "ic_" << tn << "_" << old;\r
- d_const_map[tn][ old ] = NodeManager::currentNM()->mkSkolem( ss.str(), tn, "constant created during sort inference" ); //use mkConst???\r
- }\r
- return d_const_map[tn][ old ];\r
- }else{\r
- std::stringstream ss;\r
- ss << "i_$$_" << old;\r
- return NodeManager::currentNM()->mkSkolem( ss.str(), tn, "created during sort inference" );\r
- }\r
-}\r
-\r
-Node SortInference::simplify( Node n, std::map< Node, Node >& var_bound ){\r
- std::vector< Node > children;\r
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){\r
- //recreate based on types of variables\r
- std::vector< Node > new_children;\r
- for( size_t i=0; i<n[0].getNumChildren(); i++ ){\r
- TypeNode tn = getOrCreateTypeForId( d_var_types[n][ n[0][i] ], n[0][i].getType() );\r
- Node v = getNewSymbol( n[0][i], tn );\r
- new_children.push_back( v );\r
- var_bound[ n[0][i] ] = v;\r
- }\r
- children.push_back( NodeManager::currentNM()->mkNode( n[0].getKind(), new_children ) );\r
- }\r
-\r
- //process children\r
- if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){\r
- children.push_back( n.getOperator() );\r
- }\r
- for( size_t i=0; i<n.getNumChildren(); i++ ){\r
- bool processChild = true;\r
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){\r
- processChild = i>=1;\r
- }\r
- if( processChild ){\r
- children.push_back( simplify( n[i], var_bound ) );\r
- }\r
- }\r
-\r
- //remove from variable bindings\r
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){\r
- //erase from variable bound\r
- for( size_t i=0; i<n[0].getNumChildren(); i++ ){\r
- var_bound.erase( n[0][i] );\r
- }\r
- return NodeManager::currentNM()->mkNode( n.getKind(), children );\r
- }else if( n.getKind()==kind::EQUAL ){\r
- if( children[0].getType()!=children[1].getType() ){\r
- if( children[0].isConst() ){\r
- children[0] = getNewSymbol( children[0], children[1].getType() );\r
- }else if( children[1].isConst() ){\r
- children[1] = getNewSymbol( children[1], children[0].getType() );\r
- }else{\r
- Trace("sort-inference-warn") << "Sort inference created bad equality: " << children[0] << " = " << children[1] << std::endl;\r
- Trace("sort-inference-warn") << " Types : " << children[0].getType() << " " << children[1].getType() << std::endl;\r
- Assert( false );\r
- }\r
- }\r
- return NodeManager::currentNM()->mkNode( kind::APPLY_UF, children );\r
- }else if( n.getKind()==kind::APPLY_UF ){\r
- Node op = n.getOperator();\r
- if( d_symbol_map.find( op )==d_symbol_map.end() ){\r
- //make the new operator if necessary\r
- bool opChanged = false;\r
- std::vector< TypeNode > argTypes;\r
- for( size_t i=0; i<n.getNumChildren(); i++ ){\r
- TypeNode tn = getOrCreateTypeForId( d_op_arg_types[op][i], n[i].getType() );\r
- argTypes.push_back( tn );\r
- if( tn!=n[i].getType() ){\r
- opChanged = true;\r
- }\r
- }\r
- TypeNode retType = getOrCreateTypeForId( d_op_return_types[op], n.getType() );\r
- if( retType!=n.getType() ){\r
- opChanged = true;\r
- }\r
- if( opChanged ){\r
- std::stringstream ss;\r
- ss << "io_$$_" << op;\r
- TypeNode typ = NodeManager::currentNM()->mkFunctionType( argTypes, retType );\r
- d_symbol_map[op] = NodeManager::currentNM()->mkSkolem( ss.str(), typ, "op created during sort inference" );\r
- }else{\r
- d_symbol_map[op] = op;\r
- }\r
- }\r
- children[0] = d_symbol_map[op];\r
- //make sure all children have been taken care of\r
- for( size_t i=0; i<n.getNumChildren(); i++ ){\r
- TypeNode tn = children[i+1].getType();\r
- TypeNode tna = getTypeForId( d_op_arg_types[op][i] );\r
- if( tn!=tna ){\r
- if( n[i].isConst() ){\r
- children[i+1] = getNewSymbol( n[i], tna );\r
- }else{\r
- Trace("sort-inference-warn") << "Sort inference created bad child: " << n[i] << " " << tn << " " << tna << std::endl;\r
- Assert( false );\r
- }\r
- }\r
- }\r
- return NodeManager::currentNM()->mkNode( kind::APPLY_UF, children );\r
- }else{\r
- std::map< Node, Node >::iterator it = var_bound.find( n );\r
- if( it!=var_bound.end() ){\r
- return it->second;\r
- }else if( n.getKind() == kind::VARIABLE ){\r
- if( d_symbol_map.find( n )==d_symbol_map.end() ){\r
- TypeNode tn = getOrCreateTypeForId( d_op_return_types[n], n.getType() );\r
- d_symbol_map[n] = getNewSymbol( n, tn );\r
- }\r
- return d_symbol_map[n];\r
- }else if( n.isConst() ){\r
- //just return n, we will fix at higher scope\r
- return n;\r
- }else{\r
- return NodeManager::currentNM()->mkNode( n.getKind(), children );\r
- }\r
- }\r
-\r
-}\r
-int SortInference::getSortId( Node n ) {\r
- Node op = n.getKind()==kind::APPLY_UF ? n.getOperator() : n;\r
- return getRepresentative( d_op_return_types[op] );\r
-}\r
-\r
-int SortInference::getSortId( Node f, Node v ) {\r
- return getRepresentative( d_var_types[f][v] );\r
-}\r
-\r
-void SortInference::setSkolemVar( Node f, Node v, Node sk ){\r
- d_op_return_types[sk] = getSortId( f, v );\r
-}\r
-\r
+/********************* */
+/*! \file sort_inference.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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 sort inference, based on a simple algorithm:
+ ** First, we assume all functions and predicates have distinct uninterpreted types.
+ ** One pass is made through the input assertions, while a union-find data structure
+ ** maintains necessary information regarding constraints on these types.
+ **/
+
+#include <vector>
+
+#include "util/sort_inference.h"
+
+using namespace CVC4;
+using namespace std;
+
+namespace CVC4 {
+
+
+void SortInference::printSort( const char* c, int t ){
+ int rt = getRepresentative( t );
+ if( d_type_types.find( rt )!=d_type_types.end() ){
+ Trace(c) << d_type_types[rt];
+ }else{
+ Trace(c) << "s_" << rt;
+ }
+}
+
+void SortInference::simplify( std::vector< Node >& assertions, bool doRewrite ){
+ //process all assertions
+ for( unsigned i=0; i<assertions.size(); i++ ){
+ Trace("sort-inference-debug") << "Process " << assertions[i] << std::endl;
+ std::map< Node, Node > var_bound;
+ process( assertions[i], var_bound );
+ }
+ //print debug
+ if( Trace.isOn("sort-inference") ){
+ for( std::map< Node, int >::iterator it = d_op_return_types.begin(); it != d_op_return_types.end(); ++it ){
+ Trace("sort-inference") << it->first << " : ";
+ if( !d_op_arg_types[ it->first ].empty() ){
+ Trace("sort-inference") << "( ";
+ for( size_t i=0; i<d_op_arg_types[ it->first ].size(); i++ ){
+ printSort( "sort-inference", d_op_arg_types[ it->first ][i] );
+ Trace("sort-inference") << " ";
+ }
+ Trace("sort-inference") << ") -> ";
+ }
+ printSort( "sort-inference", it->second );
+ Trace("sort-inference") << std::endl;
+ }
+ for( std::map< Node, std::map< Node, int > >::iterator it = d_var_types.begin(); it != d_var_types.end(); ++it ){
+ Trace("sort-inference") << "Quantified formula " << it->first << " : " << std::endl;
+ for( std::map< Node, int >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
+ printSort( "sort-inference", it2->second );
+ Trace("sort-inference") << std::endl;
+ }
+ Trace("sort-inference") << std::endl;
+ }
+ }
+ if( doRewrite ){
+ //simplify all assertions by introducing new symbols wherever necessary (NOTE: this is unsound for quantifiers)
+ for( unsigned i=0; i<assertions.size(); i++ ){
+ std::map< Node, Node > var_bound;
+ assertions[i] = simplify( assertions[i], var_bound );
+ Trace("sort-inference-rewrite") << " --> " << assertions[i] << std::endl;
+ }
+ //now, ensure constants are distinct
+ for( std::map< TypeNode, std::map< Node, Node > >::iterator it = d_const_map.begin(); it != d_const_map.end(); ++it ){
+ std::vector< Node > consts;
+ for( std::map< Node, Node >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
+ consts.push_back( it2->second );
+ }
+ //add lemma enforcing introduced constants to be distinct?
+ }
+ }
+}
+
+int SortInference::getRepresentative( int t ){
+ std::map< int, int >::iterator it = d_type_union_find.find( t );
+ if( it!=d_type_union_find.end() ){
+ if( it->second==t ){
+ return t;
+ }else{
+ int rt = getRepresentative( it->second );
+ d_type_union_find[t] = rt;
+ return rt;
+ }
+ }else{
+ return t;
+ }
+}
+
+void SortInference::setEqual( int t1, int t2 ){
+ if( t1!=t2 ){
+ int rt1 = getRepresentative( t1 );
+ int rt2 = getRepresentative( t2 );
+ if( rt1!=rt2 ){
+ Trace("sort-inference-debug") << "Set equal : ";
+ printSort( "sort-inference-debug", rt1 );
+ Trace("sort-inference-debug") << " ";
+ printSort( "sort-inference-debug", rt2 );
+ Trace("sort-inference-debug") << std::endl;
+ //check if they must be a type
+ std::map< int, TypeNode >::iterator it1 = d_type_types.find( rt1 );
+ std::map< int, TypeNode >::iterator it2 = d_type_types.find( rt2 );
+ if( it2!=d_type_types.end() ){
+ if( it1==d_type_types.end() ){
+ //swap sides
+ int swap = rt1;
+ rt1 = rt2;
+ rt2 = swap;
+ }else{
+ Assert( rt1==rt2 );
+ }
+ }
+ /*
+ d_type_eq_class[rt1].insert( d_type_eq_class[rt1].end(), d_type_eq_class[rt2].begin(), d_type_eq_class[rt2].end() );
+ d_type_eq_class[rt2].clear();
+ Trace("sort-inference-debug") << "EqClass : { ";
+ for( int i=0; i<(int)d_type_eq_class[rt1].size(); i++ ){
+ Trace("sort-inference-debug") << d_type_eq_class[rt1][i] << ", ";
+ }
+ Trace("sort-inference-debug") << "}" << std::endl;
+ */
+ d_type_union_find[rt2] = rt1;
+ }
+ }
+}
+
+int SortInference::getIdForType( TypeNode tn ){
+ //register the return type
+ std::map< TypeNode, int >::iterator it = d_id_for_types.find( tn );
+ if( it==d_id_for_types.end() ){
+ int sc = sortCount;
+ d_type_types[ sortCount ] = tn;
+ d_id_for_types[ tn ] = sortCount;
+ sortCount++;
+ return sc;
+ }else{
+ return it->second;
+ }
+}
+
+int SortInference::process( Node n, std::map< Node, Node >& var_bound ){
+ Trace("sort-inference-debug") << "Process " << n << std::endl;
+ //add to variable bindings
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ for( size_t i=0; i<n[0].getNumChildren(); i++ ){
+ //TODO: try applying sort inference to quantified variables
+ d_var_types[n][ n[0][i] ] = sortCount;
+ sortCount++;
+
+ //type of the quantified variable must be the same
+ //d_var_types[n][ n[0][i] ] = getIdForType( n[0][i].getType() );
+ var_bound[ n[0][i] ] = n;
+ }
+ }
+
+ //process children
+ std::vector< Node > children;
+ std::vector< int > child_types;
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ bool processChild = true;
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ processChild = i==1;
+ }
+ if( processChild ){
+ children.push_back( n[i] );
+ child_types.push_back( process( n[i], var_bound ) );
+ }
+ }
+
+ //remove from variable bindings
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ //erase from variable bound
+ for( size_t i=0; i<n[0].getNumChildren(); i++ ){
+ var_bound.erase( n[0][i] );
+ }
+ }
+
+ int retType;
+ if( n.getKind()==kind::EQUAL ){
+ //we only require that the left and right hand side must be equal
+ setEqual( child_types[0], child_types[1] );
+ retType = getIdForType( n.getType() );
+ }else if( n.getKind()==kind::APPLY_UF ){
+ Node op = n.getOperator();
+ if( d_op_return_types.find( op )==d_op_return_types.end() ){
+ //assign arbitrary sort for return type
+ d_op_return_types[op] = sortCount;
+ sortCount++;
+ //d_type_eq_class[sortCount].push_back( op );
+ //assign arbitrary sort for argument types
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ d_op_arg_types[op].push_back( sortCount );
+ sortCount++;
+ }
+ }
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ //the argument of the operator must match the return type of the subterm
+ setEqual( child_types[i], d_op_arg_types[op][i] );
+ }
+ //return type is the return type
+ retType = d_op_return_types[op];
+ }else{
+ std::map< Node, Node >::iterator it = var_bound.find( n );
+ if( it!=var_bound.end() ){
+ Trace("sort-inference-debug") << n << " is a bound variable." << std::endl;
+ //the return type was specified while binding
+ retType = d_var_types[it->second][n];
+ }else if( n.getKind() == kind::VARIABLE ){
+ Trace("sort-inference-debug") << n << " is a variable." << std::endl;
+ if( d_op_return_types.find( n )==d_op_return_types.end() ){
+ //assign arbitrary sort
+ d_op_return_types[n] = sortCount;
+ sortCount++;
+ //d_type_eq_class[sortCount].push_back( n );
+ }
+ retType = d_op_return_types[n];
+ }else if( n.isConst() ){
+ Trace("sort-inference-debug") << n << " is a constant." << std::endl;
+ //can be any type we want
+ retType = sortCount;
+ sortCount++;
+ }else{
+ Trace("sort-inference-debug") << n << " is a interpreted symbol." << std::endl;
+ //it is an interpretted term
+ for( size_t i=0; i<children.size(); i++ ){
+ Trace("sort-inference-debug") << children[i] << " forced to have " << children[i].getType() << std::endl;
+ //must enforce the actual type of the operator on the children
+ int ct = getIdForType( children[i].getType() );
+ setEqual( child_types[i], ct );
+ }
+ //return type must be the actual return type
+ retType = getIdForType( n.getType() );
+ }
+ }
+ Trace("sort-inference-debug") << "Type( " << n << " ) = ";
+ printSort("sort-inference-debug", retType );
+ Trace("sort-inference-debug") << std::endl;
+ return retType;
+}
+
+
+TypeNode SortInference::getOrCreateTypeForId( int t, TypeNode pref ){
+ int rt = getRepresentative( t );
+ if( d_type_types.find( rt )!=d_type_types.end() ){
+ return d_type_types[rt];
+ }else{
+ TypeNode retType;
+ //see if we can assign pref
+ if( !pref.isNull() && d_id_for_types.find( pref )==d_id_for_types.end() ){
+ retType = pref;
+ }else{
+ if( d_subtype_count.find( pref )==d_subtype_count.end() ){
+ d_subtype_count[pref] = 0;
+ }
+ //must create new type
+ std::stringstream ss;
+ ss << "it_" << d_subtype_count[pref] << "_" << pref;
+ d_subtype_count[pref]++;
+ retType = NodeManager::currentNM()->mkSort( ss.str() );
+ }
+ d_id_for_types[ retType ] = rt;
+ d_type_types[ rt ] = retType;
+ return retType;
+ }
+}
+
+TypeNode SortInference::getTypeForId( int t ){
+ int rt = getRepresentative( t );
+ if( d_type_types.find( rt )!=d_type_types.end() ){
+ return d_type_types[rt];
+ }else{
+ return TypeNode::null();
+ }
+}
+
+Node SortInference::getNewSymbol( Node old, TypeNode tn ){
+ if( tn==old.getType() ){
+ return old;
+ }else if( old.isConst() ){
+ //must make constant of type tn
+ if( d_const_map[tn].find( old )==d_const_map[tn].end() ){
+ std::stringstream ss;
+ ss << "ic_" << tn << "_" << old;
+ d_const_map[tn][ old ] = NodeManager::currentNM()->mkSkolem( ss.str(), tn, "constant created during sort inference" ); //use mkConst???
+ }
+ return d_const_map[tn][ old ];
+ }else{
+ std::stringstream ss;
+ ss << "i_$$_" << old;
+ return NodeManager::currentNM()->mkSkolem( ss.str(), tn, "created during sort inference" );
+ }
+}
+
+Node SortInference::simplify( Node n, std::map< Node, Node >& var_bound ){
+ std::vector< Node > children;
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ //recreate based on types of variables
+ std::vector< Node > new_children;
+ for( size_t i=0; i<n[0].getNumChildren(); i++ ){
+ TypeNode tn = getOrCreateTypeForId( d_var_types[n][ n[0][i] ], n[0][i].getType() );
+ Node v = getNewSymbol( n[0][i], tn );
+ new_children.push_back( v );
+ var_bound[ n[0][i] ] = v;
+ }
+ children.push_back( NodeManager::currentNM()->mkNode( n[0].getKind(), new_children ) );
+ }
+
+ //process children
+ if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ children.push_back( n.getOperator() );
+ }
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ bool processChild = true;
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ processChild = i>=1;
+ }
+ if( processChild ){
+ children.push_back( simplify( n[i], var_bound ) );
+ }
+ }
+
+ //remove from variable bindings
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ //erase from variable bound
+ for( size_t i=0; i<n[0].getNumChildren(); i++ ){
+ var_bound.erase( n[0][i] );
+ }
+ return NodeManager::currentNM()->mkNode( n.getKind(), children );
+ }else if( n.getKind()==kind::EQUAL ){
+ if( children[0].getType()!=children[1].getType() ){
+ if( children[0].isConst() ){
+ children[0] = getNewSymbol( children[0], children[1].getType() );
+ }else if( children[1].isConst() ){
+ children[1] = getNewSymbol( children[1], children[0].getType() );
+ }else{
+ Trace("sort-inference-warn") << "Sort inference created bad equality: " << children[0] << " = " << children[1] << std::endl;
+ Trace("sort-inference-warn") << " Types : " << children[0].getType() << " " << children[1].getType() << std::endl;
+ Assert( false );
+ }
+ }
+ return NodeManager::currentNM()->mkNode( kind::APPLY_UF, children );
+ }else if( n.getKind()==kind::APPLY_UF ){
+ Node op = n.getOperator();
+ if( d_symbol_map.find( op )==d_symbol_map.end() ){
+ //make the new operator if necessary
+ bool opChanged = false;
+ std::vector< TypeNode > argTypes;
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ TypeNode tn = getOrCreateTypeForId( d_op_arg_types[op][i], n[i].getType() );
+ argTypes.push_back( tn );
+ if( tn!=n[i].getType() ){
+ opChanged = true;
+ }
+ }
+ TypeNode retType = getOrCreateTypeForId( d_op_return_types[op], n.getType() );
+ if( retType!=n.getType() ){
+ opChanged = true;
+ }
+ if( opChanged ){
+ std::stringstream ss;
+ ss << "io_$$_" << op;
+ TypeNode typ = NodeManager::currentNM()->mkFunctionType( argTypes, retType );
+ d_symbol_map[op] = NodeManager::currentNM()->mkSkolem( ss.str(), typ, "op created during sort inference" );
+ }else{
+ d_symbol_map[op] = op;
+ }
+ }
+ children[0] = d_symbol_map[op];
+ //make sure all children have been taken care of
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ TypeNode tn = children[i+1].getType();
+ TypeNode tna = getTypeForId( d_op_arg_types[op][i] );
+ if( tn!=tna ){
+ if( n[i].isConst() ){
+ children[i+1] = getNewSymbol( n[i], tna );
+ }else{
+ Trace("sort-inference-warn") << "Sort inference created bad child: " << n[i] << " " << tn << " " << tna << std::endl;
+ Assert( false );
+ }
+ }
+ }
+ return NodeManager::currentNM()->mkNode( kind::APPLY_UF, children );
+ }else{
+ std::map< Node, Node >::iterator it = var_bound.find( n );
+ if( it!=var_bound.end() ){
+ return it->second;
+ }else if( n.getKind() == kind::VARIABLE ){
+ if( d_symbol_map.find( n )==d_symbol_map.end() ){
+ TypeNode tn = getOrCreateTypeForId( d_op_return_types[n], n.getType() );
+ d_symbol_map[n] = getNewSymbol( n, tn );
+ }
+ return d_symbol_map[n];
+ }else if( n.isConst() ){
+ //just return n, we will fix at higher scope
+ return n;
+ }else{
+ return NodeManager::currentNM()->mkNode( n.getKind(), children );
+ }
+ }
+
+}
+int SortInference::getSortId( Node n ) {
+ Node op = n.getKind()==kind::APPLY_UF ? n.getOperator() : n;
+ return getRepresentative( d_op_return_types[op] );
+}
+
+int SortInference::getSortId( Node f, Node v ) {
+ return getRepresentative( d_var_types[f][v] );
+}
+
+void SortInference::setSkolemVar( Node f, Node v, Node sk ){
+ d_op_return_types[sk] = getSortId( f, v );
+}
+
}
\ No newline at end of file
-/********************* */\r
-/*! \file sort_inference.h\r
- ** \verbatim\r
- ** Original author: ajreynol\r
- ** Major contributors: none\r
- ** Minor contributors (to current version): none\r
- ** This file is part of the CVC4 prototype.\r
- ** Copyright (c) 2009-2012 New York University and The University of Iowa\r
- ** See the file COPYING in the top-level source directory for licensing\r
- ** information.\endverbatim\r
- **\r
- ** \brief Pre-process step for performing sort inference\r
- **/\r
-\r
-#include "cvc4_private.h"\r
-\r
-#ifndef __CVC4__SORT_INFERENCE_H\r
-#define __CVC4__SORT_INFERENCE_H\r
-\r
-#include <iostream>\r
-#include <string>\r
-#include <vector>\r
-#include <map>\r
-#include "expr/node.h"\r
-#include "expr/type_node.h"\r
-\r
-namespace CVC4 {\r
-\r
-class SortInference{\r
-private:\r
- //for debugging\r
- //std::map< int, std::vector< Node > > d_type_eq_class;\r
-private:\r
- int sortCount;\r
- std::map< int, int > d_type_union_find;\r
- std::map< int, TypeNode > d_type_types;\r
- std::map< TypeNode, int > d_id_for_types;\r
- //for apply uf operators\r
- std::map< Node, int > d_op_return_types;\r
- std::map< Node, std::vector< int > > d_op_arg_types;\r
- //for bound variables\r
- std::map< Node, std::map< Node, int > > d_var_types;\r
- //get representative\r
- int getRepresentative( int t );\r
- void setEqual( int t1, int t2 );\r
- int getIdForType( TypeNode tn );\r
- void printSort( const char* c, int t );\r
- //process\r
- int process( Node n, std::map< Node, Node >& var_bound );\r
-private:\r
- //mapping from old symbols to new symbols\r
- std::map< Node, Node > d_symbol_map;\r
- //mapping from constants to new symbols\r
- std::map< TypeNode, std::map< Node, Node > > d_const_map;\r
- //number of subtypes generated\r
- std::map< TypeNode, int > d_subtype_count;\r
- //helper functions for simplify\r
- TypeNode getOrCreateTypeForId( int t, TypeNode pref );\r
- TypeNode getTypeForId( int t );\r
- Node getNewSymbol( Node old, TypeNode tn );\r
- //simplify\r
- Node simplify( Node n, std::map< Node, Node >& var_bound );\r
-public:\r
- SortInference() : sortCount( 0 ){}\r
- ~SortInference(){}\r
-\r
- void simplify( std::vector< Node >& assertions, bool doRewrite = false );\r
- int getSortId( Node n );\r
- int getSortId( Node f, Node v );\r
- //set that sk is the skolem variable of v for quantifier f\r
- void setSkolemVar( Node f, Node v, Node sk );\r
-};\r
-\r
-}\r
-\r
-#endif\r
+/********************* */
+/*! \file sort_inference.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** 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 Pre-process step for performing sort inference
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__SORT_INFERENCE_H
+#define __CVC4__SORT_INFERENCE_H
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <map>
+#include "expr/node.h"
+#include "expr/type_node.h"
+
+namespace CVC4 {
+
+class SortInference{
+private:
+ //for debugging
+ //std::map< int, std::vector< Node > > d_type_eq_class;
+private:
+ int sortCount;
+ std::map< int, int > d_type_union_find;
+ std::map< int, TypeNode > d_type_types;
+ std::map< TypeNode, int > d_id_for_types;
+ //for apply uf operators
+ std::map< Node, int > d_op_return_types;
+ std::map< Node, std::vector< int > > d_op_arg_types;
+ //for bound variables
+ std::map< Node, std::map< Node, int > > d_var_types;
+ //get representative
+ int getRepresentative( int t );
+ void setEqual( int t1, int t2 );
+ int getIdForType( TypeNode tn );
+ void printSort( const char* c, int t );
+ //process
+ int process( Node n, std::map< Node, Node >& var_bound );
+private:
+ //mapping from old symbols to new symbols
+ std::map< Node, Node > d_symbol_map;
+ //mapping from constants to new symbols
+ std::map< TypeNode, std::map< Node, Node > > d_const_map;
+ //number of subtypes generated
+ std::map< TypeNode, int > d_subtype_count;
+ //helper functions for simplify
+ TypeNode getOrCreateTypeForId( int t, TypeNode pref );
+ TypeNode getTypeForId( int t );
+ Node getNewSymbol( Node old, TypeNode tn );
+ //simplify
+ Node simplify( Node n, std::map< Node, Node >& var_bound );
+public:
+ SortInference() : sortCount( 0 ){}
+ ~SortInference(){}
+
+ void simplify( std::vector< Node >& assertions, bool doRewrite = false );
+ int getSortId( Node n );
+ int getSortId( Node f, Node v );
+ //set that sk is the skolem variable of v for quantifier f
+ void setSkolemVar( Node f, Node v, Node sk );
+};
+
+}
+
+#endif