fixed files with DOS newlines; fixed contrib/ scripts to use git
authorMorgan Deters <mdeters@cs.nyu.edu>
Mon, 4 Feb 2013 22:30:18 +0000 (17:30 -0500)
committerMorgan Deters <mdeters@cs.nyu.edu>
Mon, 4 Feb 2013 22:30:18 +0000 (17:30 -0500)
23 files changed:
contrib/get-authors
contrib/update-copyright.pl
src/theory/arrays/theory_arrays_model.h
src/theory/quantifiers/inst_gen.cpp [changed mode: 0755->0644]
src/theory/quantifiers/inst_gen.h [changed mode: 0755->0644]
src/theory/quantifiers/inst_match_generator.cpp [changed mode: 0755->0644]
src/theory/quantifiers/inst_match_generator.h [changed mode: 0755->0644]
src/theory/quantifiers/inst_strategy_cbqi.cpp [changed mode: 0755->0644]
src/theory/quantifiers/inst_strategy_cbqi.h [changed mode: 0755->0644]
src/theory/quantifiers/inst_strategy_e_matching.cpp [changed mode: 0755->0644]
src/theory/quantifiers/inst_strategy_e_matching.h [changed mode: 0755->0644]
src/theory/quantifiers/macros.cpp [changed mode: 0755->0644]
src/theory/quantifiers/macros.h [changed mode: 0755->0644]
src/theory/quantifiers/quant_util.cpp [changed mode: 0755->0644]
src/theory/quantifiers/quant_util.h [changed mode: 0755->0644]
src/theory/quantifiers/quantifiers_attributes.cpp
src/theory/quantifiers/quantifiers_attributes.h
src/theory/rep_set.cpp
src/theory/rep_set.h
src/theory/rewriterules/efficient_e_matching.cpp [changed mode: 0755->0644]
src/theory/rewriterules/efficient_e_matching.h [changed mode: 0755->0644]
src/util/sort_inference.cpp [changed mode: 0755->0644]
src/util/sort_inference.h [changed mode: 0755->0644]

index ef6abff8efd3123e4a078d6a1edf344b71af20bf..118ca44662edb9d6234d2ef5fcc35eee0d5770be 100755 (executable)
@@ -2,13 +2,15 @@
 #
 # 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
@@ -16,8 +18,8 @@ while [ $# -gt 0 ]; do
   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
index 8ac920bbfbe0b191aad4a855330d7f6e6c4e1d78..4811a4bbe04afd0692823e3f3607e569ee3fff9a 100755 (executable)
@@ -2,7 +2,7 @@
 #
 # 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
@@ -37,17 +39,17 @@ my $excluded_paths = '^(src/parser/antlr_input_imports.cpp|src/bindings/compat/.
 
 # 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
@@ -71,7 +73,7 @@ if($#ARGV >= 0 && $ARGV[0] eq '-h' || $ARGV[0] eq '--help') {
   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') {
@@ -87,11 +89,12 @@ if($#ARGV == -1) {
   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:
@@ -101,7 +104,8 @@ EOF
   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;
 }
@@ -129,9 +133,9 @@ while($#searchdirs >= 0) {
 
 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';
index 8dfc7fc4a15842086cdc55f6483420bb55b8ac2c..c82c7635deb5cb77851a47334f2d914bf444f7cd 100644 (file)
@@ -1,58 +1,58 @@
 /*********************                                                        */
 /*! \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
old mode 100755 (executable)
new mode 100644 (file)
index d3bd6ad..dea371e
-/*********************                                                        */\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();
+        }
+      }
+    }
+  }
+}
old mode 100755 (executable)
new mode 100644 (file)
index f6e6a37..94922df
@@ -1,61 +1,59 @@
-/*********************                                                        */\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
old mode 100755 (executable)
new mode 100644 (file)
index 7dc0058..e5922e7
-/*********************                                                        */\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 */
old mode 100755 (executable)
new mode 100644 (file)
index a544f60..602e71c
-/*********************                                                        */\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
old mode 100755 (executable)
new mode 100644 (file)
index ddf763b..b12fed6
-/*********************                                                        */\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();
+          }
+        }
+      }
+    }
+  }
+  */
+}
old mode 100755 (executable)
new mode 100644 (file)
index 3ee423f..de548ab
-/*********************                                                        */\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
old mode 100755 (executable)
new mode 100644 (file)
index 91cd282..3f5cc76
-/*********************                                                        */\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);
+}
+*/
old mode 100755 (executable)
new mode 100644 (file)
index fa40946..13d443c
-/*********************                                                        */\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
old mode 100755 (executable)
new mode 100644 (file)
index c116b73..9f08764
-/*********************                                                        */\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;
+  }
+}
old mode 100755 (executable)
new mode 100644 (file)
index b1fbb3e..140f029
@@ -1,62 +1,62 @@
-/*********************                                                        */\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
old mode 100755 (executable)
new mode 100644 (file)
index d1b0e0f..9e4a2a1
-/*********************                                                        */\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 );
+      }
+    }
+  }
+}
old mode 100755 (executable)
new mode 100644 (file)
index bb6855c..85602db
@@ -1,99 +1,99 @@
-/*********************                                                        */\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
index 2f6dc47dbb4e6966e1108dafeb9007266d3aa832..b00fe45f43c784458b7d29d33966345e89b2858b 100644 (file)
@@ -1,41 +1,41 @@
 /*********************                                                        */
 /*! \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] );
+    }
+  }
+}
index 88bac8bc94f5f5f45cbb06eb0679e272f96d4706..8e8ebe97a6a03772bdfcd0fe4ed46ba6386688cd 100644 (file)
@@ -1,51 +1,51 @@
 /*********************                                                        */
 /*! \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
index b50878e703fa50d177ce0bf7e0a5c7aee09b1438..4ae7f2d0c3e136a6ff85f7fc0c1fe1fade880911 100644 (file)
 /*********************                                                        */
 /*! \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;
+}
index 61b2ebf9fab217332df48cfa7ee5c72eb6728e2c..dc31f2d5fe77ad2c5f795f165f3ebda45ecb3865 100644 (file)
 /*********************                                                        */
 /*! \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
old mode 100755 (executable)
new mode 100644 (file)
index 2f39d80..5ed34d4
-/*********************                                                        */\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 */
old mode 100755 (executable)
new mode 100644 (file)
index 2f0a071..11c6b78
-/*********************                                                        */\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 */
old mode 100755 (executable)
new mode 100644 (file)
index cab5dac..0304a8e
-/*********************                                                        */\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
old mode 100755 (executable)
new mode 100644 (file)
index 1378a26..0b1f96f
@@ -1,76 +1,76 @@
-/*********************                                                        */\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