Merge branch '1.4.x'
authorMorgan Deters <mdeters@cs.nyu.edu>
Sat, 11 Oct 2014 17:04:27 +0000 (13:04 -0400)
committerMorgan Deters <mdeters@cs.nyu.edu>
Sat, 11 Oct 2014 17:04:27 +0000 (13:04 -0400)
193 files changed:
Makefile.builds.in
NEWS
configure.ac
contrib/theoryskel/theory_DIR.cpp
contrib/update-copyright.pl
doc/SmtEngine.3cvc_template.in
doc/options.3cvc_template.in
examples/sets-translate/sets_translate.cpp
library_versions
proofs/signatures/ex_bv.plf [new file with mode: 0755]
proofs/signatures/smt.plf
proofs/signatures/th_bv.plf [new file with mode: 0755]
src/Makefile.am
src/bindings/Makefile.am
src/bindings/compat/c/Makefile.am
src/bindings/compat/java/Makefile.am
src/compat/Makefile.am
src/compat/cvc3_compat.cpp
src/decision/decision_engine.cpp
src/decision/decision_engine.h
src/decision/decision_strategy.h
src/decision/justification_heuristic.cpp
src/decision/justification_heuristic.h
src/expr/command.cpp
src/expr/command.h
src/expr/expr_template.cpp
src/expr/options
src/expr/symbol_table.cpp
src/expr/symbol_table.h
src/main/command_executor.cpp
src/main/command_executor_portfolio.cpp
src/main/driver_unified.cpp
src/main/options
src/options/mkoptions
src/parser/Makefile.am
src/parser/cvc/Cvc.g
src/parser/parser.h
src/parser/smt2/Smt2.g
src/parser/smt2/smt2.cpp
src/parser/smt2/smt2.h
src/printer/ast/ast_printer.cpp
src/printer/cvc/cvc_printer.cpp
src/printer/printer.cpp
src/printer/printer.h
src/printer/smt2/smt2_printer.cpp
src/printer/smt2/smt2_printer.h
src/proof/cnf_proof.cpp
src/proof/cnf_proof.h
src/proof/proof.h
src/proof/proof_manager.cpp
src/proof/proof_manager.h
src/proof/sat_proof.cpp
src/proof/sat_proof.h
src/prop/bvminisat/bvminisat.cpp
src/prop/bvminisat/bvminisat.h
src/prop/cnf_stream.cpp
src/prop/cnf_stream.h
src/prop/minisat/core/Solver.cc
src/prop/minisat/core/Solver.h
src/prop/minisat/minisat.cpp
src/prop/minisat/minisat.h
src/prop/minisat/simp/SimpSolver.cc
src/prop/minisat/simp/SimpSolver.h
src/prop/prop_engine.cpp
src/prop/prop_engine.h
src/prop/sat_solver.h
src/prop/theory_proxy.cpp
src/smt/boolean_terms.cpp
src/smt/options
src/smt/options_handlers.h
src/smt/simplification_mode.cpp
src/smt/simplification_mode.h
src/smt/smt_engine.cpp
src/smt/smt_engine.h
src/smt/smt_engine_scope.h
src/theory/arith/theory_arith_private.cpp
src/theory/arrays/array_info.cpp
src/theory/arrays/array_info.h
src/theory/arrays/options
src/theory/arrays/theory_arrays.cpp
src/theory/arrays/theory_arrays.h
src/theory/booleans/circuit_propagator.h
src/theory/booleans/theory_bool_type_rules.h
src/theory/builtin/kinds
src/theory/builtin/theory_builtin_type_rules.h
src/theory/bv/aig_bitblaster.cpp
src/theory/bv/bitblaster_template.h
src/theory/bv/bv_quick_check.cpp
src/theory/bv/bv_subtheory_bitblast.cpp
src/theory/bv/bv_subtheory_bitblast.h
src/theory/bv/eager_bitblaster.cpp
src/theory/bv/lazy_bitblaster.cpp
src/theory/bv/theory_bv.cpp
src/theory/bv/theory_bv.h
src/theory/datatypes/kinds
src/theory/datatypes/options
src/theory/datatypes/theory_datatypes.cpp
src/theory/datatypes/theory_datatypes.h
src/theory/datatypes/theory_datatypes_type_rules.h
src/theory/datatypes/type_enumerator.h
src/theory/idl/theory_idl.cpp
src/theory/quantifiers/bounded_integers.cpp
src/theory/quantifiers/bounded_integers.h
src/theory/quantifiers/candidate_generator.cpp
src/theory/quantifiers/candidate_generator.h
src/theory/quantifiers/ce_guided_instantiation.cpp [new file with mode: 0644]
src/theory/quantifiers/ce_guided_instantiation.h [new file with mode: 0644]
src/theory/quantifiers/conjecture_generator.cpp [new file with mode: 0755]
src/theory/quantifiers/conjecture_generator.h [new file with mode: 0755]
src/theory/quantifiers/first_order_model.cpp
src/theory/quantifiers/first_order_model.h
src/theory/quantifiers/full_model_check.cpp
src/theory/quantifiers/inst_match_generator.cpp
src/theory/quantifiers/inst_match_generator.h
src/theory/quantifiers/inst_strategy_cbqi.cpp
src/theory/quantifiers/inst_strategy_cbqi.h
src/theory/quantifiers/inst_strategy_e_matching.cpp
src/theory/quantifiers/inst_strategy_e_matching.h
src/theory/quantifiers/instantiation_engine.cpp
src/theory/quantifiers/instantiation_engine.h
src/theory/quantifiers/kinds
src/theory/quantifiers/macros.cpp
src/theory/quantifiers/model_builder.cpp
src/theory/quantifiers/model_engine.cpp
src/theory/quantifiers/model_engine.h
src/theory/quantifiers/modes.h
src/theory/quantifiers/options
src/theory/quantifiers/options_handlers.h
src/theory/quantifiers/quant_conflict_find.cpp [changed mode: 0644->0755]
src/theory/quantifiers/quant_conflict_find.h [changed mode: 0644->0755]
src/theory/quantifiers/quantifiers_attributes.cpp
src/theory/quantifiers/quantifiers_attributes.h
src/theory/quantifiers/quantifiers_rewriter.cpp
src/theory/quantifiers/rewrite_engine.cpp
src/theory/quantifiers/rewrite_engine.h
src/theory/quantifiers/term_database.cpp
src/theory/quantifiers/term_database.h
src/theory/quantifiers/theory_quantifiers.cpp
src/theory/quantifiers/theory_quantifiers.h
src/theory/quantifiers/theory_quantifiers_type_rules.h
src/theory/quantifiers/trigger.cpp
src/theory/quantifiers/trigger.h
src/theory/quantifiers_engine.cpp
src/theory/quantifiers_engine.h
src/theory/rep_set.cpp
src/theory/sets/options
src/theory/sets/scrutinize.h
src/theory/sets/theory_sets.cpp
src/theory/sets/theory_sets.h
src/theory/sets/theory_sets_private.cpp
src/theory/sets/theory_sets_private.h
src/theory/sets/theory_sets_type_rules.h
src/theory/strings/kinds
src/theory/strings/regexp_operation.cpp
src/theory/strings/regexp_operation.h
src/theory/strings/theory_strings.cpp
src/theory/strings/theory_strings_rewriter.cpp
src/theory/strings/theory_strings_type_rules.h
src/theory/theory.h
src/theory/theory_engine.cpp
src/theory/theory_engine.h
src/theory/uf/options
src/theory/uf/options_handlers.h
src/theory/uf/theory_uf.cpp
src/theory/uf/theory_uf_strong_solver.cpp
src/theory/uf/theory_uf_strong_solver.h
src/theory/valuation.cpp
src/util/Makefile.am
src/util/datatype.cpp
src/util/ite_removal.cpp
src/util/ite_removal.h
src/util/unsat_core.cpp [new file with mode: 0644]
src/util/unsat_core.h [new file with mode: 0644]
src/util/unsat_core.i [new file with mode: 0644]
test/regress/regress0/Makefile.am
test/regress/regress0/arrays/Makefile.am
test/regress/regress0/arrays/constarr.cvc [new file with mode: 0644]
test/regress/regress0/arrays/constarr.smt2 [new file with mode: 0644]
test/regress/regress0/arrays/constarr2.cvc [new file with mode: 0644]
test/regress/regress0/arrays/constarr2.smt2 [new file with mode: 0644]
test/regress/regress0/arrays/constarr3.cvc [new file with mode: 0644]
test/regress/regress0/arrays/constarr3.smt2 [new file with mode: 0644]
test/regress/regress0/arrays/parsing_ringer.cvc
test/regress/regress0/bug567.smt2
test/regress/regress0/datatypes/Makefile.am
test/regress/regress0/datatypes/tenum-bug.smt2 [new file with mode: 0644]
test/regress/regress0/quantifiers/Makefile.am
test/regress/regress0/quantifiers/macros-int-real.smt2 [new file with mode: 0644]
test/regress/regress0/simplification_bug3.cvc [deleted file]
test/regress/regress0/strings/Makefile.am
test/regress/run_regression
test/unit/prop/cnf_stream_white.h
test/unit/theory/type_enumerator_white.h

index 296e5a9746cc75c86edfff64d78a6892952a060c..265556f4df865e347851d57dc241eb741b938f70 100644 (file)
@@ -6,14 +6,8 @@
 #
 # Its main purposes are to:
 # 1. build the current build profile
-# 2. install into "builds/$(CURRENT_BUILD)/$(prefix)"
-# 3. set up "builds/$(CURRENT_BUILD)/{bin,lib}" symlinks
-# 4. install into "builds/$(prefix)"
-# 5. set up "builds/bin" and "builds/lib"
-#
-# Steps 2 and 4 require libtool-relinking for dynamically-linked
-# executables and libraries, since build/bin is not the final
-# installation path.
+# 2. set up builds/$(CURRENT_BUILD)/{bin,lib} symlinks
+# 3. set up builds/bin and builds/lib symlinks
 
 # Include the "current" build profile.
 include current
@@ -40,12 +34,6 @@ LIBTOOL = $(CURRENT_BUILD)/libtool
 # Are we building the libcvc4compat library ?
 CVC4_BUILD_LIBCOMPAT = @CVC4_BUILD_LIBCOMPAT@
 
-# Are we building static/dynamic libraries/binaries?  One or the other can be
-# on, or both.
-BUILDING_STATIC = @BUILDING_STATIC@
-BUILDING_SHARED = @BUILDING_SHARED@
-STATIC_BINARY = @STATIC_BINARY@
-
 # @
 AM_V_at = $(am__v_at_$(V))
 am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
@@ -61,21 +49,6 @@ AM_V_mkdir = $(am__v_mkdir_$(V))
 am__v_mkdir_ = $(am__v_mkdir_$(AM_DEFAULT_VERBOSITY))
 am__v_mkdir_0 = @$(am__v_mkdir_noat_0)
 am__v_mkdir_1 = $(am__v_mkdir_noat_1)
-# libtool --mode=install $(install_sh)
-AM_V_ltinstall = $(am__v_ltinstall_$(V))
-am__v_ltinstall_ = $(am__v_ltinstall_$(AM_DEFAULT_VERBOSITY))
-am__v_ltinstall_0 = @$(SHELL) -c 'echo "   LTINS $$1"; $(LIBTOOL) --silent --mode=install $(install_sh) "$$@"' bash
-am__v_ltinstall_1 = $(LIBTOOL) --mode=install $(install_sh)
-# install_sh (never prefix with @)
-AM_V_install_sh_noat = $(am__v_install_sh_noat_$(V))
-am__v_install_sh_noat_ = $(am__v_install_sh_noat_$(AM_DEFAULT_VERBOSITY))
-am__v_install_sh_noat_0 = $(SHELL) -c 'echo "   INSTL $$1"; $(install_sh) "$$@"' bash
-am__v_install_sh_noat_1 = $(install_sh)
-# relinking
-AM_V_relink = $(am__v_relink_$(V))
-am__v_relink_ = $(am__v_relink_$(AM_DEFAULT_VERBOSITY))
-am__v_relink_0 = echo "   RELNK"
-am__v_relink_1 = :
 
 # all the binaries that might need to be installed
 # (it's not a fatal error for one/some don't exist in a given build
@@ -87,108 +60,47 @@ _default_build_: all
 all:
 #      build the current build profile
        $(AM_V_at)(cd $(CURRENT_BUILD) && $(MAKE) $@)
-#      set up builds/$(CURRENT_BUILD)/...prefix.../bin
-#      and builds/$(CURRENT_BUILD)/...prefix.../lib
-       $(AM_V_mkdir) "$(CURRENT_BUILD)$(bindir)"
-       $(AM_V_mkdir) "$(CURRENT_BUILD)$(libdir)"
-#      install libcvc4
-       $(AM_V_ltinstall) $(CURRENT_BUILD)/src/libcvc4.la \
-               "$(abs_builddir)$(libdir)"
-#      install libcvc4parser
-       $(AM_V_ltinstall) $(CURRENT_BUILD)/src/parser/libcvc4parser.la \
-               "$(abs_builddir)$(libdir)"
+#      set up builds/$(CURRENT_BUILD)/{bin,lib}
+       $(AM_V_mkdir) $(CURRENT_BUILD)/bin
+       $(AM_V_mkdir) $(CURRENT_BUILD)/lib
+#      symlink libcvc4, libcvc4parser
+       $(AM_V_at)cd $(CURRENT_BUILD)/lib && \
+       ln -sf ../src/libcvc4.* \
+               ../src/parser/libcvc4parser.* \
+               .
+       -$(AM_V_at)cd $(CURRENT_BUILD)/lib && \
+       test -d ../src/.libs && \
+       ln -sf ../src/.libs/libcvc4.* \
+               .
+       -$(AM_V_at)cd $(CURRENT_BUILD)/lib && \
+       test -d ../src/parser/.libs && \
+       ln -sf ../src/parser/.libs/libcvc4parser.* \
+               .
 ifeq ($(CVC4_BUILD_LIBCOMPAT),yes)
-#      install libcvc4compat
-       $(CURRENT_BUILD)/libtool --mode=install $(install_sh) \
-               $(CURRENT_BUILD)/src/compat/libcvc4compat.la \
-               "$(abs_builddir)$(libdir)"
+#      symlink libcvc4compat
+       $(AM_V_at)cd $(CURRENT_BUILD)/lib && \
+       ln -sf ../src/compat/libcvc4compat.* \
+               .
+       -$(AM_V_at)cd $(CURRENT_BUILD)/lib && \
+       test -d ../src/compat/.libs && \
+       ln -sf ../src/compat/.libs/libcvc4compat.* \
+               .
 endif
-ifeq ($(BUILDING_SHARED)$(STATIC_BINARY),10)
-#      if we're building shared libs and the binary is not static, relink
-#      the handling with empty $relink_command is a hack for Mac OS
-       $(AM_V_at)thelibdir="$(abs_builddir)$(libdir)"; \
-       progdir="$(abs_builddir)$(bindir)"; for file in $(CVC4_BINARIES); do \
-               if test -r $(CURRENT_BUILD)/src/main/$$file; then \
-                       eval `grep '^relink_command=' $(CURRENT_BUILD)/src/main/$$file | sed 's:-Wl,-rpath:-Wl,-rpath -Wl,\\\\$$thelibdir -Wl,-rpath:'`; \
-                       if test -z "$$relink_command"; then \
-                               $(AM_V_mkdir_noat) "$(CURRENT_BUILD)$(bindir)/.libs"; \
-                               $(AM_V_install_sh_noat) \
-                                       $(CURRENT_BUILD)/src/main/.libs/$$file \
-                                       "$(abs_builddir)$(bindir)/.libs"; \
-                               $(AM_V_install_sh_noat) \
-                                       $(CURRENT_BUILD)/src/main/$$file \
-                                       "$(abs_builddir)$(bindir)"; \
-                       else \
-                               $(AM_V_relink) "$$file"; eval "(cd $(CURRENT_BUILD)/src/main && $$relink_command)"; \
-                       fi; \
-               else \
-                       rm -f "$(abs_builddir)$(bindir)/$$file"; \
-               fi; \
-       done
-else
-#      if we're building static libs only, just install the driver binary directly
-       $(AM_V_at)for file in $(CVC4_BINARIES); do \
-               if test -r $(CURRENT_BUILD)/src/main/$$file; then \
-                       $(AM_V_install_sh_noat) \
-                               $(CURRENT_BUILD)/src/main/$$file \
-                               "$(abs_builddir)$(bindir)"; \
+#      symlink the binaries
+       $(AM_V_at)cd $(CURRENT_BUILD)/bin && \
+       for binary in $(CVC4_BINARIES); do \
+               if test -x ../src/main/$$binary; then \
+                       ln -sf ../src/main/$$binary \
+                               . ; \
                else \
-                       rm -f "$(abs_builddir)$(bindir)/$$file"; \
+                       rm -f "$$binary"; \
                fi; \
        done
-endif
-#      set up builds/$(CURRENT_BUILD)/bin and builds/$(CURRENT_BUILD)/lib
-       rm -f $(CURRENT_BUILD)/lib; ln -sf "$(abs_builddir)$(libdir)" $(CURRENT_BUILD)/lib
-       rm -f $(CURRENT_BUILD)/bin; ln -sf "$(abs_builddir)$(bindir)" $(CURRENT_BUILD)/bin
-#      set up builds/...prefix.../bin and builds/...prefix.../lib
-       $(AM_V_mkdir) ".$(bindir)"
-       $(AM_V_mkdir) ".$(libdir)"
-#      install libcvc4
-       $(AM_V_ltinstall) $(CURRENT_BUILD)/src/libcvc4.la "`pwd`$(libdir)"
-#      install libcvc4parser
-       $(AM_V_ltinstall) $(CURRENT_BUILD)/src/parser/libcvc4parser.la "`pwd`$(libdir)"
-ifeq ($(CVC4_BUILD_LIBCOMPAT),yes)
-#      install libcvc4compat
-       $(CURRENT_BUILD)/libtool --mode=install $(install_sh) $(CURRENT_BUILD)/src/compat/libcvc4compat.la "`pwd`$(libdir)"
-endif
-ifeq ($(BUILDING_SHARED)$(STATIC_BINARY),10)
-#      if we're building shared libs and the binary is not static, relink
-#      the handling with empty $relink_command is a hack for Mac OS
-       $(AM_V_at)thelibdir="`pwd`$(libdir)"; progdir="`pwd`$(bindir)"; for file in $(CVC4_BINARIES); do \
-               if test -r $(CURRENT_BUILD)/src/main/$$file; then \
-                       eval `grep '^relink_command=' $(CURRENT_BUILD)/src/main/$$file | sed 's:-Wl,-rpath:-Wl,-rpath -Wl,\\\\$$thelibdir -Wl,-rpath:'`; \
-                       if test -z "$$relink_command"; then \
-                               $(AM_V_mkdir_noat) ".$(bindir)/.libs"; \
-                               $(AM_V_install_sh_noat) \
-                                       $(CURRENT_BUILD)/src/main/.libs/$$file \
-                                       "`pwd`$(bindir)/.libs"; \
-                               $(AM_V_install_sh_noat) \
-                                       $(CURRENT_BUILD)/src/main/$$file \
-                                       "`pwd`$(bindir)"; \
-                       else \
-                               $(AM_V_relink) "$$file"; eval "(cd $(CURRENT_BUILD)/src/main && $$relink_command)"; \
-                       fi; \
-               else \
-                       rm -f "`pwd`$(bindir)/$$file"; \
-               fi; \
-       done
-else
-#      if we're building static libs only, just install the driver binary directly
-       $(AM_V_at)for file in $(CVC4_BINARIES); do \
-               if test -r $(CURRENT_BUILD)/src/main/$$file; then \
-                       $(AM_V_install_sh_noat) \
-                               $(CURRENT_BUILD)/src/main/$$file \
-                               "`pwd`$(bindir)"; \
-               else \
-                       rm -f "`pwd`$(bindir)/$$file"; \
-               fi; \
-       done
-endif
-#      set up builds/bin and builds/lib
-       rm -f lib; ln -sf ".$(libdir)" lib
-       rm -f bin; ln -sf ".$(bindir)" bin
-       rm -f doc; ln -sf "$(CURRENT_BUILD)/doc" doc
-       rm -f examples; ln -sf "$(CURRENT_BUILD)/examples" examples
+#      set up builds/doc and builds/examples
+       $(AM_V_at)rm -f bin; ln -sf $(CURRENT_BUILD)/bin bin
+       $(AM_V_at)rm -f lib; ln -sf $(CURRENT_BUILD)/lib lib
+       $(AM_V_at)rm -f doc; ln -sf $(CURRENT_BUILD)/doc doc
+       $(AM_V_at)rm -f examples; ln -sf $(CURRENT_BUILD)/examples examples
 
 # The descent into "src" with target "check" is to build check
 # prerequisites (e.g. CHECK_PROGRAMS, CHECK_LTLIBRARIES, ...).
diff --git a/NEWS b/NEWS
index 4c0de2ce30a02837c2a00435a2e81c61d16c9ea7..7e3a30d742cc580254c05ae4b6357f8595973835 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,10 @@ This file contains a summary of important user-visible changes.
 Changes since 1.4
 =================
 
+* Support for unsat cores.
+* Simplification mode "incremental" no longer supported.
+* Support for array constants in constraints.
+* Syntax for array models have changed in some language front-ends.
 * In SMT-LIB model output, real-sorted but integer-valued constants are
   now printed in accordance with the standard (e.g. "1.0").
 
index 1ae4dbe21cc48b37dad85808c4f683e780cda0a1..d8329307956e504a6c01412171924272e5408dbb 100644 (file)
@@ -2,8 +2,8 @@
 # Process this file with autoconf to produce a configure script.
 
 m4_define(_CVC4_MAJOR,          1)       dnl version (major)
-m4_define(_CVC4_MINOR,          4)       dnl version (minor)
-m4_define(_CVC4_RELEASE,        1)       dnl version (alpha)
+m4_define(_CVC4_MINOR,          5)       dnl version (minor)
+m4_define(_CVC4_RELEASE,        0)       dnl version (alpha)
 m4_define(_CVC4_EXTRAVERSION,   [-prerelease])      dnl version (extra)
 m4_define(_CVC4_RELEASE_STRING, _CVC4_MAJOR[.]_CVC4_MINOR[]m4_if(_CVC4_RELEASE,[0],,[.]_CVC4_RELEASE)_CVC4_EXTRAVERSION) dnl version string
 
@@ -126,6 +126,10 @@ if test -n "${enable_optimized+set}"; then
     btargs="$btargs nooptimized"
   fi
 fi
+# --enable-staticbinary is an alias for --enable-static-binary
+if test -n "${enable_staticbinary+set}"; then
+  enable_static_binary="$enable_staticbinary"
+fi
 if test -n "${enable_static_binary+set}"; then
   if test "$enable_static_binary" = yes; then
     btargs="$btargs staticbinary"
index 72101a5a660ac08b01769f86056458d6d23c3a8b..535a54fd7ae8b9b2b259ab033ecdc4d24b8dbb4f 100644 (file)
@@ -16,6 +16,9 @@ Theory$camel::Theory$camel(context::Context* c,
 }/* Theory$camel::Theory$camel() */
 
 void Theory$camel::check(Effort level) {
+  if (done() && !fullEffort(level)) {
+    return;
+  }
 
   while(!done()) {
     // Get all the assertions
index f3c4248ac25dd24f7582b0a57525e9dda9e69ed5..2a581698c5a1123fd02c682346b163b84546663d 100755 (executable)
@@ -48,13 +48,6 @@ my $standard_template = <<EOF;
  ** information.\\endverbatim
 EOF
 
-my $public_template = <<EOF;
- ** 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
-
 ## end config ##
 
 use strict;
@@ -164,17 +157,25 @@ sub handleFile {
     print $OUT " ** Original author: $author\n";
     print $OUT " ** Major contributors: $major_contributors\n";
     print $OUT " ** Minor contributors (to current version): $minor_contributors\n";
-    print $OUT $standard_template;
-    print $OUT " **\n";
+    my $comment_stub = "";
     while(my $line = <$IN>) {
+      if($line =~ /\b[Cc]opyright\b/ && $line !~ /\bNew York University and The University of Iowa\b/) {
+        # someone else holds this copyright
+        print $OUT $line;
+      }
       last if $line =~ /^ \*\*\s*$/;
       if($line =~ /\*\//) {
-        print $OUT " ** [[ Add lengthier description here ]]\n";
-        print $OUT " ** \\todo document this file\n";
-        print $OUT $line;
+        $comment_stub = " ** [[ Add lengthier description here ]]\n\
+ ** \\todo document this file\n\
+$line";
         last;
       }
     }
+    print $OUT $standard_template;
+    print $OUT " **\n";
+    if($comment_stub) {
+      print $OUT $comment_stub;
+    }
   } else {
     my $line = $_;
     print "adding\n";
index 3a876fefcc96406426fdce5628f1e0a0a2165a39..d741fd33f8da96994a10a6a9c947bb063302b3f2 100644 (file)
@@ -19,6 +19,8 @@ and
 .I SmtEngine::getOption()
 use the following option keys.
 
+.ad l
+
 .RS
 .TP 10
 .I "COMMON OPTIONS"
@@ -28,6 +30,8 @@ ${remaining_manpage_smt_documentation}
 .PD
 .RE
 
+.ad b
+
 .SH VERSION
 This manual page refers to
 .B CVC4
index a0d6c1640b78bd30366cb29a1cdacd4a75da4552..f92faf47ff19c8159243bacffd3e3bac73263bc4 100644 (file)
@@ -7,6 +7,8 @@ options \- the options infrastructure
 
 .SH AVAILABLE INTERNAL OPTIONS
 
+.ad l
+
 .RS
 .TP 10
 .I "COMMON OPTIONS"
@@ -16,6 +18,8 @@ ${remaining_manpage_internals_documentation}
 .PD
 .RE
 
+.ad b
+
 .SH VERSION
 This manual page refers to
 .B CVC4
index d214b6ab8b6b5f7c970aa79a52a60f5d7097e2f4..fbec42829e46b7973ce2e30ffa14a97cba3bf880 100644 (file)
@@ -159,7 +159,7 @@ class Mapper {
                    em->mkFunctionType( t_t, t ) );
 
       if(!enableAxioms)
-        sout << "(define-fun in" << elementTypeAsString << "          "
+        sout << "(define-fun member" << elementTypeAsString << "          "
              << " ( (x " << elementType << ")" << " (s " << name << "))"
              << " Bool"
              << " (select s x) )" << endl;
index 13bdad78e757b8ecfd11aada47eaa0e9dc9bc702..a487695d7e78f146f8e349be66d8aec358c90dde 100644 (file)
@@ -58,3 +58,4 @@
 1\.4-prerelease libcvc4:2:0:0 libcvc4parser:2:0:0 libcvc4compat:2:0:0 libcvc4bindings:2:0:0
 1\.4 libcvc4:3:0:0 libcvc4parser:3:0:0 libcvc4compat:3:0:0 libcvc4bindings:3:0:0
 1\.4\.1-prerelease libcvc4:3:0:0 libcvc4parser:3:0:0 libcvc4compat:3:0:0 libcvc4bindings:3:0:0
+1\.5-prerelease libcvc4:3:0:0 libcvc4parser:3:0:0 libcvc4compat:3:0:0 libcvc4bindings:3:0:0
diff --git a/proofs/signatures/ex_bv.plf b/proofs/signatures/ex_bv.plf
new file mode 100755 (executable)
index 0000000..02cadae
--- /dev/null
@@ -0,0 +1,57 @@
+; a = b ^ a = 00000 ^ b = 11111 is UNSAT\r
+\r
+(check\r
+(% a var_bv\r
+(% b var_bv\r
+(% f1 (th_holds (= BitVec (a_var_bv a) (a_var_bv b)))\r
+(% f2 (th_holds (= BitVec (a_var_bv a) (a_bv (bvc b0 (bvc b0 (bvc b0 (bvc b0 (bvc b0 bvn))))))))\r
+(% f3 (th_holds (= BitVec (a_var_bv b) (a_bv (bvc b1 (bvc b1 (bvc b1 (bvc b1 (bvc b1 bvn))))))))\r
+(: (holds cln)\r
+\r
+(decl_bv_atom_var 5 a (\ ba1\r
+(decl_bv_atom_var 5 b (\ ba2\r
+(decl_bv_atom_const _ (bvc b0 (bvc b0 (bvc b0 (bvc b0 (bvc b0 bvn))))) (\ c (\ ba3\r
+(decl_bv_atom_const _ (bvc b1 (bvc b1 (bvc b1 (bvc b1 (bvc b1 bvn))))) (\ d (\ ba4\r
+\r
+(decl_atom (bblast a 4) (\ v1 (\ a1\r
+(decl_atom (bblast b 4) (\ v2 (\ a2\r
+\r
+; bitblasting terms\r
+(th_let_pf _ (bv_bbl_var _ _ _ ba1) (\ bt1\r
+(th_let_pf _ (bv_bbl_var _ _ _ ba2) (\ bt2\r
+(th_let_pf _ (bv_bbl_const _ _ _ _ ba3) (\ bt3\r
+(th_let_pf _ (bv_bbl_const _ _ _ _ ba4) (\ bt4\r
+\r
+; bitblasting formulas\r
+(th_let_pf _ (bv_bbl_eq _ _ _ _ _ bt1 bt2) (\ bf1\r
+(th_let_pf _ (bv_bbl_eq _ _ _ _ _ bt1 bt3) (\ bf2\r
+(th_let_pf _ (bv_bbl_eq _ _ _ _ _ bt2 bt4) (\ bf3\r
+\r
+; CNFication\r
+; a.4 V ~b.4\r
+(satlem _ _\r
+(asf _ _ _ a1 (\ l1\r
+(ast _ _ _ a2 (\ l2\r
+(clausify_false\r
+  (contra _ (impl_elim _ _ l2 (iff_elim_2 _ _ (and_elim_1 _ _ (impl_elim _ _ f1 bf1)))) l1)   ; notice at the intermost we impl_elim, which converts from atom to bit-blasting representation\r
+))))) (\ C2\r
+\r
+; ~a.4\r
+(satlem _ _\r
+(ast _ _ _ a1 (\ l1\r
+(clausify_false\r
+  (impl_elim _ _ l1 (iff_elim_1 _ _ (and_elim_1 _ _ (impl_elim _ _ f2 bf2))))\r
+))) (\ C3\r
+\r
+; b.4 \r
+(satlem _ _\r
+(asf _ _ _ a2 (\ l2\r
+(clausify_false\r
+  (contra _ (impl_elim _ _ truth (iff_elim_2 _ _ (and_elim_1 _ _ (impl_elim _ _ f3 bf3)))) l2)\r
+))) (\ C6\r
+\r
+\r
+(satlem_simplify _ _ _ \r
+(R _ _ (R _ _ C6 C2 v2) C3 v1) (\ x x))\r
+\r
+)))))))))))))))))))))))))))))))))))))))))))
\ No newline at end of file
index bbee2d49bca2685102b077fe270b9053aa4cc5a1..942e17df0d8447b935babf44e1033329797d487e 100755 (executable)
   (! r2 (th_holds (not f))
     (th_holds false)))))
 
+; truth
+(declare truth (th_holds true))
+
 ;; not not
 
 (declare not_not_intro
diff --git a/proofs/signatures/th_bv.plf b/proofs/signatures/th_bv.plf
new file mode 100755 (executable)
index 0000000..3fb9d13
--- /dev/null
@@ -0,0 +1,145 @@
+; "bitvec" is a term of type "sort"\r
+(declare BitVec sort)\r
+\r
+; bit type\r
+(declare bit type)\r
+(declare b0 bit)\r
+(declare b1 bit)\r
+\r
+; bit vector type\r
+(declare bv type)\r
+(declare bvn bv)\r
+(declare bvc (! b bit (! v bv bv)))\r
+; a bv constant term\r
+(declare a_bv (! v bv (term BitVec)))\r
+\r
+; calculate the length of a bitvector\r
+(program bv_len ((v bv)) mpz \r
+  (match v\r
+    (bvn 0)\r
+    ((bvc b v') (mp_add (bv_len v') 1))))\r
+\r
+; a bv variable\r
+(declare var_bv type)\r
+; a bv variable term\r
+(declare a_var_bv (! v var_bv (term BitVec)))\r
+\r
+\r
+; bit vector operators\r
+(define bvoper (! x (term BitVec) \r
+               (! y (term BitVec) \r
+                    (term BitVec))))\r
+(declare bvand bvoper)\r
+(declare bvadd bvoper)\r
+;....\r
+\r
+; all bit-vector terms are mapped with "bv_atom" to:\r
+;  - a simply-typed term of type "var_bv", which is necessary for bit-blasting\r
+;  - a integer size\r
+(declare bv_atom (! x (term BitVec) (! y var_bv (! n mpz type))))\r
+\r
+(declare decl_bv_atom_var (! n mpz    ; must be specified\r
+                          (! x var_bv\r
+                          (! p (! u (bv_atom (a_var_bv x) x n)\r
+                                 (holds cln))\r
+                             (holds cln)))))\r
+\r
+(declare decl_bv_atom_const (! n mpz\r
+                            (! v bv\r
+                            (! s (^ (bv_len v) n)\r
+                            (! p (! w var_bv\r
+                                 (! u (bv_atom (a_bv v) w n)\r
+                                   (holds cln)))\r
+                             (holds cln))))))\r
+\r
+\r
+; other terms here?\r
+\r
+\r
+; bit blasted terms\r
+(declare bblt type)\r
+(declare bbltn bblt)\r
+(declare bbltc (! f formula (! v bblt bblt)))\r
+\r
+; (bblast_term x y) means term x corresponds to bit level interpretation y\r
+(declare bblast_term (! x (term BitVec) (! y bblt formula)))\r
+\r
+; a predicate to represent the n^th bit of a bitvector term\r
+(declare bblast (! x var_bv (! n mpz formula)))\r
+\r
+\r
+; bit blast  constant\r
+(program bblast_const ((v bv) (n mpz)) bblt\r
+  (mp_ifneg n (match v (bvn bbltn) \r
+                       (default (fail bblt)))\r
+              (match v ((bvc b v') (bbltc (match b (b0 false) (b1 true)) (bblast_const v' (mp_add n (~ 1)))))\r
+                       (default (fail bblt)))))\r
+              \r
+(declare bv_bbl_const (! n mpz\r
+                      (! v bv\r
+                      (! x var_bv\r
+                      (! f bblt\r
+                      (! u (bv_atom (a_bv v) x n)\r
+                      (! c (^ (bblast_const v (mp_add n (~ 1))) f)\r
+                         (th_holds (bblast_term (a_bv v) f)))))))))\r
+\r
+; bit blast  variable\r
+(program bblast_var ((x var_bv) (n mpz)) bblt\r
+  (mp_ifneg n bbltn \r
+              (bbltc (bblast x n) (bblast_var x (mp_add n (~ 1))))))\r
+\r
+(declare bv_bbl_var (! n mpz\r
+                    (! x var_bv\r
+                    (! f bblt                    \r
+                    (! u (bv_atom (a_var_bv x) x n)\r
+                    (! c (^ (bblast_var x (mp_add n (~ 1))) f)\r
+                       (th_holds (bblast_term (a_var_bv x) f))))))))\r
+\r
+; bit blast  x = y\r
+;  for x,y of size n, it will return a conjuction (x.{n-1} = y.{n-1} ^ ( ... ^ (x.0 = y.0 ^ true)))\r
+(program bblast_eq ((x bblt) (y bblt)) formula\r
+  (match x \r
+    (bbltn (match y (bbltn true) (default (fail formula))))\r
+    ((bbltc fx x') (match y \r
+                      (bbltn (fail formula))\r
+                      ((bbltc fy y') (and (iff fx fy) (bblast_eq x' y')))))))\r
+\r
+(declare bv_bbl_eq (! x (term BitVec)\r
+                   (! y (term BitVec)\r
+                   (! fx bblt\r
+                   (! fy bblt\r
+                   (! f formula\r
+                   (! ux (th_holds (bblast_term x fx))\r
+                   (! uy (th_holds (bblast_term y fy))\r
+                   (! c (^ (bblast_eq fx fy) f)\r
+                      (th_holds (impl (= BitVec x y) f)))))))))))\r
+\r
+\r
+; rewrite rule :\r
+; x + y = y + x\r
+(declare bvadd_symm (! x (term BitVec)\r
+                    (! y (term BitVec)\r
+                    (! x' var_bv\r
+                    (! y' var_bv\r
+                    (! n mpz\r
+                    (! ux (bv_atom x x' n)\r
+                    (! uy (bv_atom y y' n)\r
+                       (th_holds (= BitVec (bvadd x y) (bvadd y x)))))))))))\r
+\r
+\r
+\r
+; necessary? \r
+(program calc_bvand ((a bv) (b bv)) bv\r
+  (match a\r
+    (bvn (match b (bvn bvn) (default (fail bv))))\r
+    ((bvc ba a') (match b\r
+                      ((bvc bb b') (bvc (match ba (b0 b0) (b1 bb)) (calc_bvand a' b')))\r
+                      (default (fail bv))))))\r
+\r
+; rewrite rule (w constants) :\r
+; a & b = c    \r
+(declare bvand_const (! c bv\r
+                    (! a bv\r
+                     (! b bv\r
+                     (! u (^ (calc_bvand a b) c)\r
+                        (th_holds (= BitVec (bvand (a_bv a) (a_bv b)) (a_bv c))))))))                        
\ No newline at end of file
index 805ed6cb7f404c586cbe6bbb7883e4e5ea198736..3e083146734e196248edc99a422c324303106bcd 100644 (file)
@@ -327,6 +327,10 @@ libcvc4_la_SOURCES = \
        theory/quantifiers/ambqi_builder.cpp \
        theory/quantifiers/quant_conflict_find.h \
        theory/quantifiers/quant_conflict_find.cpp \
+       theory/quantifiers/conjecture_generator.h \
+       theory/quantifiers/conjecture_generator.cpp \
+       theory/quantifiers/ce_guided_instantiation.h \
+       theory/quantifiers/ce_guided_instantiation.cpp \
        theory/quantifiers/options_handlers.h \
        theory/arith/theory_arith_type_rules.h \
        theory/arith/type_enumerator.h \
index 2214d9b88e93c30ceb34e008215b6a2945126bb6..e7548bbe143a835f1dc42c41e73f6c4ef6ccf62a 100644 (file)
@@ -63,8 +63,8 @@ java_libcvc4jni_la_LDFLAGS = \
        -shrext $(CVC4_JAVA_MODULE_EXT) \
        -version-info $(LIBCVC4BINDINGS_VERSION)
 java_libcvc4jni_la_LIBADD = \
-       -L@builddir@/.. -lcvc4 \
-       -L@builddir@/../parser -lcvc4parser
+       @builddir@/../libcvc4.la \
+       @builddir@/../parser/libcvc4parser.la
 endif
 if CVC4_LANGUAGE_BINDING_CSHARP
 csharplib_LTLIBRARIES += csharp/CVC4.la
@@ -72,8 +72,8 @@ csharp_CVC4_la_LDFLAGS = \
        -module \
        -version-info $(LIBCVC4BINDINGS_VERSION)
 csharp_CVC4_la_LIBADD = \
-       -L@builddir@/.. -lcvc4 \
-       -L@builddir@/../parser -lcvc4parser
+       @builddir@/../libcvc4.la \
+       @builddir@/../parser/libcvc4parser.la
 endif
 if CVC4_LANGUAGE_BINDING_PERL
 perllib_LTLIBRARIES += perl/CVC4.la
@@ -81,8 +81,8 @@ perl_CVC4_la_LDFLAGS = \
        -module \
        -version-info $(LIBCVC4BINDINGS_VERSION)
 perl_CVC4_la_LIBADD = \
-       -L@builddir@/.. -lcvc4 \
-       -L@builddir@/../parser -lcvc4parser
+       @builddir@/../libcvc4.la \
+       @builddir@/../parser/libcvc4parser.la
 perldata_DATA += perl/CVC4.pm
 endif
 if CVC4_LANGUAGE_BINDING_PHP
@@ -91,8 +91,8 @@ php_CVC4_la_LDFLAGS = \
        -module \
        -version-info $(LIBCVC4BINDINGS_VERSION)
 php_CVC4_la_LIBADD = \
-       -L@builddir@/.. -lcvc4 \
-       -L@builddir@/../parser -lcvc4parser
+       @builddir@/../libcvc4.la \
+       @builddir@/../parser/libcvc4parser.la
 phpdata_DATA += php/CVC4.php
 endif
 if CVC4_LANGUAGE_BINDING_PYTHON
@@ -102,8 +102,8 @@ python_CVC4_la_LDFLAGS = \
        -module \
        -version-info $(LIBCVC4BINDINGS_VERSION)
 python_CVC4_la_LIBADD = \
-       -L@builddir@/.. -lcvc4 \
-       -L@builddir@/../parser -lcvc4parser
+       @builddir@/../libcvc4.la \
+       @builddir@/../parser/libcvc4parser.la
 pythondata_DATA += python/CVC4.py
 endif
 if CVC4_LANGUAGE_BINDING_OCAML
@@ -117,8 +117,8 @@ ocaml_CVC4_la_LDFLAGS = \
        -module \
        -version-info $(LIBCVC4BINDINGS_VERSION)
 ocaml_CVC4_la_LIBADD = \
-       -L@builddir@/.. -lcvc4 \
-       -L@builddir@/../parser -lcvc4parser
+       @builddir@/../libcvc4.la \
+       @builddir@/../parser/libcvc4parser.la
 endif
 if CVC4_LANGUAGE_BINDING_RUBY
 rubylib_LTLIBRARIES += ruby/CVC4.la
@@ -126,8 +126,8 @@ ruby_CVC4_la_LDFLAGS = \
        -module \
        -version-info $(LIBCVC4BINDINGS_VERSION)
 ruby_CVC4_la_LIBADD = \
-       -L@builddir@/.. -lcvc4 \
-       -L@builddir@/../parser -lcvc4parser
+       @builddir@/../libcvc4.la \
+       @builddir@/../parser/libcvc4parser.la
 endif
 if CVC4_LANGUAGE_BINDING_TCL
 tcllib_LTLIBRARIES += tcl/CVC4.la
@@ -135,8 +135,8 @@ tcl_CVC4_la_LDFLAGS = \
        -module \
        -version-info $(LIBCVC4BINDINGS_VERSION)
 tcl_CVC4_la_LIBADD = \
-       -L@builddir@/.. -lcvc4 \
-       -L@builddir@/../parser -lcvc4parser
+       @builddir@/../libcvc4.la \
+       @builddir@/../parser/libcvc4parser.la
 endif
 # this endif matches the "if CVC4_HAS_SWIG" above
 endif
index 5a788f2bfa6a73183cebb5203c55b8e792202dc7..4ec4626c6bc4f5fa04e4b739c58abafefdcef32d 100644 (file)
@@ -25,8 +25,8 @@ lib_LTLIBRARIES += libcvc4bindings_c_compat.la
 libcvc4bindings_c_compat_la_LDFLAGS = \
        -version-info $(LIBCVC4BINDINGS_VERSION)
 libcvc4bindings_c_compat_la_LIBADD = \
-       -L@builddir@/../../../compat -lcvc4compat \
-       -L@builddir@/../../.. -lcvc4
+       @builddir@/../../../compat/libcvc4compat.la \
+       @builddir@/../../../libcvc4.la
 
 endif
 
index 9eb985822b701f49430e2c611270a60de16cacef..5b052568d266e40d9e064081cc479d06d3f0fd09 100644 (file)
@@ -33,8 +33,8 @@ libcvc4compatjni_la_LDFLAGS = \
        -shrext $(CVC4_JAVA_MODULE_EXT) \
        -version-info $(LIBCVC4BINDINGS_VERSION)
 libcvc4compatjni_la_LIBADD = \
-       -L@builddir@/../../../compat -lcvc4compat \
-       -L@builddir@/../../.. -lcvc4
+       @builddir@/../../../compat/libcvc4compat.la \
+       @builddir@/../../../libcvc4.la
 BUILT_SOURCES += $(JNI_CPP_FILES)
 
 endif
index 5a8bd454ebe0eba4926a4805ed24bfd0370b8ec1..ebb13426da21bfda5857944a673070dd1c7157c4 100644 (file)
@@ -25,8 +25,8 @@ libcvc4compat_la_LDFLAGS = \
        -version-info $(LIBCVC4COMPAT_VERSION)
 
 libcvc4compat_la_LIBADD = \
-       -L@builddir@/.. -lcvc4 \
-       -L@builddir@/../parser -lcvc4parser
+       @builddir@/../libcvc4.la \
+       @builddir@/../parser/libcvc4parser.la
 
 if CVC4_NEEDS_REPLACEMENT_FUNCTIONS
 libcvc4compat_la_LIBADD += \
index 51b0c6083bf812da71da5baacdeb08ab76324fa7..08146760ff04bbd64a052360c77f4b8fe7a3611c 100644 (file)
@@ -2468,7 +2468,12 @@ Context* ValidityChecker::getCurrentContext() {
 }
 
 void ValidityChecker::reset() {
-  Unimplemented("This CVC3 compatibility function not yet implemented (sorry!)");
+  // reset everything, forget everything
+  d_smt->reset();
+  delete d_parserContext;
+  d_parserContext = CVC4::parser::ParserBuilder(d_em, "<internal>").withInputLanguage(CVC4::language::input::LANG_CVC4).withStringInput("").build();
+  s_typeToExpr.clear();
+  s_exprToType.clear();
 }
 
 void ValidityChecker::logAnnotation(const Expr& annot) {
index c3b2f28acf91c87b2d4bfc1a3082b113a45ea614..d7d463d79e7f1344e00e02b68ccfc9843540ae7e 100644 (file)
@@ -49,14 +49,14 @@ void DecisionEngine::init()
   d_engineState = 1;
 
   Trace("decision-init") << "DecisionEngine::init()" << std::endl;
-  Trace("decision-init") << " * options->decisionMode: " 
+  Trace("decision-init") << " * options->decisionMode: "
                          << options::decisionMode() << std:: endl;
   Trace("decision-init") << " * options->decisionStopOnly: "
                          << options::decisionStopOnly() << std::endl;
 
   if(options::decisionMode() == decision::DECISION_STRATEGY_INTERNAL) { }
   if(options::decisionMode() == decision::DECISION_STRATEGY_JUSTIFICATION) {
-    ITEDecisionStrategy* ds = 
+    ITEDecisionStrategy* ds =
       new decision::JustificationHeuristic(this, d_userContext, d_satContext);
     enableStrategy(ds);
     d_needIteSkolemMap.push_back(ds);
@@ -107,7 +107,7 @@ void DecisionEngine::addAssertions(const vector<Node> &assertions)
   // d_result = SAT_VALUE_UNKNOWN;
   // d_assertions.reserve(assertions.size());
   // for(unsigned i = 0; i < assertions.size(); ++i)
-  //   d_assertions.push_back(assertions[i]); 
+  //   d_assertions.push_back(assertions[i]);
 }
 
 void DecisionEngine::addAssertions(const vector<Node> &assertions,
@@ -116,11 +116,11 @@ void DecisionEngine::addAssertions(const vector<Node> &assertions,
 {
   // new assertions, reset whatever result we knew
   d_result = SAT_VALUE_UNKNOWN;
-  
+
   // d_assertions.reserve(assertions.size());
   for(unsigned i = 0; i < assertions.size(); ++i)
     d_assertions.push_back(assertions[i]);
-  
+
   for(unsigned i = 0; i < d_needIteSkolemMap.size(); ++i)
     d_needIteSkolemMap[i]->
       addAssertions(assertions, assertionsEnd, iteSkolemMap);
index bfd28e1131735f40e475c9e441f2aed0fc4ecd87..39ed89a684aed395c9f24b8eaf50bd97970a5cf3 100644 (file)
@@ -71,7 +71,7 @@ public:
   ~DecisionEngine() {
     Trace("decision") << "Destroying decision engine" << std::endl;
   }
-  
+
   // void setPropEngine(PropEngine* pe) {
   //   // setPropEngine should not be called more than once
   //   Assert(d_propEngine == NULL);
@@ -123,8 +123,8 @@ public:
            "Forgot to set satSolver for decision engine?");
 
     SatLiteral ret = undefSatLiteral;
-    for(unsigned i = 0; 
-        i < d_enabledStrategies.size() 
+    for(unsigned i = 0;
+        i < d_enabledStrategies.size()
           and ret == undefSatLiteral
           and stopSearch == false; ++i) {
       ret = d_enabledStrategies[i]->getNext(stopSearch);
@@ -137,7 +137,7 @@ public:
 
   /**
    * Try to get tell SAT solver what polarity to try for a
-   * decision. Return SAT_VALUE_UNKNOWN if it can't help 
+   * decision. Return SAT_VALUE_UNKNOWN if it can't help
    */
   SatValue getPolarity(SatVariable var);
 
@@ -193,7 +193,7 @@ public:
   // (which was possibly requested by them on initialization)
 
   /**
-   * Get the assertions. Strategies are notified when these are available. 
+   * Get the assertions. Strategies are notified when these are available.
    */
   AssertionsList& getAssertions() {
     return d_assertions;
index e4df8d4af04a1c00af42be6f425e84dfecd07453..94db110c2a3e896e2ece34e8734df92775d5e968 100644 (file)
@@ -43,9 +43,9 @@ public:
   virtual ~DecisionStrategy() { }
 
   virtual prop::SatLiteral getNext(bool&) = 0;
-  
+
   virtual bool needIteSkolemMap() { return false; }
-  
+
   virtual void notifyAssertionsAvailable() { return; }
 };/* class DecisionStrategy */
 
index ffff6952ff80e02b84540d30588915925b254b9a..84f4d507460c9d4febb540ea206f370e5dcd6c28 100644 (file)
@@ -124,7 +124,7 @@ CVC4::prop::SatLiteral JustificationHeuristic::getNextThresh(bool &stopSearch, D
 
     if(Debug.isOn("decision")) {
       if(!checkJustified(curass))
-        Debug("decision") << "****** Not justified [i="<<i<<"]: " 
+        Debug("decision") << "****** Not justified [i="<<i<<"]: "
                           << d_assertions[i] << std::endl;
     }
   }
@@ -169,7 +169,7 @@ void JustificationHeuristic::addAssertions
  IteSkolemMap iteSkolemMap) {
 
   Trace("decision")
-    << "JustificationHeuristic::addAssertions()" 
+    << "JustificationHeuristic::addAssertions()"
     << " size = " << assertions.size()
     << " assertionsEnd = " << assertionsEnd
     << std::endl;
@@ -182,7 +182,7 @@ void JustificationHeuristic::addAssertions
   for(IteSkolemMap::iterator i = iteSkolemMap.begin();
       i != iteSkolemMap.end(); ++i) {
 
-    Trace("decision::jh::ite") 
+    Trace("decision::jh::ite")
       << " jh-ite: " << (i->first) << " maps to "
       << assertions[(i->second)] << std::endl;
     Assert(i->second >= assertionsEnd && i->second < assertions.size());
@@ -199,7 +199,7 @@ SatLiteral JustificationHeuristic::findSplitter(TNode node,
   d_curDecision = undefSatLiteral;
   if(findSplitterRec(node, desiredVal)) {
     ++d_helfulness;
-  } 
+  }
   return d_curDecision;
 }
 
@@ -405,9 +405,9 @@ JustificationHeuristic::findSplitterRec(TNode node, SatValue desiredVal)
    * children to be true. this is done recursively.
    */
 
-  Trace("decision::jh") 
-    << "findSplitterRec(" << node << ", " 
-    << desiredVal << ", .. )" << std::endl; 
+  Trace("decision::jh")
+    << "findSplitterRec(" << node << ", "
+    << desiredVal << ", .. )" << std::endl;
 
   /* Handle NOT as a special case */
   while (node.getKind() == kind::NOT) {
@@ -417,7 +417,7 @@ JustificationHeuristic::findSplitterRec(TNode node, SatValue desiredVal)
 
   /* Base case */
   if (checkJustified(node)) {
-    Debug("decision::jh") << "  justified, returning" << std::endl; 
+    Debug("decision::jh") << "  justified, returning" << std::endl;
     return NO_SPLITTER;
   }
   if (getExploredThreshold(node) < d_curThreshold) {
@@ -449,7 +449,7 @@ JustificationHeuristic::findSplitterRec(TNode node, SatValue desiredVal)
   //       "invariant violated");
 
   /* What type of node is this */
-  Kind k = node.getKind();     
+  Kind k = node.getKind();
   theory::TheoryId tId = theory::kindToTheoryId(k);
 
   /* Some debugging stuff */
@@ -470,7 +470,7 @@ JustificationHeuristic::findSplitterRec(TNode node, SatValue desiredVal)
       Assert(litVal == desiredVal);
       setJustified(node);
       return NO_SPLITTER;
-    } 
+    }
     else {
       Assert(d_decisionEngine->hasSatLiteral(node));
       if(d_curThreshold != 0 && getWeightPolarized(node, desiredVal) >= d_curThreshold)
@@ -548,7 +548,7 @@ JustificationHeuristic::findSplitterRec(TNode node, SatValue desiredVal)
 JustificationHeuristic::SearchResult
 JustificationHeuristic::handleAndOrEasy(TNode node, SatValue desiredVal)
 {
-  Assert( (node.getKind() == kind::AND and desiredVal == SAT_VALUE_FALSE) or 
+  Assert( (node.getKind() == kind::AND and desiredVal == SAT_VALUE_FALSE) or
           (node.getKind() == kind::OR  and desiredVal == SAT_VALUE_TRUE) );
 
   int numChildren = node.getNumChildren();
@@ -575,7 +575,7 @@ void JustificationHeuristic::saveStartIndex(TNode node, int val) {
 
 JustificationHeuristic::SearchResult JustificationHeuristic::handleAndOrHard(TNode node,
                                              SatValue desiredVal) {
-  Assert( (node.getKind() == kind::AND and desiredVal == SAT_VALUE_TRUE) or 
+  Assert( (node.getKind() == kind::AND and desiredVal == SAT_VALUE_TRUE) or
           (node.getKind() == kind::OR  and desiredVal == SAT_VALUE_FALSE) );
 
   int numChildren = node.getNumChildren();
@@ -671,7 +671,7 @@ JustificationHeuristic::SearchResult JustificationHeuristic::handleITE(TNode nod
 
     if(findSplitterRec(node[0], ifDesiredVal) == FOUND_SPLITTER)
       return FOUND_SPLITTER;
-    
+
     Assert(d_curThreshold != 0, "No controlling input found (6)");
     return DONT_KNOW;
   } else {
index a6bc68ce560fdcbd9e365c2b6b0aa397dfb59205..9177ba44d64c533fab5592b6ccf3f124791d4ab2 100644 (file)
@@ -127,10 +127,10 @@ private:
   prop::SatLiteral getNextThresh(bool &stopSearch, DecisionWeight threshold);
 
   SatLiteral findSplitter(TNode node, SatValue desiredVal);
-  
-  /** 
-   * Do all the hard work. 
-   */ 
+
+  /**
+   * Do all the hard work.
+   */
   SearchResult findSplitterRec(TNode node, SatValue value);
 
   /* Helper functions */
index 69bdd704b7544ad47a72e63d50131328f9fef850..c976588d488a65bfe249b9f851318ceedc83696b 100644 (file)
@@ -189,8 +189,8 @@ std::string EchoCommand::getCommandName() const throw() {
 
 /* class AssertCommand */
 
-AssertCommand::AssertCommand(const Expr& e) throw() :
-  d_expr(e) {
+AssertCommand::AssertCommand(const Expr& e, bool inUnsatCore) throw() :
+  d_expr(e), d_inUnsatCore(inUnsatCore) {
 }
 
 Expr AssertCommand::getExpr() const throw() {
@@ -199,7 +199,7 @@ Expr AssertCommand::getExpr() const throw() {
 
 void AssertCommand::invoke(SmtEngine* smtEngine) throw() {
   try {
-    smtEngine->assertFormula(d_expr);
+    smtEngine->assertFormula(d_expr, d_inUnsatCore);
     d_commandStatus = CommandSuccess::instance();
   } catch(exception& e) {
     d_commandStatus = new CommandFailure(e.what());
@@ -207,18 +207,17 @@ void AssertCommand::invoke(SmtEngine* smtEngine) throw() {
 }
 
 Command* AssertCommand::exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap) {
-  return new AssertCommand(d_expr.exportTo(exprManager, variableMap));
+  return new AssertCommand(d_expr.exportTo(exprManager, variableMap), d_inUnsatCore);
 }
 
 Command* AssertCommand::clone() const {
-  return new AssertCommand(d_expr);
+  return new AssertCommand(d_expr, d_inUnsatCore);
 }
 
 std::string AssertCommand::getCommandName() const throw() {
   return "assert";
 }
 
-
 /* class PushCommand */
 
 void PushCommand::invoke(SmtEngine* smtEngine) throw() {
@@ -271,8 +270,8 @@ CheckSatCommand::CheckSatCommand() throw() :
   d_expr() {
 }
 
-CheckSatCommand::CheckSatCommand(const Expr& expr) throw() :
-  d_expr(expr) {
+CheckSatCommand::CheckSatCommand(const Expr& expr, bool inUnsatCore) throw() :
+  d_expr(expr), d_inUnsatCore(inUnsatCore) {
 }
 
 Expr CheckSatCommand::getExpr() const throw() {
@@ -301,13 +300,13 @@ void CheckSatCommand::printResult(std::ostream& out, uint32_t verbosity) const t
 }
 
 Command* CheckSatCommand::exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap) {
-  CheckSatCommand* c = new CheckSatCommand(d_expr.exportTo(exprManager, variableMap));
+  CheckSatCommand* c = new CheckSatCommand(d_expr.exportTo(exprManager, variableMap), d_inUnsatCore);
   c->d_result = d_result;
   return c;
 }
 
 Command* CheckSatCommand::clone() const {
-  CheckSatCommand* c = new CheckSatCommand(d_expr);
+  CheckSatCommand* c = new CheckSatCommand(d_expr, d_inUnsatCore);
   c->d_result = d_result;
   return c;
 }
@@ -318,8 +317,8 @@ std::string CheckSatCommand::getCommandName() const throw() {
 
 /* class QueryCommand */
 
-QueryCommand::QueryCommand(const Expr& e) throw() :
-  d_expr(e) {
+QueryCommand::QueryCommand(const Expr& e, bool inUnsatCore) throw() :
+  d_expr(e), d_inUnsatCore(inUnsatCore) {
 }
 
 Expr QueryCommand::getExpr() const throw() {
@@ -348,13 +347,13 @@ void QueryCommand::printResult(std::ostream& out, uint32_t verbosity) const thro
 }
 
 Command* QueryCommand::exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap) {
-  QueryCommand* c = new QueryCommand(d_expr.exportTo(exprManager, variableMap));
+  QueryCommand* c = new QueryCommand(d_expr.exportTo(exprManager, variableMap), d_inUnsatCore);
   c->d_result = d_result;
   return c;
 }
 
 Command* QueryCommand::clone() const {
-  QueryCommand* c = new QueryCommand(d_expr);
+  QueryCommand* c = new QueryCommand(d_expr, d_inUnsatCore);
   c->d_result = d_result;
   return c;
 }
@@ -363,11 +362,31 @@ std::string QueryCommand::getCommandName() const throw() {
   return "query";
 }
 
-/* class QuitCommand */
+/* class ResetCommand */
 
-QuitCommand::QuitCommand() throw() {
+void ResetCommand::invoke(SmtEngine* smtEngine) throw() {
+  try {
+    smtEngine->reset();
+    d_commandStatus = CommandSuccess::instance();
+  } catch(exception& e) {
+    d_commandStatus = new CommandFailure(e.what());
+  }
 }
 
+Command* ResetCommand::exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap) {
+  return new ResetCommand();
+}
+
+Command* ResetCommand::clone() const {
+  return new ResetCommand();
+}
+
+std::string ResetCommand::getCommandName() const throw() {
+  return "reset";
+}
+
+/* class QuitCommand */
+
 void QuitCommand::invoke(SmtEngine* smtEngine) throw() {
   Dump("benchmark") << *this;
   d_commandStatus = CommandSuccess::instance();
@@ -744,22 +763,22 @@ Command* DefineNamedFunctionCommand::clone() const {
 SetUserAttributeCommand::SetUserAttributeCommand( const std::string& attr, Expr expr ) throw() :
   d_attr( attr ), d_expr( expr ){
 }
-/*
-SetUserAttributeCommand::SetUserAttributeCommand( const std::string& id, Expr expr,
+
+SetUserAttributeCommand::SetUserAttributeCommand( const std::string& attr, Expr expr,
                                                   std::vector<Expr>& values ) throw() :
-  d_id( id ), d_expr( expr ){
+  d_attr( attr ), d_expr( expr ){
   d_expr_values.insert( d_expr_values.begin(), values.begin(), values.end() );
 }
 
-SetUserAttributeCommand::SetUserAttributeCommand( const std::string& id, Expr expr,
-                                                  std::string& value ) throw() :
-  d_id( id ), d_expr( expr ), d_str_value( value ){
+SetUserAttributeCommand::SetUserAttributeCommand( const std::string& attr, Expr expr,
+                                                  const std::string& value ) throw() :
+  d_attr( attr ), d_expr( expr ), d_str_value( value ){
 }
-*/
+
 void SetUserAttributeCommand::invoke(SmtEngine* smtEngine) throw(){
   try {
     if(!d_expr.isNull()) {
-      smtEngine->setUserAttribute( d_attr, d_expr );
+      smtEngine->setUserAttribute( d_attr, d_expr, d_expr_values, d_str_value );
     }
     d_commandStatus = CommandSuccess::instance();
   } catch(exception& e) {
@@ -769,11 +788,15 @@ void SetUserAttributeCommand::invoke(SmtEngine* smtEngine) throw(){
 
 Command* SetUserAttributeCommand::exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap){
   Expr expr = d_expr.exportTo(exprManager, variableMap);
-  return new SetUserAttributeCommand( d_attr, expr );
+  SetUserAttributeCommand * c = new SetUserAttributeCommand( d_attr, expr, d_str_value );
+  c->d_expr_values.insert( c->d_expr_values.end(), d_expr_values.begin(), d_expr_values.end() );
+  return c;
 }
 
 Command* SetUserAttributeCommand::clone() const{
-  return new SetUserAttributeCommand( d_attr, d_expr );
+  SetUserAttributeCommand * c = new SetUserAttributeCommand( d_attr, d_expr, d_str_value );
+  c->d_expr_values.insert( c->d_expr_values.end(), d_expr_values.begin(), d_expr_values.end() );
+  return c;
 }
 
 std::string SetUserAttributeCommand::getCommandName() const throw() {
@@ -1125,36 +1148,40 @@ std::string GetInstantiationsCommand::getCommandName() const throw() {
 GetUnsatCoreCommand::GetUnsatCoreCommand() throw() {
 }
 
+GetUnsatCoreCommand::GetUnsatCoreCommand(const std::map<Expr, std::string>& names) throw() : d_names(names) {
+}
+
 void GetUnsatCoreCommand::invoke(SmtEngine* smtEngine) throw() {
-  /*
   try {
     d_result = smtEngine->getUnsatCore();
     d_commandStatus = CommandSuccess::instance();
   } catch(exception& e) {
     d_commandStatus = new CommandFailure(e.what());
   }
-  */
-  d_commandStatus = new CommandUnsupported();
 }
 
 void GetUnsatCoreCommand::printResult(std::ostream& out, uint32_t verbosity) const throw() {
   if(! ok()) {
     this->Command::printResult(out, verbosity);
   } else {
-    //do nothing -- unsat cores not yet supported
-    // d_result->toStream(out);
+    d_result.toStream(out, d_names);
   }
 }
 
+const UnsatCore& GetUnsatCoreCommand::getUnsatCore() const throw() {
+  // of course, this will be empty if the command hasn't been invoked yet
+  return d_result;
+}
+
 Command* GetUnsatCoreCommand::exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap) {
-  GetUnsatCoreCommand* c = new GetUnsatCoreCommand();
-  //c->d_result = d_result;
+  GetUnsatCoreCommand* c = new GetUnsatCoreCommand(d_names);
+  c->d_result = d_result;
   return c;
 }
 
 Command* GetUnsatCoreCommand::clone() const {
-  GetUnsatCoreCommand* c = new GetUnsatCoreCommand();
-  //c->d_result = d_result;
+  GetUnsatCoreCommand* c = new GetUnsatCoreCommand(d_names);
+  c->d_result = d_result;
   return c;
 }
 
index 606618d21798692e9a6443bd9e30a2596129dca0..75cf80aae647efdb1b0f8aef26284a15a1cd722e 100644 (file)
@@ -35,6 +35,7 @@
 #include "util/sexpr.h"
 #include "util/datatype.h"
 #include "util/proof.h"
+#include "util/unsat_core.h"
 
 namespace CVC4 {
 
@@ -309,8 +310,9 @@ public:
 class CVC4_PUBLIC AssertCommand : public Command {
 protected:
   Expr d_expr;
+  bool d_inUnsatCore;
 public:
-  AssertCommand(const Expr& e) throw();
+  AssertCommand(const Expr& e, bool inUnsatCore = true) throw();
   ~AssertCommand() throw() {}
   Expr getExpr() const throw();
   void invoke(SmtEngine* smtEngine) throw();
@@ -439,12 +441,12 @@ class CVC4_PUBLIC SetUserAttributeCommand : public Command {
 protected:
   std::string d_attr;
   Expr d_expr;
-  //std::vector<Expr> d_expr_values;
-  //std::string d_str_value;
+  std::vector<Expr> d_expr_values;
+  std::string d_str_value;
 public:
   SetUserAttributeCommand( const std::string& attr, Expr expr ) throw();
-  //SetUserAttributeCommand( const std::string& id, Expr expr, std::vector<Expr>& values ) throw();
-  //SetUserAttributeCommand( const std::string& id, Expr expr, std::string& value ) throw();
+  SetUserAttributeCommand( const std::string& attr, Expr expr, std::vector<Expr>& values ) throw();
+  SetUserAttributeCommand( const std::string& attr, Expr expr, const std::string& value ) throw();
   ~SetUserAttributeCommand() throw() {}
   void invoke(SmtEngine* smtEngine) throw();
   Command* exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap);
@@ -452,14 +454,14 @@ public:
   std::string getCommandName() const throw();
 };/* class SetUserAttributeCommand */
 
-
 class CVC4_PUBLIC CheckSatCommand : public Command {
 protected:
   Expr d_expr;
   Result d_result;
+  bool d_inUnsatCore;
 public:
   CheckSatCommand() throw();
-  CheckSatCommand(const Expr& expr) throw();
+  CheckSatCommand(const Expr& expr, bool inUnsatCore = true) throw();
   ~CheckSatCommand() throw() {}
   Expr getExpr() const throw();
   void invoke(SmtEngine* smtEngine) throw();
@@ -474,8 +476,9 @@ class CVC4_PUBLIC QueryCommand : public Command {
 protected:
   Expr d_expr;
   Result d_result;
+  bool d_inUnsatCore;
 public:
-  QueryCommand(const Expr& e) throw();
+  QueryCommand(const Expr& e, bool inUnsatCore = true) throw();
   ~QueryCommand() throw() {}
   Expr getExpr() const throw();
   void invoke(SmtEngine* smtEngine) throw();
@@ -597,12 +600,15 @@ public:
 
 class CVC4_PUBLIC GetUnsatCoreCommand : public Command {
 protected:
-  //UnsatCore* d_result;
+  UnsatCore d_result;
+  std::map<Expr, std::string> d_names;
 public:
   GetUnsatCoreCommand() throw();
+  GetUnsatCoreCommand(const std::map<Expr, std::string>& names) throw();
   ~GetUnsatCoreCommand() throw() {}
   void invoke(SmtEngine* smtEngine) throw();
   void printResult(std::ostream& out, uint32_t verbosity = 2) const throw();
+  const UnsatCore& getUnsatCore() const throw();
   Command* exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap);
   Command* clone() const;
   std::string getCommandName() const throw();
@@ -791,10 +797,19 @@ public:
   std::string getCommandName() const throw();
 };/* class PropagateRuleCommand */
 
+class CVC4_PUBLIC ResetCommand : public Command {
+public:
+  ResetCommand() throw() {}
+  ~ResetCommand() throw() {}
+  void invoke(SmtEngine* smtEngine) throw();
+  Command* exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap);
+  Command* clone() const;
+  std::string getCommandName() const throw();
+};/* class ResetCommand */
 
 class CVC4_PUBLIC QuitCommand : public Command {
 public:
-  QuitCommand() throw();
+  QuitCommand() throw() {}
   ~QuitCommand() throw() {}
   void invoke(SmtEngine* smtEngine) throw();
   Command* exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap);
index 809064413b874632a426f5b902b37412b39cd7c0..47042b458ed15a1a4122c40c86c0aa50ddb05419 100644 (file)
@@ -114,7 +114,7 @@ ExprManager* Expr::getExprManager() const {
 
 namespace expr {
 
-static Node exportConstant(TNode n, NodeManager* to);
+static Node exportConstant(TNode n, NodeManager* to, ExprManagerMapCollection& vmap);
 
 class ExportPrivate {
 private:
@@ -139,7 +139,7 @@ public:
         Type type = from->exportType(n.getConst< ::CVC4::EmptySet >().getType(), to, vmap);
         return to->mkConst(::CVC4::EmptySet(type));
       }
-      return exportConstant(n, NodeManager::fromExprManager(to));
+      return exportConstant(n, NodeManager::fromExprManager(to), vmap);
     } else if(n.isVar()) {
       Expr from_e(from, new Node(n));
       Expr& to_e = vmap.d_typeMap[from_e];
@@ -574,14 +574,29 @@ ${getConst_implementations}
 
 namespace expr {
 
-static Node exportConstant(TNode n, NodeManager* to) {
+static Node exportConstant(TNode n, NodeManager* to, ExprManagerMapCollection& vmap) {
   Assert(n.isConst());
   Debug("export") << "constant: " << n << std::endl;
+
+  if(n.getKind() == kind::STORE_ALL) {
+    // Special export for ArrayStoreAll.
+    //
+    // Ultimately we'll need special cases also for RecordUpdate,
+    // TupleUpdate, AscriptionType, and other constant-metakinded
+    // expressions that embed types.  For now datatypes aren't supported
+    // for export so those don't matter.
+    ExprManager* toEm = to->toExprManager();
+    const ArrayStoreAll& asa = n.getConst<ArrayStoreAll>();
+    return to->mkConst(ArrayStoreAll(asa.getType().exportTo(toEm, vmap),
+                                     asa.getExpr().exportTo(toEm, vmap)));
+  }
+
   switch(n.getKind()) {
 ${exportConstant_cases}
 
   default: Unhandled(n.getKind());
   }
+
 }/* exportConstant() */
 
 }/* CVC4::expr namespace */
index ee4d40b2cf3befb12e0fc5c0f50cd8c1814f9615..b4608832f2c7d783d7cf6aca885e9556957995a6 100644 (file)
@@ -7,12 +7,12 @@ module EXPR "expr/options.h" Expression package
 
 option defaultExprDepth --default-expr-depth=N int :default 0 :predicate CVC4::expr::setDefaultExprDepth :predicate-include "expr/options_handlers.h"
  print exprs to depth N (0 == default, -1 == no limit)
-undocumented-alias --expr-depth = --default-expr-depth
+undocumented-alias --expr-depth=N = --default-expr-depth=N
 
 option defaultDagThresh default-dag-thresh --default-dag-thresh=N int :default 1 :predicate CVC4::expr::setDefaultDagThresh :predicate-include "expr/options_handlers.h"
  dagify common subexprs appearing > N times (1 == default, 0 == don't dagify)
-undocumented-alias --dag-thresh = --default-dag-thresh
-undocumented-alias --dag-threshold = --default-dag-thresh
+undocumented-alias --dag-thresh=N = --default-dag-thresh=N
+undocumented-alias --dag-threshold=N = --default-dag-thresh=N
 
 option - --print-expr-types void :handler CVC4::expr::setPrintExprTypes :handler-include "expr/options_handlers.h"
  print types with variables when printing exprs
index ce7d571db636d4c8676d4fb82e37faaeaace2d23..3d53f2e44bae67faebc0c77cda00121c6bf9d8fb 100644 (file)
@@ -34,7 +34,7 @@ using namespace std;
 namespace CVC4 {
 
 SymbolTable::SymbolTable() :
-  d_context(new Context),
+  d_context(new Context()),
   d_exprMap(new(true) CDHashMap<std::string, Expr, StringHashFunction>(d_context)),
   d_typeMap(new(true) CDHashMap<std::string, pair<vector<Type>, Type>, StringHashFunction>(d_context)),
   d_functions(new(true) CDHashSet<Expr, ExprHashFunction>(d_context)) {
@@ -206,4 +206,9 @@ size_t SymbolTable::getLevel() const throw() {
   return d_context->getLevel();
 }
 
+void SymbolTable::reset() {
+  this->SymbolTable::~SymbolTable();
+  new(this) SymbolTable();
+}
+
 }/* CVC4 namespace */
index a9ab43cfe3a699e5e531fb1ceb54f70ec1dc2e56..451a482dc9851bfb96bbee48769fbc4a131d41ca 100644 (file)
@@ -198,6 +198,9 @@ public:
   /** Get the current level of this symbol table. */
   size_t getLevel() const throw();
 
+  /** Reset everything. */
+  void reset();
+
 };/* class SymbolTable */
 
 }/* CVC4 namespace */
index 5b90ca14f861358f3bfec97ba2ac6f905fa19866..52522d59139698cec4ed793d0e30dbf6b1d9392a 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "main/options.h"
 #include "smt/options.h"
+#include "printer/options.h"
 
 #ifndef __WIN32__
 #  include <sys/resource.h>
@@ -46,7 +47,6 @@ void setNoLimitCPU() {
 #endif /* ! __WIN32__ */
 }
 
-
 void printStatsIncremental(std::ostream& out, const std::string& prvsStatsString, const std::string& curStatsString);
 
 CommandExecutor::CommandExecutor(ExprManager &exprMgr, Options &options) :
@@ -119,24 +119,31 @@ bool CommandExecutor::doCommandSingleton(Command* cmd)
     d_lastStatistics = ossCurStats.str();
   }
 
-  // dump the model/proof if option is set
+  // dump the model/proof/unsat core if option is set
   if(status) {
-    Command * g = NULL;
+    Command* g = NULL;
     if( d_options[options::produceModels] &&
         d_options[options::dumpModels] &&
         ( res.asSatisfiabilityResult() == Result::SAT ||
           (res.isUnknown() && res.whyUnknown() == Result::INCOMPLETE) ) ) {
       g = new GetModelCommand();
-    } else if( d_options[options::proof] &&
-               d_options[options::dumpProofs] &&
-               res.asSatisfiabilityResult() == Result::UNSAT ) {
+    }
+    if( d_options[options::proof] &&
+        d_options[options::dumpProofs] &&
+        res.asSatisfiabilityResult() == Result::UNSAT ) {
       g = new GetProofCommand();
-    } else if( d_options[options::dumpInstantiations] &&
-               res.asSatisfiabilityResult() == Result::UNSAT ) {
+    }
+    if( d_options[options::dumpInstantiations] &&
+        ( ( d_options[options::instFormatMode] != INST_FORMAT_MODE_SZS &&
+            ( res.asSatisfiabilityResult() == Result::SAT || (res.isUnknown() && res.whyUnknown() == Result::INCOMPLETE) ) ) ||
+          res.asSatisfiabilityResult() == Result::UNSAT ) ) {
       g = new GetInstantiationsCommand();
     }
-    if( g ){
-      //set no time limit during dumping if applicable
+    if( d_options[options::dumpUnsatCores] && res.asSatisfiabilityResult() == Result::UNSAT ) {
+      g = new GetUnsatCoreCommand();
+    }
+    if(g != NULL) {
+      // set no time limit during dumping if applicable
       if( d_options[options::forceNoLimitCpuWhileDump] ){
         setNoLimitCPU();
       }
@@ -162,12 +169,12 @@ bool smtEngineInvoke(SmtEngine* smt, Command* cmd, std::ostream *out)
 
 void printStatsIncremental(std::ostream& out, const std::string& prvsStatsString, const std::string& curStatsString) {
   if(prvsStatsString == "") {
-      out << curStatsString;
-      return;
+    out << curStatsString;
+    return;
   }
 
   // read each line
-  // if a number, subtract and add that to parantheses
+  // if a number, subtract and add that to parentheses
   std::istringstream issPrvs(prvsStatsString);
   std::istringstream issCur(curStatsString);
 
index 36f2abdd203ba74046f03e109dfcb80be4d0f704..6e10c9a8a8db22a998b554c5775b7486bf5ce439 100644 (file)
@@ -11,7 +11,7 @@
  **
  ** \brief An additional layer between commands and invoking them.
  **
- ** The portfolio executer branches check-sat queries to several
+ ** The portfolio executor branches check-sat queries to several
  ** threads.
  **/
 
@@ -29,6 +29,7 @@
 #include "main/portfolio.h"
 #include "options/options.h"
 #include "smt/options.h"
+#include "printer/options.h"
 
 #include "cvc4autoconfig.h"
 
@@ -357,7 +358,7 @@ bool CommandExecutorPortfolio::doCommandSingleton(Command* cmd)
 
     bool status = portfolioReturn.second;
 
-    // dump the model/proof if option is set
+    // dump the model/proof/unsat core if option is set
     if(status) {
       if( d_options[options::produceModels] &&
           d_options[options::dumpModels] &&
@@ -371,9 +372,15 @@ bool CommandExecutorPortfolio::doCommandSingleton(Command* cmd)
         Command* gp = new GetProofCommand();
         status = doCommandSingleton(gp);
       } else if( d_options[options::dumpInstantiations] &&
-                 d_result.asSatisfiabilityResult() == Result::UNSAT ) {
+                 ( ( d_options[options::instFormatMode]!=INST_FORMAT_MODE_SZS && 
+                   ( d_result.asSatisfiabilityResult() == Result::SAT || (d_result.isUnknown() && d_result.whyUnknown() == Result::INCOMPLETE) ) ) || 
+                 d_result.asSatisfiabilityResult() == Result::UNSAT ) ) {
         Command* gi = new GetInstantiationsCommand();
         status = doCommandSingleton(gi);
+      } else if( d_options[options::dumpUnsatCores] &&
+                 d_result.asSatisfiabilityResult() == Result::UNSAT ) {
+        Command* guc = new GetUnsatCoreCommand();
+        status = doCommandSingleton(guc);
       }
     }
 
index 1f398875311bd1860315a9d33ff2d2158754b984..5fbd5aff53ecae34164f744ed7198b3a6f007d69 100644 (file)
@@ -267,15 +267,8 @@ int runCvc4(int argc, char* argv[], Options& opts) {
     Command* cmd;
     bool status = true;
     if(opts[options::interactive] && inputFromStdin) {
-      if(opts[options::tearDownIncremental] && opts[options::incrementalSolving]) {
-        if(opts.wasSetByUser(options::incrementalSolving)) {
-          throw OptionException("--tear-down-incremental incompatible with --incremental");
-        }
-
-        cmd = new SetOptionCommand("incremental", false);
-        cmd->setMuted(true);
-        pExecutor->doCommand(cmd);
-        delete cmd;
+      if(opts[options::tearDownIncremental]) {
+        throw OptionException("--tear-down-incremental doesn't work in interactive mode");
       }
 #ifndef PORTFOLIO_BUILD
       if(!opts.wasSetByUser(options::incrementalSolving)) {
index b9262bfa4d33e88682f8e0b455347911be9cd19a..6cc6a0ca0d613bc2603ade44c86bc80c17f8a2ed 100644 (file)
@@ -52,7 +52,7 @@ option segvSpin --segv-spin bool :default false
  spin on segfault/other crash waiting for gdb
 undocumented-alias --segv-nospin = --no-segv-spin
 
-expert-option tearDownIncremental --tear-down-incremental bool :default false
+expert-option tearDownIncremental --tear-down-incremental bool :default false
  implement PUSH/POP/multi-query by destroying and recreating SmtEngine
 
 expert-option waitToJoin --wait-to-join bool :default true
index a3a1571ec69bed151ad156e80d04059df2447ac3..03d7837ac46cd6735285f2cced86d20699e6b94c 100755 (executable)
@@ -352,6 +352,10 @@ function handle_option {
       WARN "$internal is inaccessible via SmtEngine (no smt name for option) but can be set via command-line: $long_option $short_option $long_option_alternate $short_option_alternate"
     fi
   fi
+  # in options files, use an smt name of ":" to force there not to be one
+  if [ "$smtname" = : ]; then
+    smtname=
+  fi
 
   # check for duplicates
   if [ "$internal" != - ]; then
index a178f8dd55b0800ec9fcf62cf758f1840f24a337..c8a8cc941f96bb9af4260770d6b43ad7a861d554 100644 (file)
@@ -29,7 +29,7 @@ libcvc4parser_la_LIBADD = \
        @builddir@/smt2/libparsersmt2.la \
        @builddir@/tptp/libparsertptp.la \
        @builddir@/cvc/libparsercvc.la \
-       -L@builddir@/.. -lcvc4
+       @builddir@/../libcvc4.la
 
 if CVC4_NEEDS_REPLACEMENT_FUNCTIONS
 libcvc4parser_la_LIBADD += \
index 79db2b629456cee8a30956bb2d74fdd0ca32dab0..ead8caa207b86d757462388c9cb3ea1a73962836 100644 (file)
@@ -65,6 +65,7 @@ tokens {
   EXIT_TOK = 'EXIT';
   INCLUDE_TOK = 'INCLUDE';
   DUMP_PROOF_TOK = 'DUMP_PROOF';
+  DUMP_UNSAT_CORE_TOK = 'DUMP_UNSAT_CORE';
   DUMP_ASSUMPTIONS_TOK = 'DUMP_ASSUMPTIONS';
   DUMP_SIG_TOK = 'DUMP_SIG';
   DUMP_TCC_TOK = 'DUMP_TCC';
@@ -697,7 +698,9 @@ mainCommand[CVC4::Command*& cmd]
     { UNSUPPORTED("POPTO_SCOPE command"); }
 
   | RESET_TOK
-    { UNSUPPORTED("RESET command"); }
+    { cmd = new ResetCommand();
+      PARSER_STATE->reset();
+    }
 
     // Datatypes can be mututally-recursive if they're in the same
     // definition block, separated by a comma.  So we parse everything
@@ -793,6 +796,9 @@ mainCommand[CVC4::Command*& cmd]
   | DUMP_PROOF_TOK
     { cmd = new GetProofCommand(); }
 
+  | DUMP_UNSAT_CORE_TOK
+    { cmd = new GetUnsatCoreCommand(); }
+
   | ( DUMP_ASSUMPTIONS_TOK
     | DUMP_SIG_TOK
     | DUMP_TCC_TOK
@@ -1375,14 +1381,6 @@ prefixFormula[CVC4::Expr& f]
       PARSER_STATE->preemptCommand(cmd);
       f = func;
     }
-
-    /* array literals */
-  | ARRAY_TOK { PARSER_STATE->pushScope(); } LPAREN
-    boundVarDecl[ids,t] RPAREN COLON formula[f]
-    { PARSER_STATE->popScope();
-      UNSUPPORTED("array literals not supported yet");
-      f = EXPR_MANAGER->mkVar(EXPR_MANAGER->mkArrayType(t, f.getType()), ExprManager::VAR_FLAG_GLOBAL);
-    }
   ;
 
 instantiationPatterns[ CVC4::Expr& expr ]
@@ -1467,10 +1465,6 @@ arithmeticBinop[unsigned& op]
   | EXP_TOK
   ;
 
-moreArrayStores[CVC4::Expr& f]
-  : COMMA arrayStore[f]
-  ;
-
 /** Parses an array/tuple/record assignment term. */
 term[CVC4::Expr& f]
 @init {
@@ -1904,7 +1898,7 @@ simpleTerm[CVC4::Expr& f]
   std::vector<std::string> names;
   Expr e;
   Debug("parser-extra") << "term: " << AntlrInput::tokenText(LT(1)) << std::endl;
-  Type t;
+  Type t, t2;
 }
     /* if-then-else */
   : iteTerm[f]
@@ -1934,7 +1928,6 @@ simpleTerm[CVC4::Expr& f]
       f = MK_EXPR(kind::RECORD, MK_CONST(t.getRecord()), std::vector<Expr>());
     }
 
-
     /* empty set literal */
   | LBRACE RBRACE
     { f = MK_CONST(EmptySet(Type())); }
@@ -1948,6 +1941,32 @@ simpleTerm[CVC4::Expr& f]
       }
     }
 
+    /* array literals */
+  | ARRAY_TOK /* { PARSER_STATE->pushScope(); } */ LPAREN
+    restrictedType[t, CHECK_DECLARED] OF_TOK restrictedType[t2, CHECK_DECLARED]
+    RPAREN COLON simpleTerm[f]
+    { /* Eventually if we support a bound var (like a lambda) for array
+       * literals, we can use the push/pop scope. */
+      /* PARSER_STATE->popScope(); */
+      t = EXPR_MANAGER->mkArrayType(t, t2);
+      if(!f.isConst()) {
+        std::stringstream ss;
+        ss << "expected constant term inside array constant, but found "
+           << "nonconstant term" << std::endl
+           << "the term: " << f;
+        PARSER_STATE->parseError(ss.str());
+      }
+      if(!t2.isComparableTo(f.getType())) {
+        std::stringstream ss;
+        ss << "type mismatch inside array constant term:" << std::endl
+           << "array type:          " << t << std::endl
+           << "expected const type: " << t2 << std::endl
+           << "computed const type: " << f.getType();
+        PARSER_STATE->parseError(ss.str());
+      }
+      f = MK_CONST( ArrayStoreAll(t, f) );
+    }
+
     /* boolean literals */
   | TRUE_TOK  { f = MK_CONST(bool(true)); }
   | FALSE_TOK { f = MK_CONST(bool(false)); }
@@ -1992,7 +2011,7 @@ simpleTerm[CVC4::Expr& f]
   ;
 
 /**
- * Matches (and performs) a type ascription.
+ * Matches a type ascription.
  * The f arg is the term to check (it is an input-only argument).
  */
 typeAscription[const CVC4::Expr& f, CVC4::Type& t]
index 87a331711ba23b8a031482e0106c79efb204e226..52236294a26016ed5c564c4322e4bb9c73c7b57d 100644 (file)
@@ -561,6 +561,10 @@ public:
     }
   }
 
+  inline void reset() {
+    d_symtab->reset();
+  }
+
   /**
    * Set the current symbol table used by this parser.
    * From now on, this parser will perform its definitions and
index 6964e60693ae328f9da46344f20e7f5e3e208228..6fce2648440f43b9cfa5e7a7ae591a1bca2c719f 100644 (file)
@@ -344,28 +344,6 @@ command returns [CVC4::Command* cmd = NULL]
       Expr func = PARSER_STATE->mkFunction(name, t, ExprManager::VAR_FLAG_DEFINED);
       $cmd = new DefineFunctionCommand(name, func, terms, expr);
     }
-  | DEFINE_CONST_TOK { PARSER_STATE->checkThatLogicIsSet(); }
-    symbol[name,CHECK_UNDECLARED,SYM_VARIABLE]
-    { PARSER_STATE->checkUserSymbol(name); }
-    sortSymbol[t,CHECK_DECLARED]
-    { /* add variables to parser state before parsing term */
-      Debug("parser") << "define const: '" << name << "'" << std::endl;
-      PARSER_STATE->pushScope(true);
-      for(std::vector<std::pair<std::string, CVC4::Type> >::const_iterator i =
-            sortedVarNames.begin(), iend = sortedVarNames.end();
-          i != iend;
-          ++i) {
-        terms.push_back(PARSER_STATE->mkBoundVar((*i).first, (*i).second));
-      }
-    }
-    term[expr, expr2]
-    { PARSER_STATE->popScope();
-      // declare the name down here (while parsing term, signature
-      // must not be extended with the name itself; no recursion
-      // permitted)
-      Expr func = PARSER_STATE->mkFunction(name, t, ExprManager::VAR_FLAG_DEFINED);
-      $cmd = new DefineFunctionCommand(name, func, terms, expr);
-    }
   | /* value query */
     GET_VALUE_TOK { PARSER_STATE->checkThatLogicIsSet(); }
     ( LPAREN_TOK termList[terms,expr] RPAREN_TOK
@@ -377,8 +355,14 @@ command returns [CVC4::Command* cmd = NULL]
     { cmd = new GetAssignmentCommand(); }
   | /* assertion */
     ASSERT_TOK { PARSER_STATE->checkThatLogicIsSet(); }
+    { PARSER_STATE->clearLastNamedTerm(); }
     term[expr, expr2]
-    { cmd = new AssertCommand(expr); }
+    { bool inUnsatCore = PARSER_STATE->lastNamedTerm().first == expr;
+      cmd = new AssertCommand(expr, inUnsatCore);
+      if(inUnsatCore) {
+        PARSER_STATE->registerUnsatCoreName(PARSER_STATE->lastNamedTerm());
+      }
+    }
   | /* check-sat */
     CHECKSAT_TOK { PARSER_STATE->checkThatLogicIsSet(); }
     ( term[expr, expr2]
@@ -396,7 +380,7 @@ command returns [CVC4::Command* cmd = NULL]
     { cmd = new GetProofCommand(); }
   | /* get-unsat-core */
     GET_UNSAT_CORE_TOK { PARSER_STATE->checkThatLogicIsSet(); }
-    { cmd = new GetUnsatCoreCommand(); }
+    { cmd = new GetUnsatCoreCommand(PARSER_STATE->getUnsatCoreNames()); }
   | /* push */
     PUSH_TOK { PARSER_STATE->checkThatLogicIsSet(); }
     ( k=INTEGER_LITERAL
@@ -405,11 +389,13 @@ command returns [CVC4::Command* cmd = NULL]
           cmd = new EmptyCommand();
         } else if(n == 1) {
           PARSER_STATE->pushScope();
+          PARSER_STATE->pushUnsatCoreNameScope();
           cmd = new PushCommand();
         } else {
           CommandSequence* seq = new CommandSequence();
           do {
             PARSER_STATE->pushScope();
+            PARSER_STATE->pushUnsatCoreNameScope();
             Command* c = new PushCommand();
             c->setMuted(n > 1);
             seq->addCommand(c);
@@ -421,6 +407,7 @@ command returns [CVC4::Command* cmd = NULL]
           PARSER_STATE->parseError("Strict compliance mode demands an integer to be provided to PUSH.  Maybe you want (push 1)?");
         } else {
           PARSER_STATE->pushScope();
+          PARSER_STATE->pushUnsatCoreNameScope();
           cmd = new PushCommand();
         }
       } )
@@ -433,11 +420,13 @@ command returns [CVC4::Command* cmd = NULL]
         if(n == 0) {
           cmd = new EmptyCommand();
         } else if(n == 1) {
+          PARSER_STATE->popUnsatCoreNameScope();
           PARSER_STATE->popScope();
           cmd = new PopCommand();
         } else {
           CommandSequence* seq = new CommandSequence();
           do {
+            PARSER_STATE->popUnsatCoreNameScope();
             PARSER_STATE->popScope();
             Command* c = new PopCommand();
             c->setMuted(n > 1);
@@ -449,6 +438,7 @@ command returns [CVC4::Command* cmd = NULL]
     | { if(PARSER_STATE->strictModeEnabled()) {
           PARSER_STATE->parseError("Strict compliance mode demands an integer to be provided to POP.  Maybe you want (pop 1)?");
         } else {
+          PARSER_STATE->popUnsatCoreNameScope();
           PARSER_STATE->popScope();
           cmd = new PopCommand();
         }
@@ -612,6 +602,28 @@ extendedCommand[CVC4::Command*& cmd]
         $cmd = new DefineFunctionCommand(name, func, terms, e);
       }
     )
+  | DEFINE_CONST_TOK { PARSER_STATE->checkThatLogicIsSet(); }
+    symbol[name,CHECK_UNDECLARED,SYM_VARIABLE]
+    { PARSER_STATE->checkUserSymbol(name); }
+    sortSymbol[t,CHECK_DECLARED]
+    { /* add variables to parser state before parsing term */
+      Debug("parser") << "define const: '" << name << "'" << std::endl;
+      PARSER_STATE->pushScope(true);
+      for(std::vector<std::pair<std::string, CVC4::Type> >::const_iterator i =
+            sortedVarNames.begin(), iend = sortedVarNames.end();
+          i != iend;
+          ++i) {
+        terms.push_back(PARSER_STATE->mkBoundVar((*i).first, (*i).second));
+      }
+    }
+    term[e, e2]
+    { PARSER_STATE->popScope();
+      // declare the name down here (while parsing term, signature
+      // must not be extended with the name itself; no recursion
+      // permitted)
+      Expr func = PARSER_STATE->mkFunction(name, t, ExprManager::VAR_FLAG_DEFINED);
+      $cmd = new DefineFunctionCommand(name, func, terms, e);
+    }
 
   | SIMPLIFY_TOK { PARSER_STATE->checkThatLogicIsSet(); }
     term[e,e2]
@@ -686,7 +698,7 @@ rewriterulesCommand[CVC4::Command*& cmd]
       };
       args.push_back(expr);
       expr = MK_EXPR(CVC4::kind::REWRITE_RULE, args);
-      cmd = new AssertCommand(expr); }
+      cmd = new AssertCommand(expr, false); }
     /* propagation rule */
   | rewritePropaKind[kind]
     LPAREN_TOK sortedVarList[sortedVarNames] RPAREN_TOK
@@ -737,7 +749,7 @@ rewriterulesCommand[CVC4::Command*& cmd]
       };
       args.push_back(expr);
       expr = MK_EXPR(CVC4::kind::REWRITE_RULE, args);
-      cmd = new AssertCommand(expr); }
+      cmd = new AssertCommand(expr, false); }
   ;
 
 rewritePropaKind[CVC4::Kind& kind]
@@ -987,11 +999,40 @@ term[CVC4::Expr& expr, CVC4::Expr& expr2]
       }
       expr = MK_EXPR(kind, args); }
 
-  | /* An indexed function application */
-    LPAREN_TOK indexedFunctionName[op] termList[args,expr] RPAREN_TOK
-    { expr = MK_EXPR(op, args);
-      PARSER_STATE->checkOperator(expr.getKind(), args.size());
-    }
+  | LPAREN_TOK
+    ( /* An indexed function application */
+      indexedFunctionName[op] termList[args,expr] RPAREN_TOK
+      { expr = MK_EXPR(op, args);
+        PARSER_STATE->checkOperator(expr.getKind(), args.size());
+      }
+    | /* Array constant (in Z3 syntax) */
+      LPAREN_TOK AS_TOK CONST_TOK sortSymbol[type, CHECK_DECLARED]
+      RPAREN_TOK term[f, f2] RPAREN_TOK
+      {
+        if(!type.isArray()) {
+          std::stringstream ss;
+          ss << "expected array constant term, but cast is not of array type" << std::endl
+             << "cast type: " << type;
+          PARSER_STATE->parseError(ss.str());
+        }
+        if(!f.isConst()) {
+          std::stringstream ss;
+          ss << "expected constant term inside array constant, but found "
+             << "nonconstant term:" << std::endl
+             << "the term: " << f;
+          PARSER_STATE->parseError(ss.str());
+        }
+        if(!ArrayType(type).getConstituentType().isComparableTo(f.getType())) {
+          std::stringstream ss;
+          ss << "type mismatch inside array constant term:" << std::endl
+             << "array type:          " << type << std::endl
+             << "expected const type: " << ArrayType(type).getConstituentType() << std::endl
+             << "computed const type: " << f.getType();
+          PARSER_STATE->parseError(ss.str());
+        }
+        expr = MK_CONST( ::CVC4::ArrayStoreAll(type, f) );
+      }
+    )
   | /* a let binding */
     LPAREN_TOK LET_TOK LPAREN_TOK
     { PARSER_STATE->pushScope(true); }
@@ -1037,8 +1078,8 @@ term[CVC4::Expr& expr, CVC4::Expr& expr2]
 
     /* attributed expressions */
   | LPAREN_TOK ATTRIBUTE_TOK term[expr, f2]
-    ( attribute[expr, attexpr,attr]
-      { if( attr == ":pattern" && ! attexpr.isNull()) {
+    ( attribute[expr, attexpr, attr]
+      { if( ! attexpr.isNull()) {
           patexprs.push_back( attexpr );
         }
       }
@@ -1072,11 +1113,17 @@ term[CVC4::Expr& expr, CVC4::Expr& expr2]
       } else if(! patexprs.empty()) {
         if( !f2.isNull() && f2.getKind()==kind::INST_PATTERN_LIST ){
           for( size_t i=0; i<f2.getNumChildren(); i++ ){
-            patexprs.push_back( f2[i] );
+            if( f2[i].getKind()==kind::INST_PATTERN ){
+              patexprs.push_back( f2[i] );
+            }else{
+              std::stringstream ss;
+              ss << "warning: rewrite rules do not support " << f2[i] << " within instantiation pattern list";
+              PARSER_STATE->warning(ss.str());
+            }
           }
         }
         expr2 = MK_EXPR(kind::INST_PATTERN_LIST, patexprs);
-      }else{
+      } else {
         expr2 = f2;
       }
     }
@@ -1144,7 +1191,7 @@ attribute[CVC4::Expr& expr,CVC4::Expr& retExpr, std::string& attr]
         PARSER_STATE->warning(ss.str());
       }
       // do nothing
-    } else if(attr == ":axiom" || attr == ":conjecture") {
+    } else if(attr==":axiom" || attr==":conjecture" || attr==":sygus" || attr==":synthesis") {
       if(hasValue) {
         std::stringstream ss;
         ss << "warning: Attribute " << attr << " does not take a value (ignoring)";
@@ -1152,7 +1199,11 @@ attribute[CVC4::Expr& expr,CVC4::Expr& retExpr, std::string& attr]
       }
       std::string attr_name = attr;
       attr_name.erase( attr_name.begin() );
-      Command* c = new SetUserAttributeCommand( attr_name, expr );
+      //will set the attribute on auxiliary var (preserves attribute on formula through rewriting)
+      Type t = EXPR_MANAGER->booleanType();
+      Expr avar = PARSER_STATE->mkVar(attr_name, t);
+      retExpr = MK_EXPR(kind::INST_ATTRIBUTE, avar);
+      Command* c = new SetUserAttributeCommand( attr_name, avar );
       c->setMuted(true);
       PARSER_STATE->preemptCommand(c);
     } else {
@@ -1164,10 +1215,24 @@ attribute[CVC4::Expr& expr,CVC4::Expr& retExpr, std::string& attr]
       attr = std::string(":pattern");
       retExpr = MK_EXPR(kind::INST_PATTERN, patexprs);
     }
-  | ATTRIBUTE_NO_PATTERN_TOK LPAREN_TOK term[patexpr, e2]+ RPAREN_TOK
+  | ATTRIBUTE_NO_PATTERN_TOK term[patexpr, e2]
     {
       attr = std::string(":no-pattern");
-      PARSER_STATE->attributeNotSupported(attr);
+      retExpr = MK_EXPR(kind::INST_NO_PATTERN, patexpr);
+    }
+  | tok=( ATTRIBUTE_INST_LEVEL | ATTRIBUTE_RR_PRIORITY ) INTEGER_LITERAL
+    {
+      Expr n = MK_CONST( AntlrInput::tokenToInteger($INTEGER_LITERAL) );
+      std::vector<Expr> values;
+      values.push_back( n );
+      std::string attr_name(AntlrInput::tokenText($tok));
+      attr_name.erase( attr_name.begin() );
+      Type t = EXPR_MANAGER->booleanType();
+      Expr avar = PARSER_STATE->mkVar(attr_name, t);
+      retExpr = MK_EXPR(kind::INST_ATTRIBUTE, avar);
+      Command* c = new SetUserAttributeCommand( attr_name, avar, values );
+      c->setMuted(true);
+      PARSER_STATE->preemptCommand(c);
     }
   | ATTRIBUTE_NAMED_TOK symbolicExpr[sexpr]
     {
@@ -1192,6 +1257,8 @@ attribute[CVC4::Expr& expr,CVC4::Expr& retExpr, std::string& attr]
       PARSER_STATE->reserveSymbolAtAssertionLevel(name);
       // define it
       Expr func = PARSER_STATE->mkFunction(name, expr.getType());
+      // remember the last term to have been given a :named attribute
+      PARSER_STATE->setLastNamedTerm(expr, name);
       // bind name to expr with define-fun
       Command* c =
         new DefineNamedFunctionCommand(name, func, std::vector<Expr>(), expr);
@@ -1670,6 +1737,7 @@ GET_OPTION_TOK : 'get-option';
 PUSH_TOK : 'push';
 POP_TOK : 'pop';
 AS_TOK : 'as';
+CONST_TOK : 'const';
 
 // extended commands
 DECLARE_DATATYPES_TOK : 'declare-datatypes';
@@ -1692,6 +1760,8 @@ INCLUDE_TOK : 'include';
 ATTRIBUTE_PATTERN_TOK : ':pattern';
 ATTRIBUTE_NO_PATTERN_TOK : ':no-pattern';
 ATTRIBUTE_NAMED_TOK : ':named';
+ATTRIBUTE_INST_LEVEL : ':quant-inst-max-level';
+ATTRIBUTE_RR_PRIORITY : ':rr-priority';
 
 // operators (NOTE: theory symbols go here)
 AMPERSAND_TOK     : '&';
index fecccfa44c95adf658bd6eadc9ce0454416a4c0e..21b6a1e5b91e9879c4dd5008f628c8660b78c68a 100644 (file)
@@ -31,6 +31,7 @@ namespace parser {
 Smt2::Smt2(ExprManager* exprManager, Input* input, bool strictMode, bool parseOnly) :
   Parser(exprManager,input,strictMode,parseOnly),
   d_logicSet(false) {
+  d_unsatCoreNames.push(std::map<Expr, std::string>());
   if( !strictModeEnabled() ) {
     addTheory(Smt2::THEORY_CORE);
   }
index 71161be94bb32c919afb210d2e8c474516654d4d..290bbc975e200ded0f27cb873cef239fc2f9a375 100644 (file)
 #include "theory/logic_info.h"
 #include "util/abstract_value.h"
 
+#include <string>
 #include <sstream>
+#include <utility>
+#include <stack>
 
 namespace CVC4 {
 
@@ -54,6 +57,9 @@ private:
   bool d_logicSet;
   LogicInfo d_logic;
   std::hash_map<std::string, Kind, StringHashFunction> operatorKindMap;
+  std::pair<Expr, std::string> d_lastNamedTerm;
+  // this is a user-context stack
+  std::stack< std::map<Expr, std::string> > d_unsatCoreNames;
 
 protected:
   Smt2(ExprManager* exprManager, Input* input, bool strictMode = false, bool parseOnly = false);
@@ -105,6 +111,34 @@ public:
 
   void includeFile(const std::string& filename);
 
+  void setLastNamedTerm(Expr e, std::string name) {
+    d_lastNamedTerm = std::make_pair(e, name);
+  }
+
+  void clearLastNamedTerm() {
+    d_lastNamedTerm = std::make_pair(Expr(), "");
+  }
+
+  std::pair<Expr, std::string> lastNamedTerm() {
+    return d_lastNamedTerm;
+  }
+
+  void pushUnsatCoreNameScope() {
+    d_unsatCoreNames.push(d_unsatCoreNames.top());
+  }
+
+  void popUnsatCoreNameScope() {
+    d_unsatCoreNames.pop();
+  }
+
+  void registerUnsatCoreName(std::pair<Expr, std::string> name) {
+    d_unsatCoreNames.top().insert(name);
+  }
+
+  std::map<Expr, std::string> getUnsatCoreNames() {
+    return d_unsatCoreNames.top();
+  }
+
   bool isAbstractValue(const std::string& name) {
     return name.length() >= 2 && name[0] == '@' && name[1] != '0' &&
       name.find_first_not_of("0123456789", 1) == std::string::npos;
index 9b60c8942587eda4faa2adf0de86b8847f50954d..220916a1ab70446a7479d4c4c313ecc2cdcce630 100644 (file)
@@ -140,6 +140,7 @@ void AstPrinter::toStream(std::ostream& out, const Command* c,
      tryToStream<PopCommand>(out, c) ||
      tryToStream<CheckSatCommand>(out, c) ||
      tryToStream<QueryCommand>(out, c) ||
+     tryToStream<ResetCommand>(out, c) ||
      tryToStream<QuitCommand>(out, c) ||
      tryToStream<DeclarationSequence>(out, c) ||
      tryToStream<CommandSequence>(out, c) ||
@@ -224,6 +225,10 @@ static void toStream(std::ostream& out, const QueryCommand* c) throw() {
   out << "Query(" << c->getExpr() << ')';
 }
 
+static void toStream(std::ostream& out, const ResetCommand* c) throw() {
+  out << "Reset()";
+}
+
 static void toStream(std::ostream& out, const QuitCommand* c) throw() {
   out << "Quit()";
 }
index 3f93106a029c54690454b3644d7d687598866a7e..48f1aadecb94e6d7d850e126194abb9572999783 100644 (file)
@@ -169,6 +169,13 @@ void CvcPrinter::toStream(std::ostream& out, TNode n, int depth, bool types, boo
       out << "{} :: " << n.getConst<EmptySet>().getType();
       break;
 
+    case kind::STORE_ALL: {
+      const ArrayStoreAll& asa = n.getConst<ArrayStoreAll>();
+      out << "ARRAY(" << asa.getType().getIndexType() << " OF "
+          << asa.getType().getConstituentType() << ") : " << asa.getExpr();
+      break;
+    }
+
     default:
       // Fall back to whatever operator<< does on underlying type; we
       // might luck out and print something reasonable.
@@ -852,6 +859,7 @@ void CvcPrinter::toStream(std::ostream& out, const Command* c,
      tryToStream<PopCommand>(out, c, d_cvc3Mode) ||
      tryToStream<CheckSatCommand>(out, c, d_cvc3Mode) ||
      tryToStream<QueryCommand>(out, c, d_cvc3Mode) ||
+     tryToStream<ResetCommand>(out, c, d_cvc3Mode) ||
      tryToStream<QuitCommand>(out, c, d_cvc3Mode) ||
      tryToStream<DeclarationSequence>(out, c, d_cvc3Mode) ||
      tryToStream<CommandSequence>(out, c, d_cvc3Mode) ||
@@ -866,6 +874,7 @@ void CvcPrinter::toStream(std::ostream& out, const Command* c,
      tryToStream<GetAssignmentCommand>(out, c, d_cvc3Mode) ||
      tryToStream<GetAssertionsCommand>(out, c, d_cvc3Mode) ||
      tryToStream<GetProofCommand>(out, c, d_cvc3Mode) ||
+     tryToStream<GetUnsatCoreCommand>(out, c, d_cvc3Mode) ||
      tryToStream<SetBenchmarkStatusCommand>(out, c, d_cvc3Mode) ||
      tryToStream<SetBenchmarkLogicCommand>(out, c, d_cvc3Mode) ||
      tryToStream<SetInfoCommand>(out, c, d_cvc3Mode) ||
@@ -1038,6 +1047,10 @@ static void toStream(std::ostream& out, const QueryCommand* c, bool cvc3Mode) th
   }
 }
 
+static void toStream(std::ostream& out, const ResetCommand* c, bool cvc3Mode) throw() {
+  out << "RESET;";
+}
+
 static void toStream(std::ostream& out, const QuitCommand* c, bool cvc3Mode) throw() {
   //out << "EXIT;";
 }
@@ -1137,6 +1150,10 @@ static void toStream(std::ostream& out, const GetProofCommand* c, bool cvc3Mode)
   out << "DUMP_PROOF;";
 }
 
+static void toStream(std::ostream& out, const GetUnsatCoreCommand* c, bool cvc3Mode) throw() {
+  out << "DUMP_UNSAT_CORE;";
+}
+
 static void toStream(std::ostream& out, const SetBenchmarkStatusCommand* c, bool cvc3Mode) throw() {
   out << "% (set-info :status " << c->getStatus() << ")";
 }
index 8f0f50daa08df3d41a6cfe97b5ca84f9047c9679..dd2e180e1d0d9db0a65d05f335ab59b158dda4d0 100644 (file)
@@ -153,4 +153,17 @@ void Printer::toStream(std::ostream& out, const Model& m) const throw() {
   }
 }/* Printer::toStream(Model) */
 
+void Printer::toStream(std::ostream& out, const UnsatCore& core) const throw() {
+  std::map<Expr, std::string> names;
+  toStream(out, core, names);
+}/* Printer::toStream(UnsatCore) */
+
+void Printer::toStream(std::ostream& out, const UnsatCore& core, const std::map<Expr, std::string>& names) const throw() {
+  for(UnsatCore::iterator i = core.begin(); i != core.end(); ++i) {
+    AssertCommand cmd(*i);
+    toStream(out, &cmd, -1, false, -1);
+    out << std::endl;
+  }
+}/* Printer::toStream(UnsatCore, std::map<Expr, std::string>) */
+
 }/* CVC4 namespace */
index beb2438e2b0251510efa5dd1ac4c0e00a0124378..e0b80ddfc5def86201314a74fd2e49f16c328a25 100644 (file)
@@ -19,6 +19,9 @@
 #ifndef __CVC4__PRINTER__PRINTER_H
 #define __CVC4__PRINTER__PRINTER_H
 
+#include <map>
+#include <string>
+
 #include "util/language.h"
 #include "util/sexpr.h"
 #include "util/model.h"
@@ -103,6 +106,12 @@ public:
   /** Write a Model out to a stream with this Printer. */
   virtual void toStream(std::ostream& out, const Model& m) const throw();
 
+  /** Write an UnsatCore out to a stream with this Printer. */
+  virtual void toStream(std::ostream& out, const UnsatCore& core) const throw();
+
+  /** Write an UnsatCore out to a stream with this Printer. */
+  virtual void toStream(std::ostream& out, const UnsatCore& core, const std::map<Expr, std::string>& names) const throw();
+
 };/* class Printer */
 
 /**
index 903a1e6e302bd87b2423c0fb90156c0c2b33c516..5dc5cb7ee99c1f937f5031981532c0e89cb99887 100644 (file)
@@ -194,7 +194,7 @@ void Smt2Printer::toStream(std::ostream& out, TNode n,
 
     case kind::STORE_ALL: {
       ArrayStoreAll asa = n.getConst<ArrayStoreAll>();
-      out << "(__array_store_all__ " << asa.getType() << " " << asa.getExpr() << ")";
+      out << "((as const " << asa.getType() << ") " << asa.getExpr() << ")";
       break;
     }
 
@@ -588,7 +588,6 @@ static string smtKindString(Kind k) throw() {
     // arrays theory
   case kind::SELECT: return "select";
   case kind::STORE: return "store";
-  case kind::STORE_ALL: return "__array_store_all__";
   case kind::ARRAY_TYPE: return "Array";
 
     // bv theory
@@ -699,6 +698,7 @@ void Smt2Printer::toStream(std::ostream& out, const Command* c,
      tryToStream<PopCommand>(out, c) ||
      tryToStream<CheckSatCommand>(out, c) ||
      tryToStream<QueryCommand>(out, c) ||
+     tryToStream<ResetCommand>(out, c) ||
      tryToStream<QuitCommand>(out, c) ||
      tryToStream<DeclarationSequence>(out, c) ||
      tryToStream<CommandSequence>(out, c) ||
@@ -713,6 +713,7 @@ void Smt2Printer::toStream(std::ostream& out, const Command* c,
      tryToStream<GetAssignmentCommand>(out, c) ||
      tryToStream<GetAssertionsCommand>(out, c) ||
      tryToStream<GetProofCommand>(out, c) ||
+     tryToStream<GetUnsatCoreCommand>(out, c) ||
      tryToStream<SetBenchmarkStatusCommand>(out, c) ||
      tryToStream<SetBenchmarkLogicCommand>(out, c, d_variant) ||
      tryToStream<SetInfoCommand>(out, c) ||
@@ -781,6 +782,20 @@ void Smt2Printer::toStream(std::ostream& out, const CommandStatus* s) const thro
 }/* Smt2Printer::toStream(CommandStatus*) */
 
 
+void Smt2Printer::toStream(std::ostream& out, const UnsatCore& core, const std::map<Expr, std::string>& names) const throw() {
+  out << "(" << std::endl;
+  for(UnsatCore::const_iterator i = core.begin(); i != core.end(); ++i) {
+    map<Expr, string>::const_iterator j = names.find(*i);
+    if(j == names.end()) {
+      out << *i << endl;
+    } else {
+      out << (*j).second << endl;
+    }
+  }
+  out << ")" << endl;
+}/* Smt2Printer::toStream(UnsatCore, map<Expr, string>) */
+
+
 void Smt2Printer::toStream(std::ostream& out, const Model& m) const throw() {
   out << "(model" << endl;
   this->Printer::toStream(out, m);
@@ -925,6 +940,10 @@ static void toStream(std::ostream& out, const QueryCommand* c) throw() {
   }
 }
 
+static void toStream(std::ostream& out, const ResetCommand* c) throw() {
+  out << "(reset)";
+}
+
 static void toStream(std::ostream& out, const QuitCommand* c) throw() {
   out << "(exit)";
 }
@@ -1042,6 +1061,10 @@ static void toStream(std::ostream& out, const GetProofCommand* c) throw() {
   out << "(get-proof)";
 }
 
+static void toStream(std::ostream& out, const GetUnsatCoreCommand* c) throw() {
+  out << "(get-unsat-core)";
+}
+
 static void toStream(std::ostream& out, const SetBenchmarkStatusCommand* c) throw() {
   out << "(set-info :status " << c->getStatus() << ")";
 }
index e86b3cb2b53034071037914a504b0a97e6d6b5a3..dbbc67fc24f0acb86d1afb821d9309822c64ae92 100644 (file)
@@ -37,7 +37,6 @@ class Smt2Printer : public CVC4::Printer {
 
   void toStream(std::ostream& out, TNode n, int toDepth, bool types) const throw();
   void toStream(std::ostream& out, const Model& m, const Command* c) const throw();
-  void toStream(std::ostream& out, const Model& m) const throw();
 public:
   Smt2Printer(Variant variant = no_variant) : d_variant(variant) { }
   using CVC4::Printer::toStream;
@@ -46,6 +45,8 @@ public:
   void toStream(std::ostream& out, const CommandStatus* s) const throw();
   void toStream(std::ostream& out, const Result& r) const throw();
   void toStream(std::ostream& out, const SExpr& sexpr) const throw();
+  void toStream(std::ostream& out, const Model& m) const throw();
+  void toStream(std::ostream& out, const UnsatCore& core, const std::map<Expr, std::string>& names) const throw();
 };/* class Smt2Printer */
 
 }/* CVC4::printer::smt2 namespace */
index 3dfb61428cd1fb797d099ff81cbb9e3670ae715f..22a40ff69bbe122b9638b5de0aeee73cde80ee71 100644 (file)
@@ -30,6 +30,8 @@ CnfProof::CnfProof(CnfStream* stream)
   : d_cnfStream(stream)
 {}
 
+CnfProof::~CnfProof() {
+}
 
 Expr CnfProof::getAtom(prop::SatVariable var) {
   prop::SatLiteral lit (var);
@@ -38,34 +40,33 @@ Expr CnfProof::getAtom(prop::SatVariable var) {
   return atom;
 }
 
-CnfProof::~CnfProof() {
-}
-
-LFSCCnfProof::iterator LFSCCnfProof::begin_atom_mapping() {
-  return iterator(*this, ProofManager::currentPM()->begin_vars());
+prop::SatLiteral CnfProof::getLiteral(TNode atom) {
+  return d_cnfStream->getLiteral(atom);
 }
 
-LFSCCnfProof::iterator LFSCCnfProof::end_atom_mapping() {
-  return iterator(*this, ProofManager::currentPM()->end_vars());
+Expr CnfProof::getAssertion(uint64_t id) {
+  return d_cnfStream->getAssertion(id).toExpr();
 }
 
-void LFSCCnfProof::printAtomMapping(std::ostream& os, std::ostream& paren) {
-  ProofManager::var_iterator it = ProofManager::currentPM()->begin_vars();
-  ProofManager::var_iterator end = ProofManager::currentPM()->end_vars();
-
-  for (;it != end;  ++it) {
-    os << "(decl_atom ";
-
-    if (ProofManager::currentPM()->getLogic().compare("QF_UF") == 0) {
-      Expr atom = getAtom(*it);
-      LFSCTheoryProof::printTerm(atom, os);
-    } else {
-      // print fake atoms for all other logics
-      os << "true ";
+void LFSCCnfProof::printAtomMapping(const prop::SatClause* clause, std::ostream& os, std::ostream& paren) {
+  for (unsigned i = 0; i < clause->size(); ++i) {
+    prop::SatLiteral lit = clause->operator[](i);
+    if(d_atomsDeclared.find(lit.getSatVariable()) == d_atomsDeclared.end()) {
+      d_atomsDeclared.insert(lit.getSatVariable());
+      os << "(decl_atom ";
+      if (ProofManager::currentPM()->getLogic().compare("QF_UF") == 0 ||
+          ProofManager::currentPM()->getLogic().compare("QF_AX") == 0 ||
+          ProofManager::currentPM()->getLogic().compare("QF_SAT") == 0) {
+        Expr atom = getAtom(lit.getSatVariable());
+        LFSCTheoryProof::printTerm(atom, os);
+      } else {
+        // print fake atoms for all other logics (for now)
+        os << "true ";
+      }
+
+      os << " (\\ " << ProofManager::getVarName(lit.getSatVariable()) << " (\\ " << ProofManager::getAtomName(lit.getSatVariable()) << "\n";
+      paren << ")))";
     }
-
-    os << " (\\ " << ProofManager::getVarName(*it) << " (\\ " << ProofManager::getAtomName(*it) << "\n";
-    paren << ")))";
   }
 }
 
@@ -75,36 +76,93 @@ void LFSCCnfProof::printClauses(std::ostream& os, std::ostream& paren) {
 }
 
 void LFSCCnfProof::printInputClauses(std::ostream& os, std::ostream& paren) {
-  os << " ;; Input Clauses \n";
+  os << " ;; Clauses\n";
   ProofManager::clause_iterator it = ProofManager::currentPM()->begin_input_clauses();
   ProofManager::clause_iterator end = ProofManager::currentPM()->end_input_clauses();
 
   for (; it != end; ++it) {
     ClauseId id = it->first;
     const prop::SatClause* clause = it->second;
+    printAtomMapping(clause, os, paren);
     os << "(satlem _ _ ";
     std::ostringstream clause_paren;
     printClause(*clause, os, clause_paren);
-    os << " (clausify_false trust)" << clause_paren.str();
-    os << "( \\ " << ProofManager::getInputClauseName(id) << "\n";
+    os << "(clausify_false trust)" << clause_paren.str()
+       << " (\\ " << ProofManager::getInputClauseName(id) << "\n";
     paren << "))";
   }
 }
 
-
 void LFSCCnfProof::printTheoryLemmas(std::ostream& os, std::ostream& paren) {
-  os << " ;; Theory Lemmas \n";
-  ProofManager::clause_iterator it = ProofManager::currentPM()->begin_lemmas();
-  ProofManager::clause_iterator end = ProofManager::currentPM()->end_lemmas();
+  os << " ;; Theory Lemmas\n";
+  ProofManager::ordered_clause_iterator it = ProofManager::currentPM()->begin_lemmas();
+  ProofManager::ordered_clause_iterator end = ProofManager::currentPM()->end_lemmas();
+
+  for(size_t n = 0; it != end; ++it, ++n) {
+    if(n % 100 == 0) {
+      Chat() << "proving theory conflicts...(" << n << "/" << ProofManager::currentPM()->num_lemmas() << ")" << std::endl;
+    }
 
-  for (; it != end; ++it) {
     ClauseId id = it->first;
     const prop::SatClause* clause = it->second;
+    NodeBuilder<> c(kind::AND);
+    for(unsigned i = 0; i < clause->size(); ++i) {
+      prop::SatLiteral lit = (*clause)[i];
+      prop::SatVariable var = lit.getSatVariable();
+      if(lit.isNegated()) {
+        c << Node::fromExpr(getAtom(var));
+      } else {
+        c << Node::fromExpr(getAtom(var)).notNode();
+      }
+    }
+    Node cl = c;
+    if(ProofManager::getSatProof()->d_lemmaClauses.find(id) != ProofManager::getSatProof()->d_lemmaClauses.end()) {
+      uint64_t proof_id = ProofManager::getSatProof()->d_lemmaClauses[id];
+      TNode orig = d_cnfStream->getAssertion(proof_id & 0xffffffff);
+      if(((proof_id >> 32) & 0xffffffff) == RULE_ARRAYS_EXT) {
+        Debug("cores") << "; extensional lemma!" << std::endl;
+        Assert(cl.getKind() == kind::AND && cl.getNumChildren() == 2 && cl[0].getKind() == kind::EQUAL && cl[0][0].getKind() == kind::SELECT);
+        TNode myk = cl[0][0][1];
+        Debug("cores") << "; so my skolemized k is " << myk << std::endl;
+        os << "(ext _ _ " << orig[0][0] << " " << orig[0][1] << " (\\ " << myk << " (\\ " << ProofManager::getLemmaName(id) << "\n";
+        paren << ")))";
+      }
+    }
+    printAtomMapping(clause, os, paren);
     os << "(satlem _ _ ";
     std::ostringstream clause_paren;
     printClause(*clause, os, clause_paren);
-    os << " (clausify_false trust)" << clause_paren.str();
-    os << "( \\ " << ProofManager::getLemmaClauseName(id) <<"\n";
+
+    Debug("cores") << "\n;id is " << id << std::endl;
+    if(ProofManager::getSatProof()->d_lemmaClauses.find(id) != ProofManager::getSatProof()->d_lemmaClauses.end()) {
+      uint64_t proof_id = ProofManager::getSatProof()->d_lemmaClauses[id];
+      Debug("cores") << ";getting id " << int32_t(proof_id & 0xffffffff) << std::endl;
+      Assert(int32_t(proof_id & 0xffffffff) != -1);
+      TNode orig = d_cnfStream->getAssertion(proof_id & 0xffffffff);
+      Debug("cores") << "; ID is " << id << " and that's a lemma with " << ((proof_id >> 32) & 0xffffffff) << " / " << (proof_id & 0xffffffff) << std::endl;
+      Debug("cores") << "; that means the lemma was " << orig << std::endl;
+      if(((proof_id >> 32) & 0xffffffff) == RULE_ARRAYS_EXT) {
+        Debug("cores") << "; extensional" << std::endl;
+        os << "(clausify_false trust)\n";
+      } else if(proof_id == 0) {
+        // theory propagation caused conflict
+        //ProofManager::currentPM()->printProof(os, cl);
+        os << "(clausify_false trust)\n";
+      } else if(((proof_id >> 32) & 0xffffffff) == RULE_CONFLICT) {
+        os << "\n;; need to generate a (conflict) proof of " << cl << "\n";
+        //ProofManager::currentPM()->printProof(os, cl);
+        os << "(clausify_false trust)\n";
+      } else {
+        os << "\n;; need to generate a (lemma) proof of " << cl;
+        os << "\n;; DON'T KNOW HOW !!\n";
+        os << "(clausify_false trust)\n";
+      }
+    } else {
+      os << "\n;; need to generate a (conflict) proof of " << cl << "\n";
+      ProofManager::currentPM()->printProof(os, cl);
+    }
+    os << clause_paren.str()
+       << " (\\ " << ProofManager::getLemmaClauseName(id) << "\n";
     paren << "))";
   }
 }
@@ -114,10 +172,10 @@ void LFSCCnfProof::printClause(const prop::SatClause& clause, std::ostream& os,
     prop::SatLiteral lit = clause[i];
     prop::SatVariable var = lit.getSatVariable();
     if (lit.isNegated()) {
-      os << "(ast _ _ _ " << ProofManager::getAtomName(var) <<" (\\ " << ProofManager::getLitName(lit) << " ";
+      os << "(ast _ _ _ " << ProofManager::getAtomName(var) << " (\\ " << ProofManager::getLitName(lit) << " ";
       paren << "))";
     } else {
-      os << "(asf _ _ _ " << ProofManager::getAtomName(var) <<" (\\ " << ProofManager::getLitName(lit) << " ";
+      os << "(asf _ _ _ " << ProofManager::getAtomName(var) << " (\\ " << ProofManager::getLitName(lit) << " ";
       paren << "))";
     }
   }
index b2c35c4f7a5a3b63061d600dc170a751fb92ff9c..459815e606b9dac2853cd90d393e200e26dec4e4 100644 (file)
 namespace CVC4 {
 namespace prop {
   class CnfStream;
-}
+}/* CVC4::prop namespace */
 
 class CnfProof;
 
-class AtomIterator {
-  CnfProof& d_cnf;
-  ProofManager::var_iterator d_it;
-
-public:
-  AtomIterator(CnfProof& cnf, const ProofManager::var_iterator& it)
-    : d_cnf(cnf), d_it(it)
-  {}
-  inline Expr operator*();
-  AtomIterator& operator++() { ++d_it; return *this; }
-  AtomIterator operator++(int) { AtomIterator x = *this; ++d_it; return x; }
-  bool operator==(const AtomIterator& it) const { return &d_cnf == &it.d_cnf && d_it == it.d_it; }
-  bool operator!=(const AtomIterator& it) const { return !(*this == it); }
-};/* class AtomIterator */
-
 class CnfProof {
 protected:
   CVC4::prop::CnfStream* d_cnfStream;
-  Expr getAtom(prop::SatVariable var);
-  friend class AtomIterator;
+  VarSet d_atomsDeclared;
 public:
   CnfProof(CVC4::prop::CnfStream* cnfStream);
 
-  typedef AtomIterator iterator;
-  virtual iterator begin_atom_mapping() = 0;
-  virtual iterator end_atom_mapping() = 0;
+  Expr getAtom(prop::SatVariable var);
+  Expr getAssertion(uint64_t id);
+  prop::SatLiteral getLiteral(TNode atom);
 
-  virtual void printAtomMapping(std::ostream& os, std::ostream& paren) = 0;
   virtual void printClauses(std::ostream& os, std::ostream& paren) = 0;
   virtual ~CnfProof();
-};
+};/* class CnfProof */
 
 class LFSCCnfProof : public CnfProof {
   void printInputClauses(std::ostream& os, std::ostream& paren);
   void printTheoryLemmas(std::ostream& os, std::ostream& paren);
   void printClause(const prop::SatClause& clause, std::ostream& os, std::ostream& paren);
+  virtual void printAtomMapping(const prop::SatClause* clause, std::ostream& os, std::ostream& paren);
 
 public:
   LFSCCnfProof(CVC4::prop::CnfStream* cnfStream)
     : CnfProof(cnfStream)
   {}
 
-  virtual iterator begin_atom_mapping();
-  virtual iterator end_atom_mapping();
-
-  virtual void printAtomMapping(std::ostream& os, std::ostream& paren);
   virtual void printClauses(std::ostream& os, std::ostream& paren);
-};
-
-inline Expr AtomIterator::operator*() {
-  return d_cnf.getAtom(*d_it);
-}
+};/* class LFSCCnfProof */
 
 } /* CVC4 namespace */
 
index 174913755a5db929373735a9bd2c3ec4a2291fc2..440279dbcb1d5f231abd4b82eed32e681df8d68f 100644 (file)
@@ -22,9 +22,9 @@
 #include "smt/options.h"
 
 #ifdef CVC4_PROOF
-#  define PROOF(x) if(options::proof()) { x; }
-#  define NULLPROOF(x) (options::proof()) ? x : NULL
-#  define PROOF_ON() options::proof()
+#  define PROOF(x) if(options::proof() || options::unsatCores()) { x; }
+#  define NULLPROOF(x) (options::proof() || options::unsatCores()) ? x : NULL
+#  define PROOF_ON() (options::proof() || options::unsatCores())
 #else /* CVC4_PROOF */
 #  define PROOF(x)
 #  define NULLPROOF(x) NULL
index 680e57d39725e60b3be491b74b054299b551f6e6..87eded8e6c1ae1d6439be8cdca6e9e6a7a88867b 100644 (file)
 #include "util/cvc4_assert.h"
 #include "smt/smt_engine.h"
 #include "smt/smt_engine_scope.h"
+#include "theory/output_channel.h"
+#include "theory/valuation.h"
+#include "util/node_visitor.h"
+#include "theory/term_registration_visitor.h"
+#include "theory/uf/theory_uf.h"
+#include "theory/uf/equality_engine.h"
+#include "theory/arrays/theory_arrays.h"
+#include "context/context.h"
+#include "util/hash.h"
 
 namespace CVC4 {
 
@@ -37,7 +46,8 @@ ProofManager::ProofManager(ProofFormat format):
   d_cnfProof(NULL),
   d_theoryProof(NULL),
   d_fullProof(NULL),
-  d_format(format)
+  d_format(format),
+  d_deps()
 {
 }
 
@@ -53,7 +63,7 @@ ProofManager::~ProofManager() {
     delete it->second;
   }
 
-  for(IdToClause::iterator it = d_theoryLemmas.begin();
+  for(OrderedIdToClause::iterator it = d_theoryLemmas.begin();
       it != d_theoryLemmas.end();
       ++it) {
     delete it->second;
@@ -91,11 +101,10 @@ CnfProof* ProofManager::getCnfProof() {
 }
 
 TheoryProof* ProofManager::getTheoryProof() {
-  Assert (currentPM()->d_theoryProof);
+  //Assert (currentPM()->d_theoryProof);
   return currentPM()->d_theoryProof;
 }
 
-
 void ProofManager::initSatProof(Minisat::Solver* solver) {
   Assert (currentPM()->d_satProof == NULL);
   Assert(currentPM()->d_format == LFSC);
@@ -114,35 +123,101 @@ void ProofManager::initTheoryProof() {
   currentPM()->d_theoryProof = new LFSCTheoryProof();
 }
 
-
-std::string ProofManager::getInputClauseName(ClauseId id) {return append("pb", id); }
-std::string ProofManager::getLemmaClauseName(ClauseId id) { return append("lem", id); }
+std::string ProofManager::getInputClauseName(ClauseId id) { return append("pb", id); }
+std::string ProofManager::getLemmaName(ClauseId id) { return append("lem", id); }
+std::string ProofManager::getLemmaClauseName(ClauseId id) { return append("lemc", id); }
 std::string ProofManager::getLearntClauseName(ClauseId id) { return append("cl", id); }
-std::string ProofManager::getVarName(prop::SatVariable var) { return append("v", var); }
-std::string ProofManager::getAtomName(prop::SatVariable var) { return append("a", var); }
-std::string ProofManager::getLitName(prop::SatLiteral lit) {return append("l", lit.toInt()); }
+std::string ProofManager::getVarName(prop::SatVariable var) { return append("var", var); }
+std::string ProofManager::getAtomName(prop::SatVariable var) { return append("atom", var); }
+std::string ProofManager::getLitName(prop::SatLiteral lit) { return append("lit", lit.toInt()); }
+
+std::string ProofManager::getAtomName(TNode atom) {
+  prop::SatLiteral lit = currentPM()->d_cnfProof->getLiteral(atom);
+  Assert(!lit.isNegated());
+  return getAtomName(lit.getSatVariable());
+}
+std::string ProofManager::getLitName(TNode lit) {
+  return getLitName(currentPM()->d_cnfProof->getLiteral(lit));
+}
+
+void ProofManager::traceDeps(TNode n) {
+  Debug("cores") << "trace deps " << n << std::endl;
+  if(d_inputCoreFormulas.find(n.toExpr()) != d_inputCoreFormulas.end()) {
+    // originating formula was in core set
+    Debug("cores") << " -- IN INPUT CORE LIST!" << std::endl;
+    d_outputCoreFormulas.insert(n.toExpr());
+  } else {
+    Debug("cores") << " -- NOT IN INPUT CORE LIST!" << std::endl;
+    if(d_deps.find(n) == d_deps.end()) {
+      InternalError("Cannot trace dependence information back to input assertion:\n`%s'", n.toString().c_str());
+    }
+    Assert(d_deps.find(n) != d_deps.end());
+    std::vector<Node> deps = (*d_deps.find(n)).second;
+    for(std::vector<Node>::const_iterator i = deps.begin(); i != deps.end(); ++i) {
+      Debug("cores") << " + tracing deps: " << n << " -deps-on- " << *i << std::endl;
+      traceDeps(*i);
+    }
+  }
+}
 
 void ProofManager::addClause(ClauseId id, const prop::SatClause* clause, ClauseKind kind) {
-  for (unsigned i = 0; i < clause->size(); ++i) {
+  /*for (unsigned i = 0; i < clause->size(); ++i) {
     prop::SatLiteral lit = clause->operator[](i);
     d_propVars.insert(lit.getSatVariable());
-  }
+  }*/
   if (kind == INPUT) {
     d_inputClauses.insert(std::make_pair(id, clause));
-    return;
+    Assert(d_satProof->d_inputClauses.find(id) != d_satProof->d_inputClauses.end());
+    Debug("cores") << "core id is " << d_satProof->d_inputClauses[id] << std::endl;
+    if(d_satProof->d_inputClauses[id] == uint64_t(-1)) {
+      Debug("cores") << " + constant unit (true or false)" << std::endl;
+    } else if(options::unsatCores()) {
+      Expr e = d_cnfProof->getAssertion(d_satProof->d_inputClauses[id] & 0xffffffff);
+      Debug("cores") << "core input assertion from CnfStream is " << e << std::endl;
+      Debug("cores") << "with proof rule " << ((d_satProof->d_inputClauses[id] & 0xffffffff00000000llu) >> 32) << std::endl;
+      // Invalid proof rules are currently used for parts of CVC4 that don't
+      // support proofs (these are e.g. unproven theory lemmas) or don't need
+      // proofs (e.g. split lemmas).  We can ignore these safely when
+      // constructing unsat cores.
+      if(((d_satProof->d_inputClauses[id] & 0xffffffff00000000llu) >> 32) != RULE_INVALID) {
+        // trace dependences back to actual assertions
+        traceDeps(Node::fromExpr(e));
+      }
+    }
+  } else {
+    Assert(kind == THEORY_LEMMA);
+    d_theoryLemmas.insert(std::make_pair(id, clause));
   }
-  Assert (kind == THEORY_LEMMA);
-  d_theoryLemmas.insert(std::make_pair(id, clause));
 }
 
-void ProofManager::addAssertion(Expr formula) {
+void ProofManager::addAssertion(Expr formula, bool inUnsatCore) {
+  Debug("cores") << "assert: " << formula << std::endl;
   d_inputFormulas.insert(formula);
+  d_deps[Node::fromExpr(formula)]; // empty vector of deps
+  if(inUnsatCore || options::dumpUnsatCores()) {
+    Debug("cores") << "adding to input core forms: " << formula << std::endl;
+    d_inputCoreFormulas.insert(formula);
+  }
 }
 
-void ProofManager::setLogic(const std::string& logic_string) {
-  d_logic = logic_string;
+void ProofManager::addDependence(TNode n, TNode dep) {
+  if(dep != n) {
+    Debug("cores") << "dep: " << n << " : " << dep << std::endl;
+    if(d_deps.find(dep) == d_deps.end()) {
+      Debug("cores") << "WHERE DID " << dep << " come from ??" << std::endl;
+    }
+    //Assert(d_deps.find(dep) != d_deps.end());
+    d_deps[n].push_back(dep);
+  }
+}
+
+void ProofManager::setLogic(const LogicInfo& logic) {
+  d_logic = logic;
 }
 
+void ProofManager::printProof(std::ostream& os, TNode n) {
+  // no proofs here yet
+}
 
 LFSCProof::LFSCProof(SmtEngine* smtEngine, LFSCSatProof* sat, LFSCCnfProof* cnf, LFSCTheoryProof* theory)
   : d_satProof(sat)
@@ -157,17 +232,18 @@ void LFSCProof::toStream(std::ostream& out) {
   smt::SmtScope scope(d_smtEngine);
   std::ostringstream paren;
   out << "(check\n";
+  out << " ;; Declarations\n";
   if (d_theoryProof == NULL) {
     d_theoryProof = new LFSCTheoryProof();
   }
-  for(LFSCCnfProof::iterator i = d_cnfProof->begin_atom_mapping();
+  /*for(LFSCCnfProof::iterator i = d_cnfProof->begin_atom_mapping();
       i != d_cnfProof->end_atom_mapping();
       ++i) {
     d_theoryProof->addDeclaration(*i);
-  }
+  }*/
   d_theoryProof->printAssertions(out, paren);
+  out << " ;; Proof of empty clause follows\n";
   out << "(: (holds cln)\n";
-  d_cnfProof->printAtomMapping(out, paren);
   d_cnfProof->printClauses(out, paren);
   d_satProof->printResolutions(out, paren);
   paren <<")))\n;;";
@@ -175,5 +251,4 @@ void LFSCProof::toStream(std::ostream& out) {
   out << "\n";
 }
 
-
 } /* CVC4  namespace */
index f428de36d9b060b4cbf1c730f311c29a091f13c0..d60a3f6e3c3946d3e08c0a29c63f53536ceeebf2 100644 (file)
 #define __CVC4__PROOF_MANAGER_H
 
 #include <iostream>
+#include <map>
 #include "proof/proof.h"
 #include "util/proof.h"
-
+#include "expr/node.h"
+#include "theory/logic_info.h"
+#include "theory/substitutions.h"
 
 // forward declarations
 namespace Minisat {
@@ -63,6 +66,7 @@ enum ProofFormat {
 std::string append(const std::string& str, uint64_t num);
 
 typedef __gnu_cxx::hash_map < ClauseId, const prop::SatClause* > IdToClause;
+typedef std::map < ClauseId, const prop::SatClause* > OrderedIdToClause;
 typedef __gnu_cxx::hash_set<prop::SatVariable > VarSet;
 typedef __gnu_cxx::hash_set<Expr, ExprHashFunction > ExprSet;
 
@@ -74,6 +78,18 @@ enum ClauseKind {
   LEARNT
 };/* enum ClauseKind */
 
+enum ProofRule {
+  RULE_GIVEN,       /* input assertion */
+  RULE_DERIVED,     /* a "macro" rule */
+  RULE_RECONSTRUCT, /* prove equivalence using another method */
+  RULE_TRUST,       /* trust without evidence (escape hatch until proofs are fully supported) */
+  RULE_INVALID,     /* assert-fail if this is ever needed in proof; use e.g. for split lemmas */
+  RULE_CONFLICT,    /* re-construct as a conflict */
+
+  RULE_ARRAYS_EXT,  /* arrays, extensional */
+  RULE_ARRAYS_ROW,  /* arrays, read-over-write */
+};/* enum ProofRules */
+
 class ProofManager {
   SatProof*    d_satProof;
   CnfProof*    d_cnfProof;
@@ -81,15 +97,25 @@ class ProofManager {
 
   // information that will need to be shared across proofs
   IdToClause d_inputClauses;
-  IdToClause d_theoryLemmas;
+  OrderedIdToClause d_theoryLemmas;
+  IdToClause d_theoryPropagations;
   ExprSet    d_inputFormulas;
-  VarSet     d_propVars;
+  ExprSet    d_inputCoreFormulas;
+  ExprSet    d_outputCoreFormulas;
+  //VarSet     d_propVars;
+
+  int d_nextId;
 
   Proof* d_fullProof;
   ProofFormat d_format; // used for now only in debug builds
 
+  __gnu_cxx::hash_map< Node, std::vector<Node>, NodeHashFunction > d_deps;
+
+  // trace dependences back to unsat core
+  void traceDeps(TNode n);
+
 protected:
-  std::string d_logic;
+  LogicInfo d_logic;
 
 public:
   ProofManager(ProofFormat format = LFSC);
@@ -109,35 +135,50 @@ public:
 
   // iterators over data shared by proofs
   typedef IdToClause::const_iterator clause_iterator;
+  typedef OrderedIdToClause::const_iterator ordered_clause_iterator;
   typedef ExprSet::const_iterator assertions_iterator;
   typedef VarSet::const_iterator var_iterator;
 
   clause_iterator begin_input_clauses() const { return d_inputClauses.begin(); }
   clause_iterator end_input_clauses() const { return d_inputClauses.end(); }
+  size_t num_input_clauses() const { return d_inputClauses.size(); }
 
-  clause_iterator begin_lemmas() const { return d_theoryLemmas.begin(); }
-  clause_iterator end_lemmas() const { return d_theoryLemmas.end(); }
+  ordered_clause_iterator begin_lemmas() const { return d_theoryLemmas.begin(); }
+  ordered_clause_iterator end_lemmas() const { return d_theoryLemmas.end(); }
+  size_t num_lemmas() const { return d_theoryLemmas.size(); }
 
   assertions_iterator begin_assertions() const { return d_inputFormulas.begin(); }
   assertions_iterator end_assertions() const { return d_inputFormulas.end(); }
+  size_t num_assertions() const { return d_inputFormulas.size(); }
 
-  var_iterator begin_vars() const { return d_propVars.begin(); }
-  var_iterator end_vars() const { return d_propVars.end(); }
+  void printProof(std::ostream& os, TNode n);
 
-  void addAssertion(Expr formula);
+  void addAssertion(Expr formula, bool inUnsatCore);
   void addClause(ClauseId id, const prop::SatClause* clause, ClauseKind kind);
+  // note that n depends on dep (for cores)
+  void addDependence(TNode n, TNode dep);
+
+  assertions_iterator begin_unsat_core() const { return d_outputCoreFormulas.begin(); }
+  assertions_iterator end_unsat_core() const { return d_outputCoreFormulas.end(); }
+  size_t size_unsat_core() const { return d_outputCoreFormulas.size(); }
+
+  int nextId() { return d_nextId++; }
 
   // variable prefixes
   static std::string getInputClauseName(ClauseId id);
+  static std::string getLemmaName(ClauseId id);
   static std::string getLemmaClauseName(ClauseId id);
   static std::string getLearntClauseName(ClauseId id);
 
   static std::string getVarName(prop::SatVariable var);
   static std::string getAtomName(prop::SatVariable var);
+  static std::string getAtomName(TNode atom);
   static std::string getLitName(prop::SatLiteral lit);
+  static std::string getLitName(TNode lit);
+
+  void setLogic(const LogicInfo& logic);
+  const std::string getLogic() const { return d_logic.getLogicString(); }
 
-  void setLogic(const std::string& logic_string);
-  const std::string getLogic() const { return d_logic; }
 };/* class ProofManager */
 
 class LFSCProof : public Proof {
index 0ace84b4d93f0bdd7eb7a38993f9e5a5b8dfcaab..f7b9c4889deb6e0945089cd483410351e8eaaaa1 100644 (file)
@@ -57,9 +57,6 @@ void printDebug (Minisat::Clause& c) {
   Debug("proof:sat") << endl;
 }
 
-
-int SatProof::d_idCounter = 0;
-
 /**
  * Converts the clause associated to id to a set of literals
  *
@@ -274,7 +271,7 @@ ClauseId SatProof::getClauseId(::Minisat::Lit lit) {
 
 Minisat::CRef SatProof::getClauseRef(ClauseId id) {
   if (d_idClause.find(id) == d_idClause.end()) {
-    Debug("proof:sat") << "proof:getClauseRef cannot find clause "<<id<<" "
+    Debug("proof:sat") << "proof:getClauseRef cannot find clause " << id << " "
                        << ((d_deleted.find(id) != d_deleted.end()) ? "deleted" : "")
                        << (isUnit(id)? "Unit" : "") << endl;
   }
@@ -318,16 +315,14 @@ bool SatProof::isLemmaClause(ClauseId id) {
   return (d_lemmaClauses.find(id) != d_lemmaClauses.end());
 }
 
-
 void SatProof::print(ClauseId id) {
   if (d_deleted.find(id) != d_deleted.end()) {
-    Debug("proof:sat") << "del"<<id;
+    Debug("proof:sat") << "del" << id;
   } else if (isUnit(id)) {
     printLit(getUnit(id));
   } else if (id == d_emptyClauseId) {
-    Debug("proof:sat") << "empty "<< endl;
-  }
-  else {
+    Debug("proof:sat") << "empty " << endl;
+  } else {
     CRef ref = getClauseRef(id);
     printClause(getClause(ref));
   }
@@ -335,7 +330,7 @@ void SatProof::print(ClauseId id) {
 
 void SatProof::printRes(ClauseId id) {
   Assert(hasResolution(id));
-  Debug("proof:sat") << "id "<< id <<": ";
+  Debug("proof:sat") << "id " << id << ": ";
   printRes(d_resChains[id]);
 }
 
@@ -364,42 +359,44 @@ void SatProof::printRes(ResChain* res) {
 
 /// registration methods
 
-ClauseId SatProof::registerClause(::Minisat::CRef clause, ClauseKind kind) {
+ClauseId SatProof::registerClause(::Minisat::CRef clause, ClauseKind kind, uint64_t proof_id) {
+  Debug("cores") << "registerClause " << proof_id << std::endl;
   Assert(clause != CRef_Undef);
   ClauseIdMap::iterator it = d_clauseId.find(clause);
   if (it == d_clauseId.end()) {
-    ClauseId newId = d_idCounter++;
+    ClauseId newId = ProofManager::currentPM()->nextId();
     d_clauseId[clause] = newId;
     d_idClause[newId] = clause;
     if (kind == INPUT) {
       Assert(d_inputClauses.find(newId) == d_inputClauses.end());
-      d_inputClauses.insert(newId);
+      d_inputClauses[newId] = proof_id;
     }
     if (kind == THEORY_LEMMA) {
       Assert(d_lemmaClauses.find(newId) == d_lemmaClauses.end());
-      d_lemmaClauses.insert(newId);
+      d_lemmaClauses[newId] = proof_id;
     }
   }
-  Debug("proof:sat:detailed") <<"registerClause CRef:" << clause <<" id:" << d_clauseId[clause] << " " << kind << "\n";
+  Debug("proof:sat:detailed") << "registerClause CRef:" << clause << " id:" << d_clauseId[clause] << " " << kind << " " << int32_t((proof_id >> 32) & 0xffffffff) << "\n";
   return d_clauseId[clause];
 }
 
-ClauseId SatProof::registerUnitClause(::Minisat::Lit lit, ClauseKind kind) {
+ClauseId SatProof::registerUnitClause(::Minisat::Lit lit, ClauseKind kind, uint64_t proof_id) {
+  Debug("cores") << "registerUnitClause " << kind << " " << proof_id << std::endl;
   UnitIdMap::iterator it = d_unitId.find(toInt(lit));
   if (it == d_unitId.end()) {
-    ClauseId newId = d_idCounter++;
+    ClauseId newId = ProofManager::currentPM()->nextId();
     d_unitId[toInt(lit)] = newId;
     d_idUnit[newId] = lit;
     if (kind == INPUT) {
       Assert(d_inputClauses.find(newId) == d_inputClauses.end());
-      d_inputClauses.insert(newId);
+      d_inputClauses[newId] = proof_id;
     }
     if (kind == THEORY_LEMMA) {
       Assert(d_lemmaClauses.find(newId) == d_lemmaClauses.end());
-      d_lemmaClauses.insert(newId);
+      d_lemmaClauses[newId] = proof_id;
     }
   }
-  Debug("proof:sat:detailed") <<"registerUnitClause " << d_unitId[toInt(lit)] << " " << kind <<"\n";
+  Debug("proof:sat:detailed") << "registerUnitClause " << d_unitId[toInt(lit)] << " " << kind << "\n";
   return d_unitId[toInt(lit)];
 }
 
@@ -445,7 +442,7 @@ void SatProof::removeRedundantFromRes(ResChain* res, ClauseId id) {
     removedDfs(*it, removed, removeStack, inClause, seen);
   }
 
-  for (int i = removeStack.size()-1; i >= 0; --i) {
+  for (int i = removeStack.size() - 1; i >= 0; --i) {
     Lit lit = removeStack[i];
     CRef reason_ref = d_solver->reason(var(lit));
     ClauseId reason_id;
@@ -454,7 +451,7 @@ void SatProof::removeRedundantFromRes(ResChain* res, ClauseId id) {
       Assert(isUnit(~lit));
       reason_id = getUnitId(~lit);
     } else {
-      reason_id = registerClause(reason_ref);
+      reason_id = registerClause(reason_ref, LEARNT, uint64_t(-1));
     }
     res->addStep(lit, reason_id, !sign(lit));
   }
@@ -486,14 +483,14 @@ void SatProof::startResChain(::Minisat::CRef start) {
 }
 
 void SatProof::addResolutionStep(::Minisat::Lit lit, ::Minisat::CRef clause, bool sign) {
-  ClauseId id = registerClause(clause);
+  ClauseId id = registerClause(clause, LEARNT, uint64_t(-1));
   ResChain* res = d_resStack.back();
   res->addStep(lit, id, sign);
 }
 
 void SatProof::endResChain(CRef clause) {
   Assert(d_resStack.size() > 0);
-  ClauseId id = registerClause(clause);
+  ClauseId id = registerClause(clause, LEARNT, uint64_t(-1));
   ResChain* res = d_resStack.back();
   registerResolution(id, res);
   d_resStack.pop_back();
@@ -502,7 +499,7 @@ void SatProof::endResChain(CRef clause) {
 
 void SatProof::endResChain(::Minisat::Lit lit) {
   Assert(d_resStack.size() > 0);
-  ClauseId id = registerUnitClause(lit);
+  ClauseId id = registerUnitClause(lit, LEARNT, uint64_t(-1));
   ResChain* res = d_resStack.back();
   registerResolution(id, res);
   d_resStack.pop_back();
@@ -523,6 +520,7 @@ void SatProof::resolveOutUnit(::Minisat::Lit lit) {
 }
 
 void SatProof::storeUnitResolution(::Minisat::Lit lit) {
+  Debug("cores") << "STORE UNIT RESOLUTION" << std::endl;
   resolveUnit(lit);
 }
 
@@ -536,7 +534,7 @@ ClauseId SatProof::resolveUnit(::Minisat::Lit lit) {
   CRef reason_ref = d_solver->reason(var(lit));
   Assert(reason_ref != CRef_Undef);
 
-  ClauseId reason_id = registerClause(reason_ref);
+  ClauseId reason_id = registerClause(reason_ref, LEARNT, uint64_t(-1));
 
   ResChain* res = new ResChain(reason_id);
   // Here, the call to resolveUnit() can reallocate memory in the
@@ -551,7 +549,7 @@ ClauseId SatProof::resolveUnit(::Minisat::Lit lit) {
       res->addStep(l, res_id, !sign(l));
     }
   }
-  ClauseId unit_id = registerUnitClause(lit);
+  ClauseId unit_id = registerUnitClause(lit, LEARNT, uint64_t(-1));
   registerResolution(unit_id, res);
   return unit_id;
 }
@@ -561,11 +559,12 @@ void SatProof::toStream(std::ostream& out) {
   Unimplemented("native proof printing not supported yet");
 }
 
-void SatProof::storeUnitConflict(::Minisat::Lit conflict_lit, ClauseKind kind) {
+void SatProof::storeUnitConflict(::Minisat::Lit conflict_lit, ClauseKind kind, uint64_t proof_id) {
+  Debug("cores") << "STORE UNIT CONFLICT" << std::endl;
   Assert(!d_storedUnitConflict);
-  d_unitConflictId = registerUnitClause(conflict_lit, kind);
+  d_unitConflictId = registerUnitClause(conflict_lit, kind, proof_id);
   d_storedUnitConflict = true;
-  Debug("proof:sat:detailed") <<"storeUnitConflict " << d_unitConflictId << "\n";
+  Debug("proof:sat:detailed") << "storeUnitConflict " << d_unitConflictId << "\n";
 }
 
 void SatProof::finalizeProof(::Minisat::CRef conflict_ref) {
@@ -586,7 +585,7 @@ void SatProof::finalizeProof(::Minisat::CRef conflict_ref) {
     return;
   } else {
     Assert(!d_storedUnitConflict);
-    conflict_id = registerClause(conflict_ref); //FIXME
+    conflict_id = registerClause(conflict_ref, LEARNT, uint64_t(-1)); //FIXME
   }
 
   if(Debug.isOn("proof:sat")) {
@@ -652,11 +651,10 @@ std::string SatProof::clauseName(ClauseId id) {
   if (isInputClause(id)) {
     os << ProofManager::getInputClauseName(id);
     return os.str();
-  } else
-  if (isLemmaClause(id)) {
+  } else if (isLemmaClause(id)) {
     os << ProofManager::getLemmaClauseName(id);
     return os.str();
-  }else {
+  } else {
     os << ProofManager::getLearntClauseName(id);
     return os.str();
   }
@@ -728,10 +726,9 @@ void LFSCSatProof::printResolution(ClauseId id, std::ostream& out, std::ostream&
   ResChain* res = d_resChains[id];
   ResSteps& steps = res->getSteps();
 
-  for (int i = steps.size()-1; i >= 0; i--) {
+  for (int i = steps.size() - 1; i >= 0; --i) {
     out << "(";
     out << (steps[i].sign? "R" : "Q") << " _ _ ";
-
   }
 
   ClauseId start_id = res->getStart();
@@ -742,11 +739,13 @@ void LFSCSatProof::printResolution(ClauseId id, std::ostream& out, std::ostream&
   out << clauseName(start_id) << " ";
 
   for(unsigned i = 0; i < steps.size(); i++) {
-    out << clauseName(steps[i].id) << " "<<ProofManager::getVarName(MinisatSatSolver::toSatVariable(var(steps[i].lit))) <<")";
+    out << clauseName(steps[i].id) << " "
+        << ProofManager::getVarName(MinisatSatSolver::toSatVariable(var(steps[i].lit)))
+        << ") ";
   }
 
   if (id == d_emptyClauseId) {
-    out <<"(\\empty empty)";
+    out << "(\\empty empty)";
     return;
   }
 
@@ -763,6 +762,4 @@ void LFSCSatProof::printResolutions(std::ostream& out, std::ostream& paren) {
   printResolution(d_emptyClauseId, out, paren);
 }
 
-
 } /* CVC4 namespace */
-
index 7795dfa9c5b5718a42f1e8e95090ec07fe4a91e9..ef4e7a5aa8d9b1ca655381782c1c932d30a38ce1 100644 (file)
@@ -86,6 +86,7 @@ typedef std::hash_map < ClauseId, ::Minisat::Lit>   IdUnitMap;
 typedef std::hash_map < int, ClauseId>            UnitIdMap; //FIXME
 typedef std::hash_map < ClauseId, ResChain*>      IdResMap;
 typedef std::hash_set < ClauseId >                IdHashSet;
+typedef std::hash_map < ClauseId, uint64_t >      IdProofRuleMap;
 typedef std::vector   < ResChain* >               ResStack;
 typedef std::hash_map <ClauseId, prop::SatClause* >     IdToSatClause;
 typedef std::set < ClauseId >                     IdSet;
@@ -115,14 +116,15 @@ protected:
   UnitIdMap           d_unitId;
   IdHashSet           d_deleted;
   IdToSatClause       d_deletedTheoryLemmas;
-  IdHashSet           d_inputClauses;
-  IdHashSet           d_lemmaClauses;
+public:
+  IdProofRuleMap      d_inputClauses;
+  IdProofRuleMap      d_lemmaClauses;
+protected:
   // resolutions
   IdResMap            d_resChains;
   ResStack            d_resStack;
   bool                d_checkRes;
 
-  static ClauseId     d_idCounter;
   const ClauseId      d_emptyClauseId;
   const ClauseId      d_nullId;
   // proxy class to break circular dependencies
@@ -144,6 +146,7 @@ protected:
   void printRes(ResChain* res);
 
   bool isInputClause(ClauseId id);
+  bool isTheoryConflict(ClauseId id);
   bool isLemmaClause(ClauseId id);
   bool isUnit(ClauseId id);
   bool isUnit(::Minisat::Lit lit);
@@ -207,10 +210,10 @@ public:
   void finalizeProof(::Minisat::CRef conflict);
 
   /// clause registration methods
-  ClauseId registerClause(const ::Minisat::CRef clause, ClauseKind kind = LEARNT);
-  ClauseId registerUnitClause(const ::Minisat::Lit lit, ClauseKind kind = LEARNT);
+  ClauseId registerClause(const ::Minisat::CRef clause, ClauseKind kind, uint64_t proof_id);
+  ClauseId registerUnitClause(const ::Minisat::Lit lit, ClauseKind kind, uint64_t proof_id);
 
-  void storeUnitConflict(::Minisat::Lit lit, ClauseKind kind = LEARNT);
+  void storeUnitConflict(::Minisat::Lit lit, ClauseKind kind, uint64_t proof_id);
 
   /**
    * Marks the deleted clauses as deleted. Note we may still use them in the final
@@ -242,6 +245,7 @@ public:
 protected:
   IdSet              d_seenLearnt;
   IdHashSet          d_seenInput;
+  IdHashSet          d_seenTheoryConflicts;
   IdHashSet          d_seenLemmas;
 
   inline std::string varName(::Minisat::Lit lit);
index 7322cd0faa547f9827b61f5106d9194f3ca6bc95..71b8eb69de3e455189955aaec8b66d880a97461c 100644 (file)
@@ -5,7 +5,7 @@
  ** Major contributors:
  ** Minor contributors (to current version):
  ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)
+ ** Copyright (c) 2009-2014  The Analysis of Computer Systems Group (ACSys)
  ** Courant Institute of Mathematical Sciences
  ** New York University
  ** See the file COPYING in the top-level source directory for licensing
@@ -45,7 +45,7 @@ void BVMinisatSatSolver::setNotify(Notify* notify) {
   d_minisat->setNotify(d_minisatNotify);
 }
 
-void BVMinisatSatSolver::addClause(SatClause& clause, bool removable) {
+void BVMinisatSatSolver::addClause(SatClause& clause, bool removable, uint64_t proof_id) {
   Debug("sat::minisat") << "Add clause " << clause <<"\n";
   BVMinisat::vec<BVMinisat::Lit> minisat_clause;
   toMinisatClause(clause, minisat_clause);
@@ -97,6 +97,11 @@ void BVMinisatSatSolver::markUnremovable(SatLiteral lit){
   d_minisat->setFrozen(BVMinisat::var(toMinisatLit(lit)), true);
 }
 
+bool BVMinisatSatSolver::spendResource(){
+  // Do nothing for the BV solver.
+  return false;
+}
+
 void BVMinisatSatSolver::interrupt(){
   d_minisat->interrupt();
 }
index f9d0fbd6a50f748b235acaaedd3e9b6b27bde0d8..c7ee2e0b70838f11221d87cfd4691a82c05ed3a6 100644 (file)
@@ -5,7 +5,7 @@
  ** Major contributors:
  ** Minor contributors (to current version):
  ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)
+ ** Copyright (c) 2009-2014  The Analysis of Computer Systems Group (ACSys)
  ** Courant Institute of Mathematical Sciences
  ** New York University
  ** See the file COPYING in the top-level source directory for licensing
@@ -76,7 +76,7 @@ public:
 
   void setNotify(Notify* notify);
 
-  void addClause(SatClause& clause, bool removable);
+  void addClause(SatClause& clause, bool removable, uint64_t proof_id);
 
   SatValue propagate();
 
@@ -87,6 +87,8 @@ public:
 
   void markUnremovable(SatLiteral lit);
 
+  bool spendResource();
+
   void interrupt();
   
   SatValue solve();
index e0697735f327cac0efa9917e048146ff4d58a6c1..ad187aa46222d4edc3a1fa03fe648ac5c17b82c8 100644 (file)
@@ -44,7 +44,6 @@ using namespace CVC4::kind;
 namespace CVC4 {
 namespace prop {
 
-
 CnfStream::CnfStream(SatSolver *satSolver, Registrar* registrar, context::Context* context, bool fullLitToNodeMap) :
   d_satSolver(satSolver),
   d_booleanVariables(context),
@@ -52,6 +51,7 @@ CnfStream::CnfStream(SatSolver *satSolver, Registrar* registrar, context::Contex
   d_literalToNodeMap(context),
   d_fullLitToNodeMap(fullLitToNodeMap),
   d_registrar(registrar),
+  d_assertionTable(context),
   d_removable(false) {
 }
 
@@ -74,7 +74,7 @@ void CnfStream::assertClause(TNode node, SatClause& c) {
       Dump("clauses") << AssertCommand(Expr(n.toExpr()));
     }
   }
-  d_satSolver->addClause(c, d_removable);
+  d_satSolver->addClause(c, d_removable, d_proofId);
 }
 
 void CnfStream::assertClause(TNode node, SatLiteral a) {
@@ -104,9 +104,9 @@ bool CnfStream::hasLiteral(TNode n) const {
 }
 
 void TseitinCnfStream::ensureLiteral(TNode n) {
-
-  // These are not removable
+  // These are not removable and have no proof ID
   d_removable = false;
+  d_proofId = uint64_t(-1);
 
   Debug("cnf") << "ensureLiteral(" << n << ")" << endl;
   if(hasLiteral(n)) {
@@ -188,9 +188,12 @@ SatLiteral CnfStream::newLiteral(TNode node, bool isTheoryAtom, bool preRegister
 
   // If a theory literal, we pre-register it
   if (preRegister) {
-    bool backup = d_removable;
+    // In case we are re-entered due to lemmas, save our state
+    bool backupRemovable = d_removable;
+    uint64_t backupProofId= d_proofId;
     d_registrar->preRegister(node);
-    d_removable = backup;
+    d_removable = backupRemovable;
+    d_proofId = backupProofId;
   }
 
   // Here, you can have it
@@ -642,9 +645,20 @@ void TseitinCnfStream::convertAndAssertIte(TNode node, bool negated) {
 // At the top level we must ensure that all clauses that are asserted are
 // not unit, except for the direct assertions. This allows us to remove the
 // clauses later when they are not needed anymore (lemmas for example).
-void TseitinCnfStream::convertAndAssert(TNode node, bool removable, bool negated) {
+void TseitinCnfStream::convertAndAssert(TNode node, bool removable, bool negated, ProofRule proof_id, TNode from) {
   Debug("cnf") << "convertAndAssert(" << node << ", removable = " << (removable ? "true" : "false") << ", negated = " << (negated ? "true" : "false") << ")" << endl;
   d_removable = removable;
+  if(options::proof() || options::unsatCores()) {
+    // Encode the assertion ID in the proof_id to store with generated clauses.
+    uint64_t assertionTableIndex = d_assertionTable.size();
+    Assert((uint64_t(proof_id) & 0xffffffff00000000llu) == 0 && (assertionTableIndex & 0xffffffff00000000llu) == 0, "proof_id/table_index collision");
+    d_proofId = assertionTableIndex | (uint64_t(proof_id) << 32);
+    d_assertionTable.push_back(from.isNull() ? node : from);
+    Debug("cores") << "cnf ix " << assertionTableIndex << " asst " << node << "  proof_id " << proof_id << " from " << from << endl;
+  } else {
+    // We aren't producing proofs or unsat cores; use an invalid proof id.
+    d_proofId = uint64_t(-1);
+  }
   convertAndAssert(node, negated);
 }
 
index 266362ef56aafb23e26a9ec44bb5e663ee4a8f5a..b76051279fd3625bd1ea86cf1cb5bb85b207d324 100644 (file)
@@ -28,6 +28,7 @@
 #include "expr/node.h"
 #include "prop/theory_proxy.h"
 #include "prop/registrar.h"
+#include "proof/proof_manager.h"
 #include "context/cdlist.h"
 #include "context/cdinsert_hashmap.h"
 
@@ -36,7 +37,6 @@
 namespace CVC4 {
 namespace prop {
 
-
 class PropEngine;
 
 /**
@@ -77,6 +77,9 @@ protected:
   /** The "registrar" for pre-registration of terms */
   Registrar* d_registrar;
 
+  /** A table of assertions, used for regenerating proofs. */
+  context::CDList<Node> d_assertionTable;
+
   /**
    * How many literals were already mapped at the top-level when we
    * tried to convertAndAssert() something.  This
@@ -103,11 +106,19 @@ protected:
     return node;
   }
 
+  /**
+   * A reference into the assertion table, used to map clauses back to
+   * their "original" input assertion/lemma.  This variable is manipulated
+   * by the top-level convertAndAssert().  This is needed in proofs-enabled
+   * runs, to justify where the SAT solver's clauses came from.
+   */
+  uint64_t d_proofId;
+
   /**
    * Are we asserting a removable clause (true) or a permanent clause (false).
    * This is set at the beginning of convertAndAssert so that it doesn't
-   * need to be passed on over the stack. Only pure clauses  can be asserted as
-   * removable.
+   * need to be passed on over the stack.  Only pure clauses can be asserted
+   * as removable.
    */
   bool d_removable;
 
@@ -190,7 +201,7 @@ public:
    * @param removable whether the sat solver can choose to remove the clauses
    * @param negated whether we are asserting the node negated
    */
-  virtual void convertAndAssert(TNode node, bool removable, bool negated) = 0;
+  virtual void convertAndAssert(TNode node, bool removable, bool negated, ProofRule proof_id, TNode from = TNode::null()) = 0;
 
   /**
    * Get the node that is represented by the given SatLiteral.
@@ -222,6 +233,13 @@ public:
    */
   SatLiteral getLiteral(TNode node);
 
+  /**
+   * Get the assertion with a given ID.  (Used for reconstructing proofs.)
+   */
+  TNode getAssertion(uint64_t id) {
+    return d_assertionTable[id];
+  }
+
   /**
    * Returns the Boolean variables from the input problem.
    */
@@ -258,7 +276,7 @@ public:
    * @param removable is this something that can be erased
    * @param negated true if negated
    */
-  void convertAndAssert(TNode node, bool removable, bool negated);
+  void convertAndAssert(TNode node, bool removable, bool negated, ProofRule proof_id, TNode from = TNode::null());
 
   /**
    * Constructs the stream to use the given sat solver.
index 610023b70387e480c4b86cffff50c7479d33d30e..e5e28bb0b710c68e2c535b0f679082e108657f7d 100644 (file)
@@ -106,7 +106,7 @@ Solver::Solver(CVC4::prop::TheoryProxy* proxy, CVC4::context::Context* context,
 
     // Statistics: (formerly in 'SolverStats')
     //
-  , solves(0), starts(0), decisions(0), rnd_decisions(0), propagations(0), conflicts(0)
+  , solves(0), starts(0), decisions(0), rnd_decisions(0), propagations(0), conflicts(0), resources_consumed(0)
   , dec_vars(0), clauses_literals(0), learnts_literals(0), max_literals(0), tot_literals(0)
 
   , ok                 (true)
@@ -135,8 +135,8 @@ Solver::Solver(CVC4::prop::TheoryProxy* proxy, CVC4::context::Context* context,
   // Assert the constants
   uncheckedEnqueue(mkLit(varTrue, false));
   uncheckedEnqueue(mkLit(varFalse, true));
-  PROOF( ProofManager::getSatProof()->registerUnitClause(mkLit(varTrue, false), INPUT); )
-  PROOF( ProofManager::getSatProof()->registerUnitClause(mkLit(varFalse, true), INPUT); )
+  PROOF( ProofManager::getSatProof()->registerUnitClause(mkLit(varTrue, false), INPUT, uint64_t(-1)); )
+  PROOF( ProofManager::getSatProof()->registerUnitClause(mkLit(varFalse, true), INPUT, uint64_t(-1)); )
 }
 
 
@@ -263,7 +263,7 @@ CRef Solver::reason(Var x) {
 
     // Construct the reason
     CRef real_reason = ca.alloc(explLevel, explanation, true);
-    PROOF (ProofManager::getSatProof()->registerClause(real_reason, THEORY_LEMMA); );
+    PROOF (ProofManager::getSatProof()->registerClause(real_reason, THEORY_LEMMA, (uint64_t(RULE_CONFLICT) << 32)); );
     vardata[x] = VarData(real_reason, level(x), user_level(x), intro_level(x), trail_index(x));
     clauses_removable.push(real_reason);
     attachClause(real_reason);
@@ -271,7 +271,7 @@ CRef Solver::reason(Var x) {
     return real_reason;
 }
 
-bool Solver::addClause_(vec<Lit>& ps, bool removable)
+bool Solver::addClause_(vec<Lit>& ps, bool removable, uint64_t proof_id)
 {
     if (!ok) return false;
 
@@ -321,6 +321,8 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable)
       lemmas.push();
       ps.copyTo(lemmas.last());
       lemmas_removable.push(removable);
+      Debug("cores") << "lemma push " << proof_id << " " << (proof_id & 0xffffffff) << std::endl;
+      lemmas_proof_id.push(proof_id);
     } else {
       // If all false, we're in conflict
       if (ps.size() == falseLiteralsCount) {
@@ -329,7 +331,7 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable)
           // construct the clause below to give to the proof manager
           // as the final conflict.
           if(falseLiteralsCount == 1) {
-            PROOF( ProofManager::getSatProof()->storeUnitConflict(ps[0], INPUT); )
+            PROOF( ProofManager::getSatProof()->storeUnitConflict(ps[0], INPUT, proof_id); )
             PROOF( ProofManager::getSatProof()->finalizeProof(::Minisat::CRef_Lazy); )
             return ok = false;
           }
@@ -351,7 +353,7 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable)
        attachClause(cr);
 
         if(PROOF_ON()) {
-          PROOF( ProofManager::getSatProof()->registerClause(cr, INPUT); )
+          PROOF( ProofManager::getSatProof()->registerClause(cr, INPUT, proof_id); )
           if(ps.size() == falseLiteralsCount) {
             PROOF( ProofManager::getSatProof()->finalizeProof(cr); )
             return ok = false;
@@ -364,11 +366,12 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable)
         if(assigns[var(ps[0])] == l_Undef) {
           assert(assigns[var(ps[0])] != l_False);
           uncheckedEnqueue(ps[0], cr);
-          PROOF( if(ps.size() == 1) { ProofManager::getSatProof()->registerUnitClause(ps[0], INPUT); } );
+          Debug("cores") << "i'm registering a unit clause, input, proof id " << proof_id << std::endl;
+          PROOF( if(ps.size() == 1) { ProofManager::getSatProof()->registerUnitClause(ps[0], INPUT, proof_id); } );
           CRef confl = propagate(CHECK_WITHOUT_THEORY);
           if(! (ok = (confl == CRef_Undef)) ) {
             if(ca[confl].size() == 1) {
-              PROOF( ProofManager::getSatProof()->storeUnitConflict(ca[confl][0], LEARNT); );
+              PROOF( ProofManager::getSatProof()->storeUnitConflict(ca[confl][0], LEARNT, proof_id); );
               PROOF( ProofManager::getSatProof()->finalizeProof(::Minisat::CRef_Lazy); )
             } else {
               PROOF( ProofManager::getSatProof()->finalizeProof(confl); );
@@ -812,7 +815,8 @@ CRef Solver::propagate(TheoryCheckType type)
     if (type == CHECK_FINAL) {
       // Do the theory check
       theoryCheck(CVC4::theory::Theory::EFFORT_FULL);
-      // Pick up the theory propagated literals (there could be some, if new lemmas are added)
+      // Pick up the theory propagated literals (there could be some,
+      // if new lemmas are added)
       propagateTheory();
       // If there are lemmas (or conflicts) update them
       if (lemmas.size() > 0) {
@@ -842,7 +846,7 @@ CRef Solver::propagate(TheoryCheckType type)
             propagateTheory();
             // If there are lemmas (or conflicts) update them
             if (lemmas.size() > 0) {
-                confl = updateLemmas();
+              confl = updateLemmas();
             }
         } else {
           // Even though in conflict, we still need to discharge the lemmas
@@ -891,7 +895,7 @@ void Solver::propagateTheory() {
         proxy->explainPropagation(MinisatSatSolver::toSatLiteral(p), explanation_cl);
         vec<Lit> explanation;
         MinisatSatSolver::toMinisatClause(explanation_cl, explanation);
-        addClause(explanation, true);
+        addClause(explanation, true, 0);
       }
     }
   }
@@ -1588,6 +1592,9 @@ CRef Solver::updateLemmas() {
 
   Debug("minisat::lemmas") << "Solver::updateLemmas() begin" << std::endl;
 
+  // Avoid adding lemmas indefinitely without resource-out
+  spendResource();
+
   CRef conflict = CRef_Undef;
 
   // Decision level to backtrack to
@@ -1642,6 +1649,8 @@ CRef Solver::updateLemmas() {
     // The current lemma
     vec<Lit>& lemma = lemmas[i];
     bool removable = lemmas_removable[i];
+    uint64_t proof_id = lemmas_proof_id[i];
+    Debug("cores") << "pulled lemma proof id " << proof_id << " " << (proof_id & 0xffffffff) << std::endl;
 
     // Attach it if non-unit
     CRef lemma_ref = CRef_Undef;
@@ -1656,7 +1665,7 @@ CRef Solver::updateLemmas() {
       }
 
       lemma_ref = ca.alloc(clauseLevel, lemma, removable);
-      PROOF( ProofManager::getSatProof()->registerClause(lemma_ref, THEORY_LEMMA); );
+      PROOF( ProofManager::getSatProof()->registerClause(lemma_ref, THEORY_LEMMA, proof_id); );
       if (removable) {
         clauses_removable.push(lemma_ref);
       } else {
@@ -1664,7 +1673,7 @@ CRef Solver::updateLemmas() {
       }
       attachClause(lemma_ref);
     } else {
-      PROOF( ProofManager::getSatProof()->registerUnitClause(lemma[0], THEORY_LEMMA); );
+      PROOF( ProofManager::getSatProof()->registerUnitClause(lemma[0], THEORY_LEMMA, proof_id); );
     }
 
     // If the lemma is propagating enqueue its literal (or set the conflict)
@@ -1678,7 +1687,7 @@ CRef Solver::updateLemmas() {
           } else {
             Debug("minisat::lemmas") << "Solver::updateLemmas(): unit conflict or empty clause" << std::endl;
             conflict = CRef_Lazy;
-            PROOF( ProofManager::getSatProof()->storeUnitConflict(lemma[0]); );
+            PROOF( ProofManager::getSatProof()->storeUnitConflict(lemma[0], LEARNT, proof_id); );
           }
         } else {
           Debug("minisat::lemmas") << "lemma size is " << lemma.size() << std::endl;
@@ -1691,6 +1700,7 @@ CRef Solver::updateLemmas() {
   // Clear the lemmas
   lemmas.clear();
   lemmas_removable.clear();
+  lemmas_proof_id.clear();
 
   if (conflict != CRef_Undef) {
     theoryConflict = true;
index 30d72ac751a82e8175a719b52900b4e43a85d19e..6d9fd538f59c5fb0dd2deaa1f2b905b15d0dc9ad 100644 (file)
@@ -37,12 +37,11 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
 #include "expr/command.h"
 
 namespace CVC4 {
-class SatProof;
-
-namespace prop {
-  class TheoryProxy;
-}/* CVC4::prop namespace */
+  class SatProof;
 
+  namespace prop {
+    class TheoryProxy;
+  }/* CVC4::prop namespace */
 }/* CVC4 namespace */
 
 namespace Minisat {
@@ -85,6 +84,9 @@ protected:
   /** Is the lemma removable */
   vec<bool> lemmas_removable;
 
+  /** Proof IDs for lemmas */
+  vec<uint64_t> lemmas_proof_id;
+
   /** Do a another check if FULL_EFFORT was the last one */
   bool recheck;
 
@@ -154,12 +156,14 @@ public:
     void          push                     ();
     void          pop                      ();
 
-    bool    addClause (const vec<Lit>& ps, bool removable);                     // Add a clause to the solver.
+    // CVC4 adds the "proof_id" here to refer to the input assertion/lemma
+    // that produced this clause
+    bool    addClause (const vec<Lit>& ps, bool removable, uint64_t proof_id);  // Add a clause to the solver.
     bool    addEmptyClause(bool removable);                                     // Add the empty clause, making the solver contradictory.
-    bool    addClause (Lit p, bool removable);                                  // Add a unit clause to the solver.
-    bool    addClause (Lit p, Lit q, bool removable);                           // Add a binary clause to the solver.
-    bool    addClause (Lit p, Lit q, Lit r, bool removable);                    // Add a ternary clause to the solver.
-    bool    addClause_(      vec<Lit>& ps, bool removable);                     // Add a clause to the solver without making superflous internal copy. Will
+    bool    addClause (Lit p, bool removable, uint64_t proof_id);               // Add a unit clause to the solver.
+    bool    addClause (Lit p, Lit q, bool removable, uint64_t proof_id);        // Add a binary clause to the solver.
+    bool    addClause (Lit p, Lit q, Lit r, bool removable, uint64_t proof_id); // Add a ternary clause to the solver.
+    bool    addClause_(      vec<Lit>& ps, bool removable, uint64_t proof_id);  // Add a clause to the solver without making superflous internal copy. Will
                                                                                  // change the passed vector 'ps'.
 
     // Solving:
@@ -215,6 +219,7 @@ public:
     void    budgetOff();
     void    interrupt();          // Trigger a (potentially asynchronous) interruption of the solver.
     void    clearInterrupt();     // Clear interrupt indicator flag.
+    void    spendResource();
 
     // Memory managment:
     //
@@ -252,7 +257,7 @@ public:
 
     // Statistics: (read-only member variable)
     //
-    uint64_t solves, starts, decisions, rnd_decisions, propagations, conflicts;
+    uint64_t solves, starts, decisions, rnd_decisions, propagations, conflicts, resources_consumed;
     uint64_t dec_vars, clauses_literals, learnts_literals, max_literals, tot_literals;
 
 protected:
@@ -418,7 +423,9 @@ protected:
     int      intro_level      (Var x) const; // User level at which this variable was created
     int      trail_index      (Var x) const; // Index in the trail
     double   progressEstimate ()      const; // DELETE THIS ?? IT'S NOT VERY USEFUL ...
+public:
     bool     withinBudget     ()      const;
+protected:
 
     // Static helpers:
     //
@@ -488,11 +495,15 @@ inline void Solver::checkGarbage(double gf){
 
 // NOTE: enqueue does not set the ok flag! (only public methods do)
 inline bool     Solver::enqueue         (Lit p, CRef from)      { return value(p) != l_Undef ? value(p) != l_False : (uncheckedEnqueue(p, from), true); }
-inline bool     Solver::addClause       (const vec<Lit>& ps, bool removable)    { ps.copyTo(add_tmp); return addClause_(add_tmp, removable); }
-inline bool     Solver::addEmptyClause  (bool removable)                        { add_tmp.clear(); return addClause_(add_tmp, removable); }
-inline bool     Solver::addClause       (Lit p, bool removable)                 { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp, removable); }
-inline bool     Solver::addClause       (Lit p, Lit q, bool removable)          { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp, removable); }
-inline bool     Solver::addClause       (Lit p, Lit q, Lit r, bool removable)   { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp, removable); }
+inline bool     Solver::addClause       (const vec<Lit>& ps, bool removable, uint64_t proof_id)
+                                                                { ps.copyTo(add_tmp); return addClause_(add_tmp, removable, proof_id); }
+inline bool     Solver::addEmptyClause  (bool removable)        { add_tmp.clear(); return addClause_(add_tmp, removable, uint64_t(-1)); }
+inline bool     Solver::addClause       (Lit p, bool removable, uint64_t proof_id)
+                                                                { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp, removable, proof_id); }
+inline bool     Solver::addClause       (Lit p, Lit q, bool removable, uint64_t proof_id)
+                                                                { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp, removable, proof_id); }
+inline bool     Solver::addClause       (Lit p, Lit q, Lit r, bool removable, uint64_t proof_id)
+                                                                { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp, removable, proof_id); }
 inline bool     Solver::locked          (const Clause& c) const { return value(c[0]) == l_True && isPropagatedBy(var(c[0]), c); }
 inline void     Solver::newDecisionLevel()                      { trail_lim.push(trail.size()); flipped.push(false); context->push(); if(Dump.isOn("state")) { Dump("state") << CVC4::PushCommand(); } }
 
@@ -526,8 +537,9 @@ inline void     Solver::clearInterrupt(){ asynch_interrupt = false; }
 inline void     Solver::budgetOff(){ conflict_budget = propagation_budget = -1; }
 inline bool     Solver::withinBudget() const {
     return !asynch_interrupt &&
-           (conflict_budget    < 0 || conflicts < (uint64_t)conflict_budget) &&
+           (conflict_budget    < 0 || conflicts + resources_consumed < (uint64_t)conflict_budget) &&
            (propagation_budget < 0 || propagations < (uint64_t)propagation_budget); }
+inline void     Solver::spendResource() { ++resources_consumed; }
 
 // FIXME: after the introduction of asynchronous interrruptions the solve-versions that return a
 // pure bool do not give a safe interface. Either interrupts must be possible to turn off here, or
index e4956ecc82067a13059b92cbd7a892f7ba13e68d..99341455cce97a15b65adaf9c092abbd51bb3dcc 100644 (file)
@@ -149,10 +149,10 @@ void MinisatSatSolver::setupOptions() {
   d_minisat->restart_inc = options::satRestartInc();
 }
 
-void MinisatSatSolver::addClause(SatClause& clause, bool removable) {
+void MinisatSatSolver::addClause(SatClause& clause, bool removable, uint64_t proof_id) {
   Minisat::vec<Minisat::Lit> minisat_clause;
   toMinisatClause(clause, minisat_clause);
-  d_minisat->addClause(minisat_clause, removable);
+  d_minisat->addClause(minisat_clause, removable, proof_id);
 }
 
 SatVariable MinisatSatSolver::newVar(bool isTheoryAtom, bool preRegister, bool canErase) {
@@ -168,10 +168,10 @@ SatValue MinisatSatSolver::solve(unsigned long& resource) {
     d_minisat->setConfBudget(resource);
   }
   Minisat::vec<Minisat::Lit> empty;
-  unsigned long conflictsBefore = d_minisat->conflicts;
+  unsigned long conflictsBefore = d_minisat->conflicts + d_minisat->resources_consumed;
   SatValue result = toSatLiteralValue(d_minisat->solveLimited(empty));
   d_minisat->clearInterrupt();
-  resource = d_minisat->conflicts - conflictsBefore;
+  resource = d_minisat->conflicts + d_minisat->resources_consumed - conflictsBefore;
   Trace("limit") << "SatSolver::solve(): it took " << resource << " conflicts" << std::endl;
   return result;
 }
@@ -182,6 +182,10 @@ SatValue MinisatSatSolver::solve() {
   return toSatLiteralValue(d_minisat->solve());
 }
 
+bool MinisatSatSolver::spendResource() {
+  d_minisat->spendResource();
+  return !d_minisat->withinBudget();
+}
 
 void MinisatSatSolver::interrupt() {
   d_minisat->interrupt();
@@ -225,7 +229,7 @@ void MinisatSatSolver::push() {
   d_minisat->push();
 }
 
-void MinisatSatSolver::pop(){
+void MinisatSatSolver::pop() {
   d_minisat->pop();
 }
 
index a919bbcc4597f252ac9b23a92fefb215c4c3e466..3d3cea356a14263720868b3b2515383a3f31d839 100644 (file)
@@ -53,7 +53,7 @@ public:
   static void  toSatClause    (const Minisat::Clause& clause, SatClause& sat_clause);
   void initialize(context::Context* context, TheoryProxy* theoryProxy);
 
-  void addClause(SatClause& clause, bool removable);
+  void addClause(SatClause& clause, bool removable, uint64_t proof_id);
 
   SatVariable newVar(bool isTheoryAtom, bool preRegister, bool canErase);
   SatVariable trueVar() { return d_minisat->trueVar(); }
@@ -62,6 +62,7 @@ public:
   SatValue solve();
   SatValue solve(long unsigned int&);
 
+  bool spendResource();
   void interrupt();
 
   SatValue value(SatLiteral l);
index 6dcdb76c735dcd989c65bcefe7c50a811f6249d8..71e747f72c4cf78057c6719562c660082ea81517 100644 (file)
@@ -159,7 +159,7 @@ lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp)
 
 
 
-bool SimpSolver::addClause_(vec<Lit>& ps, bool removable)
+bool SimpSolver::addClause_(vec<Lit>& ps, bool removable, uint64_t proof_id)
 {
 #ifndef NDEBUG
     if (use_simplification) {
@@ -173,7 +173,7 @@ bool SimpSolver::addClause_(vec<Lit>& ps, bool removable)
     if (use_rcheck && implied(ps))
         return true;
 
-    if (!Solver::addClause_(ps, removable))
+    if (!Solver::addClause_(ps, removable, proof_id))
         return false;
 
     if (use_simplification && clauses_persistent.size() == nclauses + 1){
@@ -545,7 +545,7 @@ bool SimpSolver::eliminateVar(Var v)
     for (int i = 0; i < pos.size(); i++)
         for (int j = 0; j < neg.size(); j++) {
             bool removable = ca[pos[i]].removable() && ca[pos[neg[j]]].removable();
-            if (merge(ca[pos[i]], ca[neg[j]], v, resolvent) && !addClause_(resolvent, removable)) {
+            if (merge(ca[pos[i]], ca[neg[j]], v, resolvent) && !addClause_(resolvent, removable, uint64_t(-1))) {
                 return false;
             }
         }
@@ -585,7 +585,7 @@ bool SimpSolver::substitute(Var v, Lit x)
 
         removeClause(cls[i]);
 
-        if (!addClause_(subst_clause, c.removable())) {
+        if (!addClause_(subst_clause, c.removable(), uint64_t(-1))) {
             return ok = false;
         }
     }
index 878d799a5b72af33e1c9050d03b379b15d59bd80..04130954678dd407470858ee82c8b9f334c99a40 100644 (file)
@@ -47,12 +47,12 @@ class SimpSolver : public Solver {
     // Problem specification:
     //
     Var     newVar    (bool polarity = true, bool dvar = true, bool isTheoryAtom = false, bool preRegister = false, bool canErase = true);
-    bool    addClause (const vec<Lit>& ps, bool removable);
-    bool    addEmptyClause(bool removable);                  // Add the empty clause to the solver.
-    bool    addClause (Lit p, bool removable);               // Add a unit clause to the solver.
-    bool    addClause (Lit p, Lit q, bool removable);        // Add a binary clause to the solver.
-    bool    addClause (Lit p, Lit q, Lit r, bool removable); // Add a ternary clause to the solver.
-    bool    addClause_(vec<Lit>& ps, bool removable);
+    bool    addClause (const vec<Lit>& ps, bool removable, uint64_t proof_id);
+    bool    addEmptyClause(bool removable, uint64_t proof_id); // Add the empty clause to the solver.
+    bool    addClause (Lit p, bool removable, uint64_t proof_id); // Add a unit clause to the solver.
+    bool    addClause (Lit p, Lit q, bool removable, uint64_t proof_id); // Add a binary clause to the solver.
+    bool    addClause (Lit p, Lit q, Lit r, bool removable, uint64_t proof_id); // Add a ternary clause to the solver.
+    bool    addClause_(vec<Lit>& ps, bool removable, uint64_t proof_id);
     bool    substitute(Var v, Lit x);  // Replace all occurences of v with x (may cause a contradiction).
 
     // Variable mode:
@@ -182,11 +182,15 @@ inline void SimpSolver::updateElimHeap(Var v) {
         elim_heap.update(v); }
 
 
-inline bool SimpSolver::addClause    (const vec<Lit>& ps, bool removable)    { ps.copyTo(add_tmp); return addClause_(add_tmp, removable); }
-inline bool SimpSolver::addEmptyClause(bool removable)                       { add_tmp.clear(); return addClause_(add_tmp, removable); }
-inline bool SimpSolver::addClause    (Lit p, bool removable)                 { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp, removable); }
-inline bool SimpSolver::addClause    (Lit p, Lit q, bool removable)          { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp, removable); }
-inline bool SimpSolver::addClause    (Lit p, Lit q, Lit r, bool removable)   { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp, removable); }
+inline bool SimpSolver::addClause    (const vec<Lit>& ps, bool removable, uint64_t proof_id)
+                                                                             { ps.copyTo(add_tmp); return addClause_(add_tmp, removable, proof_id); }
+inline bool SimpSolver::addEmptyClause(bool removable, uint64_t proof_id)    { add_tmp.clear(); return addClause_(add_tmp, removable, proof_id); }
+inline bool SimpSolver::addClause    (Lit p, bool removable, uint64_t proof_id)
+                                                                             { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp, removable, proof_id); }
+inline bool SimpSolver::addClause    (Lit p, Lit q, bool removable, uint64_t proof_id)
+                                                                             { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp, removable, proof_id); }
+inline bool SimpSolver::addClause    (Lit p, Lit q, Lit r, bool removable, uint64_t proof_id)
+                                                                             { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp, removable, proof_id); }
 inline void SimpSolver::setFrozen    (Var v, bool b) { frozen[v] = (char)b; if (use_simplification && !b) { updateElimHeap(v); } }
 
 inline bool SimpSolver::solve        (                     bool do_simp, bool turn_off_simp)  { budgetOff(); assumptions.clear(); return solve_(do_simp, turn_off_simp) == l_True; }
index 82c0bae1aa7b911c1200c8a9506da7bfba5c210c..a998d4240ce7e8af254d150dedf13b7aae35bf21 100644 (file)
@@ -25,6 +25,7 @@
 #include "decision/options.h"
 #include "theory/theory_engine.h"
 #include "theory/theory_registrar.h"
+#include "proof/proof_manager.h"
 #include "util/cvc4_assert.h"
 #include "options/options.h"
 #include "smt/options.h"
@@ -78,14 +79,14 @@ PropEngine::PropEngine(TheoryEngine* te, DecisionEngine *de, Context* satContext
 
   Debug("prop") << "Constructing the PropEngine" << endl;
 
-  d_satSolver = SatSolverFactory::createDPLLMinisat(); 
+  d_satSolver = SatSolverFactory::createDPLLMinisat();
 
   d_registrar = new theory::TheoryRegistrar(d_theoryEngine);
   d_cnfStream = new CVC4::prop::TseitinCnfStream
     (d_satSolver, d_registrar,
      userContext,
-     // fullLitToNode Map = 
-     options::threads() > 1 || 
+     // fullLitToNode Map =
+     options::threads() > 1 ||
      options::decisionMode() == decision::DECISION_STRATEGY_RELEVANCY
      );
 
@@ -94,7 +95,7 @@ PropEngine::PropEngine(TheoryEngine* te, DecisionEngine *de, Context* satContext
 
   d_decisionEngine->setSatSolver(d_satSolver);
   d_decisionEngine->setCnfStream(d_cnfStream);
-  PROOF (ProofManager::currentPM()->initCnfProof(d_cnfStream); ); 
+  PROOF (ProofManager::currentPM()->initCnfProof(d_cnfStream); );
 }
 
 PropEngine::~PropEngine() {
@@ -109,15 +110,15 @@ void PropEngine::assertFormula(TNode node) {
   Assert(!d_inCheckSat, "Sat solver in solve()!");
   Debug("prop") << "assertFormula(" << node << ")" << endl;
   // Assert as non-removable
-  d_cnfStream->convertAndAssert(node, false, false);
+  d_cnfStream->convertAndAssert(node, false, false, RULE_GIVEN);
 }
 
-void PropEngine::assertLemma(TNode node, bool negated, bool removable) {
+void PropEngine::assertLemma(TNode node, bool negated, bool removable, ProofRule rule, TNode from) {
   //Assert(d_inCheckSat, "Sat solver should be in solve()!");
   Debug("prop::lemmas") << "assertLemma(" << node << ")" << endl;
 
-  // Assert as removable
-  d_cnfStream->convertAndAssert(node, removable, negated);
+  // Assert as (possibly) removable
+  d_cnfStream->convertAndAssert(node, removable, negated, rule, from);
 }
 
 void PropEngine::requirePhase(TNode n, bool phase) {
@@ -278,12 +279,15 @@ void PropEngine::interrupt() throw(ModalException) {
 
   d_interrupted = true;
   d_satSolver->interrupt();
-  d_theoryEngine->interrupt(); 
+  d_theoryEngine->interrupt();
   Debug("prop") << "interrupt()" << endl;
 }
 
 void PropEngine::spendResource() throw() {
-  // TODO implement me
+  if(d_satSolver->spendResource()) {
+    d_satSolver->interrupt();
+    d_theoryEngine->interrupt();
+  }
   checkTime();
 }
 
index a5132e3da48268518de3d1534b574d8aa680b04c..ed022a64f3e36354e0842bf11fc0bb6006373adc 100644 (file)
@@ -25,6 +25,7 @@
 #include "options/options.h"
 #include "util/result.h"
 #include "smt/modal_exception.h"
+#include "proof/proof_manager.h"
 #include <sys/time.h>
 
 namespace CVC4 {
@@ -199,7 +200,7 @@ public:
    * @param removable whether this lemma can be quietly removed based
    * on an activity heuristic (or not)
    */
-  void assertLemma(TNode node, bool negated, bool removable);
+  void assertLemma(TNode node, bool negated, bool removable, ProofRule rule, TNode from = TNode::null());
 
   /**
    * If ever n is decided upon, it must be in the given phase.  This
index 929b867c9701fc38c02df6bfc19e69583f37b47f..adf6dfd073e03469cbe4326fe115a512e1db456e 100644 (file)
@@ -24,6 +24,7 @@
 #include "util/statistics_registry.h"
 #include "context/cdlist.h"
 #include "prop/sat_solver_types.h"
+#include "expr/node.h"
 
 namespace CVC4 {
 namespace prop {
@@ -38,7 +39,7 @@ public:
   virtual ~SatSolver() { }
 
   /** Assert a clause in the solver. */
-  virtual void addClause(SatClause& clause, bool removable) = 0;
+  virtual void addClause(SatClause& clause, bool removable, uint64_t proof_id) = 0;
 
   /**
    * Create a new boolean variable in the solver.
@@ -61,6 +62,12 @@ public:
   /** Check the satisfiability of the added clauses */
   virtual SatValue solve(long unsigned int&) = 0;
 
+  /**
+   * Instruct the solver that it should bump its consumed resource count.
+   * Returns true if resources are exhausted.
+   */
+  virtual bool spendResource() = 0;
+
   /** Interrupt the solver */
   virtual void interrupt() = 0;
 
index 67325cb1806d3deb782c7fc287800538ea975c82..2bcd4809937592df1f0fc5de91fa84cde51342e7 100644 (file)
@@ -122,7 +122,7 @@ void TheoryProxy::notifyRestart() {
           if(lemmaCount % 1 == 0) {
             Debug("shared") << "=) " << asNode << std::endl;
           }
-          d_propEngine->assertLemma(d_theoryEngine->preprocess(asNode), false, true);
+          d_propEngine->assertLemma(d_theoryEngine->preprocess(asNode), false, true, RULE_INVALID);
         } else {
           Debug("shared") << "=(" << asNode << std::endl;
         }
index 89f35bf05384c4bb75eddc6bbdf1e15333dd06e7..6ce8efef913198ba3e458c31cdb56ede74fda5da 100644 (file)
@@ -724,6 +724,7 @@ Node BooleanTermConverter::rewriteBooleanTermsRec(TNode top, theory::TheoryId pa
         goto next_worklist;
       }
       switch(k) {
+      case kind::INST_ATTRIBUTE:
       case kind::BOUND_VAR_LIST:
         result.top() << top;
         worklist.pop();
index 9c7eea12fd7eb2906132f86431c6fb418b96602a..3ee3dbecbee510085bba0a53de2664c17e377196 100644 (file)
@@ -37,9 +37,11 @@ option dumpProofs --dump-proofs bool :default false :link --proof
  output proofs after every UNSAT/VALID response
 option dumpInstantiations --dump-instantiations bool :default false
  output instantiations of quantified formulas after every UNSAT/VALID response
-# this is just a placeholder for later; it doesn't show up in command-line options listings
-undocumented-option unsatCores produce-unsat-cores --produce-unsat-cores bool :predicate CVC4::smt::unsatCoresEnabledBuild CVC4::smt::beforeSearch :predicate-include "smt/options_handlers.h"
- turn on unsat core generation (NOT YET SUPPORTED)
+option unsatCores produce-unsat-cores --produce-unsat-cores bool :predicate CVC4::smt::proofEnabledBuild CVC4::smt::beforeSearch :predicate-include "smt/options_handlers.h"
+ turn on unsat core generation
+option dumpUnsatCores --dump-unsat-cores bool :default false :link --produce-unsat-cores :link-smt produce-unsat-cores :predicate CVC4::smt::beforeSearch :predicate-include "smt/options_handlers.h"
+ output unsat cores after every UNSAT/VALID response
+
 option produceAssignments produce-assignments --produce-assignments bool :default false :predicate CVC4::smt::beforeSearch :predicate-include "smt/options_handlers.h"
  support the get-assignment command
 
index 61e17801d52dcf5bb3ba98ef36f41cf3b82e44a8..fcd62526709d0b9c8efede00ea76b9341569bd70 100644 (file)
@@ -153,10 +153,6 @@ batch (default) \n\
   (MiniSat) propagation for all of them only after reaching a querying command\n\
   (CHECKSAT or QUERY or predicate SUBTYPE declaration)\n\
 \n\
-incremental\n\
-+ run nonclausal simplification and clausal propagation at each ASSERT\n\
-  (and at CHECKSAT/QUERY/SUBTYPE)\n\
-\n\
 none\n\
 + do not perform nonclausal simplification\n\
 ";
@@ -283,8 +279,6 @@ inline LogicInfo stringToLogicInfo(std::string option, std::string optarg, SmtEn
 inline SimplificationMode stringToSimplificationMode(std::string option, std::string optarg, SmtEngine* smt) throw(OptionException) {
   if(optarg == "batch") {
     return SIMPLIFICATION_MODE_BATCH;
-  } else if(optarg == "incremental") {
-    return SIMPLIFICATION_MODE_INCREMENTAL;
   } else if(optarg == "none") {
     return SIMPLIFICATION_MODE_NONE;
   } else if(optarg == "help") {
@@ -316,12 +310,6 @@ inline void proofEnabledBuild(std::string option, bool value, SmtEngine* smt) th
 #endif /* CVC4_PROOF */
 }
 
-inline void unsatCoresEnabledBuild(std::string option, bool value, SmtEngine* smt) throw(OptionException) {
-  if(value) {
-    throw UnrecognizedOptionException("CVC4 does not yet have support for unsatisfiable cores");
-  }
-}
-
 // This macro is used for setting :regular-output-channel and :diagnostic-output-channel
 // to redirect a stream.  It maintains all attributes set on the stream.
 #define __CVC4__SMT__OUTPUTCHANNELS__SETSTREAM__(__channel_get, __channel_set) \
index f728fa8622c830092b67883a2745203180b2b31b..be46badfc8c18e6c0cdb9caaf9d77762b6710a2d 100644 (file)
@@ -21,9 +21,6 @@ namespace CVC4 {
 
 std::ostream& operator<<(std::ostream& out, SimplificationMode mode) {
   switch(mode) {
-  case SIMPLIFICATION_MODE_INCREMENTAL:
-    out << "SIMPLIFICATION_MODE_INCREMENTAL";
-    break;
   case SIMPLIFICATION_MODE_BATCH:
     out << "SIMPLIFICATION_MODE_BATCH";
     break;
index 2242e8bdf9ff7e2011ecacbbe9c92328bddb60f2..b0b78d318e5d8ddfdb2891d28ce869d658b57a78 100644 (file)
@@ -26,8 +26,6 @@ namespace CVC4 {
 
 /** Enumeration of simplification modes (when to simplify). */
 typedef enum {
-  /** Simplify the assertions as they come in */
-  SIMPLIFICATION_MODE_INCREMENTAL,
   /** Simplify the assertions all together once a check is requested */
   SIMPLIFICATION_MODE_BATCH,
   /** Don't do simplification */
index dcfc526eca3fbb9dd8799be6a1b9d1274103c29c..ea48cb3d03db992266d17ff169ec3e5a40b97e3c 100644 (file)
@@ -48,6 +48,7 @@
 #include "theory/bv/theory_bv_rewriter.h"
 #include "proof/proof_manager.h"
 #include "main/options.h"
+#include "util/unsat_core.h"
 #include "util/proof.h"
 #include "proof/proof.h"
 #include "proof/proof_manager.h"
@@ -137,6 +138,30 @@ public:
   Node getFormula() const { return d_formula; }
 };/* class DefinedFunction */
 
+class AssertionPipeline {
+  vector<Node> d_nodes;
+
+public:
+
+  size_t size() const { return d_nodes.size(); }
+
+  void resize(size_t n) { d_nodes.resize(n); }
+  void clear() { d_nodes.clear(); }
+
+  Node& operator[](size_t i) { return d_nodes[i]; }
+  const Node& operator[](size_t i) const { return d_nodes[i]; }
+  void push_back(Node n) { d_nodes.push_back(n); }
+
+  vector<Node>& ref() { return d_nodes; }
+  const vector<Node>& ref() const { return d_nodes; }
+
+  void replace(size_t i, Node n) {
+    PROOF( ProofManager::currentPM()->addDependence(n, d_nodes[i]); );
+    d_nodes[i] = n;
+  }
+
+};/* class AssertionPipeline */
+
 struct SmtEngineStatistics {
   /** time spent in definition-expansion */
   TimerStat d_definitionExpansionTime;
@@ -160,6 +185,8 @@ struct SmtEngineStatistics {
   TimerStat d_iteRemovalTime;
   /** time spent in theory preprocessing */
   TimerStat d_theoryPreprocessTime;
+  /** time spent in theory preprocessing */
+  TimerStat d_rewriteApplyToConstTime;
   /** time spent converting to CNF */
   TimerStat d_cnfConversionTime;
   /** Num of assertions before ite removal */
@@ -192,6 +219,7 @@ struct SmtEngineStatistics {
     d_unconstrainedSimpTime("smt::SmtEngine::unconstrainedSimpTime"),
     d_iteRemovalTime("smt::SmtEngine::iteRemovalTime"),
     d_theoryPreprocessTime("smt::SmtEngine::theoryPreprocessTime"),
+    d_rewriteApplyToConstTime("smt::SmtEngine::rewriteApplyToConstTime"),
     d_cnfConversionTime("smt::SmtEngine::cnfConversionTime"),
     d_numAssertionsPre("smt::SmtEngine::numAssertionsPreITERemoval", 0),
     d_numAssertionsPost("smt::SmtEngine::numAssertionsPostITERemoval", 0),
@@ -214,10 +242,12 @@ struct SmtEngineStatistics {
     StatisticsRegistry::registerStat(&d_unconstrainedSimpTime);
     StatisticsRegistry::registerStat(&d_iteRemovalTime);
     StatisticsRegistry::registerStat(&d_theoryPreprocessTime);
+    StatisticsRegistry::registerStat(&d_rewriteApplyToConstTime);
     StatisticsRegistry::registerStat(&d_cnfConversionTime);
     StatisticsRegistry::registerStat(&d_numAssertionsPre);
     StatisticsRegistry::registerStat(&d_numAssertionsPost);
     StatisticsRegistry::registerStat(&d_checkModelTime);
+    StatisticsRegistry::registerStat(&d_checkProofTime);
     StatisticsRegistry::registerStat(&d_solveTime);
     StatisticsRegistry::registerStat(&d_pushPopTime);
     StatisticsRegistry::registerStat(&d_processAssertionsTime);
@@ -236,10 +266,12 @@ struct SmtEngineStatistics {
     StatisticsRegistry::unregisterStat(&d_unconstrainedSimpTime);
     StatisticsRegistry::unregisterStat(&d_iteRemovalTime);
     StatisticsRegistry::unregisterStat(&d_theoryPreprocessTime);
+    StatisticsRegistry::unregisterStat(&d_rewriteApplyToConstTime);
     StatisticsRegistry::unregisterStat(&d_cnfConversionTime);
     StatisticsRegistry::unregisterStat(&d_numAssertionsPre);
     StatisticsRegistry::unregisterStat(&d_numAssertionsPost);
     StatisticsRegistry::unregisterStat(&d_checkModelTime);
+    StatisticsRegistry::unregisterStat(&d_checkProofTime);
     StatisticsRegistry::unregisterStat(&d_solveTime);
     StatisticsRegistry::unregisterStat(&d_pushPopTime);
     StatisticsRegistry::unregisterStat(&d_processAssertionsTime);
@@ -264,9 +296,6 @@ struct SmtEngineStatistics {
 class SmtEnginePrivate : public NodeManagerListener {
   SmtEngine& d_smt;
 
-  /** The assertions yet to be preprocessed */
-  vector<Node> d_assertionsToPreprocess;
-
   /** Learned literals */
   vector<Node> d_nonClausalLearnedLiterals;
 
@@ -281,8 +310,8 @@ class SmtEnginePrivate : public NodeManagerListener {
   bool d_propagatorNeedsFinish;
   std::vector<Node> d_boolVars;
 
-  /** Assertions to push to sat */
-  vector<Node> d_assertionsToCheck;
+  /** Assertions in the preprocessing pipeline */
+  AssertionPipeline d_assertions;
 
   /** Whether any assertions have been processed */
   CDO<bool> d_assertionsProcessed;
@@ -319,7 +348,7 @@ class SmtEnginePrivate : public NodeManagerListener {
 
 public:
   /**
-   * Map from skolem variables to index in d_assertionsToCheck containing
+   * Map from skolem variables to index in d_assertions containing
    * corresponding introduced Boolean ite
    */
   IteSkolemMap d_iteSkolemMap;
@@ -375,7 +404,7 @@ private:
   bool simpITE();
 
   // Simplify based on unconstrained values
-  void unconstrainedSimp(std::vector<Node>& assertions);
+  void unconstrainedSimp();
 
   // Ensures the assertions asserted after before now
   // effectively come before d_realAssertionsEnd
@@ -386,7 +415,7 @@ private:
    * (predicate subtype or integer subrange type) must be constrained
    * to be in that type.
    */
-  void constrainSubtypes(TNode n, std::vector<Node>& assertions)
+  void constrainSubtypes(TNode n, AssertionPipeline& assertions)
     throw();
 
   // trace nodes back to their assertions using CircuitPropagator's BackEdgesMap
@@ -410,13 +439,12 @@ public:
 
   SmtEnginePrivate(SmtEngine& smt) :
     d_smt(smt),
-    d_assertionsToPreprocess(),
     d_nonClausalLearnedLiterals(),
     d_realAssertionsEnd(0),
     d_booleanTermConverter(NULL),
     d_propagator(d_nonClausalLearnedLiterals, true, true),
     d_propagatorNeedsFinish(false),
-    d_assertionsToCheck(),
+    d_assertions(),
     d_assertionsProcessed(smt.d_userContext, false),
     d_substitutionsIndex(smt.d_userContext, 0),
     d_fakeContext(),
@@ -508,9 +536,8 @@ public:
    * someone does a push-assert-pop without a check-sat.
    */
   void notifyPop() {
-    d_assertionsToPreprocess.clear();
+    d_assertions.clear();
     d_nonClausalLearnedLiterals.clear();
-    d_assertionsToCheck.clear();
     d_realAssertionsEnd = 0;
     d_iteSkolemMap.clear();
   }
@@ -546,7 +573,7 @@ public:
     hash_map<Node, Node, NodeHashFunction> cache;
     Node n = expandDefinitions(in, cache).toExpr();
     // Make sure we've done all preprocessing, etc.
-    Assert(d_assertionsToCheck.size() == 0 && d_assertionsToPreprocess.size() == 0);
+    Assert(d_assertions.size() == 0);
     return applySubstitutions(n).toExpr();
   }
 
@@ -665,8 +692,6 @@ SmtEngine::SmtEngine(ExprManager* em) throw() :
   d_statisticsRegistry = new StatisticsRegistry();
   d_stats = new SmtEngineStatistics();
 
-  PROOF( d_proofManager = new ProofManager(); );
-
   // We have mutual dependency here, so we add the prop engine to the theory
   // engine later (it is non-essential there)
   d_theoryEngine = new TheoryEngine(d_context, d_userContext, d_private->d_iteRemover, const_cast<const LogicInfo&>(d_logic));
@@ -689,6 +714,9 @@ void SmtEngine::finishInit() {
   // ensure that our heuristics are properly set up
   setDefaults();
 
+  Assert(d_proofManager == NULL);
+  PROOF( d_proofManager = new ProofManager(); );
+
   d_decisionEngine = new DecisionEngine(d_context, d_userContext);
   d_decisionEngine->init();   // enable appropriate strategies
 
@@ -927,6 +955,64 @@ void SmtEngine::setDefaults() {
     }
   }
 
+  if(options::unsatCores()) {
+    if(options::simplificationMode() != SIMPLIFICATION_MODE_NONE) {
+      if(options::simplificationMode.wasSetByUser()) {
+        throw OptionException("simplification not supported with unsat cores");
+      }
+      Notice() << "SmtEngine: turning off simplification to support unsat-cores" << endl;
+      options::simplificationMode.set(SIMPLIFICATION_MODE_NONE);
+    }
+
+    if(options::unconstrainedSimp()) {
+      if(options::unconstrainedSimp.wasSetByUser()) {
+        throw OptionException("unconstrained simplification not supported with unsat cores");
+      }
+      Notice() << "SmtEngine: turning off unconstrained simplification to support unsat-cores" << endl;
+      options::unconstrainedSimp.set(false);
+    }
+
+    if(options::pbRewrites()) {
+      if(options::pbRewrites.wasSetByUser()) {
+        throw OptionException("pseudoboolean rewrites not supported with unsat cores");
+      }
+      Notice() << "SmtEngine: turning off pseudoboolean rewrites to support unsat-cores" << endl;
+      setOption("pb-rewrites", false);
+    }
+
+    if(options::sortInference()) {
+      if(options::sortInference.wasSetByUser()) {
+        throw OptionException("sort inference not supported with unsat cores");
+      }
+      Notice() << "SmtEngine: turning off sort inference to support unsat-cores" << endl;
+      options::sortInference.set(false);
+    }
+
+    if(options::preSkolemQuant()) {
+      if(options::preSkolemQuant.wasSetByUser()) {
+        throw OptionException("pre-skolemization not supported with unsat cores");
+      }
+      Notice() << "SmtEngine: turning off pre-skolemization to support unsat-cores" << endl;
+      options::preSkolemQuant.set(false);
+    }
+
+    if(options::bitvectorToBool()) {
+      if(options::bitvectorToBool.wasSetByUser()) {
+        throw OptionException("bv-to-bool not supported with unsat cores");
+      }
+      Notice() << "SmtEngine: turning off bitvector-to-bool support unsat-cores" << endl;
+      options::bitvectorToBool.set(false);
+    }
+
+    if(options::bvIntroducePow2()) {
+      if(options::bvIntroducePow2.wasSetByUser()) {
+        throw OptionException("bv-intro-pow2 not supported with unsat cores");
+      }
+      Notice() << "SmtEngine: turning off bv-introduce-pow2 to support unsat-cores" << endl;
+      setOption("bv-intro-pow2", false);
+    }
+  }
+
   if(options::produceAssignments() && !options::produceModels()) {
     Notice() << "SmtEngine: turning on produce-models to support produce-assignments" << endl;
     setOption("produce-models", SExpr("true"));
@@ -1119,10 +1205,8 @@ void SmtEngine::setDefaults() {
   if (options::arithRewriteEq()) {
     d_earlyTheoryPP = false;
   }
-  // Turn on justification heuristic of the decision engine for QF_BV and QF_AUFBV
-  // and also use it in stop-only mode for QF_AUFLIA, QF_LRA and Quantifiers
-  // BUT use neither in ALL_SUPPORTED mode (since it doesn't yet work well
-  // with incrementality)
+
+  // Set decision mode based on logic (if not set by user)
   if(!options::decisionMode.wasSetByUser()) {
     decision::DecisionMode decMode =
       // ALL_SUPPORTED
@@ -1215,6 +1299,37 @@ void SmtEngine::setDefaults() {
   if( options::qcfMode.wasSetByUser() || options::qcfTConstraint() ){
     options::quantConflictFind.set( true );
   }
+  //for induction techniques
+  if( options::quantInduction() ){
+    if( !options::dtStcInduction.wasSetByUser() ){
+      options::dtStcInduction.set( true );
+    }
+    if( !options::intWfInduction.wasSetByUser() ){
+      options::intWfInduction.set( true );
+    }
+  }
+  if( options::dtStcInduction() ){
+    //leads to unfairness FIXME
+    if( !options::dtForceAssignment.wasSetByUser() ){
+      options::dtForceAssignment.set( true );
+    }
+  }
+  if( options::intWfInduction() ){
+    if( !options::purifyTriggers.wasSetByUser() ){
+      options::purifyTriggers.set( true );
+    }
+  }
+  if( options::conjectureNoFilter() ){
+    if( !options::conjectureFilterActiveTerms.wasSetByUser() ){
+      options::conjectureFilterActiveTerms.set( false );
+    }
+    if( !options::conjectureFilterCanonical.wasSetByUser() ){
+      options::conjectureFilterCanonical.set( false );
+    }
+    if( !options::conjectureFilterModel.wasSetByUser() ){
+      options::conjectureFilterModel.set( false );
+    }
+  }
 
   //until bugs 371,431 are fixed
   if( ! options::minisatUseElim.wasSetByUser()){
@@ -1260,17 +1375,10 @@ void SmtEngine::setDefaults() {
     }
   }
 
-  if (options::incrementalSolving() && options::proof()) {
-    Warning() << "SmtEngine: turning off incremental solving mode (not yet supported with --proof" << endl;
+  if(options::incrementalSolving() && (options::proof() || options::unsatCores())) {
+    Warning() << "SmtEngine: turning off incremental solving mode (not yet supported with --proof or --produce-unsat-cores, try --tear-down-incremental instead)" << endl;
     setOption("incremental", SExpr("false"));
   }
-
-  // datatypes theory should assign values to all datatypes terms if logic is quantified
-  if (d_logic.isQuantified() && d_logic.isTheoryEnabled(THEORY_DATATYPES)) {
-    if( !options::dtForceAssignment.wasSetByUser() ){
-      options::dtForceAssignment.set(true);
-    }
-  }
 }
 
 void SmtEngine::setInfo(const std::string& key, const CVC4::SExpr& value)
@@ -1636,11 +1744,10 @@ void SmtEnginePrivate::removeITEs() {
   Trace("simplify") << "SmtEnginePrivate::removeITEs()" << endl;
 
   // Remove all of the ITE occurrences and normalize
-  d_iteRemover.run(d_assertionsToCheck, d_iteSkolemMap);
-  for (unsigned i = 0; i < d_assertionsToCheck.size(); ++ i) {
-    d_assertionsToCheck[i] = Rewriter::rewrite(d_assertionsToCheck[i]);
+  d_iteRemover.run(d_assertions.ref(), d_iteSkolemMap, true);
+  for (unsigned i = 0; i < d_assertions.size(); ++ i) {
+    d_assertions.replace(i, Rewriter::rewrite(d_assertions[i]));
   }
-
 }
 
 void SmtEnginePrivate::staticLearning() {
@@ -1650,22 +1757,21 @@ void SmtEnginePrivate::staticLearning() {
 
   Trace("simplify") << "SmtEnginePrivate::staticLearning()" << endl;
 
-  for (unsigned i = 0; i < d_assertionsToCheck.size(); ++ i) {
+  for (unsigned i = 0; i < d_assertions.size(); ++ i) {
 
     NodeBuilder<> learned(kind::AND);
-    learned << d_assertionsToCheck[i];
-    d_smt.d_theoryEngine->ppStaticLearn(d_assertionsToCheck[i], learned);
+    learned << d_assertions[i];
+    d_smt.d_theoryEngine->ppStaticLearn(d_assertions[i], learned);
     if(learned.getNumChildren() == 1) {
       learned.clear();
     } else {
-      d_assertionsToCheck[i] = learned;
+      d_assertions.replace(i, learned);
     }
   }
 }
 
 // do dumping (before/after any preprocessing pass)
-static void dumpAssertions(const char* key,
-                           const std::vector<Node>& assertionList) {
+static void dumpAssertions(const char* key, const AssertionPipeline& assertionList) {
   if( Dump.isOn("assertions") &&
       Dump.isOn(string("assertions:") + key) ) {
     // Push the simplified assertions to the dump output stream
@@ -1680,8 +1786,11 @@ static void dumpAssertions(const char* key,
 bool SmtEnginePrivate::nonClausalSimplify() {
   d_smt.finalOptionsAreSet();
 
-  TimerStat::CodeTimer nonclausalTimer(d_smt.d_stats->d_nonclausalSimplificationTime);
+  if(options::unsatCores()) {
+    return true;
+  }
 
+  TimerStat::CodeTimer nonclausalTimer(d_smt.d_stats->d_nonclausalSimplificationTime);
 
   Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify()" << endl;
 
@@ -1694,14 +1803,15 @@ bool SmtEnginePrivate::nonClausalSimplify() {
   // Assert all the assertions to the propagator
   Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
                     << "asserting to propagator" << endl;
-  for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
-    Assert(Rewriter::rewrite(d_assertionsToPreprocess[i]) == d_assertionsToPreprocess[i]);
+  for (unsigned i = 0; i < d_assertions.size(); ++ i) {
+    Assert(Rewriter::rewrite(d_assertions[i]) == d_assertions[i]);
     // Don't reprocess substitutions
     if (d_substitutionsIndex > 0 && i == d_substitutionsIndex) {
       continue;
     }
-    Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): asserting " << d_assertionsToPreprocess[i] << endl;
-    d_propagator.assertTrue(d_assertionsToPreprocess[i]);
+    Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): asserting " << d_assertions[i] << endl;
+    Debug("cores") << "d_propagator assertTrue: " << d_assertions[i] << std::endl;
+    d_propagator.assertTrue(d_assertions[i]);
   }
 
   Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
@@ -1710,8 +1820,10 @@ bool SmtEnginePrivate::nonClausalSimplify() {
     // If in conflict, just return false
     Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
                       << "conflict in non-clausal propagation" << endl;
-    d_assertionsToPreprocess.clear();
-    d_assertionsToCheck.push_back(NodeManager::currentNM()->mkConst<bool>(false));
+    Node falseNode = NodeManager::currentNM()->mkConst<bool>(false);
+    Assert(!options::unsatCores());
+    d_assertions.clear();
+    d_assertions.push_back(falseNode);
     d_propagatorNeedsFinish = true;
     return false;
   }
@@ -1748,8 +1860,9 @@ bool SmtEnginePrivate::nonClausalSimplify() {
         Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
                           << "conflict with "
                           << d_nonClausalLearnedLiterals[i] << endl;
-        d_assertionsToPreprocess.clear();
-        d_assertionsToCheck.push_back(NodeManager::currentNM()->mkConst<bool>(false));
+        Assert(!options::unsatCores());
+        d_assertions.clear();
+        d_assertions.push_back(NodeManager::currentNM()->mkConst<bool>(false));
         d_propagatorNeedsFinish = true;
         return false;
       }
@@ -1783,8 +1896,9 @@ bool SmtEnginePrivate::nonClausalSimplify() {
         Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
                           << "conflict while solving "
                           << learnedLiteral << endl;
-        d_assertionsToPreprocess.clear();
-        d_assertionsToCheck.push_back(NodeManager::currentNM()->mkConst<bool>(false));
+        Assert(!options::unsatCores());
+        d_assertions.clear();
+        d_assertions.push_back(NodeManager::currentNM()->mkConst<bool>(false));
         d_propagatorNeedsFinish = true;
         return false;
       default:
@@ -1809,8 +1923,8 @@ bool SmtEnginePrivate::nonClausalSimplify() {
           // constantPropagations.simplifyLHS(t, c, equations, true);
           // if (!equations.empty()) {
           //   Assert(equations[0].first.isConst() && equations[0].second.isConst() && equations[0].first != equations[0].second);
-          //   d_assertionsToPreprocess.clear();
-          //   d_assertionsToCheck.push_back(NodeManager::currentNM()->mkConst<bool>(false));
+          //   d_assertions.clear();
+          //   d_assertions.push_back(NodeManager::currentNM()->mkConst<bool>(false));
           //   return;
           // }
           // d_topLevelSubstitutions.simplifyRHS(constantPropagations);
@@ -1859,8 +1973,8 @@ bool SmtEnginePrivate::nonClausalSimplify() {
 
   hash_set<TNode, TNodeHashFunction> s;
   Trace("debugging") << "NonClausal simplify pre-preprocess\n";
-  for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
-    Node assertion = d_assertionsToPreprocess[i];
+  for (unsigned i = 0; i < d_assertions.size(); ++ i) {
+    Node assertion = d_assertions[i];
     Node assertionNew = newSubstitutions.apply(assertion);
     Trace("debugging") << "assertion = " << assertion << endl;
     Trace("debugging") << "assertionNew = " << assertionNew << endl;
@@ -1881,17 +1995,16 @@ bool SmtEnginePrivate::nonClausalSimplify() {
     }
     Trace("debugging") << "\n";
     s.insert(assertion);
-    d_assertionsToCheck.push_back(assertion);
+    d_assertions.replace(i, assertion);
     Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
                       << "non-clausal preprocessed: "
                       << assertion << endl;
   }
-  d_assertionsToPreprocess.clear();
 
   // If in incremental mode, add substitutions to the list of assertions
   if (d_substitutionsIndex > 0) {
     NodeBuilder<> substitutionsBuilder(kind::AND);
-    substitutionsBuilder << d_assertionsToCheck[d_substitutionsIndex];
+    substitutionsBuilder << d_assertions[d_substitutionsIndex];
     pos = newSubstitutions.begin();
     for (; pos != newSubstitutions.end(); ++pos) {
       // Add back this substitution as an assertion
@@ -1901,8 +2014,8 @@ bool SmtEnginePrivate::nonClausalSimplify() {
       Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): will notify SAT layer of substitution: " << n << endl;
     }
     if (substitutionsBuilder.getNumChildren() > 1) {
-      d_assertionsToCheck[d_substitutionsIndex] =
-        Rewriter::rewrite(Node(substitutionsBuilder));
+      d_assertions.replace(d_substitutionsIndex,
+        Rewriter::rewrite(Node(substitutionsBuilder)));
     }
   } else {
     // If not in incremental mode, must add substitutions to model
@@ -1918,8 +2031,8 @@ bool SmtEnginePrivate::nonClausalSimplify() {
   }
 
   NodeBuilder<> learnedBuilder(kind::AND);
-  Assert(d_realAssertionsEnd <= d_assertionsToCheck.size());
-  learnedBuilder << d_assertionsToCheck[d_realAssertionsEnd - 1];
+  Assert(d_realAssertionsEnd <= d_assertions.size());
+  learnedBuilder << d_assertions[d_realAssertionsEnd - 1];
 
   for (unsigned i = 0; i < d_nonClausalLearnedLiterals.size(); ++ i) {
     Node learned = d_nonClausalLearnedLiterals[i];
@@ -1948,7 +2061,6 @@ bool SmtEnginePrivate::nonClausalSimplify() {
   }
   d_nonClausalLearnedLiterals.clear();
 
-
   for (pos = constantPropagations.begin(); pos != constantPropagations.end(); ++pos) {
     Node cProp = (*pos).first.eqNode((*pos).second);
     Assert(d_topLevelSubstitutions.apply(cProp) == cProp);
@@ -1973,8 +2085,8 @@ bool SmtEnginePrivate::nonClausalSimplify() {
   d_topLevelSubstitutions.addSubstitutions(newSubstitutions);
 
   if(learnedBuilder.getNumChildren() > 1) {
-    d_assertionsToCheck[d_realAssertionsEnd - 1] =
-      Rewriter::rewrite(Node(learnedBuilder));
+    d_assertions.replace(d_realAssertionsEnd - 1,
+      Rewriter::rewrite(Node(learnedBuilder)));
   }
 
   d_propagatorNeedsFinish = true;
@@ -1984,9 +2096,9 @@ bool SmtEnginePrivate::nonClausalSimplify() {
 void SmtEnginePrivate::bvAbstraction() {
   Trace("bv-abstraction") << "SmtEnginePrivate::bvAbstraction()" << endl;
   std::vector<Node> new_assertions;
-  bool changed = d_smt.d_theoryEngine->ppBvAbstraction(d_assertionsToPreprocess, new_assertions);
-  for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
-    d_assertionsToPreprocess[i] = Rewriter::rewrite(new_assertions[i]);
+  bool changed = d_smt.d_theoryEngine->ppBvAbstraction(d_assertions.ref(), new_assertions);
+  for (unsigned i = 0; i < d_assertions.size(); ++ i) {
+    d_assertions.replace(i, Rewriter::rewrite(new_assertions[i]));
   }
   // if we are using the lazy solver and the abstraction
   // applies, then UF symbols were introduced
@@ -2001,9 +2113,9 @@ void SmtEnginePrivate::bvAbstraction() {
 void SmtEnginePrivate::bvToBool() {
   Trace("bv-to-bool") << "SmtEnginePrivate::bvToBool()" << endl;
   std::vector<Node> new_assertions;
-  d_smt.d_theoryEngine->ppBvToBool(d_assertionsToPreprocess, new_assertions);
-  for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
-    d_assertionsToPreprocess[i] = Rewriter::rewrite(new_assertions[i]);
+  d_smt.d_theoryEngine->ppBvToBool(d_assertions.ref(), new_assertions);
+  for (unsigned i = 0; i < d_assertions.size(); ++ i) {
+    d_assertions.replace(i, Rewriter::rewrite(new_assertions[i]));
   }
 }
 
@@ -2012,23 +2124,23 @@ bool SmtEnginePrivate::simpITE() {
 
   Trace("simplify") << "SmtEnginePrivate::simpITE()" << endl;
 
-  unsigned numAssertionOnEntry = d_assertionsToCheck.size();
-  for (unsigned i = 0; i < d_assertionsToCheck.size(); ++i) {
-    Node result = d_smt.d_theoryEngine->ppSimpITE(d_assertionsToCheck[i]);
-    d_assertionsToCheck[i] = result;
+  unsigned numAssertionOnEntry = d_assertions.size();
+  for (unsigned i = 0; i < d_assertions.size(); ++i) {
+    Node result = d_smt.d_theoryEngine->ppSimpITE(d_assertions[i]);
+    d_assertions.replace(i, result);
     if(result.isConst() && !result.getConst<bool>()){
       return false;
     }
   }
-  bool result = d_smt.d_theoryEngine->donePPSimpITE(d_assertionsToCheck);
-  if(numAssertionOnEntry < d_assertionsToCheck.size()){
+  bool result = d_smt.d_theoryEngine->donePPSimpITE(d_assertions.ref());
+  if(numAssertionOnEntry < d_assertions.size()){
     compressBeforeRealAssertions(numAssertionOnEntry);
   }
   return result;
 }
 
 void SmtEnginePrivate::compressBeforeRealAssertions(size_t before){
-  size_t curr = d_assertionsToCheck.size();
+  size_t curr = d_assertions.size();
   if(before >= curr ||
      d_realAssertionsEnd <= 0 ||
      d_realAssertionsEnd >= curr){
@@ -2048,24 +2160,24 @@ void SmtEnginePrivate::compressBeforeRealAssertions(size_t before){
 
   std::vector<Node> intoConjunction;
   for(size_t i = before; i<curr; ++i){
-    intoConjunction.push_back(d_assertionsToCheck[i]);
+    intoConjunction.push_back(d_assertions[i]);
   }
-  d_assertionsToCheck.resize(before);
+  d_assertions.resize(before);
   size_t lastBeforeItes = d_realAssertionsEnd - 1;
-  intoConjunction.push_back(d_assertionsToCheck[lastBeforeItes]);
+  intoConjunction.push_back(d_assertions[lastBeforeItes]);
   Node newLast = util::NaryBuilder::mkAssoc(kind::AND, intoConjunction);
-  d_assertionsToCheck[lastBeforeItes] = newLast;
-  Assert(d_assertionsToCheck.size() == before);
+  d_assertions.replace(lastBeforeItes, newLast);
+  Assert(d_assertions.size() == before);
 }
 
-void SmtEnginePrivate::unconstrainedSimp(std::vector<Node>& assertions) {
+void SmtEnginePrivate::unconstrainedSimp() {
   TimerStat::CodeTimer unconstrainedSimpTimer(d_smt.d_stats->d_unconstrainedSimpTime);
   Trace("simplify") << "SmtEnginePrivate::unconstrainedSimp()" << endl;
-  d_smt.d_theoryEngine->ppUnconstrainedSimp(assertions);
+  d_smt.d_theoryEngine->ppUnconstrainedSimp(d_assertions.ref());
 }
 
 
-void SmtEnginePrivate::constrainSubtypes(TNode top, std::vector<Node>& assertions)
+void SmtEnginePrivate::constrainSubtypes(TNode top, AssertionPipeline& assertions)
   throw() {
 
   Trace("constrainSubtypes") << "constrainSubtypes(): looking at " << top << endl;
@@ -2187,8 +2299,7 @@ size_t SmtEnginePrivate::removeFromConjunction(Node& n, const std::hash_set<unsi
 }
 
 void SmtEnginePrivate::doMiplibTrick() {
-  Assert(d_assertionsToPreprocess.empty());
-  Assert(d_realAssertionsEnd == d_assertionsToCheck.size());
+  Assert(d_realAssertionsEnd == d_assertions.size());
   Assert(!options::incrementalSolving());
 
   const booleans::CircuitPropagator::BackEdgesMap& backEdges = d_propagator.getBackEdges();
@@ -2419,7 +2530,7 @@ void SmtEnginePrivate::doMiplibTrick() {
               Node newVar = nm->mkSkolem(ss.str(), nm->integerType(), "a variable introduced due to scrubbing a miplib encoding", NodeManager::SKOLEM_EXACT_NAME);
               Node geq = Rewriter::rewrite(nm->mkNode(kind::GEQ, newVar, zero));
               Node leq = Rewriter::rewrite(nm->mkNode(kind::LEQ, newVar, one));
-              d_assertionsToCheck.push_back(Rewriter::rewrite(geq.andNode(leq)));
+              d_assertions.push_back(Rewriter::rewrite(geq.andNode(leq)));
               SubstitutionMap nullMap(&d_fakeContext);
               Theory::PPAssertStatus status CVC4_UNUSED; // just for assertions
               status = d_smt.d_theoryEngine->solve(geq, nullMap);
@@ -2470,7 +2581,7 @@ void SmtEnginePrivate::doMiplibTrick() {
           }
           newAssertion = Rewriter::rewrite(newAssertion);
           Debug("miplib") << "  " << newAssertion << endl;
-          d_assertionsToCheck.push_back(newAssertion);
+          d_assertions.push_back(newAssertion);
           Debug("miplib") << "  assertions to remove: " << endl;
           for(vector<TNode>::const_iterator k = asserts[pos_var].begin(), k_end = asserts[pos_var].end(); k != k_end; ++k) {
             Debug("miplib") << "    " << *k << endl;
@@ -2483,26 +2594,26 @@ void SmtEnginePrivate::doMiplibTrick() {
   if(!removeAssertions.empty()) {
     Debug("miplib") << "SmtEnginePrivate::simplify(): scrubbing miplib encoding..." << endl;
     for(size_t i = 0; i < d_realAssertionsEnd; ++i) {
-      if(removeAssertions.find(d_assertionsToCheck[i].getId()) != removeAssertions.end()) {
-        Debug("miplib") << "SmtEnginePrivate::simplify(): - removing " << d_assertionsToCheck[i] << endl;
-        d_assertionsToCheck[i] = d_true;
+      if(removeAssertions.find(d_assertions[i].getId()) != removeAssertions.end()) {
+        Debug("miplib") << "SmtEnginePrivate::simplify(): - removing " << d_assertions[i] << endl;
+        d_assertions[i] = d_true;
         ++d_smt.d_stats->d_numMiplibAssertionsRemoved;
-      } else if(d_assertionsToCheck[i].getKind() == kind::AND) {
-        size_t removals = removeFromConjunction(d_assertionsToCheck[i], removeAssertions);
+      } else if(d_assertions[i].getKind() == kind::AND) {
+        size_t removals = removeFromConjunction(d_assertions[i], removeAssertions);
         if(removals > 0) {
-          Debug("miplib") << "SmtEnginePrivate::simplify(): - reduced " << d_assertionsToCheck[i] << endl;
+          Debug("miplib") << "SmtEnginePrivate::simplify(): - reduced " << d_assertions[i] << endl;
           Debug("miplib") << "SmtEnginePrivate::simplify(): -      by " << removals << " conjuncts" << endl;
           d_smt.d_stats->d_numMiplibAssertionsRemoved += removals;
         }
       }
-      Debug("miplib") << "had: " << d_assertionsToCheck[i] << endl;
-      d_assertionsToCheck[i] = Rewriter::rewrite(d_topLevelSubstitutions.apply(d_assertionsToCheck[i]));
-      Debug("miplib") << "now: " << d_assertionsToCheck[i] << endl;
+      Debug("miplib") << "had: " << d_assertions[i] << endl;
+      d_assertions[i] = Rewriter::rewrite(d_topLevelSubstitutions.apply(d_assertions[i]));
+      Debug("miplib") << "now: " << d_assertions[i] << endl;
     }
   } else {
     Debug("miplib") << "SmtEnginePrivate::simplify(): miplib pass found nothing." << endl;
   }
-  d_realAssertionsEnd = d_assertionsToCheck.size();
+  d_realAssertionsEnd = d_assertions.size();
 }
 
 
@@ -2536,7 +2647,7 @@ bool SmtEnginePrivate::simplifyAssertions()
           // we add new assertions and need this (in practice, this
           // restriction only disables miplib processing during
           // re-simplification, which we don't expect to be useful anyway)
-          d_realAssertionsEnd == d_assertionsToCheck.size() ) {
+          d_realAssertionsEnd == d_assertions.size() ) {
         Chat() << "...fixing miplib encodings..." << endl;
         Trace("simplify") << "SmtEnginePrivate::simplify(): "
                           << "looking for miplib pseudobooleans..." << endl;
@@ -2548,18 +2659,16 @@ bool SmtEnginePrivate::simplifyAssertions()
         Trace("simplify") << "SmtEnginePrivate::simplify(): "
                           << "skipping miplib pseudobooleans pass (either incrementalSolving is on, or miplib pbs are turned off)..." << endl;
       }
-    } else {
-      Assert(d_assertionsToCheck.empty());
-      d_assertionsToCheck.swap(d_assertionsToPreprocess);
     }
 
-    dumpAssertions("post-nonclausal", d_assertionsToCheck);
+    dumpAssertions("post-nonclausal", d_assertions);
     Trace("smt") << "POST nonClausalSimplify" << endl;
-    Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
-    Debug("smt") << " d_assertionsToCheck     : " << d_assertionsToCheck.size() << endl;
+    Debug("smt") << " d_assertions     : " << d_assertions.size() << endl;
 
     // before ppRewrite check if only core theory for BV theory
-    d_smt.d_theoryEngine->staticInitializeBVOptions(d_assertionsToCheck);
+    d_smt.d_theoryEngine->staticInitializeBVOptions(d_assertions.ref());
+
+    dumpAssertions("pre-theorypp", d_assertions);
 
     // Theory preprocessing
     if (d_smt.d_earlyTheoryPP) {
@@ -2567,17 +2676,16 @@ bool SmtEnginePrivate::simplifyAssertions()
       TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_theoryPreprocessTime);
       // Call the theory preprocessors
       d_smt.d_theoryEngine->preprocessStart();
-      for (unsigned i = 0; i < d_assertionsToCheck.size(); ++ i) {
-        Assert(Rewriter::rewrite(d_assertionsToCheck[i]) == d_assertionsToCheck[i]);
-        d_assertionsToCheck[i] = d_smt.d_theoryEngine->preprocess(d_assertionsToCheck[i]);
-        Assert(Rewriter::rewrite(d_assertionsToCheck[i]) == d_assertionsToCheck[i]);
+      for (unsigned i = 0; i < d_assertions.size(); ++ i) {
+        Assert(Rewriter::rewrite(d_assertions[i]) == d_assertions[i]);
+        d_assertions.replace(i, d_smt.d_theoryEngine->preprocess(d_assertions[i]));
+        Assert(Rewriter::rewrite(d_assertions[i]) == d_assertions[i]);
       }
     }
 
-    dumpAssertions("post-theorypp", d_assertionsToCheck);
+    dumpAssertions("post-theorypp", d_assertions);
     Trace("smt") << "POST theoryPP" << endl;
-    Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
-    Debug("smt") << " d_assertionsToCheck     : " << d_assertionsToCheck.size() << endl;
+    Debug("smt") << " d_assertions     : " << d_assertions.size() << endl;
 
     // ITE simplification
     if(options::doITESimp() &&
@@ -2590,38 +2698,33 @@ bool SmtEnginePrivate::simplifyAssertions()
       }
     }
 
-    dumpAssertions("post-itesimp", d_assertionsToCheck);
+    dumpAssertions("post-itesimp", d_assertions);
     Trace("smt") << "POST iteSimp" << endl;
-    Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
-    Debug("smt") << " d_assertionsToCheck     : " << d_assertionsToCheck.size() << endl;
+    Debug("smt") << " d_assertions     : " << d_assertions.size() << endl;
 
     // Unconstrained simplification
     if(options::unconstrainedSimp()) {
       Chat() << "...doing unconstrained simplification..." << endl;
-      unconstrainedSimp(d_assertionsToCheck);
+      unconstrainedSimp();
     }
 
-    dumpAssertions("post-unconstrained", d_assertionsToCheck);
+    dumpAssertions("post-unconstrained", d_assertions);
     Trace("smt") << "POST unconstrainedSimp" << endl;
-    Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
-    Debug("smt") << " d_assertionsToCheck     : " << d_assertionsToCheck.size() << endl;
+    Debug("smt") << " d_assertions     : " << d_assertions.size() << endl;
 
     if(options::repeatSimp() && options::simplificationMode() != SIMPLIFICATION_MODE_NONE) {
       Chat() << "...doing another round of nonclausal simplification..." << endl;
       Trace("simplify") << "SmtEnginePrivate::simplify(): "
                         << " doing repeated simplification" << endl;
-      d_assertionsToCheck.swap(d_assertionsToPreprocess);
-      Assert(d_assertionsToCheck.empty());
       bool noConflict = nonClausalSimplify();
       if(!noConflict) {
         return false;
       }
     }
 
-    dumpAssertions("post-repeatsimp", d_assertionsToCheck);
+    dumpAssertions("post-repeatsimp", d_assertions);
     Trace("smt") << "POST repeatSimp" << endl;
-    Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
-    Debug("smt") << " d_assertionsToCheck     : " << d_assertionsToCheck.size() << endl;
+    Debug("smt") << " d_assertions     : " << d_assertions.size() << endl;
 
   } catch(TypeCheckingExceptionPrivate& tcep) {
     // Calls to this function should have already weeded out any
@@ -2807,52 +2910,45 @@ void SmtEnginePrivate::processAssertions() {
   Assert(d_smt.d_pendingPops == 0);
 
   // Dump the assertions
-  dumpAssertions("pre-everything", d_assertionsToPreprocess);
+  dumpAssertions("pre-everything", d_assertions);
 
   Trace("smt") << "SmtEnginePrivate::processAssertions()" << endl;
 
-  Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
-  Debug("smt") << " d_assertionsToCheck     : " << d_assertionsToCheck.size() << endl;
-
-  Assert(d_assertionsToCheck.size() == 0);
+  Debug("smt") << " d_assertions     : " << d_assertions.size() << endl;
 
-  if (d_assertionsToPreprocess.size() == 0) {
+  if (d_assertions.size() == 0) {
     // nothing to do
     return;
   }
 
-  if (d_assertionsProcessed &&
-      ( options::incrementalSolving() ||
-        options::simplificationMode() == SIMPLIFICATION_MODE_INCREMENTAL )) {
+  if (d_assertionsProcessed && options::incrementalSolving()) {
     // Placeholder for storing substitutions
-    d_substitutionsIndex = d_assertionsToPreprocess.size();
-    d_assertionsToPreprocess.push_back(NodeManager::currentNM()->mkConst<bool>(true));
+    d_substitutionsIndex = d_assertions.size();
+    d_assertions.push_back(NodeManager::currentNM()->mkConst<bool>(true));
   }
 
   // Add dummy assertion in last position - to be used as a
   // placeholder for any new assertions to get added
-  d_assertionsToPreprocess.push_back(NodeManager::currentNM()->mkConst<bool>(true));
+  d_assertions.push_back(NodeManager::currentNM()->mkConst<bool>(true));
   // any assertions added beyond realAssertionsEnd must NOT affect the
   // equisatisfiability
-  d_realAssertionsEnd = d_assertionsToPreprocess.size();
+  d_realAssertionsEnd = d_assertions.size();
 
   // Assertions are NOT guaranteed to be rewritten by this point
 
-  dumpAssertions("pre-definition-expansion", d_assertionsToPreprocess);
+  dumpAssertions("pre-definition-expansion", d_assertions);
   {
     Chat() << "expanding definitions..." << endl;
     Trace("simplify") << "SmtEnginePrivate::simplify(): expanding definitions" << endl;
     TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_definitionExpansionTime);
     hash_map<Node, Node, NodeHashFunction> cache;
-    for(unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
-      d_assertionsToPreprocess[i] =
-        expandDefinitions(d_assertionsToPreprocess[i], cache);
+    for(unsigned i = 0; i < d_assertions.size(); ++ i) {
+      d_assertions.replace(i, expandDefinitions(d_assertions[i], cache));
     }
   }
-  dumpAssertions("post-definition-expansion", d_assertionsToPreprocess);
+  dumpAssertions("post-definition-expansion", d_assertions);
 
-  Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
-  Debug("smt") << " d_assertionsToCheck     : " << d_assertionsToCheck.size() << endl;
+  Debug("smt") << " d_assertions     : " << d_assertions.size() << endl;
 
   if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER &&
       !d_smt.d_logic.isPure(THEORY_BV)) {
@@ -2862,146 +2958,153 @@ void SmtEnginePrivate::processAssertions() {
   }
 
   if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
-    d_smt.d_theoryEngine->mkAckermanizationAsssertions(d_assertionsToPreprocess);
+    d_smt.d_theoryEngine->mkAckermanizationAsssertions(d_assertions.ref());
   }
 
   if ( options::bvAbstraction() &&
       !options::incrementalSolving()) {
-    dumpAssertions("pre-bv-abstraction", d_assertionsToPreprocess);
+    dumpAssertions("pre-bv-abstraction", d_assertions);
     bvAbstraction();
-    dumpAssertions("post-bv-abstraction", d_assertionsToPreprocess);
+    dumpAssertions("post-bv-abstraction", d_assertions);
   }
 
-  dumpAssertions("pre-boolean-terms", d_assertionsToPreprocess);
+  dumpAssertions("pre-boolean-terms", d_assertions);
   {
     Chat() << "rewriting Boolean terms..." << endl;
-    for(unsigned i = 0, i_end = d_assertionsToPreprocess.size(); i != i_end; ++i) {
-      d_assertionsToPreprocess[i] = rewriteBooleanTerms(d_assertionsToPreprocess[i]);
+    for(unsigned i = 0, i_end = d_assertions.size(); i != i_end; ++i) {
+      d_assertions.replace(i, rewriteBooleanTerms(d_assertions[i]));
     }
   }
-  dumpAssertions("post-boolean-terms", d_assertionsToPreprocess);
+  dumpAssertions("post-boolean-terms", d_assertions);
 
-  Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
-  Debug("smt") << " d_assertionsToCheck     : " << d_assertionsToCheck.size() << endl;
+  Debug("smt") << " d_assertions     : " << d_assertions.size() << endl;
 
-  dumpAssertions("pre-constrain-subtypes", d_assertionsToPreprocess);
+  dumpAssertions("pre-constrain-subtypes", d_assertions);
   {
     // Any variables of subtype types need to be constrained properly.
     // Careful, here: constrainSubtypes() adds to the back of
-    // d_assertionsToPreprocess, but we don't need to reprocess those.
+    // d_assertions, but we don't need to reprocess those.
     // We also can't use an iterator, because the vector may be moved in
     // memory during this loop.
     Chat() << "constraining subtypes..." << endl;
-    for(unsigned i = 0, i_end = d_assertionsToPreprocess.size(); i != i_end; ++i) {
-      constrainSubtypes(d_assertionsToPreprocess[i], d_assertionsToPreprocess);
+    for(unsigned i = 0, i_end = d_assertions.size(); i != i_end; ++i) {
+      constrainSubtypes(d_assertions[i], d_assertions);
     }
   }
-  dumpAssertions("post-constrain-subtypes", d_assertionsToPreprocess);
+  dumpAssertions("post-constrain-subtypes", d_assertions);
 
-  Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
-  Debug("smt") << " d_assertionsToCheck     : " << d_assertionsToCheck.size() << endl;
+  Debug("smt") << " d_assertions     : " << d_assertions.size() << endl;
 
+  bool noConflict = true;
 
   // Unconstrained simplification
   if(options::unconstrainedSimp()) {
-    dumpAssertions("pre-unconstrained-simp", d_assertionsToPreprocess);
+    dumpAssertions("pre-unconstrained-simp", d_assertions);
     Chat() << "...doing unconstrained simplification..." << endl;
-    unconstrainedSimp(d_assertionsToPreprocess);
-    dumpAssertions("post-unconstrained-simp", d_assertionsToPreprocess);
+    unconstrainedSimp();
+    dumpAssertions("post-unconstrained-simp", d_assertions);
   }
 
   if(options::bvIntroducePow2()){
-    theory::bv::BVIntroducePow2::pow2Rewrite(d_assertionsToPreprocess);
+    theory::bv::BVIntroducePow2::pow2Rewrite(d_assertions.ref());
   }
 
-  dumpAssertions("pre-substitution", d_assertionsToPreprocess);
+  dumpAssertions("pre-substitution", d_assertions);
 
-  // Apply the substitutions we already have, and normalize
-  Chat() << "applying substitutions..." << endl;
-  Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
-                    << "applying substitutions" << endl;
-  for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
-    Trace("simplify") << "applying to " << d_assertionsToPreprocess[i] << endl;
-    d_assertionsToPreprocess[i] =
-      Rewriter::rewrite(d_topLevelSubstitutions.apply(d_assertionsToPreprocess[i]));
-    Trace("simplify") << "  got " << d_assertionsToPreprocess[i] << endl;
+  if(options::unsatCores()) {
+    // special rewriting pass for unsat cores, since many of the passes below are skipped
+    for (unsigned i = 0; i < d_assertions.size(); ++ i) {
+      d_assertions.replace(i, Rewriter::rewrite(d_assertions[i]));
+    }
+  } else {
+    // Apply the substitutions we already have, and normalize
+    if(!options::unsatCores()) {
+      Chat() << "applying substitutions..." << endl;
+      Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
+                        << "applying substitutions" << endl;
+      for (unsigned i = 0; i < d_assertions.size(); ++ i) {
+        Trace("simplify") << "applying to " << d_assertions[i] << endl;
+        d_assertions.replace(i, Rewriter::rewrite(d_topLevelSubstitutions.apply(d_assertions[i])));
+        Trace("simplify") << "  got " << d_assertions[i] << endl;
+      }
+    }
   }
-  dumpAssertions("post-substitution", d_assertionsToPreprocess);
 
-  // Assertions ARE guaranteed to be rewritten by this point
+  dumpAssertions("post-substitution", d_assertions);
 
+  // Assertions ARE guaranteed to be rewritten by this point
 
   // Lift bit-vectors of size 1 to bool
   if(options::bitvectorToBool()) {
-    dumpAssertions("pre-bv-to-bool", d_assertionsToPreprocess);
+    dumpAssertions("pre-bv-to-bool", d_assertions);
     Chat() << "...doing bvToBool..." << endl;
     bvToBool();
-    dumpAssertions("post-bv-to-bool", d_assertionsToPreprocess);
+    dumpAssertions("post-bv-to-bool", d_assertions);
   }
 
   if( d_smt.d_logic.isTheoryEnabled(THEORY_STRINGS) ) {
-    dumpAssertions("pre-strings-pp", d_assertionsToPreprocess);
+    dumpAssertions("pre-strings-pp", d_assertions);
     CVC4::theory::strings::StringsPreprocess sp;
     std::vector<Node> newNodes;
-    newNodes.push_back(d_assertionsToPreprocess[d_realAssertionsEnd - 1]);
-    sp.simplify( d_assertionsToPreprocess, newNodes );
+    newNodes.push_back(d_assertions[d_realAssertionsEnd - 1]);
+    sp.simplify( d_assertions.ref(), newNodes );
     if(newNodes.size() > 1) {
-      d_assertionsToPreprocess[d_realAssertionsEnd - 1] = NodeManager::currentNM()->mkNode(kind::AND, newNodes);
+      d_assertions[d_realAssertionsEnd - 1] = NodeManager::currentNM()->mkNode(kind::AND, newNodes);
     }
-    for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
-      d_assertionsToPreprocess[i] = Rewriter::rewrite( d_assertionsToPreprocess[i] );
+    for (unsigned i = 0; i < d_assertions.size(); ++ i) {
+      d_assertions[i] = Rewriter::rewrite( d_assertions[i] );
     }
-    dumpAssertions("post-strings-pp", d_assertionsToPreprocess);
+    dumpAssertions("post-strings-pp", d_assertions);
   }
   if( d_smt.d_logic.isQuantified() ){
     //remove rewrite rules
-    for( unsigned i=0; i < d_assertionsToPreprocess.size(); i++ ) {
-      if( d_assertionsToPreprocess[i].getKind() == kind::REWRITE_RULE ){
-        Node prev = d_assertionsToPreprocess[i];
+    for( unsigned i=0; i < d_assertions.size(); i++ ) {
+      if( d_assertions[i].getKind() == kind::REWRITE_RULE ){
+        Node prev = d_assertions[i];
         Trace("quantifiers-rewrite-debug") << "Rewrite rewrite rule " << prev << "..." << std::endl;
-        d_assertionsToPreprocess[i] = Rewriter::rewrite( quantifiers::QuantifiersRewriter::rewriteRewriteRule( d_assertionsToPreprocess[i] ) );
+        d_assertions[i] = Rewriter::rewrite( quantifiers::QuantifiersRewriter::rewriteRewriteRule( d_assertions[i] ) );
         Trace("quantifiers-rewrite") << "*** rr-rewrite " << prev << endl;
-        Trace("quantifiers-rewrite") << "   ...got " << d_assertionsToPreprocess[i] << endl;
+        Trace("quantifiers-rewrite") << "   ...got " << d_assertions[i] << endl;
       }
     }
 
-    dumpAssertions("pre-skolem-quant", d_assertionsToPreprocess);
+    dumpAssertions("pre-skolem-quant", d_assertions);
     if( options::preSkolemQuant() ){
       //apply pre-skolemization to existential quantifiers
-      for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
-        Node prev = d_assertionsToPreprocess[i];
+      for (unsigned i = 0; i < d_assertions.size(); ++ i) {
+        Node prev = d_assertions[i];
         Trace("quantifiers-rewrite-debug") << "Pre-skolemize " << prev << "..." << std::endl;
         vector< TypeNode > fvTypes;
         vector< TNode > fvs;
-        d_assertionsToPreprocess[i] = quantifiers::QuantifiersRewriter::preSkolemizeQuantifiers( prev, true, fvTypes, fvs );
-        if( prev!=d_assertionsToPreprocess[i] ){
-          d_assertionsToPreprocess[i] = Rewriter::rewrite( d_assertionsToPreprocess[i] );
+        d_assertions.replace(i, quantifiers::QuantifiersRewriter::preSkolemizeQuantifiers( prev, true, fvTypes, fvs ));
+        if( prev!=d_assertions[i] ){
+          d_assertions.replace(i, Rewriter::rewrite( d_assertions[i] ));
           Trace("quantifiers-rewrite") << "*** Pre-skolemize " << prev << endl;
-          Trace("quantifiers-rewrite") << "   ...got " << d_assertionsToPreprocess[i] << endl;
+          Trace("quantifiers-rewrite") << "   ...got " << d_assertions[i] << endl;
         }
       }
     }
-    dumpAssertions("post-skolem-quant", d_assertionsToPreprocess);
+    dumpAssertions("post-skolem-quant", d_assertions);
     if( options::macrosQuant() ){
       //quantifiers macro expansion
       bool success;
       do{
         quantifiers::QuantifierMacros qm;
-        success = qm.simplify( d_assertionsToPreprocess, true );
+        success = qm.simplify( d_assertions.ref(), true );
       }while( success );
     }
 
     Trace("fo-rsn-enable") << std::endl;
     if( options::foPropQuant() ){
       quantifiers::FirstOrderPropagation fop;
-      fop.simplify( d_assertionsToPreprocess );
+      fop.simplify( d_assertions.ref() );
     }
   }
 
   if( options::sortInference() ){
     //sort inference technique
     SortInference * si = d_smt.d_theoryEngine->getSortInference();
-    si->simplify( d_assertionsToPreprocess );
+    si->simplify( d_assertions.ref() );
     for( std::map< Node, Node >::iterator it = si->d_model_replace_f.begin(); it != si->d_model_replace_f.end(); ++it ){
       d_smt.setPrintFuncInModel( it->first.toExpr(), false );
       d_smt.setPrintFuncInModel( it->second.toExpr(), true );
@@ -3009,25 +3112,25 @@ void SmtEnginePrivate::processAssertions() {
   }
 
   //if( options::quantConflictFind() ){
-  //  d_smt.d_theoryEngine->getQuantConflictFind()->registerAssertions( d_assertionsToPreprocess );
+  //  d_smt.d_theoryEngine->getQuantConflictFind()->registerAssertions( d_assertions );
   //}
 
   if( options::pbRewrites() ){
-    d_pbsProcessor.learn(d_assertionsToPreprocess);
+    d_pbsProcessor.learn(d_assertions.ref());
     if(d_pbsProcessor.likelyToHelp()){
-      d_pbsProcessor.applyReplacements(d_assertionsToPreprocess);
+      d_pbsProcessor.applyReplacements(d_assertions.ref());
     }
   }
 
-  dumpAssertions("pre-simplify", d_assertionsToPreprocess);
+  dumpAssertions("pre-simplify", d_assertions);
   Chat() << "simplifying assertions..." << endl;
-  bool noConflict = simplifyAssertions();
+  noConflict = simplifyAssertions();
   if(!noConflict){
     ++(d_smt.d_stats->d_simplifiedToFalse);
   }
-  dumpAssertions("post-simplify", d_assertionsToCheck);
+  dumpAssertions("post-simplify", d_assertions);
 
-  dumpAssertions("pre-static-learning", d_assertionsToCheck);
+  dumpAssertions("pre-static-learning", d_assertions);
   if(options::doStaticLearning()) {
     // Perform static learning
     Chat() << "doing static learning..." << endl;
@@ -3035,27 +3138,25 @@ void SmtEnginePrivate::processAssertions() {
                       << "performing static learning" << endl;
     staticLearning();
   }
-  dumpAssertions("post-static-learning", d_assertionsToCheck);
+  dumpAssertions("post-static-learning", d_assertions);
 
   Trace("smt") << "POST bvToBool" << endl;
-  Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
-  Debug("smt") << " d_assertionsToCheck     : " << d_assertionsToCheck.size() << endl;
+  Debug("smt") << " d_assertions     : " << d_assertions.size() << endl;
 
 
-  dumpAssertions("pre-ite-removal", d_assertionsToCheck);
+  dumpAssertions("pre-ite-removal", d_assertions);
   {
     Chat() << "removing term ITEs..." << endl;
     TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_iteRemovalTime);
     // Remove ITEs, updating d_iteSkolemMap
-    d_smt.d_stats->d_numAssertionsPre += d_assertionsToCheck.size();
+    d_smt.d_stats->d_numAssertionsPre += d_assertions.size();
     removeITEs();
-    d_smt.d_stats->d_numAssertionsPost += d_assertionsToCheck.size();
+    d_smt.d_stats->d_numAssertionsPost += d_assertions.size();
   }
-  dumpAssertions("post-ite-removal", d_assertionsToCheck);
+  dumpAssertions("post-ite-removal", d_assertions);
 
-  dumpAssertions("pre-repeat-simplify", d_assertionsToCheck);
+  dumpAssertions("pre-repeat-simplify", d_assertions);
   if(options::repeatSimp()) {
-    d_assertionsToCheck.swap(d_assertionsToPreprocess);
     Chat() << "re-simplifying assertions..." << endl;
     ScopeCounter depth(d_simplifyAssertionsDepth);
     noConflict &= simplifyAssertions();
@@ -3084,11 +3185,11 @@ void SmtEnginePrivate::processAssertions() {
       IteSkolemMap::iterator it = d_iteSkolemMap.begin();
       IteSkolemMap::iterator iend = d_iteSkolemMap.end();
       NodeBuilder<> builder(kind::AND);
-      builder << d_assertionsToCheck[d_realAssertionsEnd - 1];
+      builder << d_assertions[d_realAssertionsEnd - 1];
       vector<TNode> toErase;
       for (; it != iend; ++it) {
         if (skolemSet.find((*it).first) == skolemSet.end()) {
-          TNode iteExpr = d_assertionsToCheck[(*it).second];
+          TNode iteExpr = d_assertions[(*it).second];
           if (iteExpr.getKind() == kind::ITE &&
               iteExpr[1].getKind() == kind::EQUAL &&
               iteExpr[1][0] == (*it).first &&
@@ -3104,8 +3205,8 @@ void SmtEnginePrivate::processAssertions() {
           }
         }
         // Move this iteExpr into the main assertions
-        builder << d_assertionsToCheck[(*it).second];
-        d_assertionsToCheck[(*it).second] = NodeManager::currentNM()->mkConst<bool>(true);
+        builder << d_assertions[(*it).second];
+        d_assertions[(*it).second] = NodeManager::currentNM()->mkConst<bool>(true);
         toErase.push_back((*it).first);
       }
       if(builder.getNumChildren() > 1) {
@@ -3113,60 +3214,58 @@ void SmtEnginePrivate::processAssertions() {
           d_iteSkolemMap.erase(toErase.back());
           toErase.pop_back();
         }
-        d_assertionsToCheck[d_realAssertionsEnd - 1] =
+        d_assertions[d_realAssertionsEnd - 1] =
           Rewriter::rewrite(Node(builder));
       }
       // For some reason this is needed for some benchmarks, such as
       // http://cvc4.cs.nyu.edu/benchmarks/smtlib2/QF_AUFBV/dwp_formulas/try5_small_difret_functions_dwp_tac.re_node_set_remove_at.il.dwp.smt2
       // Figure it out later
       removeITEs();
-      //      Assert(iteRewriteAssertionsEnd == d_assertionsToCheck.size());
+      //      Assert(iteRewriteAssertionsEnd == d_assertions.size());
     }
   }
-  dumpAssertions("post-repeat-simplify", d_assertionsToCheck);
+  dumpAssertions("post-repeat-simplify", d_assertions);
 
-  dumpAssertions("pre-rewrite-apply-to-const", d_assertionsToCheck);
+  dumpAssertions("pre-rewrite-apply-to-const", d_assertions);
   if(options::rewriteApplyToConst()) {
     Chat() << "Rewriting applies to constants..." << endl;
-    TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_theoryPreprocessTime);
-    for (unsigned i = 0; i < d_assertionsToCheck.size(); ++ i) {
-      d_assertionsToCheck[i] = Rewriter::rewrite(rewriteApplyToConst(d_assertionsToCheck[i]));
+    TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_rewriteApplyToConstTime);
+    for (unsigned i = 0; i < d_assertions.size(); ++ i) {
+      d_assertions[i] = Rewriter::rewrite(rewriteApplyToConst(d_assertions[i]));
     }
   }
-  dumpAssertions("post-rewrite-apply-to-const", d_assertionsToCheck);
+  dumpAssertions("post-rewrite-apply-to-const", d_assertions);
 
   // begin: INVARIANT to maintain: no reordering of assertions or
   // introducing new ones
 #ifdef CVC4_ASSERTIONS
-  unsigned iteRewriteAssertionsEnd = d_assertionsToCheck.size();
+  unsigned iteRewriteAssertionsEnd = d_assertions.size();
 #endif
 
-  Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
-  Debug("smt") << " d_assertionsToCheck     : " << d_assertionsToCheck.size() << endl;
+  Debug("smt") << " d_assertions     : " << d_assertions.size() << endl;
 
   Debug("smt") << "SmtEnginePrivate::processAssertions() POST SIMPLIFICATION" << endl;
-  Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
-  Debug("smt") << " d_assertionsToCheck     : " << d_assertionsToCheck.size() << endl;
+  Debug("smt") << " d_assertions     : " << d_assertions.size() << endl;
 
-  dumpAssertions("pre-theory-preprocessing", d_assertionsToCheck);
+  dumpAssertions("pre-theory-preprocessing", d_assertions);
   {
     Chat() << "theory preprocessing..." << endl;
     TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_theoryPreprocessTime);
     // Call the theory preprocessors
     d_smt.d_theoryEngine->preprocessStart();
-    for (unsigned i = 0; i < d_assertionsToCheck.size(); ++ i) {
-      d_assertionsToCheck[i] = d_smt.d_theoryEngine->preprocess(d_assertionsToCheck[i]);
+    for (unsigned i = 0; i < d_assertions.size(); ++ i) {
+      d_assertions.replace(i, d_smt.d_theoryEngine->preprocess(d_assertions[i]));
     }
   }
-  dumpAssertions("post-theory-preprocessing", d_assertionsToCheck);
+  dumpAssertions("post-theory-preprocessing", d_assertions);
 
   // If we are using eager bit-blasting wrap assertions in fake atom so that
   // everything gets bit-blasted to internal SAT solver
   if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
-    for (unsigned i = 0; i < d_assertionsToCheck.size(); ++i) {
-      TNode atom = d_assertionsToCheck[i];
+    for (unsigned i = 0; i < d_assertions.size(); ++i) {
+      TNode atom = d_assertions[i];
       Node eager_atom = NodeManager::currentNM()->mkNode(kind::BITVECTOR_EAGER_ATOM, atom);
-      d_assertionsToCheck[i] = eager_atom;
+      d_assertions.replace(i, eager_atom);
       TheoryModel* m = d_smt.d_theoryEngine->getModel();
       m->addSubstitution(eager_atom, atom);
     }
@@ -3175,28 +3274,36 @@ void SmtEnginePrivate::processAssertions() {
   // Push the formula to decision engine
   if(noConflict) {
     Chat() << "pushing to decision engine..." << endl;
-    Assert(iteRewriteAssertionsEnd == d_assertionsToCheck.size());
+    Assert(iteRewriteAssertionsEnd == d_assertions.size());
     d_smt.d_decisionEngine->addAssertions
-      (d_assertionsToCheck, d_realAssertionsEnd, d_iteSkolemMap);
+      (d_assertions.ref(), d_realAssertionsEnd, d_iteSkolemMap);
   }
 
   // end: INVARIANT to maintain: no reordering of assertions or
   // introducing new ones
 
-  dumpAssertions("post-everything", d_assertionsToCheck);
-
+  dumpAssertions("post-everything", d_assertions);
+  
+  //set instantiation level of everything to zero
+  if( options::instLevelInputOnly() && options::instMaxLevel()!=-1 ){
+    for( unsigned i=0; i < d_assertions.size(); i++ ) {
+      theory::QuantifiersEngine::setInstantiationLevelAttr( d_assertions[i], 0 );
+    }
+  }
+  
   // Push the formula to SAT
   {
     Chat() << "converting to CNF..." << endl;
     TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_cnfConversionTime);
-    for (unsigned i = 0; i < d_assertionsToCheck.size(); ++ i) {
-      d_smt.d_propEngine->assertFormula(d_assertionsToCheck[i]);
+    for (unsigned i = 0; i < d_assertions.size(); ++ i) {
+      Chat() << "+ " << d_assertions[i] << std::endl;
+      d_smt.d_propEngine->assertFormula(d_assertions[i]);
     }
   }
 
   d_assertionsProcessed = true;
 
-  d_assertionsToCheck.clear();
+  d_assertions.clear();
   d_iteSkolemMap.clear();
 }
 
@@ -3211,13 +3318,8 @@ void SmtEnginePrivate::addFormula(TNode n)
   Trace("smt") << "SmtEnginePrivate::addFormula(" << n << ")" << endl;
 
   // Add the normalized formula to the queue
-  d_assertionsToPreprocess.push_back(n);
-  //d_assertionsToPreprocess.push_back(Rewriter::rewrite(n));
-
-  // If the mode of processing is incremental prepreocess and assert immediately
-  if (options::simplificationMode() == SIMPLIFICATION_MODE_INCREMENTAL) {
-    processAssertions();
-  }
+  d_assertions.push_back(n);
+  //d_assertions.push_back(Rewriter::rewrite(n));
 }
 
 void SmtEngine::ensureBoolean(const Expr& e) throw(TypeCheckingException) {
@@ -3232,7 +3334,7 @@ void SmtEngine::ensureBoolean(const Expr& e) throw(TypeCheckingException) {
   }
 }
 
-Result SmtEngine::checkSat(const Expr& ex) throw(TypeCheckingException, ModalException, LogicException) {
+Result SmtEngine::checkSat(const Expr& ex, bool inUnsatCore) throw(TypeCheckingException, ModalException, LogicException) {
   Assert(ex.isNull() || ex.getExprManager() == d_exprManager);
   SmtScope smts(this);
   finalOptionsAreSet();
@@ -3253,7 +3355,7 @@ Result SmtEngine::checkSat(const Expr& ex) throw(TypeCheckingException, ModalExc
     // Ensure expr is type-checked at this point.
     ensureBoolean(e);
     // Give it to proof manager
-    PROOF( ProofManager::currentPM()->addAssertion(e); );
+    PROOF( ProofManager::currentPM()->addAssertion(e, inUnsatCore); );
   }
 
   // check to see if a postsolve() is pending
@@ -3315,7 +3417,7 @@ Result SmtEngine::checkSat(const Expr& ex) throw(TypeCheckingException, ModalExc
   return r;
 }/* SmtEngine::checkSat() */
 
-Result SmtEngine::query(const Expr& ex) throw(TypeCheckingException, ModalException, LogicException) {
+Result SmtEngine::query(const Expr& ex, bool inUnsatCore) throw(TypeCheckingException, ModalException, LogicException) {
   Assert(!ex.isNull());
   Assert(ex.getExprManager() == d_exprManager);
   SmtScope smts(this);
@@ -3334,7 +3436,7 @@ Result SmtEngine::query(const Expr& ex) throw(TypeCheckingException, ModalExcept
   // Ensure that the expression is type-checked at this point, and Boolean
   ensureBoolean(e);
   // Give it to proof manager
-  PROOF( ProofManager::currentPM()->addAssertion(e.notExpr()); );
+  PROOF( ProofManager::currentPM()->addAssertion(e.notExpr(), inUnsatCore); );
 
   // check to see if a postsolve() is pending
   if(d_needPostsolve) {
@@ -3393,13 +3495,13 @@ Result SmtEngine::query(const Expr& ex) throw(TypeCheckingException, ModalExcept
   return r;
 }/* SmtEngine::query() */
 
-Result SmtEngine::assertFormula(const Expr& ex) throw(TypeCheckingException, LogicException) {
+Result SmtEngine::assertFormula(const Expr& ex, bool inUnsatCore) throw(TypeCheckingException, LogicException) {
   Assert(ex.getExprManager() == d_exprManager);
   SmtScope smts(this);
   finalOptionsAreSet();
   doPendingPops();
 
-  PROOF( ProofManager::currentPM()->addAssertion(ex); );
+  PROOF( ProofManager::currentPM()->addAssertion(ex, inUnsatCore); );
 
   Trace("smt") << "SmtEngine::assertFormula(" << ex << ")" << endl;
 
@@ -3412,7 +3514,7 @@ Result SmtEngine::assertFormula(const Expr& ex) throw(TypeCheckingException, Log
   }
   d_private->addFormula(e.getNode());
   return quickCheck().asValidityResult();
-}
+}/* SmtEngine::assertFormula() */
 
 Node SmtEngine::postprocess(TNode node, TypeNode expectedType) const {
   ModelPostprocessor mpost;
@@ -3882,6 +3984,30 @@ void SmtEngine::checkModel(bool hardFailure) {
   Notice() << "SmtEngine::checkModel(): all assertions checked out OK !" << endl;
 }
 
+UnsatCore SmtEngine::getUnsatCore() throw(ModalException) {
+  Trace("smt") << "SMT getUnsatCore()" << endl;
+  SmtScope smts(this);
+  finalOptionsAreSet();
+  if(Dump.isOn("benchmark")) {
+    Dump("benchmark") << GetUnsatCoreCommand();
+  }
+#ifdef CVC4_PROOF
+  if(!options::unsatCores()) {
+    throw ModalException("Cannot get an unsat core when produce-unsat-cores option is off.");
+  }
+  if(d_status.isNull() ||
+     d_status.asSatisfiabilityResult() != Result::UNSAT ||
+     d_problemExtended) {
+    throw ModalException("Cannot get an unsat core unless immediately preceded by UNSAT/VALID response.");
+  }
+
+  d_proofManager->getProof(this);// just to trigger core creation
+  return UnsatCore(this, d_proofManager->begin_unsat_core(), d_proofManager->end_unsat_core());
+#else /* CVC4_PROOF */
+  throw ModalException("This build of CVC4 doesn't have proof support (required for unsat cores).");
+#endif /* CVC4_PROOF */
+}
+
 Proof* SmtEngine::getProof() throw(ModalException) {
   Trace("smt") << "SMT getProof()" << endl;
   SmtScope smts(this);
@@ -3891,16 +4017,12 @@ Proof* SmtEngine::getProof() throw(ModalException) {
   }
 #ifdef CVC4_PROOF
   if(!options::proof()) {
-    const char* msg =
-      "Cannot get a proof when produce-proofs option is off.";
-    throw ModalException(msg);
+    throw ModalException("Cannot get a proof when produce-proofs option is off.");
   }
   if(d_status.isNull() ||
      d_status.asSatisfiabilityResult() != Result::UNSAT ||
      d_problemExtended) {
-    const char* msg =
-      "Cannot get a proof unless immediately preceded by UNSAT/VALID response.";
-    throw ModalException(msg);
+    throw ModalException("Cannot get a proof unless immediately preceded by UNSAT/VALID response.");
   }
 
   return ProofManager::getProof(this);
@@ -4048,6 +4170,33 @@ void SmtEngine::doPendingPops() {
   }
 }
 
+void SmtEngine::reset() throw() {
+  SmtScope smts(this);
+  ExprManager *em = d_exprManager;
+  Trace("smt") << "SMT reset()" << endl;
+  if(Dump.isOn("benchmark")) {
+    Dump("benchmark") << ResetCommand();
+  }
+  this->~SmtEngine();
+  new(this) SmtEngine(em);
+}
+
+void SmtEngine::resetAssertions() throw() {
+  SmtScope smts(this);
+
+  while(!d_userLevels.empty()) {
+    pop();
+  }
+
+  // Also remember the global push/pop around everything.
+  Assert(d_userLevels.size() == 0 && d_userContext->getLevel() == 1);
+  d_context->popto(0);
+  d_userContext->popto(0);
+  d_modelGlobalCommands.clear();
+  d_userContext->push();
+  d_context->push();
+}
+
 void SmtEngine::interrupt() throw(ModalException) {
   if(!d_fullyInited) {
     return;
@@ -4110,9 +4259,13 @@ SExpr SmtEngine::getStatistic(std::string name) const throw() {
   return d_statisticsRegistry->getStatistic(name);
 }
 
-void SmtEngine::setUserAttribute(const std::string& attr, Expr expr) {
+void SmtEngine::setUserAttribute(const std::string& attr, Expr expr, std::vector<Expr> expr_values, std::string str_value) {
   SmtScope smts(this);
-  d_theoryEngine->setUserAttribute(attr, expr.getNode());
+  std::vector<Node> node_values;
+  for( unsigned i=0; i<expr_values.size(); i++ ){
+    node_values.push_back( expr_values[i].getNode() );
+  }
+  d_theoryEngine->setUserAttribute(attr, expr.getNode(), node_values, str_value);
 }
 
 void SmtEngine::setPrintFuncInModel(Expr f, bool p) {
index 71b42534a539a4fb325b740b51222c2a475ea43b..7effa521ac441645461a044723992117db0c16fd 100644 (file)
@@ -28,6 +28,7 @@
 #include "expr/expr.h"
 #include "expr/expr_manager.h"
 #include "util/proof.h"
+#include "util/unsat_core.h"
 #include "smt/modal_exception.h"
 #include "smt/logic_exception.h"
 #include "options/options.h"
@@ -255,7 +256,7 @@ class CVC4_PUBLIC SmtEngine {
   smt::SmtEnginePrivate* d_private;
 
   /**
-   * Check that a generated Proof (via getProof()) checks.
+   * Check that a generated proof (via getProof()) checks.
    */
   void checkProof();
 
@@ -424,8 +425,8 @@ public:
   /**
    * Add a formula to the current context: preprocess, do per-theory
    * setup, use processAssertionList(), asserting to T-solver for
-   * literals and conjunction of literals.  Returns false iff
-   * inconsistent.
+   * literals and conjunction of literals.  Returns false if
+   * immediately determined to be inconsistent.
    */
   void defineFunction(Expr func,
                       const std::vector<Expr>& formals,
@@ -434,23 +435,25 @@ public:
   /**
    * Add a formula to the current context: preprocess, do per-theory
    * setup, use processAssertionList(), asserting to T-solver for
-   * literals and conjunction of literals.  Returns false iff
-   * inconsistent.
+   * literals and conjunction of literals.  Returns false if
+   * immediately determined to be inconsistent.  This version
+   * takes a Boolean flag to determine whether to include this asserted
+   * formula in an unsat core (if one is later requested).
    */
-  Result assertFormula(const Expr& e) throw(TypeCheckingException, LogicException);
+  Result assertFormula(const Expr& e, bool inUnsatCore = true) throw(TypeCheckingException, LogicException);
 
   /**
    * Check validity of an expression with respect to the current set
    * of assertions by asserting the query expression's negation and
    * calling check().  Returns valid, invalid, or unknown result.
    */
-  Result query(const Expr& e) throw(TypeCheckingException, ModalException, LogicException);
+  Result query(const Expr& e, bool inUnsatCore = true) throw(TypeCheckingException, ModalException, LogicException);
 
   /**
    * Assert a formula (if provided) to the current context and call
    * check().  Returns sat, unsat, or unknown result.
    */
-  Result checkSat(const Expr& e = Expr()) throw(TypeCheckingException, ModalException, LogicException);
+  Result checkSat(const Expr& e = Expr(), bool inUnsatCore = true) throw(TypeCheckingException, ModalException, LogicException);
 
   /**
    * Simplify a formula without doing "much" work.  Does not involve
@@ -506,6 +509,13 @@ public:
    */
   void printInstantiations( std::ostream& out );
 
+  /**
+   * Get an unsatisfiable core (only if immediately preceded by an
+   * UNSAT or VALID query).  Only permitted if CVC4 was built with
+   * unsat-core support and produce-unsat-cores is on.
+   */
+  UnsatCore getUnsatCore() throw(ModalException);
+
   /**
    * Get the current set of assertions.  Only permitted if the
    * SmtEngine is set to operate interactively.
@@ -522,6 +532,18 @@ public:
    */
   void pop() throw(ModalException);
 
+  /**
+   * Completely reset the state of the solver, as though destroyed and
+   * recreated.  The result is as if newly constructed (so it still
+   * retains the same options structure and ExprManager).
+   */
+  void reset() throw();
+
+  /**
+   * Reset all assertions, global declarations, etc.
+   */
+  void resetAssertions() throw();
+
   /**
    * Interrupt a running query.  This can be called from another thread
    * or from a signal handler.  Throws a ModalException if the SmtEngine
@@ -651,7 +673,7 @@ public:
    * This function is called when an attribute is set by a user.
    * In SMT-LIBv2 this is done via the syntax (! expr :attr)
    */
-  void setUserAttribute(const std::string& attr, Expr expr);
+  void setUserAttribute(const std::string& attr, Expr expr, std::vector<Expr> expr_values, std::string str_value);
 
   /**
    * Set print function in model
index 54b9fa1d0aa17cfeaab5fac0800b056fa2383075..fb5810fd54e9cfdf6b466041e61f4fc926492ee8 100644 (file)
@@ -40,9 +40,14 @@ inline SmtEngine* currentSmtEngine() {
 }
 
 inline ProofManager* currentProofManager() {
-  Assert(PROOF_ON());
+#ifdef CVC4_PROOF
+  Assert(options::proof() || options::unsatCores());
   Assert(s_smtEngine_current != NULL);
   return s_smtEngine_current->d_proofManager;
+#else /* CVC4_PROOF */
+  InternalError("proofs/unsat cores are not on, but ProofManager requested");
+  return NULL;
+#endif /* CVC4_PROOF */
 }
 
 class SmtScope : public NodeManagerScope {
index 220737d2e39a318512b453d887afbec206b93073..c657796ee8a8f95ef6d3c33de4f305103a18f322 100644 (file)
@@ -335,7 +335,7 @@ TheoryArithPrivate::Statistics::Statistics()
   , d_unsatPivots("theory::arith::pivots::unsat")
   , d_unknownPivots("theory::arith::pivots::unkown")
   , d_solveIntModelsAttempts("theory::arith::z::solveInt::models::attempts", 0)
-  , d_solveIntModelsSuccessful("zzz::solveInt::models::successful", 0)
+  , d_solveIntModelsSuccessful("theory::arith::zzz::solveInt::models::successful", 0)
   , d_mipTimer("theory::arith::z::approx::mip::timer")
   , d_lpTimer("theory::arith::z::approx::lp::timer")
   , d_mipProofsAttempted("theory::arith::z::mip::proofs::attempted", 0)
index dc907ba0b0c1966be1afca7241aa0cc81c1746ac..9b2d3647e0c36f7377ed5b5b7bebce726cf66bc0 100644 (file)
@@ -181,6 +181,20 @@ void ArrayInfo::setModelRep(const TNode a, const TNode b) {
   
 }
 
+void ArrayInfo::setConstArr(const TNode a, const TNode constArr) {
+  Assert(a.getType().isArray());
+  Info* temp_info;
+  CNodeInfoMap::iterator it = info_map.find(a);
+  if(it == info_map.end()) {
+    temp_info = new Info(ct, bck);
+    temp_info->constArr = constArr;
+    info_map[a] = temp_info;
+  } else {
+    (*it).second->constArr = constArr;
+  }
+  
+}
+
 /**
  * Returns the information associated with TNode a
  */
@@ -224,6 +238,16 @@ const TNode ArrayInfo::getModelRep(const TNode a) const
   return TNode();
 }
 
+const TNode ArrayInfo::getConstArr(const TNode a) const
+{
+  CNodeInfoMap::const_iterator it = info_map.find(a);
+
+  if(it!= info_map.end()) {
+    return (*it).second->constArr;
+  }
+  return TNode();
+}
+
 const CTNodeList* ArrayInfo::getIndices(const TNode a) const{
   CNodeInfoMap::const_iterator it = info_map.find(a);
   if(it!= info_map.end()) {
index 09230bba78598f68df5f80961ab0c5fd844e84a6..f3c6385e592fce218f7fabe3f3ed0b663f616899 100644 (file)
@@ -64,11 +64,12 @@ public:
   context::CDO<bool> isNonLinear;
   context::CDO<bool> rIntro1Applied;
   context::CDO<TNode> modelRep;
+  context::CDO<TNode> constArr;
   CTNodeList* indices;
   CTNodeList* stores;
   CTNodeList* in_stores;
 
-  Info(context::Context* c, Backtracker<TNode>* bck) : isNonLinear(c, false), rIntro1Applied(c, false), modelRep(c,TNode()) {
+  Info(context::Context* c, Backtracker<TNode>* bck) : isNonLinear(c, false), rIntro1Applied(c, false), modelRep(c,TNode()), constArr(c,TNode()) {
     indices = new(true)CTNodeList(c);
     stores = new(true)CTNodeList(c);
     in_stores = new(true)CTNodeList(c);
@@ -210,6 +211,7 @@ public:
   void setRIntro1Applied(const TNode a);
   void setModelRep(const TNode a, const TNode rep);
 
+  void setConstArr(const TNode a, const TNode constArr);
   /**
    * Returns the information associated with TNode a
    */
@@ -222,6 +224,8 @@ public:
 
   const TNode getModelRep(const TNode a) const;
 
+  const TNode getConstArr(const TNode a) const;
+
   const CTNodeList* getIndices(const TNode a) const;
 
   const CTNodeList* getStores(const TNode a) const;
index 15220fbc218e63184f5e2060fd1ca9c3ca7752e1..8ed80c1f136c3b42e0042c6f8e797c751aaaa68f 100644 (file)
@@ -12,7 +12,7 @@ option arraysLazyRIntro1 --arrays-lazy-rintro1 bool :default true :read-write
  turn on optimization to only perform RIntro1 rule lazily (see Jovanovic/Barrett 2012: Being Careful with Theory Combination)
 
 option arraysModelBased --arrays-model-based bool :default false :read-write
- turn on model-based arrray solver
+ turn on model-based array solver
 
 option arraysEagerIndexSplitting --arrays-eager-index bool :default true :read-write
  turn on eager index splitting for generated array lemmas
@@ -20,4 +20,13 @@ option arraysEagerIndexSplitting --arrays-eager-index bool :default true :read-w
 option arraysEagerLemmas --arrays-eager-lemmas bool :default false :read-write
  turn on eager lemma generation for arrays
 
+option arraysConfig --arrays-config int :default 0 :read-write
+ set different array option configurations - for developers only
+
+option arraysReduceSharing --arrays-reduce-sharing bool :default false :read-write
+ use model information to reduce size of care graph for arrays
+
+option arraysPropagate --arrays-prop int :default 2 :read-write
+ propagation effort for arrays: 0 is none, 1 is some, 2 is full
+
 endmodule
index e73c059d410ceb04b88107eb9d70f438a2dc37af..cf0eeb14bf2c0a3912ad54d213bb29856b1b40bc 100644 (file)
@@ -40,11 +40,11 @@ namespace arrays {
 const bool d_ccStore = false;
 const bool d_useArrTable = false;
   //const bool d_eagerLemmas = false;
-const bool d_propagateLemmas = true;
 const bool d_preprocess = true;
 const bool d_solveWrite = true;
 const bool d_solveWrite2 = false;
   // These are now options
+  //const bool d_propagateLemmas = true;
   //bool d_useNonLinearOpt = true;
   //bool d_lazyRIntro1 = true;
   //bool d_eagerIndexSplitting = false;
@@ -87,6 +87,7 @@ TheoryArrays::TheoryArrays(context::Context* c, context::UserContext* u, OutputC
   d_permRef(c),
   d_modelConstraints(c),
   d_lemmasSaved(c),
+  d_defValues(c),
   d_inCheckModel(false)
 {
   StatisticsRegistry::registerStat(&d_numRow);
@@ -449,6 +450,7 @@ void TheoryArrays::preRegisterTermInternal(TNode node)
 
     if (node.getType().isArray()) {
       d_equalityEngine.addTriggerTerm(node, THEORY_ARRAY);
+      d_mayEqualEqualityEngine.addTerm(node);
     }
     else {
       d_equalityEngine.addTerm(node);
@@ -468,7 +470,6 @@ void TheoryArrays::preRegisterTermInternal(TNode node)
     break;
   }
   case kind::STORE: {
-    // Invariant: array terms should be preregistered before being added to the equality engine
     if (d_equalityEngine.hasTerm(node)) {
       break;
     }
@@ -499,13 +500,28 @@ void TheoryArrays::preRegisterTermInternal(TNode node)
     break;
   }
   case kind::STORE_ALL: {
-    throw LogicException("Array theory solver does not yet support assertions using constant array value");
+    if (d_equalityEngine.hasTerm(node)) {
+      break;
+    }
+    ArrayStoreAll storeAll = node.getConst<ArrayStoreAll>();
+    Node defaultValue = Node::fromExpr(storeAll.getExpr());
+    if (!defaultValue.isConst()) {
+      throw LogicException("Array theory solver does not yet support non-constant default values for arrays");
+    }
+    d_infoMap.setConstArr(node, node);
+    d_equalityEngine.addTriggerTerm(node, THEORY_ARRAY);
+    d_mayEqualEqualityEngine.addTerm(node);
+    Assert(d_mayEqualEqualityEngine.getRepresentative(node) == node);
+    d_defValues[node] = defaultValue;
+    break;
   }
   default:
     // Variables etc
     if (node.getType().isArray()) {
       d_equalityEngine.addTriggerTerm(node, THEORY_ARRAY);
       Assert(d_equalityEngine.getSize(node) == 1);
+      // The may equal needs the node
+      d_mayEqualEqualityEngine.addTerm(node);
     }
     else {
       d_equalityEngine.addTerm(node);
@@ -566,12 +582,11 @@ EqualityStatus TheoryArrays::getEqualityStatus(TNode a, TNode b) {
     // The terms are implied to be equal
     return EQUALITY_TRUE;
   }
-  if (d_equalityEngine.areDisequal(a, b, false)) {
+  else if (d_equalityEngine.areDisequal(a, b, false)) {
     // The terms are implied to be dis-equal
     return EQUALITY_FALSE;
   }
-  //TODO: can we be more precise sometimes?
-  return EQUALITY_UNKNOWN;
+  return EQUALITY_UNKNOWN;//FALSE_IN_MODEL;
 }
 
 
@@ -665,18 +680,19 @@ void TheoryArrays::computeCareGraph()
             // Should have been propagated to us
             Assert(false);
             break;
-          case EQUALITY_FALSE_AND_PROPAGATED:
-            // Should have been propagated to us
-            Assert(false);
-            break;
-          case EQUALITY_FALSE:
           case EQUALITY_TRUE:
             // Missed propagation - need to add the pair so that theory engine can force propagation
             Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): missed propagation" << std::endl;
             break;
+          case EQUALITY_FALSE_AND_PROPAGATED:
+            // Should have been propagated to us
+            Assert(false);
+          case EQUALITY_FALSE:
           case EQUALITY_FALSE_IN_MODEL:
-            Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): false in model" << std::endl;
-            break;
+            // Don't need to include this pair
+            if (options::arraysReduceSharing()) {
+              continue;
+            }
           default:
             break;
         }
@@ -811,10 +827,22 @@ void TheoryArrays::collectModelInfo( TheoryModel* m, bool fullModel )
   }
 
   Node rep;
-  map<Node, Node> defValues;
-  map<Node, Node>::iterator it;
+  DefValMap::iterator it;
   TypeSet defaultValuesSet;
 
+  // Compute all default values already in use
+  if (fullModel) {
+    for (size_t i=0; i<arrays.size(); ++i) {
+      TNode nrep = d_equalityEngine.getRepresentative(arrays[i]);
+      d_mayEqualEqualityEngine.addTerm(nrep); // add the term in case it isn't there already
+      TNode mayRep = d_mayEqualEqualityEngine.getRepresentative(nrep);
+      it = d_defValues.find(mayRep);
+      if (it != d_defValues.end()) {
+        defaultValuesSet.add(nrep.getType().getArrayConstituentType(), (*it).second);
+      }
+    }
+  }
+
   // Loop through all array equivalence classes that need a representative computed
   for (size_t i=0; i<arrays.size(); ++i) {
     TNode n = arrays[i];
@@ -822,11 +850,10 @@ void TheoryArrays::collectModelInfo( TheoryModel* m, bool fullModel )
 
     if (fullModel) {
       // Compute default value for this array - there is one default value for every mayEqual equivalence class
-      d_mayEqualEqualityEngine.addTerm(nrep); // add the term in case it isn't there already
       TNode mayRep = d_mayEqualEqualityEngine.getRepresentative(nrep);
-      it = defValues.find(mayRep);
+      it = d_defValues.find(mayRep);
       // If this mayEqual EC doesn't have a default value associated, get the next available default value for the associated array element type
-      if (it == defValues.end()) {
+      if (it == d_defValues.end()) {
         TypeNode valueType = nrep.getType().getArrayConstituentType();
         rep = defaultValuesSet.nextTypeEnum(valueType);
         if (rep.isNull()) {
@@ -834,7 +861,7 @@ void TheoryArrays::collectModelInfo( TheoryModel* m, bool fullModel )
           rep = *(defaultValuesSet.getSet(valueType)->begin());
         }
         Trace("arrays-models") << "New default value = " << rep << endl;
-        defValues[mayRep] = rep;
+        d_defValues[mayRep] = rep;
       }
       else {
         rep = (*it).second;
@@ -992,7 +1019,9 @@ void TheoryArrays::check(Effort e) {
   if(!options::arraysEagerLemmas() && fullEffort(e) && !d_conflict && !options::arraysModelBased()) {
     // generate the lemmas on the worklist
     Trace("arrays-lem")<<"Arrays::discharging lemmas: "<<d_RowQueue.size()<<"\n";
-    dischargeLemmas();
+    while (d_RowQueue.size() > 0 && !d_conflict) {
+      dischargeLemmas();
+    }
   }
 
   Trace("arrays") << spaces(getSatContext()->getLevel()) << "Arrays::check(): done" << endl;
@@ -2036,7 +2065,42 @@ void TheoryArrays::mergeArrays(TNode a, TNode b)
       }
     }
 
+    TNode constArrA = d_infoMap.getConstArr(a);
+    TNode constArrB = d_infoMap.getConstArr(b);
+    if (constArrA.isNull()) {
+      if (!constArrB.isNull()) {
+        d_infoMap.setConstArr(a,constArrB);
+      }
+    }
+    else if (!constArrB.isNull()) {
+      if (constArrA != constArrB) {
+        conflict(constArrA,constArrB);
+      }
+    }
+
+    // If a and b have different default values associated with their mayequal equivalence classes,
+    // things get complicated - disallow this for now.  -Clark
+    TNode mayRepA = d_mayEqualEqualityEngine.getRepresentative(a);
+    TNode mayRepB = d_mayEqualEqualityEngine.getRepresentative(b);
+
+    DefValMap::iterator it = d_defValues.find(mayRepA);
+    DefValMap::iterator it2 = d_defValues.find(mayRepB);
+    TNode defValue;
+
+    if (it != d_defValues.end()) {
+      defValue = (*it).second;
+      if (it2 != d_defValues.end() && (defValue != (*it2).second)) {
+        throw LogicException("Array theory solver does not yet support write-chains connecting two different constant arrays");
+      }
+    }
+    else if (it2 != d_defValues.end()) {
+      defValue = (*it2).second;
+    }
     d_mayEqualEqualityEngine.assertEquality(a.eqNode(b), true, d_true);
+    if (!defValue.isNull()) {
+      mayRepA = d_mayEqualEqualityEngine.getRepresentative(a);
+      d_defValues[mayRepA] = defValue;
+    }
 
     checkRowLemmas(a,b);
     checkRowLemmas(b,a);
@@ -2168,6 +2232,17 @@ void TheoryArrays::checkRowForIndex(TNode i, TNode a)
   Assert(a.getType().isArray());
   Assert(d_equalityEngine.getRepresentative(a) == a);
 
+  TNode constArr = d_infoMap.getConstArr(a);
+  if (!constArr.isNull()) {
+    ArrayStoreAll storeAll = constArr.getConst<ArrayStoreAll>();
+    Node defValue = Node::fromExpr(storeAll.getExpr());
+    Node selConst = NodeManager::currentNM()->mkNode(kind::SELECT, constArr, i);
+    if (!d_equalityEngine.hasTerm(selConst)) {
+      preRegisterTermInternal(selConst);
+    }
+    d_equalityEngine.assertEquality(selConst.eqNode(defValue), true, d_true);
+  }
+
   const CTNodeList* stores = d_infoMap.getStores(a);
   const CTNodeList* instores = d_infoMap.getInStores(a);
   size_t it = 0;
@@ -2211,15 +2286,25 @@ void TheoryArrays::checkRowLemmas(TNode a, TNode b)
     d_infoMap.getInfo(b)->print();
 
   const CTNodeList* i_a = d_infoMap.getIndices(a);
+  size_t it = 0;
+  TNode constArr = d_infoMap.getConstArr(b);
+  if (!constArr.isNull()) {
+    for( ; it < i_a->size(); ++it) {
+      TNode i = (*i_a)[it];
+      Node selConst = NodeManager::currentNM()->mkNode(kind::SELECT, constArr, i);
+      if (!d_equalityEngine.hasTerm(selConst)) {
+        preRegisterTermInternal(selConst);
+      }
+    }
+  }
+
   const CTNodeList* st_b = d_infoMap.getStores(b);
   const CTNodeList* inst_b = d_infoMap.getInStores(b);
-
-  size_t it = 0;
   size_t its;
 
   RowLemmaType lem;
 
-  for( ; it < i_a->size(); ++it) {
+  for(it = 0 ; it < i_a->size(); ++it) {
     TNode i = (*i_a)[it];
     its = 0;
     for ( ; its < st_b->size(); ++its) {
@@ -2277,8 +2362,9 @@ void TheoryArrays::queueRowLemma(RowLemmaType lem)
   bool bothExist = ajExists && bjExists;
 
   // If propagating, check propagations
-  if (d_propagateLemmas) {
-    if (d_equalityEngine.areDisequal(i,j,true)) {
+  int prop = options::arraysPropagate();
+  if (prop > 0) {
+    if (d_equalityEngine.areDisequal(i,j,true) && (bothExist || prop > 1)) {
       Trace("arrays-lem") << spaces(getSatContext()->getLevel()) <<"Arrays::queueRowLemma: propagating aj = bj ("<<aj<<", "<<bj<<")\n";
       Node aj_eq_bj = aj.eqNode(bj);
       Node i_eq_j = i.eqNode(j);
index 9e9d3c890f84e573f0e586b47632a53a2bf618c5..649232dae917778ed94d8ba3c434ab1dc2354c0b 100644 (file)
@@ -361,6 +361,10 @@ class TheoryArrays : public Theory {
   context::CDHashSet<Node, NodeHashFunction > d_lemmasSaved;
   std::vector<Node> d_lemmas;
 
+  // Default values for each mayEqual equivalence class
+  typedef context::CDHashMap<Node,Node,NodeHashFunction> DefValMap;
+  DefValMap d_defValues;
+
   Node getSkolem(TNode ref, const std::string& name, const TypeNode& type, const std::string& comment, bool makeEqual = true);
   Node mkAnd(std::vector<TNode>& conjunctions, bool invert = false, unsigned startIndex = 0);
   void setNonLinear(TNode a);
index 7dbef40416367f9cf04d990a7c41ce67cb5e30e0..169ac6fa74f2bdf78adaad64f6ebd291ce1f587d 100644 (file)
@@ -144,7 +144,7 @@ private:
       }
     }
 
-    // Get the current assignement
+    // Get the current assignment
     AssignmentStatus state = d_state[n];
 
     if(state != UNASSIGNED) {
index d2836c85e802baa301145d8890bcf83d32e2e118..9d12e1bb1e69877d4080bc3bec5660360e827a14 100644 (file)
@@ -42,10 +42,10 @@ public:
     }
     return booleanType;
   }
-};
+};/* class BooleanTypeRule */
 
 class IteTypeRule {
-  public:
+public:
   inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
       throw (TypeCheckingExceptionPrivate, AssertionException) {
     TypeNode thenType = n[1].getType(check);
@@ -57,15 +57,21 @@ class IteTypeRule {
         throw TypeCheckingExceptionPrivate(n, "condition of ITE is not Boolean");
       }
       if (iteType.isNull()) {
-        throw TypeCheckingExceptionPrivate(n, "both branches of the ITE must be a subtype of a common type.");
+        std::stringstream ss;
+        ss << "Both branches of the ITE must be a subtype of a common type." << std::endl
+           << "then branch: " << n[1] << std::endl
+           << "its type   : " << thenType << std::endl
+           << "else branch: " << n[2] << std::endl
+           << "its type   : " << elseType << std::endl;
+        throw TypeCheckingExceptionPrivate(n, ss.str());
       }
     }
     return iteType;
   }
-};
+};/* class IteTypeRule */
 
-}/* namespace CVC4::theory::boolean */
-}/* namespace CVC4::theory */
-}/* namespace CVC4 */
+}/* CVC4::theory::boolean namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
 
 #endif /* __CVC4__THEORY_BOOL_TYPE_RULES_H */
index 508106106480ea3e367325387e1970fed72f15be..44474c18a108bdca7f0523e9295d5a14b2d334b4 100644 (file)
@@ -302,9 +302,6 @@ operator SEXPR 0: "a symbolic expression (any arity)"
 
 operator LAMBDA 2 "a lambda expression; first parameter is a BOUND_VAR_LIST, second is lambda body"
 
-## for co-datatypes, not yet supported
-# operator MU 2 "mu"
-
 parameterized CHAIN CHAIN_OP 2: "chained operator (N-ary), turned into a conjuction of binary applications of the operator on adjoining parameters; first parameter is a CHAIN_OP representing a binary operator, rest are arguments to that operator"
 constant CHAIN_OP \
     ::CVC4::Chain \
@@ -336,7 +333,6 @@ typerule EQUAL ::CVC4::theory::builtin::EqualityTypeRule
 typerule DISTINCT ::CVC4::theory::builtin::DistinctTypeRule
 typerule SEXPR ::CVC4::theory::builtin::SExprTypeRule
 typerule LAMBDA ::CVC4::theory::builtin::LambdaTypeRule
-#typerule MU ::CVC4::theory::builtin::MuTypeRule
 typerule CHAIN ::CVC4::theory::builtin::ChainTypeRule
 typerule CHAIN_OP ::CVC4::theory::builtin::ChainedOperatorTypeRule
 
index 045f440e6ca1c350e12ade992862f98e5aa7ad81..977a097d0a68d868a3df61da0928799472632b35 100644 (file)
@@ -164,27 +164,6 @@ public:
   }
 };/* class LambdaTypeRule */
 
-/* For co-datatypes, not yet supported--
-**
-class MuTypeRule {
-public:
-  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
-    if( n[0].getType(check) != nodeManager->boundVarListType() ) {
-      std::stringstream ss;
-      ss << "expected a bound var list for MU expression, got `"
-         << n[0].getType().toString() << "'";
-      throw TypeCheckingExceptionPrivate(n, ss.str());
-    }
-    std::vector<TypeNode> argTypes;
-    for(TNode::iterator i = n[0].begin(); i != n[0].end(); ++i) {
-      argTypes.push_back((*i).getType());
-    }
-    TypeNode rangeType = n[1].getType(check);
-    return nodeManager->mkFunctionType(argTypes, rangeType);
-  }
-};
-**/
-
 class ChainTypeRule {
 public:
   inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
index ce775874f16e53e0e4db99d9c52b5bae31e243ca..6270995eff5df2e81f5542025ced34000fe48690 100644 (file)
@@ -402,7 +402,7 @@ void AigBitblaster::assertToSatSolver(Cnf_Dat_t* pCnf) {
       prop::SatLiteral lit(sat_variables[index-1], int_lit < 0); 
       clause.push_back(lit); 
     }
-    d_satSolver->addClause(clause, false); 
+    d_satSolver->addClause(clause, false, RULE_INVALID);
   }
 }
 
index ecd7013c7d9df381a81f85e70cad498c2f83bb13..ea31e382118236fd416bd6c7112b1e325eea76db 100644 (file)
@@ -74,19 +74,22 @@ protected:
   typedef std::vector<T> Bits;
   typedef __gnu_cxx::hash_map <Node, Bits, NodeHashFunction>  TermDefMap;
   typedef __gnu_cxx::hash_set<TNode, TNodeHashFunction>       TNodeSet;
+  typedef __gnu_cxx::hash_map<Node, Node, NodeHashFunction>   ModelCache;
 
   typedef void  (*TermBBStrategy) (TNode, Bits&, TBitblaster<T>*);
   typedef T     (*AtomBBStrategy) (TNode, TBitblaster<T>*);
 
   // caches and mappings
-  TermDefMap                   d_termCache;
-
+  TermDefMap d_termCache;
+  ModelCache d_modelCache;
+  
   void initAtomBBStrategies();
   void initTermBBStrategies();
 protected:
   /// function tables for the various bitblasting strategies indexed by node kind
   TermBBStrategy d_termBBStrategies[kind::LAST_KIND];
   AtomBBStrategy d_atomBBStrategies[kind::LAST_KIND]; 
+  virtual Node getModelFromSatSolver(TNode node, bool fullModel) = 0; 
 public:
   TBitblaster(); 
   virtual ~TBitblaster() {}
@@ -97,9 +100,18 @@ public:
   virtual bool hasBBAtom(TNode atom) const = 0;
   virtual void storeBBAtom(TNode atom, T atom_bb) = 0;
   
+  
   bool hasBBTerm(TNode node) const;
   void getBBTerm(TNode node, Bits& bits) const;
-  void storeBBTerm(TNode term, const Bits& bits); 
+  void storeBBTerm(TNode term, const Bits& bits);
+  /**
+   * Return a constant representing the value of a in the  model.
+   * If fullModel is true set unconstrained bits to 0. If not return
+   * NullNode() for a fully or partially unconstrained.
+   *
+   */
+  Node getTermModel(TNode node, bool fullModel);
+  void invalidateModelCache();
 }; 
 
 
@@ -109,7 +121,6 @@ class TLazyBitblaster :  public TBitblaster<Node> {
   typedef std::vector<Node> Bits;
   typedef context::CDList<prop::SatLiteral> AssertionList;
   typedef context::CDHashMap<prop::SatLiteral, std::vector<prop::SatLiteral> , prop::SatLiteralHashFunction> ExplanationMap;
-  
   /** This class gets callbacks from minisat on propagations */
   class MinisatNotify : public prop::BVSatSolverInterface::Notify {
     prop::CnfStream* d_cnf;
@@ -143,9 +154,12 @@ class TLazyBitblaster :  public TBitblaster<Node> {
   TNodeSet d_bbAtoms; 
   AbstractionModule* d_abstraction;
   bool d_emptyNotify;
+
+  context::CDO<bool> d_satSolverFullModel;
   
   void addAtom(TNode atom);
   bool hasValue(TNode a);
+  Node getModelFromSatSolver(TNode a, bool fullModel);  
 public:
   void bbTerm(TNode node, Bits&  bits);
   void bbAtom(TNode node);
@@ -172,14 +186,7 @@ public:
   void setAbstraction(AbstractionModule* abs);
   
   theory::EqualityStatus getEqualityStatus(TNode a, TNode b);
-  /**
-   * Return a constant Node representing the value of a variable
-   * in the current model.
-   * @param a
-   *
-   * @return
-   */
-  Node getVarValue(TNode a, bool fullModel=true);
+
   /**
    * Adds a constant value for each bit-blasted variable in the model.
    *
@@ -245,7 +252,7 @@ class EagerBitblaster : public TBitblaster<Node> {
   TNodeSet d_bbAtoms;
   TNodeSet d_variables;
 
-  Node getVarValue(TNode a, bool fullModel);
+  Node getModelFromSatSolver(TNode a, bool fullModel);
   bool isSharedTerm(TNode node); 
 
 public:
@@ -299,7 +306,7 @@ class AigBitblaster : public TBitblaster<Abc_Obj_t*> {
   bool hasInput(TNode input);
   void convertToCnfAndAssert();
   void assertToSatSolver(Cnf_Dat_t* pCnf);
-
+  Node getModelFromSatSolver(TNode a, bool fullModel) { Unreachable(); }
 public:
   AigBitblaster();
   ~AigBitblaster();
@@ -387,6 +394,7 @@ template <class T> void TBitblaster<T>::initTermBBStrategies() {
 template <class T>
 TBitblaster<T>::TBitblaster()
   : d_termCache()
+  , d_modelCache()
 {
   initAtomBBStrategies();
   initTermBBStrategies(); 
@@ -407,6 +415,53 @@ void TBitblaster<T>::storeBBTerm(TNode node, const Bits& bits) {
   d_termCache.insert(std::make_pair(node, bits));
 }
 
+template <class T>
+void TBitblaster<T>::invalidateModelCache() {
+  d_modelCache.clear();
+}
+
+template <class T>
+Node TBitblaster<T>::getTermModel(TNode node, bool fullModel) {
+  if (d_modelCache.find(node) != d_modelCache.end())
+    return d_modelCache[node]; 
+
+  if (node.isConst())
+    return node; 
+
+  Node value = getModelFromSatSolver(node, false);
+  if (!value.isNull()) {
+    Debug("bv-equality-status")<< "TLazyBitblaster::getTermModel from SatSolver" << node <<" => " << value <<"\n";
+    d_modelCache[node] = value;
+    Assert (value.isConst()); 
+    return value;
+  }
+
+  if (Theory::isLeafOf(node, theory::THEORY_BV)) {
+    // if it is a leaf may ask for fullModel
+    value = getModelFromSatSolver(node, fullModel); 
+    Debug("bv-equality-status")<< "TLazyBitblaster::getTermModel from VarValue" << node <<" => " << value <<"\n";
+    Assert (!value.isNull()); 
+    d_modelCache[node] = value;
+    return value;
+  }
+  Assert (node.getType().isBitVector());
+  
+  NodeBuilder<> nb(node.getKind());
+  if (node.getMetaKind() == kind::metakind::PARAMETERIZED) {
+    nb << node.getOperator(); 
+  }
+
+  for (unsigned i = 0; i < node.getNumChildren(); ++i) {
+    nb << getTermModel(node[i], fullModel); 
+  }
+  value = nb; 
+  value = Rewriter::rewrite(value);
+  Assert (value.isConst()); 
+  d_modelCache[node] = value;
+  Debug("bv-term-model")<< "TLazyBitblaster::getTermModel Building Value" << node <<" => " << value <<"\n";
+  return value; 
+}
+
 
 } /* bv namespace */
 
index 5f35f95e37385b88056ed22d5b145238d0d9ec30..b2b4eebdf3456061ab057068af450c8936c298b2 100644 (file)
@@ -115,7 +115,7 @@ BVQuickCheck::vars_iterator BVQuickCheck::endVars() {
 }
 
 Node BVQuickCheck::getVarValue(TNode var) {
-  return d_bitblaster->getVarValue(var); 
+  return d_bitblaster->getTermModel(var, true); 
 }
 
 
index a2a6e19ac604c892bccbdb9d6dedca680985653c..35542fc68122578ae33dd78f5d8bcd9b3b123379 100644 (file)
@@ -103,6 +103,7 @@ void BitblastSolver::bitblastQueue() {
       // don't bit-blast lemma atoms
       continue;
     }
+    Debug("bitblast-queue") << "Bitblasting atom " << atom <<"\n"; 
     d_bitblaster->bbAtom(atom);
   }
 }
@@ -218,48 +219,45 @@ void BitblastSolver::collectModelInfo(TheoryModel* m, bool fullModel) {
 
 Node BitblastSolver::getModelValue(TNode node)
 {
-  if (!d_validModelCache) {
-    d_modelCache.clear();
-    d_validModelCache = true;
-  }
-  return getModelValueRec(node);
-}
-
-Node BitblastSolver::getModelValueRec(TNode node)
-{
-  Node val;
-  if (node.isConst()) {
-    return node;
-  }
-  NodeMap::iterator it = d_modelCache.find(node);
-  if (it != d_modelCache.end()) {
-    val = (*it).second;
-    Debug("bitvector-model") << node << " => (cached) " << val <<"\n";
-    return val;
-  }
-  if (d_bv->isLeaf(node)) {
-    val = d_bitblaster->getVarValue(node);
-    if (val == Node()) {
-      // If no value in model, just set to 0
-      val = utils::mkConst(utils::getSize(node), (unsigned)0);
-    }
-  } else {
-    NodeBuilder<> valBuilder(node.getKind());
-    if (node.getMetaKind() == kind::metakind::PARAMETERIZED) {
-      valBuilder << node.getOperator();
-    }
-    for (unsigned i = 0; i < node.getNumChildren(); ++i) {
-      valBuilder << getModelValueRec(node[i]);
-    }
-    val = valBuilder;
-    val = Rewriter::rewrite(val);
-  }
-  Assert(val.isConst());
-  d_modelCache[node] = val;
-  Debug("bitvector-model") << node << " => " << val <<"\n";
+  Node val = d_bitblaster->getTermModel(node, false);
   return val;
 }
 
+// Node BitblastSolver::getModelValueRec(TNode node)
+// {
+//   Node val;
+//   if (node.isConst()) {
+//     return node;
+//   }
+//   NodeMap::iterator it = d_modelCache.find(node);
+//   if (it != d_modelCache.end()) {
+//     val = (*it).second;
+//     Debug("bitvector-model") << node << " => (cached) " << val <<"\n";
+//     return val;
+//   }
+//   if (d_bv->isLeaf(node)) {
+//     val = d_bitblaster->getVarValue(node);
+//     if (val == Node()) {
+//       // If no value in model, just set to 0
+//       val = utils::mkConst(utils::getSize(node), (unsigned)0);
+//     }
+//   } else {
+//     NodeBuilder<> valBuilder(node.getKind());
+//     if (node.getMetaKind() == kind::metakind::PARAMETERIZED) {
+//       valBuilder << node.getOperator();
+//     }
+//     for (unsigned i = 0; i < node.getNumChildren(); ++i) {
+//       valBuilder << getModelValueRec(node[i]);
+//     }
+//     val = valBuilder;
+//     val = Rewriter::rewrite(val);
+//   }
+//   Assert(val.isConst());
+//   d_modelCache[node] = val;
+//   Debug("bitvector-model") << node << " => " << val <<"\n";
+//   return val;
+// }
+
 
 void BitblastSolver::setConflict(TNode conflict) {
   Node final_conflict = conflict;
index 414abdccebd24e7bd0b977d1ac5828f7bc9e069c..77461163c98565ee55e350525caf5a5ccb576ee2 100644 (file)
@@ -57,7 +57,7 @@ class BitblastSolver : public SubtheorySolver {
   AbstractionModule* d_abstractionModule;
   BVQuickCheck* d_quickCheck;
   QuickXPlain* d_quickXplain;
-  Node getModelValueRec(TNode node);
+  //  Node getModelValueRec(TNode node);
   void setConflict(TNode conflict); 
 public:
   BitblastSolver(context::Context* c, TheoryBV* bv);
index e8fee00f588e80333aafd2ac6d2fdf5b2c20ea2f..877baec4eed9743a632f752cdd2d9d8db2ac2b8a 100644 (file)
@@ -56,7 +56,7 @@ EagerBitblaster::~EagerBitblaster() {
 }
 
 void EagerBitblaster::bbFormula(TNode node) {
-  d_cnfStream->convertAndAssert(node, false, false); 
+  d_cnfStream->convertAndAssert(node, false, false, RULE_INVALID, TNode::null());
 }
 
 /**
@@ -85,7 +85,7 @@ void EagerBitblaster::bbAtom(TNode node) {
 
   AlwaysAssert (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER); 
   storeBBAtom(node, atom_definition);
-  d_cnfStream->convertAndAssert(atom_definition, false, false);
+  d_cnfStream->convertAndAssert(atom_definition, false, false, RULE_INVALID, TNode::null());
 }
 
 void EagerBitblaster::storeBBAtom(TNode atom, Node atom_bb) {
@@ -156,11 +156,11 @@ bool EagerBitblaster::solve() {
  *
  * @return
  */
-Node EagerBitblaster::getVarValue(TNode a, bool fullModel) {
+Node EagerBitblaster::getModelFromSatSolver(TNode a, bool fullModel) {
   if (!hasBBTerm(a)) {
-    Assert(isSharedTerm(a));
-    return Node();
+    return fullModel? utils::mkConst(utils::getSize(a), 0u) : Node();
   }
+  
   Bits bits;
   getBBTerm(a, bits);
   Integer value(0);
@@ -171,7 +171,8 @@ Node EagerBitblaster::getVarValue(TNode a, bool fullModel) {
       bit_value = d_satSolver->value(bit);
       Assert (bit_value != prop::SAT_VALUE_UNKNOWN);
     } else {
-      // the bit is unconstrainted so we can give it an arbitrary value
+      if (!fullModel) return Node();
+      // unconstrained bits default to false
       bit_value = prop::SAT_VALUE_FALSE;
     }
     Integer bit_int = bit_value == prop::SAT_VALUE_TRUE ? Integer(1) : Integer(0);
@@ -182,19 +183,17 @@ Node EagerBitblaster::getVarValue(TNode a, bool fullModel) {
 
 
 void EagerBitblaster::collectModelInfo(TheoryModel* m, bool fullModel) {
-  TNodeSet::const_iterator it = d_variables.begin();
+  TNodeSet::iterator it = d_variables.begin();
   for (; it!= d_variables.end(); ++it) {
     TNode var = *it;
-    if (Theory::theoryOf(var) == theory::THEORY_BV || isSharedTerm(var))  {
-      Node const_value = getVarValue(var, fullModel);
-      if(const_value == Node()) {
-        if( fullModel ){
-          // if the value is unassigned just set it to zero
-          const_value = utils::mkConst(BitVector(utils::getSize(var), 0u));
-        }
-      }
+    if (d_bv->isLeaf(var) || isSharedTerm(var))  {
+      // only shared terms could not have been bit-blasted
+      Assert (hasBBTerm(var) || isSharedTerm(var));
+      
+      Node const_value = getModelFromSatSolver(var, fullModel);
+      
       if(const_value != Node()) {
-        Debug("bitvector-model") << "TLazyBitblaster::collectModelInfo (assert (= "
+        Debug("bitvector-model") << "EagerBitblaster::collectModelInfo (assert (= "
                                  << var << " "
                                  << const_value << "))\n";
         m->assertEquality(var, const_value, true);
index f721a22f032491be37ccf59eb4fd392153fb35ce..f8927284fd68f3024356baaefb5bdc85b1232902 100644 (file)
@@ -41,6 +41,7 @@ TLazyBitblaster::TLazyBitblaster(context::Context* c, bv::TheoryBV* bv, const st
   , d_bbAtoms()
   , d_abstraction(NULL)
   , d_emptyNotify(emptyNotify)
+  , d_satSolverFullModel(c, false)
   , d_name(name)
   , d_statistics(name) {
   d_satSolver = prop::SatSolverFactory::createMinisat(c, name);
@@ -113,7 +114,7 @@ void TLazyBitblaster::bbAtom(TNode node) {
     Assert (!atom_bb.isNull()); 
     Node atom_definition = utils::mkNode(kind::IFF, node, atom_bb);
     storeBBAtom(node, atom_bb);
-    d_cnfStream->convertAndAssert(atom_definition, false, false); 
+    d_cnfStream->convertAndAssert(atom_definition, false, false, RULE_INVALID, TNode::null());
     return; 
   }
 
@@ -125,7 +126,7 @@ void TLazyBitblaster::bbAtom(TNode node) {
   // asserting that the atom is true iff the definition holds
   Node atom_definition = utils::mkNode(kind::IFF, node, atom_bb);
   storeBBAtom(node, atom_bb);
-  d_cnfStream->convertAndAssert(atom_definition, false, false);
+  d_cnfStream->convertAndAssert(atom_definition, false, false, RULE_INVALID, TNode::null());
 }
 
 void TLazyBitblaster::storeBBAtom(TNode atom, Node atom_bb) {
@@ -258,6 +259,7 @@ bool TLazyBitblaster::solve() {
     }
   }
   Debug("bitvector") << "TLazyBitblaster::solve() asserted atoms " << d_assertedAtoms->size() <<"\n";
+  d_satSolverFullModel.set(true); 
   return prop::SAT_VALUE_TRUE == d_satSolver->solve();
 }
 
@@ -354,42 +356,38 @@ void TLazyBitblaster::MinisatNotify::safePoint() {
   d_bv->d_out->safePoint();
 }
 
+
 EqualityStatus TLazyBitblaster::getEqualityStatus(TNode a, TNode b) {
+  Debug("bv-equality-status")<< "TLazyBitblaster::getEqualityStatus " << a <<" = " << b <<"\n";
+  Debug("bv-equality-status")<< "BVSatSolver has full model? " << d_satSolverFullModel.get() <<"\n";
 
-  // We don't want to bit-blast every possibly expensive term for the sake of equality checking
-  if (hasBBTerm(a) && hasBBTerm(b)) {
-
-    Bits a_bits, b_bits;
-    getBBTerm(a, a_bits);
-    getBBTerm(b, b_bits);
-    theory::EqualityStatus status = theory::EQUALITY_TRUE_IN_MODEL;
-    for (unsigned i = 0; i < a_bits.size(); ++ i) {
-      if (d_cnfStream->hasLiteral(a_bits[i]) && d_cnfStream->hasLiteral(b_bits[i])) {
-        prop::SatLiteral a_lit = d_cnfStream->getLiteral(a_bits[i]);
-        prop::SatValue a_lit_value = d_satSolver->value(a_lit);
-        if (a_lit_value != prop::SAT_VALUE_UNKNOWN) {
-          prop::SatLiteral b_lit = d_cnfStream->getLiteral(b_bits[i]);
-          prop::SatValue b_lit_value = d_satSolver->value(b_lit);
-          if (b_lit_value != prop::SAT_VALUE_UNKNOWN) {
-            if (a_lit_value != b_lit_value) {
-              return theory::EQUALITY_FALSE_IN_MODEL;
-            }
-          } else {
-            status = theory::EQUALITY_UNKNOWN;
-          }
-        } {
-          status = theory::EQUALITY_UNKNOWN;
-        }
-      } else {
-        status = theory::EQUALITY_UNKNOWN;
-      }
-    }
+  // First check if it trivially rewrites to false/true
+  Node a_eq_b = Rewriter::rewrite(utils::mkNode(kind::EQUAL, a, b));
 
-    return status;
+  if (a_eq_b == utils::mkFalse()) return theory::EQUALITY_FALSE;
+  if (a_eq_b == utils::mkTrue()) return theory::EQUALITY_TRUE;
 
-  } else {
-    return theory::EQUALITY_UNKNOWN;
+  if (!d_satSolverFullModel.get())
+    return theory::EQUALITY_UNKNOWN; 
+  
+  // Check if cache is valid (invalidated in check and pops)
+  if (d_bv->d_invalidateModelCache.get()) {
+    invalidateModelCache(); 
   }
+  d_bv->d_invalidateModelCache.set(false); 
+
+  Node a_value = getTermModel(a, true);
+  Node b_value = getTermModel(b, true);
+
+  Assert (a_value.isConst() &&
+          b_value.isConst());
+
+  if (a_value == b_value) {
+    Debug("bv-equality-status")<< "theory::EQUALITY_TRUE_IN_MODEL\n";
+    return theory::EQUALITY_TRUE_IN_MODEL; 
+  }
+  Debug("bv-equality-status")<< "theory::EQUALITY_FALSE_IN_MODEL\n";
+  return theory::EQUALITY_FALSE_IN_MODEL; 
 }
 
 
@@ -424,11 +422,11 @@ bool TLazyBitblaster::hasValue(TNode a) {
  *
  * @return
  */
-Node TLazyBitblaster::getVarValue(TNode a, bool fullModel) {
+Node TLazyBitblaster::getModelFromSatSolver(TNode a, bool fullModel) {
   if (!hasBBTerm(a)) {
-    Assert(isSharedTerm(a));
-    return Node();
+    return fullModel? utils::mkConst(utils::getSize(a), 0u) : Node();
   }
+  
   Bits bits;
   getBBTerm(a, bits);
   Integer value(0);
@@ -439,7 +437,8 @@ Node TLazyBitblaster::getVarValue(TNode a, bool fullModel) {
       bit_value = d_satSolver->value(bit);
       Assert (bit_value != prop::SAT_VALUE_UNKNOWN);
     } else {
-      // the bit is unconstrainted so we can give it an arbitrary value
+      if (!fullModel) return Node();
+      // unconstrained bits default to false
       bit_value = prop::SAT_VALUE_FALSE;
     }
     Integer bit_int = bit_value == prop::SAT_VALUE_TRUE ? Integer(1) : Integer(0);
@@ -449,23 +448,26 @@ Node TLazyBitblaster::getVarValue(TNode a, bool fullModel) {
 }
 
 void TLazyBitblaster::collectModelInfo(TheoryModel* m, bool fullModel) {
-  TNodeSet::iterator it = d_variables.begin();
-  for (; it!= d_variables.end(); ++it) {
+  std::set<Node> termSet;
+  d_bv->computeRelevantTerms(termSet);
+
+  for (std::set<Node>::const_iterator it = termSet.begin(); it != termSet.end(); ++it) {
     TNode var = *it;
-    if (Theory::theoryOf(var) == theory::THEORY_BV || isSharedTerm(var))  {
-      Node const_value = getVarValue(var, fullModel);
-      if(const_value == Node()) {
-        if( fullModel ){
-          // if the value is unassigned just set it to zero
-          const_value = utils::mkConst(BitVector(utils::getSize(var), 0u));
-        }
-      }
-      if(const_value != Node()) {
-        Debug("bitvector-model") << "TLazyBitblaster::collectModelInfo (assert (= "
-                                 << var << " "
-                                 << const_value << "))\n";
+    // not actually a leaf of the bit-vector theory
+    if (d_variables.find(var) == d_variables.end())
+      continue;
+    
+    Assert (Theory::theoryOf(var) == theory::THEORY_BV || isSharedTerm(var)); 
+    // only shared terms could not have been bit-blasted
+    Assert (hasBBTerm(var) || isSharedTerm(var));
+    
+    Node const_value = getModelFromSatSolver(var, fullModel);
+    Assert (const_value.isNull() || const_value.isConst()); 
+    if(const_value != Node()) {
+      Debug("bitvector-model") << "TLazyBitblaster::collectModelInfo (assert (= "
+                               << var << " "
+                               << const_value << "))\n";
         m->assertEquality(var, const_value, true);
-      }
     }
   }
 }
@@ -481,7 +483,7 @@ void TLazyBitblaster::clearSolver() {
   d_bbAtoms.clear();
   d_variables.clear();
   d_termCache.clear(); 
-
+  
   // recreate sat solver
   d_satSolver = prop::SatSolverFactory::createMinisat(d_ctx);
   d_cnfStream = new prop::TseitinCnfStream(d_satSolver,
index 4abf25bb1bd1388e1697a98c0ebd600a7b7adc64..91150f663a2fc675c6df1974dd727e20b7532619 100644 (file)
@@ -49,6 +49,7 @@ TheoryBV::TheoryBV(context::Context* c, context::UserContext* u, OutputChannel&
     d_staticLearnCache(),
     d_lemmasAdded(c, false),
     d_conflict(c, false),
+    d_invalidateModelCache(c, true),
     d_literalsToPropagate(c),
     d_literalsToPropagateIndex(c, 0),
     d_propagatedBy(c),
@@ -356,8 +357,12 @@ void TheoryBV::checkForLemma(TNode fact) {
 
 void TheoryBV::check(Effort e)
 {
+  if (done() && !fullEffort(e)) {
+    return;
+  }
   Debug("bitvector") << "TheoryBV::check(" << e << ")" << std::endl;
-
+  // we may be getting new assertions so the model cache may not be sound
+  d_invalidateModelCache.set(true); 
   // if we are using the eager solver
   if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
     // this can only happen on an empty benchmark
index 22d9f677515d6133dd2b1a77bff30a684635e1ae..a37a4019e648a9ff652e2b3d8848749384c7b605 100644 (file)
@@ -141,6 +141,9 @@ private:
   // Are we in conflict?
   context::CDO<bool> d_conflict;
 
+  // Invalidate the model cache if check was called
+  context::CDO<bool> d_invalidateModelCache;
+
   /** The conflict node */
   Node d_conflictNode;
 
index d8b42111ca4e2bd657eb0e5c56a3d165e330b281..faaf78fe49e778263d3cc76e35196ac09a5aff94 100644 (file)
@@ -89,6 +89,12 @@ typerule APPLY_TYPE_ASCRIPTION ::CVC4::theory::datatypes::DatatypeAscriptionType
 # constructor applications are constant if they are applied only to constants
 construle APPLY_CONSTRUCTOR ::CVC4::theory::datatypes::DatatypeConstructorTypeRule
 
+## for co-datatypes
+operator MU 2 "a mu operator, first argument is a bound variable, second argument is body"
+typerule MU ::CVC4::theory::datatypes::DatatypeMuTypeRule
+# mu applications are constant expressions
+construle MU ::CVC4::theory::datatypes::DatatypeMuTypeRule
+
 operator TUPLE_TYPE 0: "tuple type"
 cardinality TUPLE_TYPE \
     "::CVC4::theory::datatypes::TupleProperties::computeCardinality(%TYPE%)" \
index 5fc59b54939546575f18d54e6761cb96c97aa1ae..7e56b4d7a77d72480f2d1711418c3a343d99d9ad 100644 (file)
@@ -13,5 +13,7 @@ expert-option dtRewriteErrorSel --dt-rewrite-error-sel bool :default false
  rewrite incorrectly applied selectors to arbitrary ground term
 option dtForceAssignment --dt-force-assignment bool :default false :read-write
  force the datatypes solver to give specific values to all datatypes terms before answering sat
+option cdtBisimilar --cdt-bisimilar bool :default true
+ do bisimilarity check for co-datatypes
  
 endmodule
index 544589306cfd0b56fd2400203ba7b1151c2a30a2..145cd32dd924fcb458becc422095f901d85cd7d5 100644 (file)
@@ -62,6 +62,7 @@ TheoryDatatypes::TheoryDatatypes(Context* c, UserContext* u, OutputChannel& out,
   d_equalityEngine.addFunctionKind(kind::APPLY_UF);
 
   d_true = NodeManager::currentNM()->mkConst( true );
+  d_dtfCounter = 0;
 }
 
 TheoryDatatypes::~TheoryDatatypes() {
@@ -118,6 +119,10 @@ TNode TheoryDatatypes::getEqcConstructor( TNode r ) {
 }
 
 void TheoryDatatypes::check(Effort e) {
+  if (done() && !fullEffort(e)) {
+    return;
+  }
+
   Trace("datatypes-debug") << "Check effort " << e << std::endl;
   while(!done() && !d_conflict) {
     // Get all the assertions
@@ -142,7 +147,7 @@ void TheoryDatatypes::check(Effort e) {
     flushPendingFacts();
   }
 
-  if( e == EFFORT_FULL ) {
+  if( e == EFFORT_FULL && !d_conflict ) {
     //check for cycles
     bool addedFact;
     do {
@@ -190,19 +195,23 @@ void TheoryDatatypes::check(Effort e) {
                 }
               }
             }
-            /*
-            if( !needSplit && mustSpecifyAssignment() ){
+            //d_dtfCounter++;
+            if( !needSplit && options::dtForceAssignment() && d_dtfCounter%2==0 ){
               //for the sake of termination, we must choose the constructor of a ground term
               //NEED GUARENTEE: groundTerm should not contain any subterms of the same type
               // TODO: this is probably not good enough, actually need fair enumeration strategy
-              Node groundTerm = n.getType().mkGroundTerm();
-              int index = Datatype::indexOf( groundTerm.getOperator().toExpr() );
-              if( pcons[index] ){
-                consIndex = index;
+              if( !n.getType().isRecord() ){ //FIXME
+                Node groundTerm = n.getType().mkGroundTerm();
+                if( groundTerm.getOperator().getType().isConstructor() ){ //FIXME
+                  int index = Datatype::indexOf( groundTerm.getOperator().toExpr() );
+                  if( pcons[index] ){
+                    consIndex = index;
+                  }
+                  needSplit = true;
+                }
               }
-              needSplit = true;
             }
-            */
+
             if( needSplit && consIndex!=-1 ) {
               //if only one constructor, then this term must be this constructor
               if( dt.getNumConstructors()==1 ){
@@ -570,7 +579,12 @@ void TheoryDatatypes::explain(TNode literal, std::vector<TNode>& assumptions){
   TNode atom = polarity ? literal : literal[0];
   if (atom.getKind() == kind::EQUAL || atom.getKind() == kind::IFF) {
     explainEquality( atom[0], atom[1], polarity, assumptions );
+  } else if( atom.getKind() == kind::AND && polarity ){
+    for( unsigned i=0; i<atom.getNumChildren(); i++ ){
+      explain( atom[i], assumptions );
+    }
   } else {
+    Assert( atom.getKind()!=kind::AND );
     explainPredicate( atom, polarity, assumptions );
   }
 }
@@ -670,7 +684,7 @@ void TheoryDatatypes::merge( Node t1, Node t2 ){
             for( unsigned i=0; i<deq_cand.size(); i++ ){
               if( d_equalityEngine.areDisequal( deq_cand[i].first, deq_cand[i].second, true ) ){
                 conf = true;
-                Node eq = NodeManager::currentNM()->mkNode( deq_cand[i].first.getType().isBoolean() ? kind::IFF : kind::EQUAL, 
+                Node eq = NodeManager::currentNM()->mkNode( deq_cand[i].first.getType().isBoolean() ? kind::IFF : kind::EQUAL,
                                                             deq_cand[i].first, deq_cand[i].second );
                 exp.push_back( eq.negate() );
               }
@@ -1307,32 +1321,44 @@ void TheoryDatatypes::collectModelInfo( TheoryModel* m, bool fullModel ){
     const Datatype& dt = ((DatatypeType)(eqc.getType()).toType()).getDatatype();
     if( dt.isCodatatype() ){
       std::map< Node, Node > vmap;
-      Node v = getCodatatypesValue( it->first, eqc_cons, eqc_mu, vmap );
-      Trace("dt-cmi-cod") << "  EQC(" << it->first << "), constructor is " << it->second << ", value is " << v << std::endl;
+      std::vector< Node > fv;
+      Node v = getCodatatypesValue( it->first, eqc_cons, eqc_mu, vmap, fv );
+      Trace("dt-cmi-cdt") << "  EQC(" << it->first << "), constructor is " << it->second << ", value is " << v << ", const = " << v.isConst() << std::endl;
+      m->assertEquality( eqc, v, true );
     }
   }
 }
 
 
-Node TheoryDatatypes::getCodatatypesValue( Node n, std::map< Node, Node >& eqc_cons, std::map< Node, Node >& eqc_mu, std::map< Node, Node >& vmap ){
+Node TheoryDatatypes::getCodatatypesValue( Node n, std::map< Node, Node >& eqc_cons, std::map< Node, Node >& eqc_mu, std::map< Node, Node >& vmap, std::vector< Node >& fv ){
   std::map< Node, Node >::iterator itv = vmap.find( n );
   if( itv!=vmap.end() ){
+    if( std::find( fv.begin(), fv.end(), itv->second )==fv.end() ){
+      fv.push_back( itv->second );
+    }
     return itv->second;
   }else if( DatatypesRewriter::isTermDatatype( n ) ){
-    Node nv = NodeManager::currentNM()->mkBoundVar( n.getType() );
+    std::stringstream ss;
+    ss << "$x" << vmap.size();
+    Node nv = NodeManager::currentNM()->mkBoundVar( ss.str().c_str(), n.getType() );
     vmap[n] = nv;
-    Trace("dt-cmi-cod-debug") << "    map " << n << " -> " << nv << std::endl;
+    Trace("dt-cmi-cdt-debug") << "    map " << n << " -> " << nv << std::endl;
     Node nc = eqc_cons[n];
     Assert( nc.getKind()==APPLY_CONSTRUCTOR );
     std::vector< Node > children;
     children.push_back( nc.getOperator() );
     for( unsigned i=0; i<nc.getNumChildren(); i++ ){
       Node r = getRepresentative( nc[i] );
-      Node rv = getCodatatypesValue( r, eqc_cons, eqc_mu, vmap );
+      Node rv = getCodatatypesValue( r, eqc_cons, eqc_mu, vmap, fv );
       children.push_back( rv );
     }
     vmap.erase( n );
-    return NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, children );
+    Node v = NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, children );
+    //add mu if we found a circular reference
+    if( std::find( fv.begin(), fv.end(), nv )!=fv.end() ){
+      v = NodeManager::currentNM()->mkNode( MU, nv, v );
+    }
+    return v;
   }else{
     return n;
   }
@@ -1450,7 +1476,7 @@ void TheoryDatatypes::instantiate( EqcInfo* eqc, Node n ){
 
 void TheoryDatatypes::checkCycles() {
   Debug("datatypes-cycle-check") << "Check cycles" << std::endl;
-  std::vector< Node > cod_eqc;
+  std::vector< Node > cdt_eqc;
   eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &d_equalityEngine );
   while( !eqcs_i.isFinished() ){
     Node eqc = (*eqcs_i);
@@ -1481,27 +1507,30 @@ void TheoryDatatypes::checkCycles() {
         }
       }else{
         //indexing
-        cod_eqc.push_back( eqc );
+        cdt_eqc.push_back( eqc );
       }
     }
     ++eqcs_i;
   }
   //process codatatypes
-  if( cod_eqc.size()>1 ){
+  if( cdt_eqc.size()>1 && options::cdtBisimilar() ){
+    Trace("dt-cdt-debug") << "Process " << cdt_eqc.size() << " co-datatypes" << std::endl;
     std::vector< std::vector< Node > > part_out;
     std::vector< TNode > exp;
     std::map< Node, Node > cn;
     std::map< Node, std::map< Node, int > > dni;
-    for( unsigned i=0; i<cod_eqc.size(); i++ ){
-      cn[cod_eqc[i]] = cod_eqc[i];
+    for( unsigned i=0; i<cdt_eqc.size(); i++ ){
+      cn[cdt_eqc[i]] = cdt_eqc[i];
     }
-    separateBisimilar( cod_eqc, part_out, exp, cn, dni, 0, false );
+    separateBisimilar( cdt_eqc, part_out, exp, cn, dni, 0, false );
+    Trace("dt-cdt-debug") << "Done separate bisimilar." << std::endl;
     if( !part_out.empty() ){
+      Trace("dt-cdt-debug") << "Process partition size " << part_out.size() << std::endl;
       for( unsigned i=0; i<part_out.size(); i++ ){
         std::vector< Node > part;
         part.push_back( part_out[i][0] );
         for( unsigned j=1; j<part_out[i].size(); j++ ){
-          Trace("dt-cod") << "Codatatypes : " << part_out[i][0] << " and " << part_out[i][j] << " must be equal!!" << std::endl;
+          Trace("dt-cdt") << "Codatatypes : " << part_out[i][0] << " and " << part_out[i][j] << " must be equal!!" << std::endl;
           part.push_back( part_out[i][j] );
           std::vector< std::vector< Node > > tpart_out;
           exp.clear();
@@ -1513,16 +1542,16 @@ void TheoryDatatypes::checkCycles() {
           Assert( tpart_out.size()==1 && tpart_out[0].size()==2 );
           part.pop_back();
           //merge based on explanation
-          Trace("dt-cod") << "  exp is : ";
+          Trace("dt-cdt") << "  exp is : ";
           for( unsigned k=0; k<exp.size(); k++ ){
-            Trace("dt-cod") << exp[k] << " ";
+            Trace("dt-cdt") << exp[k] << " ";
           }
-          Trace("dt-cod") << std::endl;
+          Trace("dt-cdt") << std::endl;
           Node eq = part_out[i][0].eqNode( part_out[i][j] );
           Node eqExp = mkAnd( exp );
           d_pending.push_back( eq );
           d_pending_exp[ eq ] = eqExp;
-          Trace("datatypes-infer") << "DtInfer : cod-bisimilar : " << eq << " by " << eqExp << std::endl;
+          Trace("datatypes-infer") << "DtInfer : cdt-bisimilar : " << eq << " by " << eqExp << std::endl;
           d_infer.push_back( eq );
           d_infer_exp.push_back( eqExp );
         }
@@ -1537,9 +1566,9 @@ void TheoryDatatypes::separateBisimilar( std::vector< Node >& part, std::vector<
                                          std::map< Node, Node >& cn,
                                          std::map< Node, std::map< Node, int > >& dni, int dniLvl, bool mkExp ){
   if( !mkExp ){
-    Trace("dt-cod-debug") << "Separate bisimilar : " << std::endl;
+    Trace("dt-cdt-debug") << "Separate bisimilar : " << std::endl;
     for( unsigned i=0; i<part.size(); i++ ){
-      Trace("dt-cod-debug") << "   " << part[i] << ", current = " << cn[part[i]] << std::endl;
+      Trace("dt-cdt-debug") << "   " << part[i] << ", current = " << cn[part[i]] << std::endl;
     }
   }
   Assert( part.size()>1 );
@@ -1553,7 +1582,7 @@ void TheoryDatatypes::separateBisimilar( std::vector< Node >& part, std::vector<
     std::map< Node, int >::iterator it_rec = dni[part[j]].find( c );
     if( it_rec!=dni[part[j]].end() ){
       //looped
-      if( !mkExp ){ Trace("dt-cod-debug") << "  - " << part[j] << " is looping at index " << it_rec->second << std::endl; }
+      if( !mkExp ){ Trace("dt-cdt-debug") << "  - " << part[j] << " is looping at index " << it_rec->second << std::endl; }
       new_part_rec[ it_rec->second ].push_back( part[j] );
     }else{
       if( DatatypesRewriter::isTermDatatype( c ) ){
@@ -1565,14 +1594,14 @@ void TheoryDatatypes::separateBisimilar( std::vector< Node >& part, std::vector<
             explainEquality( c, ncons, true, exp );
           }
           new_part[cc].push_back( part[j] );
-          if( !mkExp ){ Trace("dt-cod-debug") << "  - " << part[j] << " is datatype " << ncons << "." << std::endl; }
+          if( !mkExp ){ Trace("dt-cdt-debug") << "  - " << part[j] << " is datatype " << ncons << "." << std::endl; }
         }else{
           new_part_c[c].push_back( part[j] );
-          if( !mkExp ){ Trace("dt-cod-debug") << "  - " << part[j] << " is unspecified datatype." << std::endl; }
+          if( !mkExp ){ Trace("dt-cdt-debug") << "  - " << part[j] << " is unspecified datatype." << std::endl; }
         }
       }else{
         //add equivalences
-        if( !mkExp ){ Trace("dt-cod-debug") << "  - " << part[j] << " is term " << c << "." << std::endl; }
+        if( !mkExp ){ Trace("dt-cdt-debug") << "  - " << part[j] << " is term " << c << "." << std::endl; }
         new_part_c[c].push_back( part[j] );
       }
     }
@@ -1614,7 +1643,7 @@ void TheoryDatatypes::separateBisimilar( std::vector< Node >& part, std::vector<
       //for each child of constructor
       unsigned cindex = 0;
       while( cindex<nChildren && !split_new_part.empty() ){
-        if( !mkExp ){ Trace("dt-cod-debug") << "Split argument #" << cindex << " of " << it->first << "..." << std::endl; }
+        if( !mkExp ){ Trace("dt-cdt-debug") << "Split argument #" << cindex << " of " << it->first << "..." << std::endl; }
         std::vector< std::vector< Node > > next_split_new_part;
         for( unsigned j=0; j<split_new_part.size(); j++ ){
           //set current node
index 132077e293cb491a9fec70f3ef212b7c42016397..74d10e7547fbb25acdd42cff581e8c2a9ea3d2e7 100644 (file)
@@ -174,6 +174,8 @@ private:
   context::CDList<TNode> d_consTerms;
   /** All the selector terms that the theory has seen */
   context::CDList<TNode> d_selTerms;
+  /** counter for forcing assignments (ensures fairness) */
+  unsigned d_dtfCounter;
 private:
   /** assert fact */
   void assertFact( Node fact, Node exp );
@@ -254,7 +256,7 @@ private:
                           std::map< Node, Node >& cn,
                           std::map< Node, std::map< Node, int > >& dni, int dniLvl, bool mkExp );
   /** build model */
-  Node getCodatatypesValue( Node n, std::map< Node, Node >& eqc_cons, std::map< Node, Node >& eqc_mu, std::map< Node, Node >& vmap );
+  Node getCodatatypesValue( Node n, std::map< Node, Node >& eqc_cons, std::map< Node, Node >& eqc_mu, std::map< Node, Node >& vmap, std::vector< Node >& fv );
   /** collect terms */
   void collectTerms( Node n );
   /** get instantiate cons */
index ddad913fe42cffa64b636c48440d04e1aac569d8..8ce8ee7dfe305e47f02f97811824cab3ba40debc 100644 (file)
@@ -209,6 +209,49 @@ struct DatatypeAscriptionTypeRule {
   }
 };/* struct DatatypeAscriptionTypeRule */
 
+/* For co-datatypes */
+class DatatypeMuTypeRule {
+private:
+  //a Mu-expression is constant iff its body is composed of constructors applied to constant expr and bound variables only
+  inline static bool computeIsConstNode(TNode n, std::vector< TNode >& fv ){
+    if( n.getKind()==kind::MU ){
+      fv.push_back( n[0] );
+      bool ret = computeIsConstNode( n[1], fv );
+      fv.pop_back();
+      return ret;
+    }else if( n.isConst() || std::find( fv.begin(), fv.end(), n )!=fv.end() ){
+      return true;
+    }else if( n.getKind()==kind::APPLY_CONSTRUCTOR ){
+      for( unsigned i=0; i<n.getNumChildren(); i++ ){
+        if( !computeIsConstNode( n[i], fv ) ){
+          return false;
+        }
+      }
+      return true; 
+    }else{
+      return false;
+    }
+  }
+public:
+  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
+    if( n[0].getKind()!=kind::BOUND_VARIABLE  ) {
+      std::stringstream ss;
+      ss << "expected a bound var for MU expression, got `"
+         << n[0] << "'";
+      throw TypeCheckingExceptionPrivate(n, ss.str());
+    }
+    return n[1].getType(check);
+  }
+  inline static bool computeIsConst(NodeManager* nodeManager, TNode n)
+    throw(AssertionException) {
+    Assert(n.getKind() == kind::MU);
+    NodeManagerScope nms(nodeManager);
+    std::vector< TNode > fv;
+    return computeIsConstNode( n, fv );
+  }
+};
+
+
 struct ConstructorProperties {
   inline static Cardinality computeCardinality(TypeNode type) {
     // Constructors aren't exactly functions, they're like
index 256dcaef266afbb2565b4aace1b9bea3b7b227a3..dc2a83841bd2d45fbf1997c6b524432c4da69a9f 100644 (file)
@@ -28,168 +28,254 @@ namespace CVC4 {
 namespace theory {
 namespace datatypes {
 
+
 class DatatypesEnumerator : public TypeEnumeratorBase<DatatypesEnumerator> {
   /** The datatype we're enumerating */
   const Datatype& d_datatype;
-  /** The datatype constructor we're currently enumerating */
-  size_t d_ctor;
-  /** The "first" constructor to consider; it's non-recursive */
-  size_t d_zeroCtor;
-  /** Delegate enumerators for the arguments of the current constructor */
-  TypeEnumerator** d_argEnumerators;
   /** type */
   TypeNode d_type;
-
-  /** Allocate and initialize the delegate enumerators */
-  void newEnumerators() {
-    d_argEnumerators = new TypeEnumerator*[d_datatype[d_ctor].getNumArgs()];
-    for(size_t a = 0; a < d_datatype[d_ctor].getNumArgs(); ++a) {
-      d_argEnumerators[a] = NULL;
+  /** The datatype constructor we're currently enumerating */
+  unsigned d_ctor;
+  /** The "first" constructor to consider; it's non-recursive */
+  unsigned d_zeroCtor;
+  /** list of type enumerators (one for each type in a selector argument) */
+  std::map< TypeNode, unsigned > d_te_index;
+  std::vector< TypeEnumerator > d_children;
+  /** terms produced for types */
+  std::map< TypeNode, std::vector< Node > > d_terms;
+  /** arg type of each selector, for each constructor */
+  std::vector< std::vector< TypeNode > > d_sel_types;
+  /** current index for each argument, for each constructor */
+  std::vector< std::vector< unsigned > > d_sel_index;
+  /** current sum of argument indicies for each constructor */
+  std::vector< int > d_sel_sum;
+  /** current bound on the number of times we can iterate argument enumerators */
+  unsigned d_size_limit;
+
+  Node getTermEnum( TypeNode tn, unsigned i ){
+    if( i<d_terms[tn].size() ){
+      return d_terms[tn][i];
+    }else{
+      Debug("dt-enum-debug") << "get term enum " << tn << " " << i << std::endl;
+      std::map< TypeNode, unsigned >::iterator it = d_te_index.find( tn );
+      unsigned tei;
+      if( it==d_te_index.end() ){
+        //initialize child enumerator for type
+        tei = d_children.size();
+        d_te_index[tn] = tei;
+        d_children.push_back( TypeEnumerator( tn ) );
+        d_terms[tn].push_back( *d_children[tei] );
+      }else{
+        tei = it->second;
+      }
+      //enumerate terms until index is reached
+      while( i>=d_terms[tn].size() ){
+        ++d_children[tei];
+        if( d_children[tei].isFinished() ){
+          Debug("dt-enum-debug") << "...fail term enum " << tn << " " << i << std::endl;
+          return Node::null();
+        }
+        d_terms[tn].push_back( *d_children[tei] );
+      }
+      Debug("dt-enum-debug") << "...return term enum " << tn << " " << i << " : " << d_terms[tn][i] << std::endl;
+      return d_terms[tn][i];
     }
   }
 
-  /** Delete the delegate enumerators */
-  void deleteEnumerators() {
-    if(d_argEnumerators != NULL) {
-      for(size_t a = 0; a < d_datatype[d_ctor].getNumArgs(); ++a) {
-        delete d_argEnumerators[a];
+  bool increment( unsigned index ){
+    Debug("dt-enum") << "Incrementing " << d_type << " " << d_ctor << " at size " << d_sel_sum[index] << "/" << d_size_limit << std::endl;
+    if( d_sel_sum[index]==-1 ){
+      //first time
+      d_sel_sum[index] = 0;
+      //special case: no children to iterate
+      if( d_sel_types[index].size()==0 ){
+        Debug("dt-enum") << "...success (nc) = " << (d_size_limit==0) << std::endl;
+        return d_size_limit==0;
+      }else{
+        Debug("dt-enum") << "...success" << std::endl;
+        return true;
+      }
+    }else{
+      unsigned i = 0;
+      while( i < d_sel_index[index].size() ){
+        //increment if the sum of iterations on arguments is less than the limit
+        if( d_sel_sum[index]<(int)d_size_limit ){
+          //also check if child enumerator has enough terms
+          if( !getTermEnum( d_sel_types[index][i], d_sel_index[index][i]+1 ).isNull() ){
+            Debug("dt-enum") << "...success increment child " << i << std::endl;
+            d_sel_index[index][i]++;
+            d_sel_sum[index]++;
+            return true;
+          }
+        }
+        Debug("dt-enum") << "......failed increment child " << i << std::endl;
+        //reset child, iterate next
+        d_sel_sum[index] -= d_sel_index[index][i];
+        d_sel_index[index][i] = 0;
+        i++;
       }
-      delete [] d_argEnumerators;
-      d_argEnumerators = NULL;
+      Debug("dt-enum") << "...failure." << std::endl;
+      return false;
     }
   }
 
+  Node getCurrentTerm( unsigned index ){
+    Debug("dt-enum-debug") << "Get current term at " << index << " " << d_type << "..." << std::endl;
+    DatatypeConstructor ctor = d_datatype[index];
+    Debug("dt-enum-debug") << "Check last term..." << std::endl;
+    //we first check if the last argument (which is forced to make sum of iterated arguments equal to d_size_limit) is defined
+    Node lc;
+    if( ctor.getNumArgs()>0 ){
+      lc = getTermEnum( d_sel_types[index][ctor.getNumArgs()-1], d_size_limit - d_sel_sum[index] );
+      if( lc.isNull() ){
+        Debug("dt-enum-debug") << "Current infeasible." << std::endl;
+        return Node::null();
+      }
+    }
+    Debug("dt-enum-debug") << "Get constructor..." << std::endl;
+    NodeBuilder<> b(kind::APPLY_CONSTRUCTOR);
+    Type typ;
+    if( d_datatype.isParametric() ){
+      typ = ctor.getSpecializedConstructorType(d_type.toType());
+      b << NodeManager::currentNM()->mkNode(kind::APPLY_TYPE_ASCRIPTION,
+                                            NodeManager::currentNM()->mkConst(AscriptionType(typ)), Node::fromExpr( ctor.getConstructor() ) );
+    }else{
+      b << ctor.getConstructor();
+    }
+    Debug("dt-enum-debug") << "Get arguments..." << std::endl;
+    if( ctor.getNumArgs()>0 ){
+      Assert( index<d_sel_types.size() );
+      Assert( index<d_sel_index.size() );
+      Assert( d_sel_types[index].size()==ctor.getNumArgs() );
+      Assert( d_sel_index[index].size()==ctor.getNumArgs()-1 );
+      for( int i=0; i<(int)(ctor.getNumArgs()-1); i++ ){
+        Node c = getTermEnum( d_sel_types[index][i], d_sel_index[index][i] );
+        Assert( !c.isNull() );
+        b << c;
+      }
+      b << lc;
+    }
+    Node nnn = Node(b);
+    Debug("dt-enum-debug") << "Return... " <<  nnn  << std::endl;
+    return nnn;
+  }
 
 public:
 
   DatatypesEnumerator(TypeNode type) throw() :
     TypeEnumeratorBase<DatatypesEnumerator>(type),
     d_datatype(DatatypeType(type.toType()).getDatatype()),
+    d_type(type),
     d_ctor(0),
-    d_zeroCtor(0),
-    d_argEnumerators(NULL),
-    d_type(type) {
+    d_zeroCtor(0) {
 
     //Assert(type.isDatatype());
     Debug("te") << "datatype is datatype? " << type.isDatatype() << std::endl;
     Debug("te") << "datatype is kind " << type.getKind() << std::endl;
     Debug("te") << "datatype is " << type << std::endl;
 
-    /* find the "zero" constructor (the first non-recursive one) */
-    /* FIXME: this isn't sufficient for mutually-recursive datatypes! */
-    while(d_zeroCtor < d_datatype.getNumConstructors()) {
-      bool recursive = false;
+    /* find the "zero" constructor via mkGroundTerm */
+    Node t = type.mkGroundTerm();
+    Assert( t.getKind()==kind::APPLY_CONSTRUCTOR );
+    d_zeroCtor = Datatype::indexOf( t.getOperator().toExpr() );
+    /* start with the constructor for which a ground term is constructed */
+    d_ctor = d_zeroCtor;
+
+    for( unsigned i=0; i<d_datatype.getNumConstructors(); ++i ){
+      d_sel_types.push_back( std::vector< TypeNode >() );
+      d_sel_index.push_back( std::vector< unsigned >() );
+      d_sel_sum.push_back( -1 );
+      DatatypeConstructor ctor = d_datatype[i];
+      Type typ;
       if( d_datatype.isParametric() ){
-        TypeNode tn = TypeNode::fromType( d_datatype[d_zeroCtor].getSpecializedConstructorType(d_type.toType()) );
-        for( unsigned i=0; i<tn.getNumChildren()-1; i++ ){
-          if( tn[i]==type ){
-            recursive = true;
-            break;
-          }
-        }
-      }else{
-        for(size_t a = 0; a < d_datatype[d_zeroCtor].getNumArgs() && !recursive; ++a) {
-          if(Node::fromExpr(d_datatype[d_zeroCtor][a].getSelector()).getType()[1] == type) {
-            recursive = true;
-            break;
-          }
+        typ = ctor.getSpecializedConstructorType(d_type.toType());
+      }
+      for( unsigned a = 0; a < ctor.getNumArgs(); ++a ){
+        TypeNode tn;
+        if( d_datatype.isParametric() ){
+          tn = TypeNode::fromType( typ )[a];
+        }else{
+          tn = Node::fromExpr(ctor[a].getSelector()).getType()[1];
         }
+        d_sel_types[i].push_back( tn );
+        d_sel_index[i].push_back( 0 );
       }
-      if(!recursive) {
-        break;
+      if( !d_sel_index[i].empty() ){
+        d_sel_index[i].pop_back();
       }
-      ++d_zeroCtor;
     }
-
-    /* start with the non-recursive constructor */
-    d_ctor = d_zeroCtor;
-
-    /* allocate space for the enumerators */
-    newEnumerators();
+    d_size_limit = 0;
+    //set up initial conditions (should always succeed)
+    bool init_inc = increment( d_ctor );
+    AlwaysAssert( init_inc );
   }
 
   DatatypesEnumerator(const DatatypesEnumerator& de) throw() :
     TypeEnumeratorBase<DatatypesEnumerator>(de.getType()),
     d_datatype(de.d_datatype),
+    d_type(de.d_type),
     d_ctor(de.d_ctor),
-    d_zeroCtor(de.d_zeroCtor),
-    d_argEnumerators(NULL),
-    d_type(de.d_type) {
+    d_zeroCtor(de.d_zeroCtor) {
 
-    if(de.d_argEnumerators != NULL) {
-      newEnumerators();
-      for(size_t a = 0; a < d_datatype[d_ctor].getNumArgs(); ++a) {
-        if(de.d_argEnumerators[a] != NULL) {
-          d_argEnumerators[a] = new TypeEnumerator(*de.d_argEnumerators[a]);
-        }
-      }
+    for( std::map< TypeNode, unsigned >::const_iterator it = de.d_te_index.begin(); it != de.d_te_index.end(); ++it ){
+      d_te_index[it->first] = it->second;
+    }
+    for( std::map< TypeNode, std::vector< Node > >::const_iterator it = de.d_terms.begin(); it != de.d_terms.end(); ++it ){
+      d_terms[it->first].insert( d_terms[it->first].end(), it->second.begin(), it->second.end() );
+    }
+    for( unsigned i=0; i<de.d_sel_types.size(); i++ ){
+      d_sel_types.push_back( std::vector< TypeNode >() );
+      d_sel_types[i].insert( d_sel_types[i].end(), de.d_sel_types[i].begin(), de.d_sel_types[i].end() );
     }
+    for( unsigned i=0; i<de.d_sel_index.size(); i++ ){
+      d_sel_index.push_back( std::vector< unsigned >() );
+      d_sel_index[i].insert( d_sel_index[i].end(), de.d_sel_index[i].begin(), de.d_sel_index[i].end() );
+    }
+
+    d_children.insert( d_children.end(), de.d_children.begin(), de.d_children.end() );
+    d_sel_sum.insert( d_sel_sum.end(), de.d_sel_sum.begin(), de.d_sel_sum.end() );
+    d_size_limit = de.d_size_limit;
   }
 
   ~DatatypesEnumerator() throw() {
-    deleteEnumerators();
   }
 
   Node operator*() throw(NoMoreValuesException) {
+    Debug("dt-enum-debug") << ": get term " << this << std::endl;
     if(d_ctor < d_datatype.getNumConstructors()) {
-      DatatypeConstructor ctor = d_datatype[d_ctor];
-      NodeBuilder<> b(kind::APPLY_CONSTRUCTOR);
-      Type typ;
-      if( d_datatype.isParametric() ){
-        typ = d_datatype[d_ctor].getSpecializedConstructorType(d_type.toType());
-        b << NodeManager::currentNM()->mkNode(kind::APPLY_TYPE_ASCRIPTION,
-                                              NodeManager::currentNM()->mkConst(AscriptionType(typ)), Node::fromExpr( ctor.getConstructor() ) );
-      }else{
-        b << ctor.getConstructor();
-      }
-      try {
-        for(size_t a = 0; a < d_datatype[d_ctor].getNumArgs(); ++a) {
-          if(d_argEnumerators[a] == NULL) {
-            if( d_datatype.isParametric() ){
-              d_argEnumerators[a] = new TypeEnumerator(TypeNode::fromType( typ )[a]);
-            }else{
-              d_argEnumerators[a] = new TypeEnumerator(Node::fromExpr(d_datatype[d_ctor][a].getSelector()).getType()[1]);
-            }
-          }
-          b << **d_argEnumerators[a];
-        }
-      } catch(NoMoreValuesException&) {
-        InternalError();
-      }
-      Node nnn = Node(b);
-      //if( nnn.getType()!=d_type || !nnn.getType().isComparableTo(d_type) ){
-      //  Debug("dt-warn") << "WARNING : Enum : " << nnn << " bad type : " << nnn.getType() << " " << d_type << std::endl;
-      //}
-      return nnn;
+      return getCurrentTerm( d_ctor );
     } else {
       throw NoMoreValuesException(getType());
     }
   }
 
   DatatypesEnumerator& operator++() throw() {
-    if(d_ctor < d_datatype.getNumConstructors()) {
-      for(size_t a = d_datatype[d_ctor].getNumArgs(); a > 0; --a) {
-        if((++*d_argEnumerators[a - 1]).isFinished()) {
-          *d_argEnumerators[a - 1] = TypeEnumerator(Node::fromExpr(d_datatype[d_ctor][a - 1].getSelector()).getType()[1]);
-        } else {
+    Debug("dt-enum-debug") << ": increment " << this << std::endl;
+    unsigned prevSize = d_size_limit;
+    while(d_ctor < d_datatype.getNumConstructors()) {
+      //increment at index
+      while( increment( d_ctor ) ){
+        Node n = getCurrentTerm( d_ctor );
+        if( !n.isNull() ){
           return *this;
         }
       }
-
       // Here, we need to step from the current constructor to the next one
 
-      // first, delete the current delegate enumerators
-      deleteEnumerators();
-
       // Find the next constructor (only complicated by the notion of the "zero" constructor
       d_ctor = (d_ctor == d_zeroCtor) ? 0 : d_ctor + 1;
       if(d_ctor == d_zeroCtor) {
         ++d_ctor;
       }
-
-      // If we aren't out of constructors, allocate space for the new delegate enumerators
-      if(d_ctor < d_datatype.getNumConstructors()) {
-        newEnumerators();
+      if( d_ctor>=d_datatype.getNumConstructors() ){
+        //try next size limit as long as new terms were generated at last size
+        if( prevSize==d_size_limit ){
+          d_size_limit++;
+          d_ctor = d_zeroCtor;
+          for( unsigned i=0; i<d_sel_sum.size(); i++ ){
+            d_sel_sum[i] = -1;
+          }
+        }
       }
     }
     return *this;
index 8597c117d2e1b7d9cbcfb2a50b479ac8709ce1b9..9e402f4306a68c571dd00bcd1ec4f2d889c82705 100644 (file)
@@ -49,6 +49,10 @@ Node TheoryIdl::ppRewrite(TNode atom) {
 }
 
 void TheoryIdl::check(Effort level) {
+  //// Not needed for now, as no code outside while() loop below.
+  // if (done() && !fullEffort(e)) {
+  //   return;
+  // }
 
   while(!done()) {
 
index d6f9704b3850a9ef900ecbc2b6a4aec29608d073..57799fd8edb976721fa83b83c593434fb459da4f 100644 (file)
@@ -243,8 +243,13 @@ void BoundedIntegers::process( Node f, Node n, bool pol,
   }
 }
 
-void BoundedIntegers::check( Theory::Effort e ) {
-  if( e==Theory::EFFORT_LAST_CALL ){
+bool BoundedIntegers::needsCheck( Theory::Effort e ) {
+  return e==Theory::EFFORT_LAST_CALL;
+}
+
+void BoundedIntegers::check( Theory::Effort e, unsigned quant_e ) {
+  if( quant_e==QuantifiersEngine::QEFFORT_STANDARD ){
+    Trace("bint-engine") << "---Bounded Integers---" << std::endl;
     bool addedLemma = false;
     //make sure proxies are up-to-date with range
     for( unsigned i=0; i<d_ranges.size(); i++) {
@@ -252,9 +257,7 @@ void BoundedIntegers::check( Theory::Effort e ) {
         addedLemma = true;
       }
     }
-    if( addedLemma ){
-      d_quantEngine->flushLemmas( &d_quantEngine->getOutputChannel() );
-    }
+    Trace("bint-engine") << "   addedLemma = " << addedLemma << std::endl;
   }
 }
 
index ac188ca656a2e202a975d20c8acac34f51198b5d..355360e41f9e0801ba43d37805320c7d3f67543d 100644 (file)
@@ -110,7 +110,8 @@ private:
 public:
   BoundedIntegers( context::Context* c, QuantifiersEngine* qe );
 
-  void check( Theory::Effort e );
+  bool needsCheck( Theory::Effort e );
+  void check( Theory::Effort e, unsigned quant_e );
   void registerQuantifier( Node f );
   void assertNode( Node n );
   Node getNextDecisionRequest();
index 9ce79c301bd013291b1102d9bc4ecf6050d62179..0f2adf3b40eff53624531e61e55ae89aecf0edcb 100644 (file)
@@ -213,7 +213,10 @@ Node CandidateGeneratorQELitDeq::getNextCandidate(){
 
 CandidateGeneratorQEAll::CandidateGeneratorQEAll( QuantifiersEngine* qe, Node mpat ) :
   d_match_pattern( mpat ), d_qe( qe ){
-
+  d_match_pattern_type = mpat.getType();
+  Assert( mpat.getKind()==INST_CONSTANT );
+  d_f = quantifiers::TermDb::getInstConstAttr( mpat );
+  d_index = mpat.getAttribute(InstVarNumAttribute());
 }
 
 void CandidateGeneratorQEAll::resetInstantiationRound() {
@@ -227,6 +230,9 @@ void CandidateGeneratorQEAll::reset( Node eqc ) {
 Node CandidateGeneratorQEAll::getNextCandidate() {
   while( !d_eq.isFinished() ){
     Node n = (*d_eq);
+    if( options::instMaxLevel()!=-1 ){
+      n = d_qe->getEqualityQuery()->getInternalRepresentative( n, d_f, d_index );
+    }
     ++d_eq;
     if( n.getType().isSubtypeOf( d_match_pattern.getType() ) ){
       //an equivalence class with the same type as the pattern, return it
index 4569c2335c27c980adad6bf2d76c4d5141259b0f..011e2924d21c3cf2ca6811572ffb13043324920e 100644 (file)
@@ -144,8 +144,12 @@ private:
   eq::EqClassesIterator d_eq;
   //equality you are trying to match equalities for
   Node d_match_pattern;
+  TypeNode d_match_pattern_type;
   //einstantiator pointer
   QuantifiersEngine* d_qe;
+  // quantifier/index for the variable we are matching
+  Node d_f;
+  unsigned d_index;
 public:
   CandidateGeneratorQEAll( QuantifiersEngine* qe, Node mpat );
   ~CandidateGeneratorQEAll(){}
diff --git a/src/theory/quantifiers/ce_guided_instantiation.cpp b/src/theory/quantifiers/ce_guided_instantiation.cpp
new file mode 100644 (file)
index 0000000..f4cdd1a
--- /dev/null
@@ -0,0 +1,216 @@
+/*********************                                                        */
+/*! \file ce_guided_instantiation.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014  New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief counterexample guided instantiation class
+ **
+ **/
+
+#include "theory/quantifiers/ce_guided_instantiation.h"
+#include "theory/theory_engine.h"
+#include "theory/quantifiers/options.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/first_order_model.h"
+
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+using namespace std;
+
+namespace CVC4 {
+
+CegInstantiation::CegConjecture::CegConjecture() {
+}
+
+void CegInstantiation::CegConjecture::assign( Node q ) {
+  Assert( d_quant.isNull() );
+  Assert( q.getKind()==FORALL );
+  d_quant = q;
+  for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
+    d_candidates.push_back( NodeManager::currentNM()->mkSkolem( "e", q[0][i].getType() ) );
+  }
+}
+void CegInstantiation::CegConjecture::initializeGuard( QuantifiersEngine * qe ){
+  if( d_guard.isNull() ){
+    d_guard = Rewriter::rewrite( NodeManager::currentNM()->mkSkolem( "G", NodeManager::currentNM()->booleanType() ) );
+    //specify guard behavior
+    qe->getValuation().ensureLiteral( d_guard );
+    qe->getOutputChannel().requirePhase( d_guard, true );
+  }
+}
+
+CegInstantiation::CegInstantiation( QuantifiersEngine * qe, context::Context* c ) : QuantifiersModule( qe ), d_conj_active( c, false ), d_conj_infeasible( c, false ), d_guard_assertions( c ) {
+
+}
+
+bool CegInstantiation::needsCheck( Theory::Effort e ) {
+  return e>=Theory::EFFORT_LAST_CALL;
+}
+
+void CegInstantiation::check( Theory::Effort e, unsigned quant_e ) {
+  if( quant_e==QuantifiersEngine::QEFFORT_STANDARD ){
+    Trace("cegqi-engine") << "---Countexample Guided Instantiation Engine---" << std::endl;
+    Trace("cegqi-debug") << "Current conjecture status : " << d_conj_active << " " << d_conj_infeasible << std::endl;
+    if( d_conj_active && !d_conj_infeasible ){
+      checkCegConjecture( &d_conj );
+    }
+    Trace("cegqi-engine") << "Finished Countexample Guided Instantiation engine." << std::endl;
+  }
+}
+
+void CegInstantiation::registerQuantifier( Node q ) {
+  if( d_quantEngine->getOwner( q )==this ){
+    if( !d_conj.isAssigned() ){
+      Trace("cegqi") << "Register conjecture : " << q << std::endl;
+      d_conj.assign( q );
+      //construct base instantiation
+      d_conj.d_base_inst = Rewriter::rewrite( d_quantEngine->getInstantiation( q, d_conj.d_candidates ) );
+      Trace("cegqi") << "Base instantiation is : " << d_conj.d_base_inst << std::endl;
+      if( getTermDatabase()->isQAttrSygus( q ) ){
+        Assert( d_conj.d_base_inst.getKind()==NOT );
+        Assert( d_conj.d_base_inst[0].getKind()==FORALL );
+        for( unsigned j=0; j<d_conj.d_base_inst[0][0].getNumChildren(); j++ ){
+          d_conj.d_inner_vars.push_back( d_conj.d_base_inst[0][0][j] );
+        }
+      }else if( getTermDatabase()->isQAttrSynthesis( q ) ){
+        //add immediate lemma
+        Node lem = NodeManager::currentNM()->mkNode( OR, d_conj.d_guard.negate(), d_conj.d_base_inst );
+      }
+    }else{
+      Assert( d_conj.d_quant==q );
+    }
+  }
+}
+
+void CegInstantiation::assertNode( Node n ) {
+  Trace("cegqi-debug") << "Cegqi : Assert : " << n << std::endl;
+  bool pol = n.getKind()!=NOT;
+  Node lit = n.getKind()==NOT ? n[0] : n;
+  if( lit==d_conj.d_guard ){
+    d_guard_assertions[lit] = pol;
+    d_conj_infeasible = !pol;
+  }
+  if( lit==d_conj.d_quant ){
+    d_conj_active = true;
+  }
+}
+
+Node CegInstantiation::getNextDecisionRequest() {
+  d_conj.initializeGuard( d_quantEngine );
+  bool value;
+  if( !d_quantEngine->getValuation().hasSatValue( d_conj.d_guard, value ) ) {
+    if( d_guard_assertions.find( d_conj.d_guard )==d_guard_assertions.end() ){
+      if( d_conj.d_guard_split.isNull() ){
+        Node lem = NodeManager::currentNM()->mkNode( OR, d_conj.d_guard.negate(), d_conj.d_guard );
+        d_quantEngine->getOutputChannel().lemma( lem );
+      }
+      Trace("cegqi-debug") << "Decide next on : " << d_conj.d_guard << "..." << std::endl;
+      return d_conj.d_guard;
+    }
+  }
+  return Node::null();
+}
+
+void CegInstantiation::checkCegConjecture( CegConjecture * conj ) {
+  Node q = conj->d_quant;
+  Trace("cegqi-engine-debug") << "Synthesis conjecture : " << q << std::endl;
+  Trace("cegqi-engine-debug") << "  * Candidate program/output : ";
+  for( unsigned i=0; i<conj->d_candidates.size(); i++ ){
+    Trace("cegqi-engine-debug") << conj->d_candidates[i] << " ";
+  }
+  Trace("cegqi-engine-debug") << std::endl;
+
+  if( getTermDatabase()->isQAttrSygus( q ) ){
+    Trace("cegqi-engine-debug") << "  * Values are : ";
+    bool success = true;
+    std::vector< Node > model_values;
+    for( unsigned i=0; i<conj->d_candidates.size(); i++ ){
+      Node v = getModelValue( conj->d_candidates[i] );
+      model_values.push_back( v );
+      Trace("cegqi-engine-debug") << v << " ";
+      if( v.isNull() ){
+        success = false;
+      }
+    }
+    Trace("cegqi-engine-debug") << std::endl;
+
+    if( success ){
+      //must get a counterexample to the value of the current candidate
+      Node inst = conj->d_base_inst.substitute( conj->d_candidates.begin(), conj->d_candidates.end(), model_values.begin(), model_values.end() );
+      inst = Rewriter::rewrite( inst );
+      //body should be an existential
+      Assert( inst.getKind()==NOT );
+      Assert( inst[0].getKind()==FORALL );
+      //immediately skolemize
+      Node inst_sk = getTermDatabase()->getSkolemizedBody( inst[0] );
+      Trace("cegqi-lemma") << "Counterexample lemma : " << inst_sk << std::endl;
+      d_quantEngine->addLemma( NodeManager::currentNM()->mkNode( OR, q.negate(), inst_sk ) );
+
+      //candidate refinement : the next candidate must satisfy the counterexample found for the current model of the candidate
+      Assert( conj->d_inner_vars.size()==getTermDatabase()->d_skolem_constants[inst[0]].size() );
+      Node inst_ce_refine = conj->d_base_inst[0][1].substitute( conj->d_inner_vars.begin(), conj->d_inner_vars.end(),
+                                                                getTermDatabase()->d_skolem_constants[inst[0]].begin(), getTermDatabase()->d_skolem_constants[inst[0]].end() );
+      Node lem = NodeManager::currentNM()->mkNode( OR, conj->d_guard.negate(), inst_ce_refine.negate() );
+      Trace("cegqi-lemma") << "Candidate refinement lemma : " << lem << std::endl;
+      d_quantEngine->addLemma( lem );
+    }
+
+  }else if( getTermDatabase()->isQAttrSynthesis( q ) ){
+    std::vector< Node > model_terms;
+    for( unsigned i=0; i<conj->d_candidates.size(); i++ ){
+      Node t = getModelTerm( conj->d_candidates[i] );
+      model_terms.push_back( t );
+    }
+    d_quantEngine->addInstantiation( q, model_terms, false );
+  }
+}
+
+Node CegInstantiation::getModelValue( Node n ) {
+  Trace("cegqi-mv") << "getModelValue for : " << n << std::endl;
+  //return d_quantEngine->getTheoryEngine()->getModelValue( n );
+  TypeNode tn = n.getType();
+  if( getEqualityEngine()->hasTerm( n ) ){
+    Node r = getRepresentative( n );
+    Node v;
+    eq::EqClassIterator eqc_i = eq::EqClassIterator( r, getEqualityEngine() );
+    while( !eqc_i.isFinished() ){
+      TNode nn = (*eqc_i);
+      if( nn.isConst() ){
+        Trace("cegqi-mv") << "..constant : " << nn << std::endl;
+        return nn;
+      }else if( nn.getKind()==APPLY_CONSTRUCTOR ){
+        v = nn;
+      }
+      ++eqc_i;
+    }
+    if( !v.isNull() ){
+      std::vector< Node > children;
+      if( v.hasOperator() ){
+        children.push_back( v.getOperator() );
+      }
+      for( unsigned i=0; i<v.getNumChildren(); i++ ){
+        children.push_back( getModelValue( v[i] ) );
+      }
+      Node vv = NodeManager::currentNM()->mkNode( v.getKind(), children );
+      Trace("cegqi-mv") << "...value : " << vv << std::endl;
+      return vv;
+    }
+  }
+  Node e = getTermDatabase()->getEnumerateTerm( tn, 0 );
+  Trace("cegqi-mv") << "...enumerate : " << e << std::endl;
+  return e;
+}
+
+Node CegInstantiation::getModelTerm( Node n ){
+  return getModelValue( n );
+}
+
+}
\ No newline at end of file
diff --git a/src/theory/quantifiers/ce_guided_instantiation.h b/src/theory/quantifiers/ce_guided_instantiation.h
new file mode 100644 (file)
index 0000000..6139f8f
--- /dev/null
@@ -0,0 +1,89 @@
+/*********************                                                        */
+/*! \file ce_guided_instantiation.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014  New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief counterexample guided instantiation class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef CE_GUIDED_INSTANTIATION_H
+#define CE_GUIDED_INSTANTIATION_H
+
+#include "context/cdhashmap.h"
+#include "context/cdchunk_list.h"
+#include "theory/quantifiers_engine.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+
+
+class CegInstantiation : public QuantifiersModule
+{
+  typedef context::CDHashMap<Node, bool, NodeHashFunction> NodeBoolMap;
+private:
+  class CegConjecture {
+  public:
+    CegConjecture();
+    /** quantified formula */
+    Node d_quant;
+    /** guard */
+    Node d_guard;
+    /** base instantiation */
+    Node d_base_inst;
+    /** guard split */
+    Node d_guard_split;
+    /** list of constants for quantified formula */
+    std::vector< Node > d_candidates;
+    /** list of variables on inner quantification */
+    std::vector< Node > d_inner_vars;
+    /** is assigned */
+    bool isAssigned() { return !d_quant.isNull(); }
+    /** assign */
+    void assign( Node q );
+    /** initialize guard */
+    void initializeGuard( QuantifiersEngine * qe );
+  };
+  /** the quantified formula stating the synthesis conjecture */
+  CegConjecture d_conj;
+  /** is conjecture active */
+  context::CDO< bool > d_conj_active;
+  /** is conjecture infeasible */
+  context::CDO< bool > d_conj_infeasible;
+  /** assertions for guards */
+  NodeBoolMap d_guard_assertions;
+private:
+  /** check conjecture */
+  void checkCegConjecture( CegConjecture * conj );
+  /** get model value */
+  Node getModelValue( Node n );
+  /** get model term */
+  Node getModelTerm( Node n );
+public:
+  CegInstantiation( QuantifiersEngine * qe, context::Context* c );
+public:
+  bool needsCheck( Theory::Effort e );
+  /* Call during quantifier engine's check */
+  void check( Theory::Effort e, unsigned quant_e );
+  /* Called for new quantifiers */
+  void registerQuantifier( Node q );
+  void assertNode( Node n );
+  Node getNextDecisionRequest();
+  /** Identify this module (for debugging, dynamic configuration, etc..) */
+  std::string identify() const { return "CegInstantiation"; }
+};
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/conjecture_generator.cpp b/src/theory/quantifiers/conjecture_generator.cpp
new file mode 100755 (executable)
index 0000000..f491adc
--- /dev/null
@@ -0,0 +1,2166 @@
+/*********************                                                        */\r
+/*! \file conjecture_generator.cpp\r
+ ** \verbatim\r
+ ** Original author: Andrew Reynolds\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 project.\r
+ ** Copyright (c) 2009-2014  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 conjecture generator class\r
+ **\r
+ **/\r
+\r
+#include "theory/quantifiers/conjecture_generator.h"\r
+#include "theory/theory_engine.h"\r
+#include "theory/quantifiers/options.h"\r
+#include "theory/quantifiers/term_database.h"\r
+#include "theory/quantifiers/trigger.h"\r
+#include "theory/quantifiers/first_order_model.h"\r
+\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::theory;\r
+using namespace CVC4::theory::quantifiers;\r
+using namespace std;\r
+\r
+namespace CVC4 {\r
+\r
+struct sortConjectureScore {\r
+  std::vector< int > d_scores;\r
+  bool operator() (unsigned i, unsigned j) { return d_scores[i]>d_scores[j]; }\r
+};\r
+\r
+\r
+void OpArgIndex::addTerm( ConjectureGenerator * s, TNode n, unsigned index ){\r
+  if( index==n.getNumChildren() ){\r
+    Assert( n.hasOperator() );\r
+    if( std::find( d_ops.begin(), d_ops.end(), n.getOperator() )==d_ops.end() ){\r
+      d_ops.push_back( n.getOperator() );\r
+      d_op_terms.push_back( n );\r
+    }\r
+  }else{\r
+    d_child[s->getTermDatabase()->d_arg_reps[n][index]].addTerm( s, n, index+1 );\r
+  }\r
+}\r
+\r
+Node OpArgIndex::getGroundTerm( ConjectureGenerator * s, std::vector< TNode >& args ) {\r
+  if( d_ops.empty() ){\r
+    for( std::map< TNode, OpArgIndex >::iterator it = d_child.begin(); it != d_child.end(); ++it ){\r
+      std::map< TNode, Node >::iterator itf = s->d_ground_eqc_map.find( it->first );\r
+      if( itf!=s->d_ground_eqc_map.end() ){\r
+        args.push_back( itf->second );\r
+        Node n = it->second.getGroundTerm( s, args );\r
+        args.pop_back();\r
+        if( !n.isNull() ){\r
+          return n;\r
+        }\r
+      }\r
+    }\r
+    return Node::null();\r
+  }else{\r
+    std::vector< TNode > args2;\r
+    args2.push_back( d_ops[0] );\r
+    args2.insert( args2.end(), args.begin(), args.end() );\r
+    return NodeManager::currentNM()->mkNode( d_op_terms[0].getKind(), args2 );\r
+  }\r
+}\r
+\r
+void OpArgIndex::getGroundTerms( ConjectureGenerator * s, std::vector< TNode >& terms ) {\r
+  terms.insert( terms.end(), d_op_terms.begin(), d_op_terms.end() );\r
+  for( std::map< TNode, OpArgIndex >::iterator it = d_child.begin(); it != d_child.end(); ++it ){\r
+    if( s->isGroundEqc( it->first ) ){\r
+      it->second.getGroundTerms( s, terms );\r
+    }\r
+  }\r
+}\r
+\r
+\r
+\r
+ConjectureGenerator::ConjectureGenerator( QuantifiersEngine * qe, context::Context* c ) : QuantifiersModule( qe ),\r
+d_notify( *this ),\r
+d_uequalityEngine(d_notify, c, "ConjectureGenerator::ee"),\r
+d_ee_conjectures( c ){\r
+  d_fullEffortCount = 0;\r
+  d_uequalityEngine.addFunctionKind( kind::APPLY_UF );\r
+  d_uequalityEngine.addFunctionKind( kind::APPLY_CONSTRUCTOR );\r
+\r
+}\r
+\r
+void ConjectureGenerator::eqNotifyNewClass( TNode t ){\r
+  Trace("thm-ee-debug") << "UEE : new equivalence class " << t << std::endl;\r
+  d_upendingAdds.push_back( t );\r
+}\r
+\r
+void ConjectureGenerator::eqNotifyPreMerge(TNode t1, TNode t2) {\r
+  //get maintained representatives\r
+  TNode rt1 = t1;\r
+  TNode rt2 = t2;\r
+  std::map< Node, EqcInfo* >::iterator it1 = d_eqc_info.find( t1 );\r
+  if( it1!=d_eqc_info.end() && !it1->second->d_rep.get().isNull() ){\r
+    rt1 = it1->second->d_rep.get();\r
+  }\r
+  std::map< Node, EqcInfo* >::iterator it2 = d_eqc_info.find( t2 );\r
+  if( it2!=d_eqc_info.end() && !it2->second->d_rep.get().isNull() ){\r
+    rt2 = it2->second->d_rep.get();\r
+  }\r
+  Trace("thm-ee-debug") << "UEE : equality holds : " << t1 << " == " << t2 << std::endl;\r
+  Trace("thm-ee-debug") << "      ureps : " << rt1 << " == " << rt2 << std::endl;\r
+  Trace("thm-ee-debug") << "      relevant : " << d_pattern_is_relevant[rt1] << " " << d_pattern_is_relevant[rt2] << std::endl;\r
+  Trace("thm-ee-debug") << "      normal : " << d_pattern_is_normal[rt1] << " " << d_pattern_is_normal[rt2] << std::endl;\r
+  Trace("thm-ee-debug") << "      size :   " << d_pattern_fun_sum[rt1] << " " << d_pattern_fun_sum[rt2] << std::endl;\r
+\r
+  if( isUniversalLessThan( rt2, rt1 ) ){\r
+    EqcInfo * ei;\r
+    if( it1==d_eqc_info.end() ){\r
+      ei = getOrMakeEqcInfo( t1, true );\r
+    }else{\r
+      ei = it1->second;\r
+    }\r
+    ei->d_rep = t2;\r
+  }\r
+}\r
+\r
+void ConjectureGenerator::eqNotifyPostMerge(TNode t1, TNode t2) {\r
+\r
+}\r
+\r
+void ConjectureGenerator::eqNotifyDisequal(TNode t1, TNode t2, TNode reason) {\r
+  Trace("thm-ee-debug") << "UEE : disequality holds : " << t1 << " != " << t2 << std::endl;\r
+\r
+}\r
+\r
+\r
+ConjectureGenerator::EqcInfo::EqcInfo( context::Context* c ) : d_rep( c, Node::null() ){\r
+\r
+}\r
+\r
+ConjectureGenerator::EqcInfo* ConjectureGenerator::getOrMakeEqcInfo( TNode n, bool doMake ) {\r
+  //Assert( getUniversalRepresentative( n )==n );\r
+  std::map< Node, EqcInfo* >::iterator eqc_i = d_eqc_info.find( n );\r
+  if( eqc_i!=d_eqc_info.end() ){\r
+    return eqc_i->second;\r
+  }else if( doMake ){\r
+    EqcInfo* ei = new EqcInfo( d_quantEngine->getSatContext() );\r
+    d_eqc_info[n] = ei;\r
+    return ei;\r
+  }else{\r
+    return NULL;\r
+  }\r
+}\r
+\r
+void ConjectureGenerator::setUniversalRelevant( TNode n ) {\r
+  //add pattern information\r
+  registerPattern( n, n.getType() );\r
+  d_urelevant_terms[n] = true;\r
+  for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+    setUniversalRelevant( n[i] );\r
+  }\r
+}\r
+\r
+bool ConjectureGenerator::isUniversalLessThan( TNode rt1, TNode rt2 ) {\r
+  //prefer the one that is (normal, smaller) lexographically\r
+  Assert( d_pattern_is_relevant.find( rt1 )!=d_pattern_is_relevant.end() );\r
+  Assert( d_pattern_is_relevant.find( rt2 )!=d_pattern_is_relevant.end() );\r
+  Assert( d_pattern_is_normal.find( rt1 )!=d_pattern_is_normal.end() );\r
+  Assert( d_pattern_is_normal.find( rt2 )!=d_pattern_is_normal.end() );\r
+  Assert( d_pattern_fun_sum.find( rt1 )!=d_pattern_fun_sum.end() );\r
+  Assert( d_pattern_fun_sum.find( rt2 )!=d_pattern_fun_sum.end() );\r
+\r
+  if( d_pattern_is_relevant[rt1] && !d_pattern_is_relevant[rt2] ){\r
+    Trace("thm-ee-debug") << "UEE : LT due to relevant." << std::endl;\r
+    return true;\r
+  }else if( d_pattern_is_relevant[rt1]==d_pattern_is_relevant[rt2] ){\r
+    if( d_pattern_is_normal[rt1] && !d_pattern_is_normal[rt2] ){\r
+      Trace("thm-ee-debug") << "UEE : LT due to normal." << std::endl;\r
+      return true;\r
+    }else if( d_pattern_is_normal[rt1]==d_pattern_is_normal[rt2] ){\r
+      if( d_pattern_fun_sum[rt1]<d_pattern_fun_sum[rt2] ){\r
+        Trace("thm-ee-debug") << "UEE : LT due to size." << std::endl;\r
+        //decide which representative to use : based on size of the term\r
+        return true;\r
+      }else if( d_pattern_fun_sum[rt1]==d_pattern_fun_sum[rt2] ){\r
+        //same size : tie goes to term that has already been reported\r
+        return isReportedCanon( rt1 ) && !isReportedCanon( rt2 );\r
+      }\r
+    }\r
+  }\r
+  return false;\r
+}\r
+\r
+\r
+bool ConjectureGenerator::isReportedCanon( TNode n ) {\r
+  return std::find( d_ue_canon.begin(), d_ue_canon.end(), n )==d_ue_canon.end();\r
+}\r
+\r
+void ConjectureGenerator::markReportedCanon( TNode n ) {\r
+  if( !isReportedCanon( n ) ){\r
+    d_ue_canon.push_back( n );\r
+  }\r
+}\r
+\r
+bool ConjectureGenerator::areUniversalEqual( TNode n1, TNode n2 ) {\r
+  return n1==n2 || ( d_uequalityEngine.hasTerm( n1 ) && d_uequalityEngine.hasTerm( n2 ) && d_uequalityEngine.areEqual( n1, n2 ) );\r
+}\r
+\r
+bool ConjectureGenerator::areUniversalDisequal( TNode n1, TNode n2 ) {\r
+  return n1!=n2 && d_uequalityEngine.hasTerm( n1 ) && d_uequalityEngine.hasTerm( n2 ) && d_uequalityEngine.areDisequal( n1, n2, false );\r
+}\r
+\r
+TNode ConjectureGenerator::getUniversalRepresentative( TNode n, bool add ) {\r
+  if( add ){\r
+    if( d_urelevant_terms.find( n )==d_urelevant_terms.end() ){\r
+      setUniversalRelevant( n );\r
+      //add term to universal equality engine\r
+      d_uequalityEngine.addTerm( n );\r
+      // addding this term to equality engine will lead to a set of new terms (the new subterms of n)\r
+      // now, do instantiation-based merging for each of these terms\r
+      Trace("thm-ee-debug") << "Merge equivalence classes based on instantiations of terms..." << std::endl;\r
+      //merge all pending equalities\r
+      while( !d_upendingAdds.empty() ){\r
+        Trace("sg-pending") << "Add " << d_upendingAdds.size() << " pending terms..." << std::endl;\r
+        std::vector< Node > pending;\r
+        pending.insert( pending.end(), d_upendingAdds.begin(), d_upendingAdds.end() );\r
+        d_upendingAdds.clear();\r
+        for( unsigned i=0; i<pending.size(); i++ ){\r
+          Node t = pending[i];\r
+          TypeNode tn = t.getType();\r
+          Trace("thm-ee-add") << "UEE : Add universal term " << t << std::endl;\r
+          std::vector< Node > eq_terms;\r
+          //if occurs modulo equality at ground level, it is equivalent to representative of ground equality engine\r
+          TNode gt = getTermDatabase()->evaluateTerm( t );\r
+          if( !gt.isNull() && gt!=t ){\r
+            eq_terms.push_back( gt );\r
+          }\r
+          //get all equivalent terms based on theorem database\r
+          d_thm_index.getEquivalentTerms( t, eq_terms );\r
+          if( !eq_terms.empty() ){\r
+            Trace("thm-ee-add") << "UEE : Based on ground EE/theorem DB, it is equivalent to " << eq_terms.size() << " terms : " << std::endl;\r
+            //add equivalent terms as equalities to universal engine\r
+            for( unsigned i=0; i<eq_terms.size(); i++ ){\r
+              Trace("thm-ee-add") << "  " << eq_terms[i] << std::endl;\r
+              bool assertEq = false;\r
+              if( d_urelevant_terms.find( eq_terms[i] )!=d_urelevant_terms.end() ){\r
+                assertEq = true;\r
+              }else{\r
+                Assert( eq_terms[i].getType()==tn );\r
+                registerPattern( eq_terms[i], tn );\r
+                if( isUniversalLessThan( eq_terms[i], t ) || ( options::conjectureUeeIntro() && d_pattern_fun_sum[t]>=d_pattern_fun_sum[eq_terms[i]] ) ){\r
+                  setUniversalRelevant( eq_terms[i] );\r
+                  assertEq = true;\r
+                }\r
+              }\r
+              if( assertEq ){\r
+                Node exp;\r
+                d_uequalityEngine.assertEquality( t.eqNode( eq_terms[i] ), true, exp );\r
+              }else{\r
+                Trace("thm-ee-no-add") << "Do not add : " << t << " == " << eq_terms[i] << std::endl;\r
+              }\r
+            }\r
+          }else{\r
+            Trace("thm-ee-add") << "UEE : No equivalent terms." << std::endl;\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if( d_uequalityEngine.hasTerm( n ) ){\r
+    Node r = d_uequalityEngine.getRepresentative( n );\r
+    EqcInfo * ei = getOrMakeEqcInfo( r );\r
+    if( ei && !ei->d_rep.get().isNull() ){\r
+      return ei->d_rep.get();\r
+    }else{\r
+      return r;\r
+    }\r
+  }else{\r
+    return n;\r
+  }\r
+}\r
+\r
+Node ConjectureGenerator::getFreeVar( TypeNode tn, unsigned i ) {\r
+  Assert( !tn.isNull() );\r
+  while( d_free_var[tn].size()<=i ){\r
+    std::stringstream oss;\r
+    oss << tn;\r
+    std::stringstream os;\r
+    os << oss.str()[0] << i;\r
+    Node x = NodeManager::currentNM()->mkBoundVar( os.str().c_str(), tn );\r
+    d_free_var_num[x] = d_free_var[tn].size();\r
+    d_free_var[tn].push_back( x );\r
+  }\r
+  return d_free_var[tn][i];\r
+}\r
+\r
+\r
+\r
+Node ConjectureGenerator::getCanonicalTerm( TNode n, std::map< TypeNode, unsigned >& var_count, std::map< TNode, TNode >& subs ) {\r
+  if( n.getKind()==BOUND_VARIABLE ){\r
+    std::map< TNode, TNode >::iterator it = subs.find( n );\r
+    if( it==subs.end() ){\r
+      TypeNode tn = n.getType();\r
+      //allocate variable\r
+      unsigned vn = var_count[tn];\r
+      var_count[tn]++;\r
+      subs[n] = getFreeVar( tn, vn );\r
+      return subs[n];\r
+    }else{\r
+      return it->second;\r
+    }\r
+  }else{\r
+    std::vector< Node > children;\r
+    if( n.getKind()!=EQUAL ){\r
+      if( n.hasOperator() ){\r
+        TNode op = n.getOperator();\r
+        if( !d_tge.isRelevantFunc( op ) ){\r
+          return Node::null();\r
+        }\r
+        children.push_back( op );\r
+      }else{\r
+        return Node::null();\r
+      }\r
+    }\r
+    for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+      Node cn = getCanonicalTerm( n[i], var_count, subs );\r
+      if( cn.isNull() ){\r
+        return Node::null();\r
+      }else{\r
+        children.push_back( cn );\r
+      }\r
+    }\r
+    return NodeManager::currentNM()->mkNode( n.getKind(), children );\r
+  }\r
+}\r
+\r
+bool ConjectureGenerator::isHandledTerm( TNode n ){\r
+  return !n.getAttribute(NoMatchAttribute()) && inst::Trigger::isAtomicTrigger( n ) && ( n.getKind()!=APPLY_UF || n.getOperator().getKind()!=SKOLEM );\r
+}\r
+\r
+Node ConjectureGenerator::getGroundEqc( TNode r ) {\r
+  std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r );\r
+  return it!=d_ground_eqc_map.end() ? it->second : Node::null();\r
+}\r
+\r
+bool ConjectureGenerator::isGroundEqc( TNode r ) {\r
+  return d_ground_eqc_map.find( r )!=d_ground_eqc_map.end();\r
+}\r
+\r
+bool ConjectureGenerator::isGroundTerm( TNode n ) {\r
+  return std::find( d_ground_terms.begin(), d_ground_terms.end(), n )!=d_ground_terms.end();\r
+}\r
+\r
+bool ConjectureGenerator::needsCheck( Theory::Effort e ) {\r
+  return e==Theory::EFFORT_FULL;\r
+}\r
+\r
+bool ConjectureGenerator::hasEnumeratedUf( Node n ) {\r
+  if( options::conjectureGenGtEnum()>0 ){\r
+    std::map< Node, bool >::iterator it = d_uf_enum.find( n.getOperator() );\r
+    if( it==d_uf_enum.end() ){\r
+      d_uf_enum[n.getOperator()] = true;\r
+      std::vector< Node > lem;\r
+      getEnumeratePredUfTerm( n, options::conjectureGenGtEnum(), lem );\r
+      if( !lem.empty() ){\r
+        for( unsigned j=0; j<lem.size(); j++ ){\r
+          d_quantEngine->addLemma( lem[j], false );\r
+          d_hasAddedLemma = true;\r
+        }\r
+        return false;\r
+      }\r
+    }\r
+  }\r
+  return true;\r
+}\r
+\r
+void ConjectureGenerator::reset_round( Theory::Effort e ) {\r
+\r
+}\r
+\r
+void ConjectureGenerator::check( Theory::Effort e, unsigned quant_e ) {\r
+  if( quant_e==QuantifiersEngine::QEFFORT_STANDARD ){\r
+    d_fullEffortCount++;\r
+    if( d_fullEffortCount%optFullCheckFrequency()==0 ){\r
+      d_hasAddedLemma = false;\r
+      d_tge.d_cg = this;\r
+      double clSet = 0;\r
+      if( Trace.isOn("sg-engine") ){\r
+        clSet = double(clock())/double(CLOCKS_PER_SEC);\r
+        Trace("sg-engine") << "---Conjecture Engine Round, effort = " << e << "---" << std::endl;\r
+      }\r
+      eq::EqualityEngine * ee = getEqualityEngine();\r
+\r
+      Trace("sg-proc") << "Get eq classes..." << std::endl;\r
+      d_op_arg_index.clear();\r
+      d_ground_eqc_map.clear();\r
+      d_bool_eqc[0] = Node::null();\r
+      d_bool_eqc[1] = Node::null();\r
+      std::vector< TNode > eqcs;\r
+      d_em.clear();\r
+      eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );\r
+      while( !eqcs_i.isFinished() ){\r
+        TNode r = (*eqcs_i);\r
+        eqcs.push_back( r );\r
+        if( r.getType().isBoolean() ){\r
+          if( areEqual( r, getTermDatabase()->d_true ) ){\r
+            d_ground_eqc_map[r] = getTermDatabase()->d_true;\r
+            d_bool_eqc[0] = r;\r
+          }else if( areEqual( r, getTermDatabase()->d_false ) ){\r
+            d_ground_eqc_map[r] = getTermDatabase()->d_false;\r
+            d_bool_eqc[1] = r;\r
+          }\r
+        }\r
+        d_em[r] = eqcs.size();\r
+        eq::EqClassIterator ieqc_i = eq::EqClassIterator( r, ee );\r
+        while( !ieqc_i.isFinished() ){\r
+          TNode n = (*ieqc_i);\r
+          if( isHandledTerm( n ) ){\r
+            d_op_arg_index[r].addTerm( this, n );\r
+          }\r
+          ++ieqc_i;\r
+        }\r
+        ++eqcs_i;\r
+      }\r
+      Assert( !d_bool_eqc[0].isNull() );\r
+      Assert( !d_bool_eqc[1].isNull() );\r
+      d_urelevant_terms.clear();\r
+      Trace("sg-proc") << "...done get eq classes" << std::endl;\r
+\r
+      Trace("sg-proc") << "Determine ground EQC..." << std::endl;\r
+      bool success;\r
+      do{\r
+        success = false;\r
+        for( unsigned i=0; i<eqcs.size(); i++ ){\r
+          TNode r = eqcs[i];\r
+          if( d_ground_eqc_map.find( r )==d_ground_eqc_map.end() ){\r
+            std::vector< TNode > args;\r
+            Trace("sg-pat-debug") << "******* Get ground term for " << r << std::endl;\r
+            Node n;\r
+            if( getTermDatabase()->isInductionTerm( r ) ){\r
+              n = d_op_arg_index[r].getGroundTerm( this, args );\r
+            }else{\r
+              n = r;\r
+            }\r
+            if( !n.isNull() ){\r
+              Trace("sg-pat") << "Ground term for eqc " << r << " : " << std::endl;\r
+              Trace("sg-pat") << "   " << n << std::endl;\r
+              d_ground_eqc_map[r] = n;\r
+              success = true;\r
+            }else{\r
+              Trace("sg-pat-debug") << "...could not find ground term." << std::endl;\r
+            }\r
+          }\r
+        }\r
+      }while( success );\r
+      //also get ground terms\r
+      d_ground_terms.clear();\r
+      for( unsigned i=0; i<eqcs.size(); i++ ){\r
+        TNode r = eqcs[i];\r
+        d_op_arg_index[r].getGroundTerms( this, d_ground_terms );\r
+      }\r
+      Trace("sg-proc") << "...done determine ground EQC" << std::endl;\r
+\r
+      //debug printing\r
+      if( Trace.isOn("sg-gen-eqc") ){\r
+        for( unsigned i=0; i<eqcs.size(); i++ ){\r
+          TNode r = eqcs[i];\r
+          //print out members\r
+          bool firstTime = true;\r
+          bool isFalse = areEqual( r, getTermDatabase()->d_false );\r
+          eq::EqClassIterator eqc_i = eq::EqClassIterator( r, ee );\r
+          while( !eqc_i.isFinished() ){\r
+            TNode n = (*eqc_i);\r
+            if( !n.getAttribute(NoMatchAttribute()) && ( n.getKind()!=EQUAL || isFalse ) ){\r
+              if( firstTime ){\r
+                Trace("sg-gen-eqc") << "e" << d_em[r] << " : { " << std::endl;\r
+                firstTime = false;\r
+              }\r
+              if( n.hasOperator() ){\r
+                Trace("sg-gen-eqc") << "   (" << n.getOperator();\r
+                getTermDatabase()->computeArgReps( n );\r
+                for( unsigned i=0; i<getTermDatabase()->d_arg_reps[n].size(); i++ ){\r
+                  Trace("sg-gen-eqc") << " e" << d_em[getTermDatabase()->d_arg_reps[n][i]];\r
+                }\r
+                Trace("sg-gen-eqc") << ") :: " << n << std::endl;\r
+              }else{\r
+                Trace("sg-gen-eqc") << "   " << n << std::endl;\r
+              }\r
+            }\r
+            ++eqc_i;\r
+          }\r
+          if( !firstTime ){\r
+            Trace("sg-gen-eqc") << "}" << std::endl;\r
+            //print out ground term\r
+            std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r );\r
+            if( it!=d_ground_eqc_map.end() ){\r
+              Trace("sg-gen-eqc") << "- Ground term : " << it->second << std::endl;\r
+            }\r
+          }\r
+        }\r
+      }\r
+\r
+      Trace("sg-proc") << "Compute relevant eqc..." << std::endl;\r
+      d_tge.d_relevant_eqc[0].clear();\r
+      d_tge.d_relevant_eqc[1].clear();\r
+      for( unsigned i=0; i<eqcs.size(); i++ ){\r
+        TNode r = eqcs[i];\r
+        std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r );\r
+        unsigned index = 1;\r
+        if( it==d_ground_eqc_map.end() ){\r
+          index = 0;\r
+        }\r
+        //based on unproven conjectures? TODO\r
+        d_tge.d_relevant_eqc[index].push_back( r );\r
+      }\r
+      Trace("sg-gen-tg-debug") << "Initial relevant eqc : ";\r
+      for( unsigned i=0; i<d_tge.d_relevant_eqc[0].size(); i++ ){\r
+        Trace("sg-gen-tg-debug") << "e" << d_em[d_tge.d_relevant_eqc[0][i]] << " ";\r
+      }\r
+      Trace("sg-gen-tg-debug") << std::endl;\r
+      Trace("sg-proc") << "...done compute relevant eqc" << std::endl;\r
+\r
+\r
+      Trace("sg-proc") << "Collect signature information..." << std::endl;\r
+      d_tge.collectSignatureInformation();\r
+      if( d_hasAddedLemma ){\r
+        Trace("sg-proc") << "...added enumeration lemmas." << std::endl;\r
+      }\r
+      Trace("sg-proc") << "...done collect signature information" << std::endl;\r
+\r
+\r
+\r
+      Trace("sg-proc") << "Build theorem index..." << std::endl;\r
+      d_ue_canon.clear();\r
+      d_thm_index.clear();\r
+      std::vector< Node > provenConj;\r
+      quantifiers::FirstOrderModel* m = d_quantEngine->getModel();\r
+      for( int i=0; i<m->getNumAssertedQuantifiers(); i++ ){\r
+        Node q = m->getAssertedQuantifier( i );\r
+        Trace("thm-db-debug") << "Is " << q << " a relevant theorem?" << std::endl;\r
+        Node conjEq;\r
+        if( q[1].getKind()==EQUAL ){\r
+          bool isSubsume = false;\r
+          bool inEe = false;\r
+          for( unsigned r=0; r<2; r++ ){\r
+            TNode nl = q[1][r==0 ? 0 : 1];\r
+            TNode nr = q[1][r==0 ? 1 : 0];\r
+            Node eq = nl.eqNode( nr );\r
+            if( r==1 || std::find( d_conjectures.begin(), d_conjectures.end(), q )==d_conjectures.end() ){\r
+              //must make it canonical\r
+              std::map< TypeNode, unsigned > var_count;\r
+              std::map< TNode, TNode > subs;\r
+              Trace("sg-proc-debug") << "get canonical " << eq << std::endl;\r
+              eq = getCanonicalTerm( eq, var_count, subs );\r
+            }\r
+            if( !eq.isNull() ){\r
+              if( r==0 ){\r
+                inEe = d_ee_conjectures.find( q[1] )!=d_ee_conjectures.end();\r
+                if( !inEe ){\r
+                  //add to universal equality engine\r
+                  Node nl = getUniversalRepresentative( eq[0], true );\r
+                  Node nr = getUniversalRepresentative( eq[1], true );\r
+                  if( areUniversalEqual( nl, nr ) ){\r
+                    isSubsume = true;\r
+                    //set inactive (will be ignored by other modules)\r
+                    d_quantEngine->getModel()->setQuantifierActive( q, false );\r
+                  }else{\r
+                    Node exp;\r
+                    d_ee_conjectures[q[1]] = true;\r
+                    d_uequalityEngine.assertEquality( nl.eqNode( nr ), true, exp );\r
+                  }\r
+                }\r
+                Trace("sg-conjecture") << "*** CONJECTURE : currently proven" << (isSubsume ? " and subsumed" : "");\r
+                Trace("sg-conjecture") << " : " << q[1] << std::endl;\r
+                provenConj.push_back( q );\r
+              }\r
+              if( !isSubsume ){\r
+                Trace("thm-db-debug") << "Adding theorem to database " << eq[0] << " == " << eq[1] << std::endl;\r
+                d_thm_index.addTheorem( eq[0], eq[1] );\r
+              }else{\r
+                break;\r
+              }\r
+            }else{\r
+              break;\r
+            }\r
+          }\r
+        }\r
+      }\r
+      //examine status of other conjectures\r
+      for( unsigned i=0; i<d_conjectures.size(); i++ ){\r
+        Node q = d_conjectures[i];\r
+        if( std::find( provenConj.begin(), provenConj.end(), q )==provenConj.end() ){\r
+          //check each skolem variable\r
+          bool disproven = true;\r
+          //std::vector< Node > sk;\r
+          //getTermDatabase()->getSkolemConstants( q, sk, true );\r
+          Trace("sg-conjecture") << "    CONJECTURE : ";\r
+          std::vector< Node > ce;\r
+          for( unsigned j=0; j<getTermDatabase()->d_skolem_constants[q].size(); j++ ){\r
+            TNode k = getTermDatabase()->d_skolem_constants[q][j];\r
+            TNode rk = getRepresentative( k );\r
+            std::map< TNode, Node >::iterator git = d_ground_eqc_map.find( rk );\r
+            //check if it is a ground term\r
+            if( git==d_ground_eqc_map.end() ){\r
+              Trace("sg-conjecture") << "ACTIVE : " << q;\r
+              if( Trace.isOn("sg-gen-eqc") ){\r
+                Trace("sg-conjecture") << " { ";\r
+                for( unsigned k=0; k<getTermDatabase()->d_skolem_constants[q].size(); k++ ){ Trace("sg-conjecture") << getTermDatabase()->d_skolem_constants[q][k] << ( j==k ? "*" : "" ) << " "; }\r
+                Trace("sg-conjecture") << "}";\r
+              }\r
+              Trace("sg-conjecture") << std::endl;\r
+              disproven = false;\r
+              break;\r
+            }else{\r
+              ce.push_back( git->second );\r
+            }\r
+          }\r
+          if( disproven ){\r
+            Trace("sg-conjecture") << "disproven : " << q << " : ";\r
+            for( unsigned i=0; i<ce.size(); i++ ){\r
+              Trace("sg-conjecture") << q[0][i] << " -> " << ce[i] << " ";\r
+            }\r
+            Trace("sg-conjecture") << std::endl;\r
+          }\r
+        }\r
+      }\r
+      Trace("thm-db") << "Theorem database is : " << std::endl;\r
+      d_thm_index.debugPrint( "thm-db" );\r
+      Trace("thm-db") << std::endl;\r
+      Trace("sg-proc") << "...done build theorem index" << std::endl;\r
+\r
+\r
+      //clear patterns\r
+      d_patterns.clear();\r
+      d_pattern_var_id.clear();\r
+      d_pattern_var_duplicate.clear();\r
+      d_pattern_is_normal.clear();\r
+      d_pattern_is_relevant.clear();\r
+      d_pattern_fun_id.clear();\r
+      d_pattern_fun_sum.clear();\r
+      d_rel_patterns.clear();\r
+      d_rel_pattern_var_sum.clear();\r
+      d_rel_pattern_typ_index.clear();\r
+      d_rel_pattern_subs_index.clear();\r
+\r
+      unsigned rel_term_count = 0;\r
+      std::map< TypeNode, unsigned > rt_var_max;\r
+      std::vector< TypeNode > rt_types;\r
+      std::map< TypeNode, std::map< int, std::vector< Node > > > conj_lhs;\r
+      unsigned addedLemmas = 0;\r
+      for( unsigned depth=1; depth<=3; depth++ ){\r
+        Trace("sg-proc") << "Generate relevant LHS at depth " << depth << "..." << std::endl;\r
+        Trace("sg-rel-term") << "Relevant terms of depth " << depth << " : " << std::endl;\r
+        //set up environment\r
+        d_tge.d_var_id.clear();\r
+        d_tge.d_var_limit.clear();\r
+        d_tge.reset( depth, true, TypeNode::null() );\r
+        while( d_tge.getNextTerm() ){\r
+          //construct term\r
+          Node nn = d_tge.getTerm();\r
+          if( !options::conjectureFilterCanonical() || considerTermCanon( nn, true ) ){\r
+            rel_term_count++;\r
+            Trace("sg-rel-term") << "*** Relevant term : ";\r
+            d_tge.debugPrint( "sg-rel-term", "sg-rel-term-debug2" );\r
+            Trace("sg-rel-term") << std::endl;\r
+\r
+            for( unsigned r=0; r<2; r++ ){\r
+              Trace("sg-rel-term-debug") << "...from equivalence classes (" << r << ") : ";\r
+              int index = d_tge.d_ccand_eqc[r].size()-1;\r
+              for( unsigned j=0; j<d_tge.d_ccand_eqc[r][index].size(); j++ ){\r
+                Trace("sg-rel-term-debug") << "e" << d_em[d_tge.d_ccand_eqc[r][index][j]] << " ";\r
+              }\r
+              Trace("sg-rel-term-debug") << std::endl;\r
+            }\r
+            TypeNode tnn = nn.getType();\r
+            Trace("sg-gen-tg-debug") << "...term is " << nn << std::endl;\r
+            conj_lhs[tnn][depth].push_back( nn );\r
+\r
+            //add information about pattern\r
+            Trace("sg-gen-tg-debug") << "Collect pattern information..." << std::endl;\r
+            Assert( std::find( d_rel_patterns[tnn].begin(), d_rel_patterns[tnn].end(), nn )==d_rel_patterns[tnn].end() );\r
+            d_rel_patterns[tnn].push_back( nn );\r
+            //build information concerning the variables in this pattern\r
+            unsigned sum = 0;\r
+            std::map< TypeNode, unsigned > typ_to_subs_index;\r
+            std::vector< TNode > gsubs_vars;\r
+            for( std::map< TypeNode, unsigned >::iterator it = d_tge.d_var_id.begin(); it != d_tge.d_var_id.end(); ++it ){\r
+              if( it->second>0 ){\r
+                typ_to_subs_index[it->first] = sum;\r
+                sum += it->second;\r
+                for( unsigned i=0; i<it->second; i++ ){\r
+                  gsubs_vars.push_back( getFreeVar( it->first, i ) );\r
+                }\r
+              }\r
+            }\r
+            d_rel_pattern_var_sum[nn] = sum;\r
+            //register the pattern\r
+            registerPattern( nn, tnn );\r
+            Assert( d_pattern_is_normal[nn] );\r
+            Trace("sg-gen-tg-debug") << "...done collect pattern information" << std::endl;\r
+\r
+            //record information about types\r
+            Trace("sg-gen-tg-debug") << "Collect type information..." << std::endl;\r
+            PatternTypIndex * pti = &d_rel_pattern_typ_index;\r
+            for( std::map< TypeNode, unsigned >::iterator it = d_tge.d_var_id.begin(); it != d_tge.d_var_id.end(); ++it ){\r
+              pti = &pti->d_children[it->first][it->second];\r
+              //record maximum\r
+              if( rt_var_max.find( it->first )==rt_var_max.end() || it->second>rt_var_max[it->first] ){\r
+                rt_var_max[it->first] = it->second;\r
+              }\r
+            }\r
+            if( std::find( rt_types.begin(), rt_types.end(), tnn )==rt_types.end() ){\r
+              rt_types.push_back( tnn );\r
+            }\r
+            pti->d_terms.push_back( nn );\r
+            Trace("sg-gen-tg-debug") << "...done collect type information" << std::endl;\r
+\r
+            Trace("sg-gen-tg-debug") << "Build substitutions for ground EQC..." << std::endl;\r
+            std::vector< TNode > gsubs_terms;\r
+            gsubs_terms.resize( gsubs_vars.size() );\r
+            int index = d_tge.d_ccand_eqc[1].size()-1;\r
+            for( unsigned j=0; j<d_tge.d_ccand_eqc[1][index].size(); j++ ){\r
+              TNode r = d_tge.d_ccand_eqc[1][index][j];\r
+              Trace("sg-rel-term-debug") << "  Matches for e" << d_em[r] << ", which is ground term " << d_ground_eqc_map[r] << ":" << std::endl;\r
+              std::map< TypeNode, std::map< unsigned, TNode > > subs;\r
+              std::map< TNode, bool > rev_subs;\r
+              //only get ground terms\r
+              unsigned mode = 2;\r
+              d_tge.resetMatching( r, mode );\r
+              while( d_tge.getNextMatch( r, subs, rev_subs ) ){\r
+                //we will be building substitutions\r
+                bool firstTime = true;\r
+                for( std::map< TypeNode, std::map< unsigned, TNode > >::iterator it = subs.begin(); it != subs.end(); ++it ){\r
+                  unsigned tindex = typ_to_subs_index[it->first];\r
+                  for( std::map< unsigned, TNode >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){\r
+                    if( !firstTime ){\r
+                      Trace("sg-rel-term-debug") << ", ";\r
+                    }else{\r
+                      firstTime = false;\r
+                      Trace("sg-rel-term-debug") << "    ";\r
+                    }\r
+                    Trace("sg-rel-term-debug") << it->first << ":x" << it2->first << " -> " << it2->second;\r
+                    Assert( tindex+it2->first<gsubs_terms.size() );\r
+                    gsubs_terms[tindex+it2->first] = it2->second;\r
+                  }\r
+                }\r
+                Trace("sg-rel-term-debug") << std::endl;\r
+                d_rel_pattern_subs_index[nn].addSubstitution( r, gsubs_vars, gsubs_terms );\r
+              }\r
+            }\r
+            Trace("sg-gen-tg-debug") << "...done build substitutions for ground EQC" << std::endl;\r
+          }else{\r
+            Trace("sg-gen-tg-debug") << "> not canonical : " << nn << std::endl;\r
+          }\r
+        }\r
+        Trace("sg-proc") << "...done generate terms at depth " << depth << std::endl;\r
+        Trace("sg-stats") << "--------> Total LHS of depth " << depth << " : " << rel_term_count << std::endl;\r
+        //Trace("conjecture-count") << "Total LHS of depth " << depth << " : " << conj_lhs[depth].size() << std::endl;\r
+\r
+        /* test...\r
+        for( unsigned i=0; i<rt_types.size(); i++ ){\r
+          Trace("sg-term-enum") << "Term enumeration for " << rt_types[i] << " : " << std::endl;\r
+          Trace("sg-term-enum") << "Ground term : " << rt_types[i].mkGroundTerm() << std::endl;\r
+          for( unsigned j=0; j<150; j++ ){\r
+            Trace("sg-term-enum") << "  " << getEnumerateTerm( rt_types[i], j ) << std::endl;\r
+          }\r
+        }\r
+        */\r
+\r
+        //consider types from relevant terms\r
+        for( unsigned rdepth=0; rdepth<=depth; rdepth++ ){\r
+          //set up environment\r
+          d_tge.d_var_id.clear();\r
+          d_tge.d_var_limit.clear();\r
+          for( std::map< TypeNode, unsigned >::iterator it = rt_var_max.begin(); it != rt_var_max.end(); ++it ){\r
+            d_tge.d_var_id[ it->first ] = it->second;\r
+            d_tge.d_var_limit[ it->first ] = it->second;\r
+          }\r
+          std::random_shuffle( rt_types.begin(), rt_types.end() );\r
+          std::map< TypeNode, std::vector< Node > > conj_rhs;\r
+          for( unsigned i=0; i<rt_types.size(); i++ ){\r
+\r
+            Trace("sg-proc") << "Generate relevant RHS terms of type " << rt_types[i] << " at depth " << rdepth << "..." << std::endl;\r
+            d_tge.reset( rdepth, false, rt_types[i] );\r
+\r
+            while( d_tge.getNextTerm() ){\r
+              Node rhs = d_tge.getTerm();\r
+              if( considerTermCanon( rhs, false ) ){\r
+                Trace("sg-rel-prop") << "Relevant RHS : " << rhs << std::endl;\r
+                //register pattern\r
+                Assert( rhs.getType()==rt_types[i] );\r
+                registerPattern( rhs, rt_types[i] );\r
+                if( rdepth<depth ){\r
+                  //consider against all LHS at depth\r
+                  for( unsigned j=0; j<conj_lhs[rt_types[i]][depth].size(); j++ ){\r
+                    processCandidateConjecture( conj_lhs[rt_types[i]][depth][j], rhs, depth, rdepth );\r
+                  }\r
+                }else{\r
+                  conj_rhs[rt_types[i]].push_back( rhs );\r
+                }\r
+              }\r
+            }\r
+          }\r
+          flushWaitingConjectures( addedLemmas, depth, rdepth );\r
+          //consider against all LHS up to depth\r
+          if( rdepth==depth ){\r
+            for( unsigned lhs_depth = 1; lhs_depth<=depth; lhs_depth++ ){\r
+              if( (int)addedLemmas<options::conjectureGenPerRound() ){\r
+                Trace("sg-proc") << "Consider conjectures at depth (" << lhs_depth << ", " << rdepth << ")..." << std::endl;\r
+                for( std::map< TypeNode, std::vector< Node > >::iterator it = conj_rhs.begin(); it != conj_rhs.end(); ++it ){\r
+                  for( unsigned j=0; j<it->second.size(); j++ ){\r
+                    for( unsigned k=0; k<conj_lhs[it->first][lhs_depth].size(); k++ ){\r
+                      processCandidateConjecture( conj_lhs[it->first][lhs_depth][k], it->second[j], lhs_depth, rdepth );\r
+                    }\r
+                  }\r
+                }\r
+                flushWaitingConjectures( addedLemmas, lhs_depth, depth );\r
+              }\r
+            }\r
+          }\r
+          if( (int)addedLemmas>=options::conjectureGenPerRound() ){\r
+            break;\r
+          }\r
+        }\r
+        if( (int)addedLemmas>=options::conjectureGenPerRound() ){\r
+          break;\r
+        }\r
+      }\r
+\r
+      if( Trace.isOn("thm-ee") ){\r
+        Trace("thm-ee") << "Universal equality engine is : " << std::endl;\r
+        eq::EqClassesIterator ueqcs_i = eq::EqClassesIterator( &d_uequalityEngine );\r
+        while( !ueqcs_i.isFinished() ){\r
+          TNode r = (*ueqcs_i);\r
+          bool firstTime = true;\r
+          TNode rr = getUniversalRepresentative( r );\r
+          Trace("thm-ee") << "  " << rr;\r
+          Trace("thm-ee") << " : { ";\r
+          eq::EqClassIterator ueqc_i = eq::EqClassIterator( r, &d_uequalityEngine );\r
+          while( !ueqc_i.isFinished() ){\r
+            TNode n = (*ueqc_i);\r
+            if( rr!=n ){\r
+              if( firstTime ){\r
+                Trace("thm-ee") << std::endl;\r
+                firstTime = false;\r
+              }\r
+              Trace("thm-ee") << "    " << n << std::endl;\r
+            }\r
+            ++ueqc_i;\r
+          }\r
+          if( !firstTime ){ Trace("thm-ee") << "  "; }\r
+          Trace("thm-ee") << "}" << std::endl;\r
+          ++ueqcs_i;\r
+        }\r
+        Trace("thm-ee") << std::endl;\r
+      }\r
+      if( Trace.isOn("sg-engine") ){\r
+        double clSet2 = double(clock())/double(CLOCKS_PER_SEC);\r
+        Trace("sg-engine") << "Finished conjecture generator, time = " << (clSet2-clSet) << std::endl;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+unsigned ConjectureGenerator::flushWaitingConjectures( unsigned& addedLemmas, int ldepth, int rdepth ) {\r
+  if( !d_waiting_conjectures_lhs.empty() ){\r
+    Trace("sg-proc") << "Generated " << d_waiting_conjectures_lhs.size() << " conjectures at depth " << ldepth << "/" << rdepth << "." << std::endl;\r
+    if( !optStatsOnly() && (int)addedLemmas<options::conjectureGenPerRound() ){\r
+      std::vector< unsigned > indices;\r
+      for( unsigned i=0; i<d_waiting_conjectures_lhs.size(); i++ ){\r
+        indices.push_back( i );\r
+      }\r
+      bool doSort = false;\r
+      if( doSort ){\r
+        //sort them based on score\r
+        sortConjectureScore scs;\r
+        scs.d_scores.insert( scs.d_scores.begin(), d_waiting_conjectures_score.begin(), d_waiting_conjectures_score.end() );\r
+        std::sort( indices.begin(), indices.end(), scs );\r
+      }\r
+      if( doSort && d_waiting_conjectures_score[indices[0]]<optFilterScoreThreshold() ){\r
+        //do splitting on demand (TODO)\r
+\r
+      }else{\r
+        for( unsigned i=0; i<indices.size(); i++ ){\r
+          //if( d_waiting_conjectures_score[indices[i]]<optFilterScoreThreshold() ){\r
+          if( d_waiting_conjectures_score[indices[i]]>=optFilterScoreThreshold() ){\r
+            //we have determined a relevant subgoal\r
+            Node lhs = d_waiting_conjectures_lhs[indices[i]];\r
+            Node rhs = d_waiting_conjectures_rhs[indices[i]];\r
+            if( options::conjectureFilterCanonical() && ( getUniversalRepresentative( lhs )!=lhs || getUniversalRepresentative( rhs )!=rhs ) ){\r
+              //skip\r
+            }else{\r
+              Trace("sg-engine") << "*** Consider conjecture : " << lhs << " == " << rhs << std::endl;\r
+              Trace("sg-engine-debug") << "      score : " << d_waiting_conjectures_score[indices[i]] << std::endl;\r
+              std::vector< Node > bvs;\r
+              for( std::map< TypeNode, unsigned >::iterator it = d_pattern_var_id[lhs].begin(); it != d_pattern_var_id[lhs].end(); ++it ){\r
+                for( unsigned i=0; i<=it->second; i++ ){\r
+                  bvs.push_back( getFreeVar( it->first, i ) );\r
+                }\r
+              }\r
+              Node rsg;\r
+              if( !bvs.empty() ){\r
+                Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, bvs );\r
+                rsg = NodeManager::currentNM()->mkNode( FORALL, bvl, lhs.eqNode( rhs ) );\r
+              }else{\r
+                rsg = lhs.eqNode( rhs );\r
+              }\r
+              rsg = Rewriter::rewrite( rsg );\r
+              d_conjectures.push_back( rsg );\r
+              d_eq_conjectures[lhs].push_back( rhs );\r
+              d_eq_conjectures[rhs].push_back( lhs );\r
+\r
+              Node lem = NodeManager::currentNM()->mkNode( OR, rsg.negate(), rsg );\r
+              d_quantEngine->addLemma( lem, false );\r
+              d_quantEngine->addRequirePhase( rsg, false );\r
+              addedLemmas++;\r
+              if( (int)addedLemmas>=options::conjectureGenPerRound() ){\r
+                break;\r
+              }\r
+            }\r
+          }else{\r
+            if( doSort ){\r
+              break;\r
+            }\r
+          }\r
+        }\r
+      }\r
+      Trace("sg-proc") << "...have now added " << addedLemmas << " conjecture lemmas." << std::endl;\r
+    }\r
+    d_waiting_conjectures_lhs.clear();\r
+    d_waiting_conjectures_rhs.clear();\r
+    d_waiting_conjectures_score.clear();\r
+    d_waiting_conjectures.clear();\r
+  }\r
+  return addedLemmas;\r
+}\r
+\r
+void ConjectureGenerator::registerQuantifier( Node q ) {\r
+\r
+}\r
+\r
+void ConjectureGenerator::assertNode( Node n ) {\r
+\r
+}\r
+\r
+bool ConjectureGenerator::considerTermCanon( Node ln, bool genRelevant ){\r
+  if( !ln.isNull() ){\r
+    //do not consider if it is non-canonical, and either:\r
+    //  (1) we are not generating relevant terms, or\r
+    //  (2) its canonical form is a generalization.\r
+    TNode lnr = getUniversalRepresentative( ln, true );\r
+    if( lnr==ln ){\r
+      markReportedCanon( ln );\r
+    }else if( !genRelevant || isGeneralization( lnr, ln ) ){\r
+      Trace("sg-gen-consider-term") << "Do not consider term, " << ln << " is not canonical representation (which is " << lnr << ")." << std::endl;\r
+      return false;\r
+    }\r
+  }\r
+  Trace("sg-gen-tg-debug") << "Will consider term canon " << ln << std::endl;\r
+  Trace("sg-gen-consider-term-debug") << std::endl;\r
+  return true;\r
+}\r
+\r
+unsigned ConjectureGenerator::collectFunctions( TNode opat, TNode pat, std::map< TNode, unsigned >& funcs,\r
+                                             std::map< TypeNode, unsigned >& mnvn, std::map< TypeNode, unsigned >& mxvn ){\r
+  if( pat.hasOperator() ){\r
+    funcs[pat.getOperator()]++;\r
+    if( !d_tge.isRelevantFunc( pat.getOperator() ) ){\r
+      d_pattern_is_relevant[opat] = false;\r
+    }\r
+    unsigned sum = 1;\r
+    for( unsigned i=0; i<pat.getNumChildren(); i++ ){\r
+      sum += collectFunctions( opat, pat[i], funcs, mnvn, mxvn );\r
+    }\r
+    return sum;\r
+  }else{\r
+    Assert( pat.getNumChildren()==0 );\r
+    funcs[pat]++;\r
+    //for variables\r
+    if( pat.getKind()==BOUND_VARIABLE ){\r
+      if( funcs[pat]>1 ){\r
+        //duplicate variable\r
+        d_pattern_var_duplicate[opat]++;\r
+      }else{\r
+        //check for max/min\r
+        TypeNode tn = pat.getType();\r
+        unsigned vn = d_free_var_num[pat];\r
+        std::map< TypeNode, unsigned >::iterator it = mnvn.find( tn );\r
+        if( it!=mnvn.end() ){\r
+          if( vn<it->second ){\r
+            d_pattern_is_normal[opat] = false;\r
+            mnvn[tn] = vn;\r
+          }else if( vn>mxvn[tn] ){\r
+            if( vn!=mxvn[tn]+1 ){\r
+              d_pattern_is_normal[opat] = false;\r
+            }\r
+            mxvn[tn] = vn;\r
+          }\r
+        }else{\r
+          //first variable of this type\r
+          mnvn[tn] = vn;\r
+          mxvn[tn] = vn;\r
+        }\r
+      }\r
+    }else{\r
+      d_pattern_is_relevant[opat] = false;\r
+    }\r
+    return 1;\r
+  }\r
+}\r
+\r
+void ConjectureGenerator::registerPattern( Node pat, TypeNode tpat ) {\r
+  if( std::find( d_patterns[tpat].begin(), d_patterns[tpat].end(), pat )==d_patterns[tpat].end() ){\r
+    d_patterns[TypeNode::null()].push_back( pat );\r
+    d_patterns[tpat].push_back( pat );\r
+\r
+    Assert( d_pattern_fun_id.find( pat )==d_pattern_fun_id.end() );\r
+    Assert( d_pattern_var_id.find( pat )==d_pattern_var_id.end() );\r
+\r
+    //collect functions\r
+    std::map< TypeNode, unsigned > mnvn;\r
+    d_pattern_fun_sum[pat] = collectFunctions( pat, pat, d_pattern_fun_id[pat], mnvn, d_pattern_var_id[pat] );\r
+    if( d_pattern_is_normal.find( pat )==d_pattern_is_normal.end() ){\r
+      d_pattern_is_normal[pat] = true;\r
+    }\r
+    if( d_pattern_is_relevant.find( pat )==d_pattern_is_relevant.end() ){\r
+      d_pattern_is_relevant[pat] = true;\r
+    }\r
+  }\r
+}\r
+\r
+bool ConjectureGenerator::isGeneralization( TNode patg, TNode pat, std::map< TNode, TNode >& subs ) {\r
+  if( patg.getKind()==BOUND_VARIABLE ){\r
+    std::map< TNode, TNode >::iterator it = subs.find( patg );\r
+    if( it!=subs.end() ){\r
+      return it->second==pat;\r
+    }else{\r
+      subs[patg] = pat;\r
+      return true;\r
+    }\r
+  }else{\r
+    Assert( patg.hasOperator() );\r
+    if( !pat.hasOperator() || patg.getOperator()!=pat.getOperator() ){\r
+      return false;\r
+    }else{\r
+      Assert( patg.getNumChildren()==pat.getNumChildren() );\r
+      for( unsigned i=0; i<patg.getNumChildren(); i++ ){\r
+        if( !isGeneralization( patg[i], pat[i], subs ) ){\r
+          return false;\r
+        }\r
+      }\r
+      return true;\r
+    }\r
+  }\r
+}\r
+\r
+int ConjectureGenerator::calculateGeneralizationDepth( TNode n, std::vector< TNode >& fv ) {\r
+  if( n.getKind()==BOUND_VARIABLE ){\r
+    if( std::find( fv.begin(), fv.end(), n )==fv.end() ){\r
+      fv.push_back( n );\r
+      return 0;\r
+    }else{\r
+      return 1;\r
+    }\r
+  }else{\r
+    int depth = 1;\r
+    for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+      depth += calculateGeneralizationDepth( n[i], fv );\r
+    }\r
+    return depth;\r
+  }\r
+}\r
+\r
+Node ConjectureGenerator::getPredicateForType( TypeNode tn ) {\r
+  std::map< TypeNode, Node >::iterator it = d_typ_pred.find( tn );\r
+  if( it==d_typ_pred.end() ){\r
+    TypeNode op_tn = NodeManager::currentNM()->mkFunctionType( tn, NodeManager::currentNM()->booleanType() );\r
+    Node op = NodeManager::currentNM()->mkSkolem( "PE", op_tn, "was created by conjecture ground term enumerator." );\r
+    d_typ_pred[tn] = op;\r
+    return op;\r
+  }else{\r
+    return it->second;\r
+  }\r
+}\r
+\r
+void ConjectureGenerator::getEnumerateUfTerm( Node n, unsigned num, std::vector< Node >& terms ) {\r
+  if( n.getNumChildren()>0 ){\r
+    std::vector< int > vec;\r
+    for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+      vec.push_back( 0 );\r
+    }\r
+    vec.pop_back();\r
+    int size_limit = 0;\r
+    int vec_sum = -1;\r
+    unsigned index = 0;\r
+    unsigned last_size = terms.size();\r
+    while( terms.size()<num ){\r
+      bool success = true;\r
+      if( vec_sum==-1 ){\r
+        vec_sum = 0;\r
+        vec.push_back( size_limit );\r
+      }else{\r
+        //see if we can iterate current\r
+        if( vec_sum<size_limit && !getTermDatabase()->getEnumerateTerm( n[index].getType(), vec[index]+1 ).isNull() ){\r
+          vec[index]++;\r
+          vec_sum++;\r
+          vec.push_back( size_limit - vec_sum );\r
+        }else{\r
+          vec_sum -= vec[index];\r
+          vec[index] = 0;\r
+          index++;\r
+          if( index==n.getNumChildren() ){\r
+            success = false;\r
+          }\r
+        }\r
+      }\r
+      if( success ){\r
+        if( vec.size()==n.getNumChildren() ){\r
+          Node lc = getTermDatabase()->getEnumerateTerm( n[vec.size()-1].getType(), vec[vec.size()-1] );\r
+          if( !lc.isNull() ){\r
+            for( unsigned i=0; i<vec.size(); i++ ){\r
+              Trace("sg-gt-enum-debug") << vec[i] << " ";\r
+            }\r
+            Trace("sg-gt-enum-debug") << " / " << size_limit << std::endl;\r
+            for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+              Trace("sg-gt-enum-debug") << n[i].getType() << " ";\r
+            }\r
+            Trace("sg-gt-enum-debug") << std::endl;\r
+            std::vector< Node > children;\r
+            children.push_back( n.getOperator() );\r
+            for( unsigned i=0; i<(vec.size()-1); i++ ){\r
+              Node nn = getTermDatabase()->getEnumerateTerm( n[i].getType(), vec[i] );\r
+              Assert( !nn.isNull() );\r
+              Assert( nn.getType()==n[i].getType() );\r
+              children.push_back( nn );\r
+            }\r
+            children.push_back( lc );\r
+            Node n = NodeManager::currentNM()->mkNode( APPLY_UF, children );\r
+            Trace("sg-gt-enum") << "Ground term enumerate : " << n << std::endl;\r
+            terms.push_back( n );\r
+          }\r
+          vec.pop_back();\r
+          index = 0;\r
+        }\r
+      }else{\r
+        if( terms.size()>last_size ){\r
+          last_size = terms.size();\r
+          size_limit++;\r
+          for( unsigned i=0; i<vec.size(); i++ ){\r
+            vec[i] = 0;\r
+          }\r
+          vec_sum = -1;\r
+        }\r
+      }\r
+    }\r
+  }else{\r
+    terms.push_back( n );\r
+  }\r
+}\r
+\r
+void ConjectureGenerator::getEnumeratePredUfTerm( Node n, unsigned num, std::vector< Node >& terms ) {\r
+  std::vector< Node > uf_terms;\r
+  getEnumerateUfTerm( n, num, uf_terms );\r
+  Node p = getPredicateForType( n.getType() );\r
+  for( unsigned i=0; i<uf_terms.size(); i++ ){\r
+    terms.push_back( NodeManager::currentNM()->mkNode( APPLY_UF, p, uf_terms[i] ) );\r
+  }\r
+}\r
+\r
+void ConjectureGenerator::processCandidateConjecture( TNode lhs, TNode rhs, unsigned lhs_depth, unsigned rhs_depth ) {\r
+  int score = considerCandidateConjecture( lhs, rhs );\r
+  if( score>0 ){\r
+    Trace("sg-conjecture") << "* Candidate conjecture : " << lhs << " == " << rhs << std::endl;\r
+    Trace("sg-conjecture-debug") << "     LHS, RHS generalization depth : " << lhs_depth << ", " << rhs_depth << std::endl;\r
+    Trace("sg-conjecture-debug") << "     confirmed = " << d_subs_confirmCount << ", #witnesses range = " << d_subs_confirmWitnessRange.size() << "." << std::endl;\r
+    Trace("sg-conjecture-debug") << "     #witnesses for ";\r
+    bool firstTime = true;\r
+    for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){\r
+      if( !firstTime ){\r
+        Trace("sg-conjecture-debug") << ", ";\r
+      }\r
+      Trace("sg-conjecture-debug") << it->first << " : " << it->second.size();\r
+      //if( it->second.size()==1 ){\r
+      //  Trace("sg-conjecture-debug") << " (" << it->second[0] << ")";\r
+      //}\r
+      Trace("sg-conjecture-debug2") << " (";\r
+      for( unsigned j=0; j<it->second.size(); j++ ){\r
+        if( j>0 ){ Trace("sg-conjecture-debug2") << " "; }\r
+        Trace("sg-conjecture-debug2") << d_ground_eqc_map[it->second[j]];\r
+      }\r
+      Trace("sg-conjecture-debug2") << ")";\r
+      firstTime = false;\r
+    }\r
+    Trace("sg-conjecture-debug") << std::endl;\r
+    Trace("sg-conjecture-debug") << "     unknown = " << d_subs_unkCount << std::endl;\r
+    //Assert( getUniversalRepresentative( rhs )==rhs );\r
+    //Assert( getUniversalRepresentative( lhs )==lhs );\r
+    d_waiting_conjectures_lhs.push_back( lhs );\r
+    d_waiting_conjectures_rhs.push_back( rhs );\r
+    d_waiting_conjectures_score.push_back( score );\r
+    d_waiting_conjectures[lhs].push_back( rhs );\r
+    d_waiting_conjectures[rhs].push_back( lhs );\r
+  }\r
+}\r
+\r
+int ConjectureGenerator::considerCandidateConjecture( TNode lhs, TNode rhs ) {\r
+  Assert( lhs.getType()==rhs.getType() );\r
+\r
+  Trace("sg-cconj-debug") << "Consider candidate conjecture : " << lhs << " == " << rhs << "?" << std::endl;\r
+  if( lhs==rhs ){\r
+    Trace("sg-cconj-debug") << "  -> trivial." << std::endl;\r
+    return -1;\r
+  }else{\r
+    if( lhs.getKind()==APPLY_CONSTRUCTOR && rhs.getKind()==APPLY_CONSTRUCTOR ){\r
+      Trace("sg-cconj-debug") << "  -> irrelevant by syntactic analysis." << std::endl;\r
+      return -1;\r
+    }\r
+    //variables of LHS must subsume variables of RHS\r
+    for( std::map< TypeNode, unsigned >::iterator it = d_pattern_var_id[rhs].begin(); it != d_pattern_var_id[rhs].end(); ++it ){\r
+      std::map< TypeNode, unsigned >::iterator itl = d_pattern_var_id[lhs].find( it->first );\r
+      if( itl!=d_pattern_var_id[lhs].end() ){\r
+        if( itl->second<it->second ){\r
+          Trace("sg-cconj-debug") << "  -> variables of sort " << it->first << " are not subsumed." << std::endl;\r
+          return -1;\r
+        }else{\r
+          Trace("sg-cconj-debug2") << "  variables of sort " << it->first << " are : " << itl->second << " vs " << it->second << std::endl;\r
+        }\r
+      }else{\r
+        Trace("sg-cconj-debug") << "  -> has no variables of sort " << it->first << "." << std::endl;\r
+        return -1;\r
+      }\r
+    }\r
+\r
+    //currently active conjecture?\r
+    std::map< Node, std::vector< Node > >::iterator iteq = d_eq_conjectures.find( lhs );\r
+    if( iteq!=d_eq_conjectures.end() ){\r
+      if( std::find( iteq->second.begin(), iteq->second.end(), rhs )!=iteq->second.end() ){\r
+        Trace("sg-cconj-debug") << "  -> this conjecture is already active." << std::endl;\r
+        return -1;\r
+      }\r
+    }\r
+    //current a waiting conjecture?\r
+    std::map< Node, std::vector< Node > >::iterator itw = d_waiting_conjectures.find( lhs );\r
+    if( itw!=d_waiting_conjectures.end() ){\r
+      if( std::find( itw->second.begin(), itw->second.end(), rhs )!=itw->second.end() ){\r
+        Trace("sg-cconj-debug") << "  -> already are considering this conjecture." << std::endl;\r
+        return -1;\r
+      }\r
+    }\r
+    //check if canonical representation (should be, but for efficiency this is not guarenteed)\r
+    //if( options::conjectureFilterCanonical() && ( getUniversalRepresentative( lhs )!=lhs || getUniversalRepresentative( rhs )!=rhs ) ){\r
+    //  Trace("sg-cconj") << "  -> after processing, not canonical." << std::endl;\r
+    //  return -1;\r
+    //}\r
+\r
+    int score;\r
+    bool scoreSet = false;\r
+\r
+    Trace("sg-cconj") << "Consider possible candidate conjecture : " << lhs << " == " << rhs << "?" << std::endl;\r
+    //find witness for counterexample, if possible\r
+    if( options::conjectureFilterModel() ){\r
+      Assert( d_rel_pattern_var_sum.find( lhs )!=d_rel_pattern_var_sum.end() );\r
+      Trace("sg-cconj-debug") << "Notify substitutions over " << d_rel_pattern_var_sum[lhs] << " variables." << std::endl;\r
+      std::map< TNode, TNode > subs;\r
+      d_subs_confirmCount = 0;\r
+      d_subs_confirmWitnessRange.clear();\r
+      d_subs_confirmWitnessDomain.clear();\r
+      d_subs_unkCount = 0;\r
+      if( !d_rel_pattern_subs_index[lhs].notifySubstitutions( this, subs, rhs, d_rel_pattern_var_sum[lhs] ) ){\r
+        Trace("sg-cconj") << "  -> found witness that falsifies the conjecture." << std::endl;\r
+        return -1;\r
+      }\r
+      //score is the minimum number of distinct substitutions for a variable\r
+      for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){\r
+        int num = (int)it->second.size();\r
+        if( !scoreSet || num<score ){\r
+          score = num;\r
+          scoreSet = true;\r
+        }\r
+      }\r
+      if( !scoreSet ){\r
+        score = 0;\r
+      }\r
+      Trace("sg-cconj") << "     confirmed = " << d_subs_confirmCount << ", #witnesses range = " << d_subs_confirmWitnessRange.size() << "." << std::endl;\r
+      for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){\r
+        Trace("sg-cconj") << "     #witnesses for " << it->first << " : " << it->second.size() << std::endl;\r
+      }\r
+    }else{\r
+      score = 0;\r
+    }\r
+\r
+    Trace("sg-cconj") << "  -> SUCCESS." << std::endl;\r
+    Trace("sg-cconj") << "     score : " << score << std::endl;\r
+\r
+    return score;\r
+  }\r
+}\r
+\r
+bool ConjectureGenerator::notifySubstitution( TNode glhs, std::map< TNode, TNode >& subs, TNode rhs ) {\r
+  if( Trace.isOn("sg-cconj-debug") ){\r
+    Trace("sg-cconj-debug") << "Ground eqc for LHS : " << glhs << ", based on substituion: " << std::endl;\r
+    for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){\r
+      Assert( getRepresentative( it->second )==it->second );\r
+      Trace("sg-cconj-debug") << "  " << it->first << " -> " << it->second << std::endl;\r
+    }\r
+  }\r
+  Trace("sg-cconj-debug") << "Evaluate RHS : : " << rhs << std::endl;\r
+  //get the representative of rhs with substitution subs\r
+  TNode grhs = getTermDatabase()->evaluateTerm( rhs, subs, true );\r
+  Trace("sg-cconj-debug") << "...done evaluating term, got : " << grhs << std::endl;\r
+  if( !grhs.isNull() ){\r
+    if( glhs!=grhs ){\r
+      Trace("sg-cconj-debug") << "Ground eqc for RHS : " << grhs << std::endl;\r
+      //check based on ground terms\r
+      std::map< TNode, Node >::iterator itl = d_ground_eqc_map.find( glhs );\r
+      if( itl!=d_ground_eqc_map.end() ){\r
+        std::map< TNode, Node >::iterator itr = d_ground_eqc_map.find( grhs );\r
+        if( itr!=d_ground_eqc_map.end() ){\r
+          Trace("sg-cconj-debug") << "We have ground terms " << itl->second << " and " << itr->second << "." << std::endl;\r
+          if( itl->second.isConst() && itr->second.isConst() ){\r
+            Trace("sg-cconj-debug") << "...disequal constants." << std::endl;\r
+            Trace("sg-cconj-witness") << "  Witness of falsification : " << itl->second << " != " << itr->second << ", substutition is : " << std::endl;\r
+            for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){\r
+              Trace("sg-cconj-witness") << "    " << it->first << " -> " << it->second << std::endl;\r
+            }\r
+            return false;\r
+          }\r
+        }\r
+      }\r
+    }\r
+    Trace("sg-cconj-debug") << "RHS is identical." << std::endl;\r
+    bool isGroundSubs = true;\r
+    for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){\r
+      std::map< TNode, Node >::iterator git = d_ground_eqc_map.find( it->second );\r
+      if( git==d_ground_eqc_map.end() ){\r
+        isGroundSubs = false;\r
+        break;\r
+      }\r
+    }\r
+    if( isGroundSubs ){\r
+      if( glhs==grhs ){\r
+        Trace("sg-cconj-witness") << "  Witnessed " << glhs << " == " << grhs << ", substutition is : " << std::endl;\r
+        for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){\r
+          Trace("sg-cconj-witness") << "    " << it->first << " -> " << it->second << std::endl;\r
+          if( std::find( d_subs_confirmWitnessDomain[it->first].begin(), d_subs_confirmWitnessDomain[it->first].end(), it->second )==d_subs_confirmWitnessDomain[it->first].end() ){\r
+            d_subs_confirmWitnessDomain[it->first].push_back( it->second );\r
+          }\r
+        }\r
+        d_subs_confirmCount++;\r
+        if( std::find( d_subs_confirmWitnessRange.begin(), d_subs_confirmWitnessRange.end(), glhs )==d_subs_confirmWitnessRange.end() ){\r
+          d_subs_confirmWitnessRange.push_back( glhs );\r
+        }\r
+      }else{\r
+        if( optFilterUnknown() ){\r
+          Trace("sg-cconj-debug") << "...ground substitution giving terms that are neither equal nor disequal." << std::endl;\r
+          return false;\r
+        }\r
+      }\r
+    }\r
+  }else{\r
+    Trace("sg-cconj-debug") << "(could not ground eqc for RHS)." << std::endl;\r
+  }\r
+  return true;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+void TermGenerator::reset( TermGenEnv * s, TypeNode tn ) {\r
+  Assert( d_children.empty() );\r
+  d_typ = tn;\r
+  d_status = 0;\r
+  d_status_num = 0;\r
+  d_children.clear();\r
+  Trace("sg-gen-tg-debug2") << "...add to context " << this << std::endl;\r
+  d_id = s->d_tg_id;\r
+  s->changeContext( true );\r
+}\r
+\r
+bool TermGenerator::getNextTerm( TermGenEnv * s, unsigned depth ) {\r
+  if( Trace.isOn("sg-gen-tg-debug2") ){\r
+    Trace("sg-gen-tg-debug2") << this << " getNextTerm depth " << depth << " : status = " << d_status << ", num = " << d_status_num;\r
+    if( d_status==5 ){\r
+      TNode f = s->getTgFunc( d_typ, d_status_num );\r
+      Trace("sg-gen-tg-debug2") << ", f = " << f;\r
+      Trace("sg-gen-tg-debug2") << ", #args = " << s->d_func_args[f].size();\r
+      Trace("sg-gen-tg-debug2") << ", childNum = " << d_status_child_num;\r
+      Trace("sg-gen-tg-debug2") << ", #children = " << d_children.size();\r
+    }\r
+    Trace("sg-gen-tg-debug2") << std::endl;\r
+  }\r
+\r
+  if( d_status==0 ){\r
+    d_status++;\r
+    if( !d_typ.isNull() ){\r
+      if( s->allowVar( d_typ ) ){\r
+        //allocate variable\r
+        d_status_num = s->d_var_id[d_typ];\r
+        s->addVar( d_typ );\r
+        Trace("sg-gen-tg-debug2") << this << " ...return unique var #" << d_status_num << std::endl;\r
+        return s->considerCurrentTerm() ? true : getNextTerm( s, depth );\r
+      }else{\r
+        //check allocating new variable\r
+        d_status++;\r
+        d_status_num = -1;\r
+        if( s->d_gen_relevant_terms ){\r
+          s->d_tg_gdepth++;\r
+        }\r
+        return getNextTerm( s, depth );\r
+      }\r
+    }else{\r
+      d_status = 4;\r
+      d_status_num = -1;\r
+      return getNextTerm( s, depth );\r
+    }\r
+  }else if( d_status==2 ){\r
+    //cleanup previous information\r
+    //if( d_status_num>=0 ){\r
+    //  s->d_var_eq_tg[d_status_num].pop_back();\r
+    //}\r
+    //check if there is another variable\r
+    if( (d_status_num+1)<(int)s->getNumTgVars( d_typ ) ){\r
+      d_status_num++;\r
+      //we have equated two variables\r
+      //s->d_var_eq_tg[d_status_num].push_back( d_id );\r
+      Trace("sg-gen-tg-debug2") << this << "...consider other var #" << d_status_num << std::endl;\r
+      return s->considerCurrentTerm() ? true : getNextTerm( s, depth );\r
+    }else{\r
+      if( s->d_gen_relevant_terms ){\r
+        s->d_tg_gdepth--;\r
+      }\r
+      d_status++;\r
+      return getNextTerm( s, depth );\r
+    }\r
+  }else if( d_status==4 ){\r
+    d_status++;\r
+    if( depth>0 && (d_status_num+1)<(int)s->getNumTgFuncs( d_typ ) ){\r
+      d_status_num++;\r
+      d_status_child_num = 0;\r
+      Trace("sg-gen-tg-debug2") << this << "...consider function " << s->getTgFunc( d_typ, d_status_num ) << std::endl;\r
+      s->d_tg_gdepth++;\r
+      if( !s->considerCurrentTerm() ){\r
+        s->d_tg_gdepth--;\r
+        //don't consider this function\r
+        d_status--;\r
+      }else{\r
+        //we have decided on a function application\r
+      }\r
+      return getNextTerm( s, depth );\r
+    }else{\r
+      //do not choose function applications at depth 0\r
+      d_status++;\r
+      return getNextTerm( s, depth );\r
+    }\r
+  }else if( d_status==5 ){\r
+    //iterating over arguments\r
+    TNode f = s->getTgFunc( d_typ, d_status_num );\r
+    if( d_status_child_num<0 ){\r
+      //no more arguments\r
+      s->d_tg_gdepth--;\r
+      d_status--;\r
+      return getNextTerm( s, depth );\r
+    }else if( d_status_child_num==(int)s->d_func_args[f].size() ){\r
+      d_status_child_num--;\r
+      return s->considerCurrentTermCanon( d_id ) ? true : getNextTerm( s, depth );\r
+      //return true;\r
+    }else{\r
+      Assert( d_status_child_num<(int)s->d_func_args[f].size() );\r
+      if( d_status_child_num==(int)d_children.size() ){\r
+        d_children.push_back( s->d_tg_id );\r
+        Assert( s->d_tg_alloc.find( s->d_tg_id )==s->d_tg_alloc.end() );\r
+        s->d_tg_alloc[d_children[d_status_child_num]].reset( s, s->d_func_args[f][d_status_child_num] );\r
+        return getNextTerm( s, depth );\r
+      }else{\r
+        Assert( d_status_child_num+1==(int)d_children.size() );\r
+        if( s->d_tg_alloc[d_children[d_status_child_num]].getNextTerm( s, depth-1 ) ){\r
+          d_status_child_num++;\r
+          return getNextTerm( s, depth );\r
+        }else{\r
+          d_children.pop_back();\r
+          d_status_child_num--;\r
+          return getNextTerm( s, depth );\r
+        }\r
+      }\r
+    }\r
+  }else if( d_status==1 || d_status==3 ){\r
+    if( d_status==1 ){\r
+      s->removeVar( d_typ );\r
+      Assert( d_status_num==(int)s->d_var_id[d_typ] );\r
+      //check if there is only one feasible equivalence class.  if so, don't make pattern any more specific.\r
+      //unsigned i = s->d_ccand_eqc[0].size()-1;\r
+      //if( s->d_ccand_eqc[0][i].size()==1 && s->d_ccand_eqc[1][i].empty() ){\r
+      //  d_status = 6;\r
+      //  return getNextTerm( s, depth );\r
+      //}\r
+      s->d_tg_gdepth++;\r
+    }\r
+    d_status++;\r
+    d_status_num = -1;\r
+    return getNextTerm( s, depth );\r
+  }else{\r
+    //clean up\r
+    Assert( d_children.empty() );\r
+    Trace("sg-gen-tg-debug2") << "...remove from context " << this << std::endl;\r
+    s->changeContext( false );\r
+    Assert( d_id==s->d_tg_id );\r
+    return false;\r
+  }\r
+}\r
+\r
+void TermGenerator::resetMatching( TermGenEnv * s, TNode eqc, unsigned mode ) {\r
+  d_match_status = 0;\r
+  d_match_status_child_num = 0;\r
+  d_match_children.clear();\r
+  d_match_children_end.clear();\r
+  d_match_mode = mode;\r
+  //if this term generalizes, it must generalize a non-ground term\r
+  //if( (d_match_mode & ( 1 << 2 ))!=0 && s->isGroundEqc( eqc ) && d_status==5 ){\r
+  //  d_match_status = -1;\r
+  //}\r
+}\r
+\r
+bool TermGenerator::getNextMatch( TermGenEnv * s, TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs ) {\r
+  if( d_match_status<0 ){\r
+    return false;\r
+  }\r
+  if( Trace.isOn("sg-gen-tg-match") ){\r
+    Trace("sg-gen-tg-match") << "Matching ";\r
+    debugPrint( s, "sg-gen-tg-match", "sg-gen-tg-match" );\r
+    Trace("sg-gen-tg-match") << " with eqc e" << s->d_cg->d_em[eqc] << "..." << std::endl;\r
+    Trace("sg-gen-tg-match") << "   mstatus = " << d_match_status;\r
+    if( d_status==5 ){\r
+      TNode f = s->getTgFunc( d_typ, d_status_num );\r
+      Trace("sg-gen-tg-debug2") << ", f = " << f;\r
+      Trace("sg-gen-tg-debug2") << ", #args = " << s->d_func_args[f].size();\r
+      Trace("sg-gen-tg-debug2") << ", mchildNum = " << d_match_status_child_num;\r
+      Trace("sg-gen-tg-debug2") << ", #mchildren = " << d_match_children.size();\r
+    }\r
+    Trace("sg-gen-tg-debug2") << ", current substitution : {";\r
+    for( std::map< TypeNode, std::map< unsigned, TNode > >::iterator itt = subs.begin(); itt != subs.end(); ++itt ){\r
+      for( std::map< unsigned, TNode >::iterator it = itt->second.begin(); it != itt->second.end(); ++it ){\r
+        Trace("sg-gen-tg-debug2")  << " " << it->first << " -> e" << s->d_cg->d_em[it->second];\r
+      }\r
+    }\r
+    Trace("sg-gen-tg-debug2") << " } " << std::endl;\r
+  }\r
+  if( d_status==1 ){\r
+    //a variable\r
+    if( d_match_status==0 ){\r
+      d_match_status++;\r
+      if( (d_match_mode & ( 1 << 1 ))!=0 ){\r
+        //only ground terms\r
+        if( !s->isGroundEqc( eqc ) ){\r
+          return false;\r
+        }\r
+      }else if( (d_match_mode & ( 1 << 2 ))!=0 ){\r
+        //only non-ground terms\r
+        //if( s->isGroundEqc( eqc ) ){\r
+        //  return false;\r
+        //}\r
+      }\r
+      //store the match : restricted if match_mode.0 = 1\r
+      if( (d_match_mode & ( 1 << 0 ))!=0 ){\r
+        std::map< TNode, bool >::iterator it = rev_subs.find( eqc );\r
+        if( it==rev_subs.end() ){\r
+          rev_subs[eqc] = true;\r
+        }else{\r
+          return false;\r
+        }\r
+      }\r
+      Assert( subs[d_typ].find( d_status_num )==subs[d_typ].end() );\r
+      subs[d_typ][d_status_num] = eqc;\r
+      return true;\r
+    }else{\r
+      //clean up\r
+      subs[d_typ].erase( d_status_num );\r
+      if( (d_match_mode & ( 1 << 0 ))!=0 ){\r
+        rev_subs.erase( eqc );\r
+      }\r
+      return false;\r
+    }\r
+  }else if( d_status==2 ){\r
+    if( d_match_status==0 ){\r
+      d_match_status++;\r
+      Assert( d_status_num<(int)s->getNumTgVars( d_typ ) );\r
+      std::map< unsigned, TNode >::iterator it = subs[d_typ].find( d_status_num );\r
+      Assert( it!=subs[d_typ].end() );\r
+      return it->second==eqc;\r
+    }else{\r
+      return false;\r
+    }\r
+  }else if( d_status==5 ){\r
+    //Assert( d_match_children.size()<=d_children.size() );\r
+    //enumerating over f-applications in eqc\r
+    if( d_match_status_child_num<0 ){\r
+      return false;\r
+    }else if( d_match_status==0 ){\r
+      //set up next binding\r
+      if( d_match_status_child_num==(int)d_match_children.size() ){\r
+        if( d_match_status_child_num==0 ){\r
+          //initial binding\r
+          TNode f = s->getTgFunc( d_typ, d_status_num );\r
+          std::map< TNode, TermArgTrie >::iterator it = s->getTermDatabase()->d_func_map_eqc_trie[f].d_data.find( eqc );\r
+          if( it!=s->getTermDatabase()->d_func_map_eqc_trie[f].d_data.end() ){\r
+            d_match_children.push_back( it->second.d_data.begin() );\r
+            d_match_children_end.push_back( it->second.d_data.end() );\r
+          }else{\r
+            d_match_status++;\r
+            d_match_status_child_num--;\r
+            return getNextMatch( s, eqc, subs, rev_subs );\r
+          }\r
+        }else{\r
+          d_match_children.push_back( d_match_children[d_match_status_child_num-1]->second.d_data.begin() );\r
+          d_match_children_end.push_back( d_match_children[d_match_status_child_num-1]->second.d_data.end() );\r
+        }\r
+      }\r
+      d_match_status++;\r
+      Assert( d_match_status_child_num+1==(int)d_match_children.size() );\r
+      if( d_match_children[d_match_status_child_num]==d_match_children_end[d_match_status_child_num] ){\r
+        //no more arguments to bind\r
+        d_match_children.pop_back();\r
+        d_match_children_end.pop_back();\r
+        d_match_status_child_num--;\r
+        return getNextMatch( s, eqc, subs, rev_subs );\r
+      }else{\r
+        if( d_match_status_child_num==(int)d_children.size() ){\r
+          //successfully matched all children\r
+          d_match_children.pop_back();\r
+          d_match_children_end.pop_back();\r
+          d_match_status_child_num--;\r
+          return true;//return d_match_children[d_match_status]!=d_match_children_end[d_match_status];\r
+        }else{\r
+          //do next binding\r
+          s->d_tg_alloc[d_children[d_match_status_child_num]].resetMatching( s, d_match_children[d_match_status_child_num]->first, d_match_mode );\r
+          return getNextMatch( s, eqc, subs, rev_subs );\r
+        }\r
+      }\r
+    }else{\r
+      Assert( d_match_status==1 );\r
+      Assert( d_match_status_child_num+1==(int)d_match_children.size() );\r
+      Assert( d_match_children[d_match_status_child_num]!=d_match_children_end[d_match_status_child_num] );\r
+      d_match_status--;\r
+      if( s->d_tg_alloc[d_children[d_match_status_child_num]].getNextMatch( s, d_match_children[d_match_status_child_num]->first, subs, rev_subs ) ){\r
+        d_match_status_child_num++;\r
+        return getNextMatch( s, eqc, subs, rev_subs );\r
+      }else{\r
+        //iterate\r
+        d_match_children[d_match_status_child_num]++;\r
+        return getNextMatch( s, eqc, subs, rev_subs );\r
+      }\r
+    }\r
+  }\r
+  Assert( false );\r
+  return false;\r
+}\r
+\r
+unsigned TermGenerator::getDepth( TermGenEnv * s ) {\r
+  if( d_status==5 ){\r
+    unsigned maxd = 0;\r
+    for( unsigned i=0; i<d_children.size(); i++ ){\r
+      unsigned d = s->d_tg_alloc[d_children[i]].getDepth( s );\r
+      if( d>maxd ){\r
+        maxd = d;\r
+      }\r
+    }\r
+    return 1+maxd;\r
+  }else{\r
+    return 0;\r
+  }\r
+}\r
+\r
+unsigned TermGenerator::calculateGeneralizationDepth( TermGenEnv * s, std::map< TypeNode, std::vector< int > >& fvs ) {\r
+  if( d_status==5 ){\r
+    unsigned sum = 1;\r
+    for( unsigned i=0; i<d_children.size(); i++ ){\r
+      sum += s->d_tg_alloc[d_children[i]].calculateGeneralizationDepth( s, fvs );\r
+    }\r
+    return sum;\r
+  }else{\r
+    Assert( d_status==2 || d_status==1 );\r
+    std::map< TypeNode, std::vector< int > >::iterator it = fvs.find( d_typ );\r
+    if( it!=fvs.end() ){\r
+      if( std::find( it->second.begin(), it->second.end(), d_status_num )!=it->second.end() ){\r
+        return 1;\r
+      }\r
+    }\r
+    fvs[d_typ].push_back( d_status_num );\r
+    return 0;\r
+  }\r
+}\r
+\r
+unsigned TermGenerator::getGeneralizationDepth( TermGenEnv * s ) {\r
+  //if( s->d_gen_relevant_terms ){\r
+  //  return s->d_tg_gdepth;\r
+  //}else{\r
+    std::map< TypeNode, std::vector< int > > fvs;\r
+    return calculateGeneralizationDepth( s, fvs );\r
+  //}\r
+}\r
+\r
+Node TermGenerator::getTerm( TermGenEnv * s ) {\r
+  if( d_status==1 || d_status==2 ){\r
+    Assert( !d_typ.isNull() );\r
+    return s->getFreeVar( d_typ, d_status_num );\r
+  }else if( d_status==5 ){\r
+    Node f = s->getTgFunc( d_typ, d_status_num );\r
+    if( d_children.size()==s->d_func_args[f].size() ){\r
+      std::vector< Node > children;\r
+      children.push_back( f );\r
+      for( unsigned i=0; i<d_children.size(); i++ ){\r
+        Node nc = s->d_tg_alloc[d_children[i]].getTerm( s );\r
+        if( nc.isNull() ){\r
+          return Node::null();\r
+        }else{\r
+          //Assert( nc.getType()==s->d_func_args[f][i] );\r
+          children.push_back( nc );\r
+        }\r
+      }\r
+      return NodeManager::currentNM()->mkNode( s->d_func_kind[f], children );\r
+    }\r
+  }else{\r
+    Assert( false );\r
+  }\r
+  return Node::null();\r
+}\r
+\r
+void TermGenerator::debugPrint( TermGenEnv * s, const char * c, const char * cd ) {\r
+  Trace(cd) << "[*" << d_id << "," << d_status << "]:";\r
+  if( d_status==1 || d_status==2 ){\r
+    Trace(c) << s->getFreeVar( d_typ, d_status_num );\r
+  }else if( d_status==5 ){\r
+    TNode f = s->getTgFunc( d_typ, d_status_num );\r
+    Trace(c) << "(" << f;\r
+    for( unsigned i=0; i<d_children.size(); i++ ){\r
+      Trace(c) << " ";\r
+       s->d_tg_alloc[d_children[i]].debugPrint( s, c, cd );\r
+    }\r
+    if( d_children.size()<s->d_func_args[f].size() ){\r
+      Trace(c) << " ...";\r
+    }\r
+    Trace(c) << ")";\r
+  }else{\r
+    Trace(c) << "???";\r
+  }\r
+}\r
+\r
+void TermGenEnv::collectSignatureInformation() {\r
+  d_typ_tg_funcs.clear();\r
+  d_funcs.clear();\r
+  d_func_kind.clear();\r
+  d_func_args.clear();\r
+  TypeNode tnull;\r
+  for( std::map< Node, TermArgTrie >::iterator it = getTermDatabase()->d_func_map_trie.begin(); it != getTermDatabase()->d_func_map_trie.end(); ++it ){\r
+    if( !getTermDatabase()->d_op_map[it->first].empty() ){\r
+      Node nn = getTermDatabase()->d_op_map[it->first][0];\r
+      if( d_cg->isHandledTerm( nn ) && nn.getKind()!=APPLY_SELECTOR_TOTAL && !nn.getType().isBoolean() ){\r
+        bool do_enum = true;\r
+        //check if we have enumerated ground terms\r
+        if( nn.getKind()==APPLY_UF ){\r
+          if( !d_cg->hasEnumeratedUf( nn ) ){\r
+            do_enum = false;\r
+          }\r
+        }\r
+        if( do_enum ){\r
+          d_funcs.push_back( it->first );\r
+          for( unsigned i=0; i<nn.getNumChildren(); i++ ){\r
+            d_func_args[it->first].push_back( nn[i].getType() );\r
+          }\r
+          d_func_kind[it->first] = nn.getKind();\r
+          d_typ_tg_funcs[tnull].push_back( it->first );\r
+          d_typ_tg_funcs[nn.getType()].push_back( it->first );\r
+          Trace("sg-rel-sig") << "Will enumerate function applications of : " << it->first << ", #args = " << d_func_args[it->first].size() << ", kind = " << nn.getKind() << std::endl;\r
+          getTermDatabase()->computeUfEqcTerms( it->first );\r
+        }\r
+      }\r
+    }\r
+  }\r
+  //shuffle functions\r
+  for( std::map< TypeNode, std::vector< TNode > >::iterator it = d_typ_tg_funcs.begin(); it != d_typ_tg_funcs.end(); ++it ){\r
+    std::random_shuffle( it->second.begin(), it->second.end() );\r
+    if( it->first.isNull() ){\r
+      Trace("sg-gen-tg-debug") << "In this order : ";\r
+      for( unsigned i=0; i<it->second.size(); i++ ){\r
+        Trace("sg-gen-tg-debug") << it->second[i] << " ";\r
+      }\r
+      Trace("sg-gen-tg-debug") << std::endl;\r
+    }\r
+  }\r
+}\r
+\r
+void TermGenEnv::reset( unsigned depth, bool genRelevant, TypeNode tn ) {\r
+  Assert( d_tg_alloc.empty() );\r
+  d_tg_alloc.clear();\r
+\r
+  if( genRelevant ){\r
+    for( unsigned i=0; i<2; i++ ){\r
+      d_ccand_eqc[i].clear();\r
+      d_ccand_eqc[i].push_back( d_relevant_eqc[i] );\r
+    }\r
+  }\r
+\r
+  d_tg_id = 0;\r
+  d_tg_gdepth = 0;\r
+  d_tg_gdepth_limit = depth;\r
+  d_gen_relevant_terms = genRelevant;\r
+  d_tg_alloc[0].reset( this, tn );\r
+}\r
+\r
+bool TermGenEnv::getNextTerm() {\r
+  if( d_tg_alloc[0].getNextTerm( this, d_tg_gdepth_limit ) ){\r
+    Assert( (int)d_tg_alloc[0].getGeneralizationDepth( this )<=d_tg_gdepth_limit );\r
+    if( (int)d_tg_alloc[0].getGeneralizationDepth( this )!=d_tg_gdepth_limit ){\r
+      return getNextTerm();\r
+    }else{\r
+      return true;\r
+    }\r
+  }else{\r
+    return false;\r
+  }\r
+}\r
+\r
+//reset matching\r
+void TermGenEnv::resetMatching( TNode eqc, unsigned mode ) {\r
+  d_tg_alloc[0].resetMatching( this, eqc, mode );\r
+}\r
+\r
+//get next match\r
+bool TermGenEnv::getNextMatch( TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs ) {\r
+  return d_tg_alloc[0].getNextMatch( this, eqc, subs, rev_subs );\r
+}\r
+\r
+//get term\r
+Node TermGenEnv::getTerm() {\r
+  return d_tg_alloc[0].getTerm( this );\r
+}\r
+\r
+void TermGenEnv::debugPrint( const char * c, const char * cd ) {\r
+  d_tg_alloc[0].debugPrint( this, c, cd );\r
+}\r
+\r
+unsigned TermGenEnv::getNumTgVars( TypeNode tn ) {\r
+  return d_var_id[tn];\r
+}\r
+\r
+bool TermGenEnv::allowVar( TypeNode tn ) {\r
+  std::map< TypeNode, unsigned >::iterator it = d_var_limit.find( tn );\r
+  if( it==d_var_limit.end() ){\r
+    return true;\r
+  }else{\r
+    return d_var_id[tn]<it->second;\r
+  }\r
+}\r
+\r
+void TermGenEnv::addVar( TypeNode tn ) {\r
+  d_var_id[tn]++;\r
+}\r
+\r
+void TermGenEnv::removeVar( TypeNode tn ) {\r
+  d_var_id[tn]--;\r
+  //d_var_eq_tg.pop_back();\r
+  //d_var_tg.pop_back();\r
+}\r
+\r
+unsigned TermGenEnv::getNumTgFuncs( TypeNode tn ) {\r
+  return d_typ_tg_funcs[tn].size();\r
+}\r
+\r
+TNode TermGenEnv::getTgFunc( TypeNode tn, unsigned i ) {\r
+  return d_typ_tg_funcs[tn][i];\r
+}\r
+\r
+Node TermGenEnv::getFreeVar( TypeNode tn, unsigned i ) {\r
+  return d_cg->getFreeVar( tn, i );\r
+}\r
+\r
+bool TermGenEnv::considerCurrentTerm() {\r
+  Assert( !d_tg_alloc.empty() );\r
+\r
+  //if generalization depth is too large, don't consider it\r
+  unsigned i = d_tg_alloc.size();\r
+  Trace("sg-gen-tg-debug") << "Consider term ";\r
+  d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" );\r
+  Trace("sg-gen-tg-debug") << "?  curr term size = " << d_tg_alloc.size() << ", last status = " << d_tg_alloc[i-1].d_status;\r
+  Trace("sg-gen-tg-debug") << std::endl;\r
+\r
+  if( d_tg_gdepth_limit>=0 && d_tg_alloc[0].getGeneralizationDepth( this )>(unsigned)d_tg_gdepth_limit ){\r
+    Trace("sg-gen-consider-term") << "-> generalization depth of ";\r
+    d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-tg-debug" );\r
+    Trace("sg-gen-consider-term") << " is too high " << d_tg_gdepth << " " << d_tg_alloc[0].getGeneralizationDepth( this ) << ", do not consider." << std::endl;\r
+    return false;\r
+  }\r
+\r
+  //----optimizations\r
+  /*\r
+  if( d_tg_alloc[i-1].d_status==1 ){\r
+  }else if( d_tg_alloc[i-1].d_status==2 ){\r
+  }else if( d_tg_alloc[i-1].d_status==5 ){\r
+  }else{\r
+    Trace("sg-gen-tg-debug") << "Bad tg: " << &d_tg_alloc[i-1] << std::endl;\r
+    Assert( false );\r
+  }\r
+  */\r
+  //if equated two variables, first check if context-independent TODO\r
+  //----end optimizations\r
+\r
+\r
+  //check based on which candidate equivalence classes match\r
+  if( d_gen_relevant_terms ){\r
+    Trace("sg-gen-tg-debug") << "Filter based on relevant ground EQC";\r
+    Trace("sg-gen-tg-debug") << ", #eqc to try = " << d_ccand_eqc[0][i-1].size() << "/" << d_ccand_eqc[1][i-1].size() << std::endl;\r
+\r
+    Assert( d_ccand_eqc[0].size()>=2 );\r
+    Assert( d_ccand_eqc[0].size()==d_ccand_eqc[1].size() );\r
+    Assert( d_ccand_eqc[0].size()==d_tg_id+1 );\r
+    Assert( d_tg_id==d_tg_alloc.size() );\r
+    for( unsigned r=0; r<2; r++ ){\r
+      d_ccand_eqc[r][i].clear();\r
+    }\r
+\r
+    //re-check feasibility of EQC\r
+    for( unsigned r=0; r<2; r++ ){\r
+      for( unsigned j=0; j<d_ccand_eqc[r][i-1].size(); j++ ){\r
+        std::map< TypeNode, std::map< unsigned, TNode > > subs;\r
+        std::map< TNode, bool > rev_subs;\r
+        unsigned mode;\r
+        if( r==0 ){\r
+          mode = d_cg->optReqDistinctVarPatterns() ? ( 1 << 0 ) : 0;\r
+          mode = mode | (1 << 2 );\r
+        }else{\r
+          mode =  1 << 1;\r
+        }\r
+        d_tg_alloc[0].resetMatching( this, d_ccand_eqc[r][i-1][j], mode );\r
+        if( d_tg_alloc[0].getNextMatch( this, d_ccand_eqc[r][i-1][j], subs, rev_subs ) ){\r
+          d_ccand_eqc[r][i].push_back( d_ccand_eqc[r][i-1][j] );\r
+        }\r
+      }\r
+    }\r
+    for( unsigned r=0; r<2; r++ ){\r
+      Trace("sg-gen-tg-debug") << "Current eqc of type " << r << " : ";\r
+      for( unsigned j=0; j<d_ccand_eqc[r][i].size(); j++ ){\r
+        Trace("sg-gen-tg-debug") << "e" << d_cg->d_em[d_ccand_eqc[r][i][j]] << " ";\r
+      }\r
+      Trace("sg-gen-tg-debug") << std::endl;\r
+    }\r
+    if( options::conjectureFilterActiveTerms() && d_ccand_eqc[0][i].empty() ){\r
+      Trace("sg-gen-consider-term") << "Do not consider term of form ";\r
+      d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-consider-term-debug" );\r
+      Trace("sg-gen-consider-term") << " since no relevant EQC matches it." << std::endl;\r
+      return false;\r
+    }\r
+    if( options::conjectureFilterModel() && d_ccand_eqc[1][i].empty() ){\r
+      Trace("sg-gen-consider-term") << "Do not consider term of form ";\r
+      d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-consider-term-debug" );\r
+      Trace("sg-gen-consider-term") << " since no ground EQC matches it." << std::endl;\r
+      return false;\r
+    }\r
+  }\r
+  Trace("sg-gen-tg-debug") << "Will consider term ";\r
+  d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" );\r
+  Trace("sg-gen-tg-debug") << std::endl;\r
+  Trace("sg-gen-consider-term-debug") << std::endl;\r
+  return true;\r
+}\r
+\r
+void TermGenEnv::changeContext( bool add ) {\r
+  if( add ){\r
+    for( unsigned r=0; r<2; r++ ){\r
+      d_ccand_eqc[r].push_back( std::vector< TNode >() );\r
+    }\r
+    d_tg_id++;\r
+  }else{\r
+    for( unsigned r=0; r<2; r++ ){\r
+      d_ccand_eqc[r].pop_back();\r
+    }\r
+    d_tg_id--;\r
+    Assert( d_tg_alloc.find( d_tg_id )!=d_tg_alloc.end() );\r
+    d_tg_alloc.erase( d_tg_id );\r
+  }\r
+}\r
+\r
+bool TermGenEnv::considerCurrentTermCanon( unsigned tg_id ){\r
+  Assert( tg_id<d_tg_alloc.size() );\r
+  if( options::conjectureFilterCanonical() ){\r
+    //check based on a canonicity of the term (if there is one)\r
+    Trace("sg-gen-tg-debug") << "Consider term canon ";\r
+    d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" );\r
+    Trace("sg-gen-tg-debug") << ", tg is [" << tg_id << "]..." << std::endl;\r
+\r
+    Node ln = d_tg_alloc[tg_id].getTerm( this );\r
+    Trace("sg-gen-tg-debug") << "Term is " << ln << std::endl;\r
+    return d_cg->considerTermCanon( ln, d_gen_relevant_terms );\r
+  }\r
+  return true;\r
+}\r
+\r
+bool TermGenEnv::isRelevantFunc( Node f ) {\r
+  return std::find( d_funcs.begin(), d_funcs.end(), f )!=d_funcs.end();\r
+}\r
+TermDb * TermGenEnv::getTermDatabase() {\r
+  return d_cg->getTermDatabase();\r
+}\r
+Node TermGenEnv::getGroundEqc( TNode r ) {\r
+  return d_cg->getGroundEqc( r );\r
+}\r
+bool TermGenEnv::isGroundEqc( TNode r ){\r
+  return d_cg->isGroundEqc( r );\r
+}\r
+bool TermGenEnv::isGroundTerm( TNode n ){\r
+  return d_cg->isGroundTerm( n );\r
+}\r
+\r
+\r
+void SubstitutionIndex::addSubstitution( TNode eqc, std::vector< TNode >& vars, std::vector< TNode >& terms, unsigned i ) {\r
+  if( i==vars.size() ){\r
+    d_var = eqc;\r
+  }else{\r
+    Assert( d_var.isNull() || d_var==vars[i] );\r
+    d_var = vars[i];\r
+    d_children[terms[i]].addSubstitution( eqc, vars, terms, i+1 );\r
+  }\r
+}\r
+\r
+bool SubstitutionIndex::notifySubstitutions( ConjectureGenerator * s, std::map< TNode, TNode >& subs, TNode rhs, unsigned numVars, unsigned i ) {\r
+  if( i==numVars ){\r
+    Assert( d_children.empty() );\r
+    return s->notifySubstitution( d_var, subs, rhs );\r
+  }else{\r
+    Assert( i==0 || !d_children.empty() );\r
+    for( std::map< TNode, SubstitutionIndex >::iterator it = d_children.begin(); it != d_children.end(); ++it ){\r
+      Trace("sg-cconj-debug2") << "Try " << d_var << " -> " << it->first << " (" << i << "/" << numVars << ")" << std::endl;\r
+      subs[d_var] = it->first;\r
+      if( !it->second.notifySubstitutions( s, subs, rhs, numVars, i+1 ) ){\r
+        return false;\r
+      }\r
+    }\r
+    return true;\r
+  }\r
+}\r
+\r
+\r
+void TheoremIndex::addTheorem( std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs ){\r
+  if( lhs_v.empty() ){\r
+    if( std::find( d_terms.begin(), d_terms.end(), rhs )==d_terms.end() ){\r
+      d_terms.push_back( rhs );\r
+    }\r
+  }else{\r
+    unsigned index = lhs_v.size()-1;\r
+    if( lhs_arg[index]==lhs_v[index].getNumChildren() ){\r
+      lhs_v.pop_back();\r
+      lhs_arg.pop_back();\r
+      addTheorem( lhs_v, lhs_arg, rhs );\r
+    }else{\r
+      lhs_arg[index]++;\r
+      addTheoremNode( lhs_v[index][lhs_arg[index]-1], lhs_v, lhs_arg, rhs );\r
+    }\r
+  }\r
+}\r
+\r
+void TheoremIndex::addTheoremNode( TNode curr, std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs ){\r
+  Trace("thm-db-debug") << "Adding conjecture for subterm " << curr << "..." << std::endl;\r
+  if( curr.hasOperator() ){\r
+    lhs_v.push_back( curr );\r
+    lhs_arg.push_back( 0 );\r
+    d_children[curr.getOperator()].addTheorem( lhs_v, lhs_arg, rhs );\r
+  }else{\r
+    Assert( curr.getKind()==kind::BOUND_VARIABLE );\r
+    TypeNode tn = curr.getType();\r
+    Assert( d_var[tn].isNull() || d_var[tn]==curr );\r
+    d_var[tn] = curr;\r
+    d_children[curr].addTheorem( lhs_v, lhs_arg, rhs );\r
+  }\r
+}\r
+\r
+void TheoremIndex::getEquivalentTerms( std::vector< TNode >& n_v, std::vector< unsigned >& n_arg,\r
+                                       std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs,\r
+                                       std::vector< Node >& terms ) {\r
+  Trace("thm-db-debug") << "Get equivalent terms " << n_v.size() << " " << n_arg.size() << std::endl;\r
+  if( n_v.empty() ){\r
+    Trace("thm-db-debug") << "Number of terms : " << d_terms.size() << std::endl;\r
+    //apply substutitions to RHS's\r
+    for( unsigned i=0; i<d_terms.size(); i++ ){\r
+      Node n = d_terms[i].substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );\r
+      terms.push_back( n );\r
+    }\r
+  }else{\r
+    unsigned index = n_v.size()-1;\r
+    if( n_arg[index]==n_v[index].getNumChildren() ){\r
+      n_v.pop_back();\r
+      n_arg.pop_back();\r
+      getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms );\r
+    }else{\r
+      n_arg[index]++;\r
+      getEquivalentTermsNode( n_v[index][n_arg[index]-1], n_v, n_arg, smap, vars, subs, terms );\r
+    }\r
+  }\r
+}\r
+\r
+void TheoremIndex::getEquivalentTermsNode( Node curr, std::vector< TNode >& n_v, std::vector< unsigned >& n_arg,\r
+                                           std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs,\r
+                                           std::vector< Node >& terms ) {\r
+  Trace("thm-db-debug") << "Get equivalent based on subterm " << curr << "..." << std::endl;\r
+  if( curr.hasOperator() ){\r
+    Trace("thm-db-debug") << "Check based on operator..." << std::endl;\r
+    std::map< TNode, TheoremIndex >::iterator it = d_children.find( curr.getOperator() );\r
+    if( it!=d_children.end() ){\r
+      n_v.push_back( curr );\r
+      n_arg.push_back( 0 );\r
+      it->second.getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms );\r
+    }\r
+    Trace("thm-db-debug") << "...done check based on operator" << std::endl;\r
+  }\r
+  TypeNode tn = curr.getType();\r
+  std::map< TypeNode, TNode >::iterator itt = d_var.find( tn );\r
+  if( itt!=d_var.end() ){\r
+    Trace("thm-db-debug") << "Check for substitution with " << itt->second << "..." << std::endl;\r
+    Assert( curr.getType()==itt->second.getType() );\r
+    //add to substitution if possible\r
+    bool success = false;\r
+    std::map< TNode, TNode >::iterator it = smap.find( itt->second );\r
+    if( it==smap.end() ){\r
+      smap[itt->second] = curr;\r
+      vars.push_back( itt->second );\r
+      subs.push_back( curr );\r
+      success = true;\r
+    }else if( it->second==curr ){\r
+      success = true;\r
+    }else{\r
+      //also check modulo equality (in universal equality engine)\r
+    }\r
+    Trace("thm-db-debug") << "...check for substitution with " << itt->second << ", success = " << success << "." << std::endl;\r
+    if( success ){\r
+      d_children[itt->second].getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms );\r
+    }\r
+  }\r
+}\r
+\r
+void TheoremIndex::debugPrint( const char * c, unsigned ind ) {\r
+  for( std::map< TNode, TheoremIndex >::iterator it = d_children.begin(); it != d_children.end(); ++it ){\r
+    for( unsigned i=0; i<ind; i++ ){ Trace(c) << "  "; }\r
+    Trace(c) << it->first << std::endl;\r
+    it->second.debugPrint( c, ind+1 );\r
+  }\r
+  if( !d_terms.empty() ){\r
+    for( unsigned i=0; i<ind; i++ ){ Trace(c) << "  "; }\r
+    Trace(c) << "{";\r
+    for( unsigned i=0; i<d_terms.size(); i++ ){\r
+      Trace(c) << " " << d_terms[i];\r
+    }\r
+    Trace(c) << " }" << std::endl;\r
+  }\r
+  //if( !d_var.isNull() ){\r
+  //  for( unsigned i=0; i<ind; i++ ){ Trace(c) << "  "; }\r
+  //  Trace(c) << "var:" << d_var << std::endl;\r
+  //}\r
+}\r
+\r
+bool ConjectureGenerator::optReqDistinctVarPatterns() { return false; }\r
+bool ConjectureGenerator::optFilterUnknown() { return true; }  //may change\r
+int ConjectureGenerator::optFilterScoreThreshold() { return 1; }\r
+unsigned ConjectureGenerator::optFullCheckFrequency() { return 1; }\r
+\r
+bool ConjectureGenerator::optStatsOnly() { return false; }\r
+\r
+}\r
diff --git a/src/theory/quantifiers/conjecture_generator.h b/src/theory/quantifiers/conjecture_generator.h
new file mode 100755 (executable)
index 0000000..59d908f
--- /dev/null
@@ -0,0 +1,433 @@
+/*********************                                                        */\r
+/*! \file conjecture_generator.h\r
+ ** \verbatim\r
+ ** Original author: Andrew Reynolds\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 project.\r
+ ** Copyright (c) 2009-2014  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 conjecture generator class\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef CONJECTURE_GENERATOR_H\r
+#define CONJECTURE_GENERATOR_H\r
+\r
+#include "context/cdhashmap.h"\r
+#include "context/cdchunk_list.h"\r
+#include "theory/quantifiers_engine.h"\r
+#include "theory/type_enumerator.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+namespace quantifiers {\r
+\r
+class TermArgTrie;\r
+\r
+//algorithm for computing candidate subgoals\r
+\r
+class ConjectureGenerator;\r
+\r
+// operator independent index of arguments for an EQC\r
+class OpArgIndex\r
+{\r
+public:\r
+  std::map< TNode, OpArgIndex > d_child;\r
+  std::vector< TNode > d_ops;\r
+  std::vector< TNode > d_op_terms;\r
+  void addTerm( ConjectureGenerator * s, TNode n, unsigned index = 0 );\r
+  Node getGroundTerm( ConjectureGenerator * s, std::vector< TNode >& args );\r
+  void getGroundTerms( ConjectureGenerator * s, std::vector< TNode >& terms );\r
+};\r
+\r
+class PatternTypIndex\r
+{\r
+public:\r
+  std::vector< TNode > d_terms;\r
+  std::map< TypeNode, std::map< unsigned, PatternTypIndex > > d_children;\r
+  void clear() {\r
+    d_terms.clear();\r
+    d_children.clear();\r
+  }\r
+};\r
+\r
+class SubstitutionIndex\r
+{\r
+public:\r
+  //current variable, or ground EQC if d_children.empty()\r
+  TNode d_var;\r
+  std::map< TNode, SubstitutionIndex > d_children;\r
+  //add substitution\r
+  void addSubstitution( TNode eqc, std::vector< TNode >& vars, std::vector< TNode >& terms, unsigned i = 0 );\r
+  //notify substitutions\r
+  bool notifySubstitutions( ConjectureGenerator * s, std::map< TNode, TNode >& subs, TNode rhs, unsigned numVars, unsigned i = 0 );\r
+};\r
+\r
+class TermGenEnv;\r
+\r
+class TermGenerator\r
+{\r
+private:\r
+  unsigned calculateGeneralizationDepth( TermGenEnv * s, std::map< TypeNode, std::vector< int > >& fvs );\r
+public:\r
+  TermGenerator(){}\r
+  TypeNode d_typ;\r
+  unsigned d_id;\r
+  //1 : consider as unique variable\r
+  //2 : consider equal to another variable\r
+  //5 : consider a function application\r
+  unsigned d_status;\r
+  int d_status_num;\r
+  //for function applications: the number of children you have built\r
+  int d_status_child_num;\r
+  //children (pointers to TermGenerators)\r
+  std::vector< unsigned > d_children;\r
+\r
+  //match status\r
+  int d_match_status;\r
+  int d_match_status_child_num;\r
+  //match mode bits\r
+  //0 : different variables must have different matches\r
+  //1 : variables must map to ground terms\r
+  //2 : variables must map to non-ground terms\r
+  unsigned d_match_mode;\r
+  //children\r
+  std::vector< std::map< TNode, TermArgTrie >::iterator > d_match_children;\r
+  std::vector< std::map< TNode, TermArgTrie >::iterator > d_match_children_end;\r
+\r
+  void reset( TermGenEnv * s, TypeNode tn );\r
+  bool getNextTerm( TermGenEnv * s, unsigned depth );\r
+  void resetMatching( TermGenEnv * s, TNode eqc, unsigned mode );\r
+  bool getNextMatch( TermGenEnv * s, TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs );\r
+\r
+  unsigned getDepth( TermGenEnv * s );\r
+  unsigned getGeneralizationDepth( TermGenEnv * s );\r
+  Node getTerm( TermGenEnv * s );\r
+\r
+  void debugPrint( TermGenEnv * s, const char * c, const char * cd );\r
+};\r
+\r
+\r
+class TermGenEnv\r
+{\r
+public:\r
+  //collect signature information\r
+  void collectSignatureInformation();\r
+  //reset function\r
+  void reset( unsigned gdepth, bool genRelevant, TypeNode tgen );\r
+  //get next term\r
+  bool getNextTerm();\r
+  //reset matching\r
+  void resetMatching( TNode eqc, unsigned mode );\r
+  //get next match\r
+  bool getNextMatch( TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs );\r
+  //get term\r
+  Node getTerm();\r
+  //debug print\r
+  void debugPrint( const char * c, const char * cd );\r
+\r
+  //conjecture generation\r
+  ConjectureGenerator * d_cg;\r
+  //the current number of enumerated variables per type\r
+  std::map< TypeNode, unsigned > d_var_id;\r
+  //the limit of number of variables per type to enumerate\r
+  std::map< TypeNode, unsigned > d_var_limit;\r
+  //the functions we can currently generate\r
+  std::map< TypeNode, std::vector< TNode > > d_typ_tg_funcs;\r
+  //the equivalence classes (if applicable) that match the currently generated term\r
+  bool d_gen_relevant_terms;\r
+  //relevant equivalence classes\r
+  std::vector< TNode > d_relevant_eqc[2];\r
+  //candidate equivalence classes\r
+  std::vector< std::vector< TNode > > d_ccand_eqc[2];\r
+  //the term generation objects\r
+  unsigned d_tg_id;\r
+  std::map< unsigned, TermGenerator > d_tg_alloc;\r
+  unsigned d_tg_gdepth;\r
+  int d_tg_gdepth_limit;\r
+\r
+  //all functions\r
+  std::vector< TNode > d_funcs;\r
+  //function to kind map\r
+  std::map< TNode, Kind > d_func_kind;\r
+  //type of each argument of the function\r
+  std::map< TNode, std::vector< TypeNode > > d_func_args;\r
+\r
+  //access functions\r
+  unsigned getNumTgVars( TypeNode tn );\r
+  bool allowVar( TypeNode tn );\r
+  void addVar( TypeNode tn );\r
+  void removeVar( TypeNode tn );\r
+  unsigned getNumTgFuncs( TypeNode tn );\r
+  TNode getTgFunc( TypeNode tn, unsigned i );\r
+  Node getFreeVar( TypeNode tn, unsigned i );\r
+  bool considerCurrentTerm();\r
+  bool considerCurrentTermCanon( unsigned tg_id );\r
+  void changeContext( bool add );\r
+  bool isRelevantFunc( Node f );\r
+  //carry\r
+  TermDb * getTermDatabase();\r
+  Node getGroundEqc( TNode r );\r
+  bool isGroundEqc( TNode r );\r
+  bool isGroundTerm( TNode n );\r
+};\r
+\r
+\r
+\r
+class TheoremIndex\r
+{\r
+private:\r
+  void addTheorem( std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs );\r
+  void addTheoremNode( TNode curr, std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs );\r
+  void getEquivalentTerms( std::vector< TNode >& n_v, std::vector< unsigned >& n_arg,\r
+                           std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs,\r
+                           std::vector< Node >& terms );\r
+  void getEquivalentTermsNode( Node curr, std::vector< TNode >& n_v, std::vector< unsigned >& n_arg,\r
+                               std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs,\r
+                               std::vector< Node >& terms );\r
+public:\r
+  std::map< TypeNode, TNode > d_var;\r
+  std::map< TNode, TheoremIndex > d_children;\r
+  std::vector< Node > d_terms;\r
+\r
+  void addTheorem( TNode lhs, TNode rhs ) {\r
+    std::vector< TNode > v;\r
+    std::vector< unsigned > a;\r
+    addTheoremNode( lhs, v, a, rhs );\r
+  }\r
+  void getEquivalentTerms( TNode n, std::vector< Node >& terms ) {\r
+    std::vector< TNode > nv;\r
+    std::vector< unsigned > na;\r
+    std::map< TNode, TNode > smap;\r
+    std::vector< TNode > vars;\r
+    std::vector< TNode > subs;\r
+    getEquivalentTermsNode( n, nv, na, smap, vars, subs, terms );\r
+  }\r
+  void clear(){\r
+    d_var.clear();\r
+    d_children.clear();\r
+    d_terms.clear();\r
+  }\r
+  void debugPrint( const char * c, unsigned ind = 0 );\r
+};\r
+\r
+\r
+\r
+class ConjectureGenerator : public QuantifiersModule\r
+{\r
+  friend class OpArgIndex;\r
+  friend class PatGen;\r
+  friend class PatternGenEqc;\r
+  friend class PatternGen;\r
+  friend class SubsEqcIndex;\r
+  friend class TermGenerator;\r
+  friend class TermGenEnv;\r
+  typedef context::CDChunkList<Node> NodeList;\r
+  typedef context::CDHashMap< Node, Node, NodeHashFunction > NodeMap;\r
+  typedef context::CDHashMap< Node, bool, NodeHashFunction > BoolMap;\r
+//this class maintains a congruence closure for *universal* facts\r
+private:\r
+  //notification class for equality engine\r
+  class NotifyClass : public eq::EqualityEngineNotify {\r
+    ConjectureGenerator& d_sg;\r
+  public:\r
+    NotifyClass(ConjectureGenerator& sg): d_sg(sg) {}\r
+    bool eqNotifyTriggerEquality(TNode equality, bool value) { return true; }\r
+    bool eqNotifyTriggerPredicate(TNode predicate, bool value) { return true; }\r
+    bool eqNotifyTriggerTermEquality(TheoryId tag, TNode t1, TNode t2, bool value) { return true; }\r
+    void eqNotifyConstantTermMerge(TNode t1, TNode t2) { }\r
+    void eqNotifyNewClass(TNode t) { d_sg.eqNotifyNewClass(t); }\r
+    void eqNotifyPreMerge(TNode t1, TNode t2) { d_sg.eqNotifyPreMerge(t1, t2); }\r
+    void eqNotifyPostMerge(TNode t1, TNode t2) { d_sg.eqNotifyPostMerge(t1, t2); }\r
+    void eqNotifyDisequal(TNode t1, TNode t2, TNode reason) {d_sg.eqNotifyDisequal(t1, t2, reason); }\r
+  };/* class ConjectureGenerator::NotifyClass */\r
+  /** The notify class */\r
+  NotifyClass d_notify;\r
+  class EqcInfo{\r
+  public:\r
+    EqcInfo( context::Context* c );\r
+    //representative\r
+    context::CDO< Node > d_rep;\r
+  };\r
+  /** get or make eqc info */\r
+  EqcInfo* getOrMakeEqcInfo( TNode n, bool doMake = false );\r
+  /** (universal) equaltity engine */\r
+  eq::EqualityEngine d_uequalityEngine;\r
+  /** pending adds */\r
+  std::vector< Node > d_upendingAdds;\r
+  /** relevant terms */\r
+  std::map< Node, bool > d_urelevant_terms;\r
+  /** information necessary for equivalence classes */\r
+  std::map< Node, EqcInfo* > d_eqc_info;\r
+  /** called when a new equivalance class is created */\r
+  void eqNotifyNewClass(TNode t);\r
+  /** called when two equivalance classes will merge */\r
+  void eqNotifyPreMerge(TNode t1, TNode t2);\r
+  /** called when two equivalance classes have merged */\r
+  void eqNotifyPostMerge(TNode t1, TNode t2);\r
+  /** called when two equivalence classes are made disequal */\r
+  void eqNotifyDisequal(TNode t1, TNode t2, TNode reason);\r
+  /** are universal equal */\r
+  bool areUniversalEqual( TNode n1, TNode n2 );\r
+  /** are universal disequal */\r
+  bool areUniversalDisequal( TNode n1, TNode n2 );\r
+  /** get universal representative */\r
+  TNode getUniversalRepresentative( TNode n, bool add = false );\r
+  /** set relevant */\r
+  void setUniversalRelevant( TNode n );\r
+  /** ordering for universal terms */\r
+  bool isUniversalLessThan( TNode rt1, TNode rt2 );\r
+\r
+  /** the nodes we have reported as canonical representative */\r
+  std::vector< TNode > d_ue_canon;\r
+  /** is reported canon */\r
+  bool isReportedCanon( TNode n );\r
+  /** mark that term has been reported as canonical rep */\r
+  void markReportedCanon( TNode n );\r
+\r
+private:  //information regarding the conjectures\r
+  /** list of all conjectures */\r
+  std::vector< Node > d_conjectures;\r
+  /** list of all waiting conjectures */\r
+  std::vector< Node > d_waiting_conjectures_lhs;\r
+  std::vector< Node > d_waiting_conjectures_rhs;\r
+  std::vector< int > d_waiting_conjectures_score;\r
+  /** map of currently considered equality conjectures */\r
+  std::map< Node, std::vector< Node > > d_waiting_conjectures;\r
+  /** map of equality conjectures */\r
+  std::map< Node, std::vector< Node > > d_eq_conjectures;\r
+  /** currently existing conjectures in equality engine */\r
+  BoolMap d_ee_conjectures;\r
+  /** conjecture index */\r
+  TheoremIndex d_thm_index;\r
+private:  //free variable list\r
+  //free variables\r
+  std::map< TypeNode, std::vector< Node > > d_free_var;\r
+  //map from free variable to FV#\r
+  std::map< TNode, unsigned > d_free_var_num;\r
+  // get canonical free variable #i of type tn\r
+  Node getFreeVar( TypeNode tn, unsigned i );\r
+  // get canonical term, return null if it contains a term apart from handled signature\r
+  Node getCanonicalTerm( TNode n, std::map< TypeNode, unsigned >& var_count, std::map< TNode, TNode >& subs );\r
+private:  //information regarding the terms\r
+  //relevant patterns (the LHS's)\r
+  std::map< TypeNode, std::vector< Node > > d_rel_patterns;\r
+  //total number of unique variables\r
+  std::map< TNode, unsigned > d_rel_pattern_var_sum;\r
+  //by types\r
+  PatternTypIndex d_rel_pattern_typ_index;\r
+  // substitution to ground EQC index\r
+  std::map< TNode, SubstitutionIndex > d_rel_pattern_subs_index;\r
+  //patterns (the RHS's)\r
+  std::map< TypeNode, std::vector< Node > > d_patterns;\r
+  //patterns to # variables per type\r
+  std::map< TNode, std::map< TypeNode, unsigned > > d_pattern_var_id;\r
+  // # duplicated variables\r
+  std::map< TNode, unsigned > d_pattern_var_duplicate;\r
+  // is normal pattern?  (variables allocated in canonical way left to right)\r
+  std::map< TNode, int > d_pattern_is_normal;\r
+  std::map< TNode, int > d_pattern_is_relevant;\r
+  // patterns to a count of # operators (variables and functions)\r
+  std::map< TNode, std::map< TNode, unsigned > > d_pattern_fun_id;\r
+  // term size\r
+  std::map< TNode, unsigned > d_pattern_fun_sum;\r
+  // collect functions\r
+  unsigned collectFunctions( TNode opat, TNode pat, std::map< TNode, unsigned >& funcs,\r
+                             std::map< TypeNode, unsigned >& mnvn, std::map< TypeNode, unsigned >& mxvn );\r
+  // add pattern\r
+  void registerPattern( Node pat, TypeNode tpat );\r
+private: //for debugging\r
+  std::map< TNode, unsigned > d_em;\r
+public:\r
+  //term generation environment\r
+  TermGenEnv d_tge;\r
+  //consider term canon\r
+  bool considerTermCanon( Node ln, bool genRelevant );\r
+public:  //for generalization\r
+  //generalizations\r
+  bool isGeneralization( TNode patg, TNode pat ) {\r
+    std::map< TNode, TNode > subs;\r
+    return isGeneralization( patg, pat, subs );\r
+  }\r
+  bool isGeneralization( TNode patg, TNode pat, std::map< TNode, TNode >& subs );\r
+  // get generalization depth\r
+  int calculateGeneralizationDepth( TNode n, std::vector< TNode >& fv );\r
+private:\r
+  //predicate for type\r
+  std::map< TypeNode, Node > d_typ_pred;\r
+  //get predicate for type\r
+  Node getPredicateForType( TypeNode tn );\r
+  //\r
+  void getEnumerateUfTerm( Node n, unsigned num, std::vector< Node >& terms );\r
+  //\r
+  void getEnumeratePredUfTerm( Node n, unsigned num, std::vector< Node >& terms );\r
+  // uf operators enumerated\r
+  std::map< Node, bool > d_uf_enum;\r
+public:  //for property enumeration\r
+  //process this candidate conjecture\r
+  void processCandidateConjecture( TNode lhs, TNode rhs, unsigned lhs_depth, unsigned rhs_depth );\r
+  //whether it should be considered, negative : no, positive returns score\r
+  int considerCandidateConjecture( TNode lhs, TNode rhs );\r
+  //notified of a substitution\r
+  bool notifySubstitution( TNode glhs, std::map< TNode, TNode >& subs, TNode rhs );\r
+  //confirmation count\r
+  unsigned d_subs_confirmCount;\r
+  //individual witnesses (for range)\r
+  std::vector< TNode > d_subs_confirmWitnessRange;\r
+  //individual witnesses (for domain)\r
+  std::map< TNode, std::vector< TNode > > d_subs_confirmWitnessDomain;\r
+  //number of ground substitutions whose equality is unknown\r
+  unsigned d_subs_unkCount;\r
+private:  //information about ground equivalence classes\r
+  TNode d_bool_eqc[2];\r
+  std::map< TNode, Node > d_ground_eqc_map;\r
+  std::vector< TNode > d_ground_terms;\r
+  //operator independent term index\r
+  std::map< TNode, OpArgIndex > d_op_arg_index;\r
+  //is handled term\r
+  bool isHandledTerm( TNode n );\r
+  Node getGroundEqc( TNode r );\r
+  bool isGroundEqc( TNode r );\r
+  bool isGroundTerm( TNode n );\r
+  //has enumerated UF\r
+  bool hasEnumeratedUf( Node n );\r
+  // count of full effort checks\r
+  unsigned d_fullEffortCount;\r
+  // has added lemma\r
+  bool d_hasAddedLemma;\r
+  //flush the waiting conjectures\r
+  unsigned flushWaitingConjectures( unsigned& addedLemmas, int ldepth, int rdepth );\r
+public:\r
+  ConjectureGenerator( QuantifiersEngine * qe, context::Context* c );\r
+  /* needs check */\r
+  bool needsCheck( Theory::Effort e );\r
+  /* reset at a round */\r
+  void reset_round( Theory::Effort e );\r
+  /* Call during quantifier engine's check */\r
+  void check( Theory::Effort e, unsigned quant_e );\r
+  /* Called for new quantifiers */\r
+  void registerQuantifier( Node q );\r
+  void assertNode( Node n );\r
+  /** Identify this module (for debugging, dynamic configuration, etc..) */\r
+  std::string identify() const { return "ConjectureGenerator"; }\r
+//options\r
+private:\r
+  bool optReqDistinctVarPatterns();\r
+  bool optFilterUnknown();\r
+  int optFilterScoreThreshold();\r
+  unsigned optFullCheckFrequency();\r
+  unsigned optFullCheckConjectures();\r
+\r
+  bool optStatsOnly();\r
+};\r
+\r
+\r
+}\r
+}\r
+}\r
+\r
+#endif\r
index 1421c639fb5b35dad6d674c985fa675894cd7849..0a0d4eba8fc84e4bd454131ee9e95be15cad47a6 100644 (file)
@@ -115,6 +115,24 @@ Node FirstOrderModel::getSomeDomainElement(TypeNode tn){
   return d_rep_set.d_type_reps[tn][0];
 }
 
+void FirstOrderModel::reset_round() {
+  d_quant_active.clear();
+}
+
+void FirstOrderModel::setQuantifierActive( TNode q, bool active ) {
+  d_quant_active[q] = active;
+}
+
+bool FirstOrderModel::isQuantifierActive( TNode q ) {
+  std::map< TNode, bool >::iterator it = d_quant_active.find( q );
+  if( it==d_quant_active.end() ){
+    return true;
+  }else{
+    return it->second;
+  }
+}
+
+
 FirstOrderModelIG::FirstOrderModelIG(QuantifiersEngine * qe, context::Context* c, std::string name) :
 FirstOrderModel(qe, c,name) {
 
index 76c3946ce2de45551e191792a50d2104c2b98ebf..6ad04a1e6a63aeb54640dede86cde4f352817abb 100644 (file)
@@ -92,6 +92,19 @@ public:
   }
   /** get some domain element */
   Node getSomeDomainElement(TypeNode tn);
+private:
+  //list of inactive quantified formulas
+  std::map< TNode, bool > d_quant_active;
+public:
+  /** reset round */
+  void reset_round();
+  /** set quantified formula active/inactive 
+   * a quantified formula may be set inactive if for instance:
+   *   - it is entailed by other quantified formulas
+   */
+  void setQuantifierActive( TNode q, bool active );
+  /** is quantified formula active */
+  bool isQuantifierActive( TNode q );
 };/* class FirstOrderModel */
 
 
index d5ed5589bba6b5668694802bfae4f19db3939d10..64ebb6cdaaf90e9a326d62bdf579449f8f2f8c4f 100644 (file)
@@ -811,9 +811,11 @@ bool FullModelChecker::exhaustiveInstantiate(FirstOrderModelFmc * fm, Node f, No
       Trace("fmc-exh-debug") << std::endl;
       int index = riter.increment();
       Trace("fmc-exh-debug") << "Incremented index " << index << std::endl;
-      if (index>=0 && riter.d_index[index]>0 && addedLemmas>0 && riter.d_enum_type[index]==RepSetIterator::ENUM_RANGE) {
-        Trace("fmc-exh-debug") << "Since this is a range enumeration, skip to the next..." << std::endl;
-        riter.increment2( index-1 );
+      if( !riter.isFinished() ){
+        if (index>=0 && riter.d_index[index]>0 && addedLemmas>0 && riter.d_enum_type[index]==RepSetIterator::ENUM_RANGE) {
+          Trace("fmc-exh-debug") << "Since this is a range enumeration, skip to the next..." << std::endl;
+          riter.increment2( index-1 );
+        }
       }
     }
     d_addedLemmas += addedLemmas;
@@ -871,7 +873,7 @@ void FullModelChecker::doCheck(FirstOrderModelFmc * fm, Node f, Def & d, Node n
       Trace("fmc-debug") << "Can't process base array " << r << std::endl;
       //can't process this array
       d.reset();
-      d.addEntry(fm, defC, Node::null());
+      d.addEntry(fm, mkCondDefault(fm, f), Node::null());
     }
   }
   else if( n.getNumChildren()==0 ){
index c024d0babf8e417dde418a8b061398d9b23ac2ac..c78ea7b013ae4400799ebebef6d2219cb2a183aa 100644 (file)
@@ -30,14 +30,21 @@ namespace CVC4 {
 namespace theory {
 namespace inst {
 
-
-InstMatchGenerator::InstMatchGenerator( Node pat, int matchPolicy ) : d_matchPolicy( matchPolicy ){
+InstMatchGenerator::InstMatchGenerator( Node pat ){
   d_needsReset = true;
   d_active_add = false;
   Assert( quantifiers::TermDb::hasInstConstAttr(pat) );
   d_pattern = pat;
   d_match_pattern = pat;
   d_next = NULL;
+  d_matchPolicy = MATCH_GEN_DEFAULT;
+}
+
+InstMatchGenerator::InstMatchGenerator() {
+  d_needsReset = true;
+  d_active_add = false;
+  d_next = NULL;
+  d_matchPolicy = MATCH_GEN_DEFAULT;
 }
 
 void InstMatchGenerator::setActiveAdd(bool val){
@@ -89,24 +96,31 @@ void InstMatchGenerator::initialize( QuantifiersEngine* qe, std::vector< InstMat
     d_match_pattern_op = qe->getTermDatabase()->getOperator( d_match_pattern );
 
     //now, collect children of d_match_pattern
-    int childMatchPolicy = MATCH_GEN_DEFAULT;
+    //int childMatchPolicy = MATCH_GEN_DEFAULT;
     for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
       if( quantifiers::TermDb::hasInstConstAttr(d_match_pattern[i]) ){
-        if( d_match_pattern[i].getKind()!=INST_CONSTANT && !Trigger::isBooleanTermTrigger( d_match_pattern[i] ) ){
-          InstMatchGenerator * cimg = new InstMatchGenerator( d_match_pattern[i], childMatchPolicy );
+        InstMatchGenerator * cimg = Trigger::getInstMatchGenerator( d_match_pattern[i] );
+        if( cimg ){
           d_children.push_back( cimg );
           d_children_index.push_back( i );
           gens.push_back( cimg );
+          d_children_types.push_back( 1 );
+        }else{
+          d_var_num[i] = d_match_pattern[i].getAttribute(InstVarNumAttribute());
+          d_children_types.push_back( 0 );
         }
+      }else{
+        d_children_types.push_back( -1 );
       }
     }
+    if( d_match_pattern.getKind()==INST_CONSTANT ){
+      d_var_num[0] = d_match_pattern.getAttribute(InstVarNumAttribute());
+    }
 
     //create candidate generator
     if( d_match_pattern.getKind()==INST_CONSTANT ){
       d_cg = new CandidateGeneratorQEAll( qe, d_match_pattern );
-    }
-    else if( d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==IFF ){
-      Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
+    }else if( d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==IFF ){
       //we will be producing candidates via literal matching heuristics
       if( d_pattern.getKind()!=NOT ){
         //candidates will be all equalities
@@ -139,15 +153,6 @@ void InstMatchGenerator::initialize( QuantifiersEngine* qe, std::vector< InstMat
       Trace("inst-match-gen-warn") << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
       d_matchPolicy = MATCH_GEN_INTERNAL_ERROR;
     }
-    for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
-      if( d_match_pattern[i].getKind()==INST_CONSTANT || Trigger::isBooleanTermTrigger( d_match_pattern[i] ) ){
-        Node vv = d_match_pattern[i];
-        if( Trigger::isBooleanTermTrigger( d_match_pattern[i] ) ){
-          vv = d_match_pattern[i][0];
-        }
-        d_var_num[i] = vv.getAttribute(InstVarNumAttribute());
-      }
-    }
   }
 }
 
@@ -157,6 +162,7 @@ bool InstMatchGenerator::getMatch( Node f, Node t, InstMatch& m, QuantifiersEngi
                     << m << ")" << ", " << d_children.size() << ", pattern is " << d_pattern << std::endl;
   Assert( !d_match_pattern.isNull() );
   if( d_matchPolicy==MATCH_GEN_INTERNAL_ERROR ){
+    Trace("matching-fail") << "Internal error for match generator." << std::endl;
     return false;
   }else{
     EqualityQuery* q = qe->getEqualityQuery();
@@ -167,27 +173,23 @@ bool InstMatchGenerator::getMatch( Node f, Node t, InstMatch& m, QuantifiersEngi
     //if t is null
     Assert( !t.isNull() );
     Assert( !quantifiers::TermDb::hasInstConstAttr(t) );
-    Assert( t.getKind()==d_match_pattern.getKind() );
+    Assert( d_match_pattern.getKind()==INST_CONSTANT || 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( quantifiers::TermDb::hasInstConstAttr(d_match_pattern[i]) ){
-        if( d_match_pattern[i].getKind()==INST_CONSTANT || Trigger::isBooleanTermTrigger( d_match_pattern[i] ) ){
-          Node tt = t[i];
-          if( Trigger::isBooleanTermTrigger( d_match_pattern[i] ) ){
-            tt = NodeManager::currentNM()->mkConst(q->areEqual( tt, d_match_pattern[i][1] ));
-          }
-          bool addToPrev = m.get( d_var_num[i] ).isNull();
-          if( !m.set( qe, d_var_num[i], tt ) ){
-            //match is in conflict
-            Trace("matching-fail") << "Match fail: " << m.get(d_var_num[i]) << " and " << tt << std::endl;
-            success = false;
-            break;
-          }else if( addToPrev ){
-            prev.push_back( d_var_num[i] );
-          }
+      if( d_children_types[i]==0 ){
+        Trace("matching-debug2") << "Setting " << d_var_num[i] << " to " << t[i] << "..." << std::endl;
+        bool addToPrev = m.get( d_var_num[i] ).isNull();
+        if( !m.set( qe, d_var_num[i], t[i] ) ){
+          //match is in conflict
+          Trace("matching-fail") << "Match fail: " << m.get(d_var_num[i]) << " and " << t[i] << std::endl;
+          success = false;
+          break;
+        }else if( addToPrev ){
+          Trace("matching-debug2") << "Success." << std::endl;
+          prev.push_back( d_var_num[i] );
         }
-      }else{
+      }else if( d_children_types[i]==-1 ){
         if( !q->areEqual( d_match_pattern[i], t[i] ) ){
           Trace("matching-fail") << "Match fail arg: " << d_match_pattern[i] << " and " << t[i] << std::endl;
           //ground arguments are not equal
@@ -196,8 +198,18 @@ bool InstMatchGenerator::getMatch( Node f, Node t, InstMatch& m, QuantifiersEngi
         }
       }
     }
+    //for variable matching
+    if( d_match_pattern.getKind()==INST_CONSTANT ){
+      bool addToPrev = m.get( d_var_num[0] ).isNull();
+      if( !m.set( qe, d_var_num[0], t ) ){
+        success = false;
+      }else{
+        if( addToPrev ){
+          prev.push_back( d_var_num[0] );
+        }
+      }
     //for relational matching
-    if( !d_eq_class.isNull() && d_eq_class.getKind()==INST_CONSTANT ){
+    }else if( !d_eq_class.isNull() && d_eq_class.getKind()==INST_CONSTANT ){
       int v = d_eq_class.getAttribute(InstVarNumAttribute());
       //also must fit match to equivalence class
       bool pol = d_pattern.getKind()!=NOT;
@@ -236,18 +248,9 @@ bool InstMatchGenerator::getMatch( Node f, Node t, InstMatch& m, QuantifiersEngi
       //now, fit children into match
       //we will be requesting candidates for matching terms for each child
       for( int i=0; i<(int)d_children.size(); i++ ){
-        Node rep = q->getRepresentative( t[ d_children_index[i] ] );
-        d_children[i]->reset( rep, qe );
-      }
-      if( d_next!=NULL ){
-        success = d_next->getNextMatch( f, m, qe );
-      }else{
-        if( d_active_add ){
-          Trace("active-add") << "Active Adding instantiation " << m << std::endl;
-          success = qe->addInstantiation( f, m, false );
-          Trace("active-add") << "Success = " << success << std::endl;
-        }
+        d_children[i]->reset( t[ d_children_index[i] ], qe );
       }
+      success = continueNextMatch( f, m, qe );
     }
     if( !success ){
       //m = InstMatch( &prev );
@@ -259,6 +262,18 @@ bool InstMatchGenerator::getMatch( Node f, Node t, InstMatch& m, QuantifiersEngi
   }
 }
 
+bool InstMatchGenerator::continueNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ){
+  if( d_next!=NULL ){
+    return d_next->getNextMatch( f, m, qe );
+  }else{
+    if( d_active_add ){
+      return qe->addInstantiation( f, m, false );
+    }else{
+      return true;
+    }
+  }
+}
+
 /** reset instantiation round */
 void InstMatchGenerator::resetInstantiationRound( QuantifiersEngine* qe ){
   if( !d_match_pattern.isNull() ){
@@ -274,6 +289,7 @@ void InstMatchGenerator::resetInstantiationRound( QuantifiersEngine* qe ){
 }
 
 void InstMatchGenerator::reset( Node eqc, QuantifiersEngine* qe ){
+  eqc = qe->getEqualityQuery()->getRepresentative( eqc );
   Trace("matching-debug2") << this << " reset " << eqc << "." << std::endl;
   if( !eqc.isNull() ){
     d_eq_class = eqc;
@@ -321,7 +337,7 @@ int InstMatchGenerator::addInstantiations( Node f, InstMatch& baseMatch, Quantif
   while( getNextMatch( f, m, qe ) ){
     if( !d_active_add ){
       m.add( baseMatch );
-      if( qe->addInstantiation( f, m ) ){
+      if( qe->addInstantiation( f, m, false ) ){
         addedLemmas++;
       }
     }else{
@@ -338,7 +354,7 @@ int InstMatchGenerator::addTerm( Node f, Node t, QuantifiersEngine* qe ){
   if( !d_match_pattern.isNull() ){
     InstMatch m( f );
     if( getMatch( f, t, m, qe ) ){
-      if( qe->addInstantiation( f, m ) ){
+      if( qe->addInstantiation( f, m, false ) ){
         return 1;
       }
     }
@@ -384,6 +400,59 @@ InstMatchGenerator* InstMatchGenerator::mkInstMatchGenerator( std::vector< Node
   return oinit;
 }
 
+VarMatchGeneratorBooleanTerm::VarMatchGeneratorBooleanTerm( Node var, Node comp ) :
+  InstMatchGenerator(), d_comp( comp ), d_rm_prev( false ) {
+  d_var_num[0] = var.getAttribute(InstVarNumAttribute());
+}
+
+bool VarMatchGeneratorBooleanTerm::getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ) {
+  if( !d_eq_class.isNull() ){
+    Node s = NodeManager::currentNM()->mkConst(qe->getEqualityQuery()->areEqual( d_eq_class, d_pattern ));
+    d_eq_class = Node::null();
+    d_rm_prev = m.get( d_var_num[0] ).isNull();
+    if( !m.set( qe, d_var_num[0], s ) ){
+      return false;
+    }else{
+      if( continueNextMatch( f, m, qe ) ){
+        return true;
+      }
+    }
+  }
+  if( d_rm_prev ){
+    m.d_vals[d_var_num[0]] = Node::null();
+    d_rm_prev = false;
+  }
+  return false;
+}
+
+VarMatchGeneratorTermSubs::VarMatchGeneratorTermSubs( Node var, Node subs ) :
+  InstMatchGenerator(), d_var( var ), d_subs( subs ), d_rm_prev( false ){
+  d_var_num[0] = d_var.getAttribute(InstVarNumAttribute());
+}
+
+bool VarMatchGeneratorTermSubs::getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ) {
+  if( !d_eq_class.isNull() ){
+    Trace("var-trigger-matching") << "Matching " << d_eq_class << " against " << d_var << " in " << d_subs << std::endl;
+    Node s = d_subs.substitute( d_var, d_eq_class );
+    s = Rewriter::rewrite( s );
+    Trace("var-trigger-matching") << "...got " << s << std::endl;
+    d_eq_class = Node::null();
+    d_rm_prev = m.get( d_var_num[0] ).isNull();
+    if( !m.set( qe, d_var_num[0], s ) ){
+      return false;
+    }else{
+      if( continueNextMatch( f, m, qe ) ){
+        return true;
+      }
+    }
+  }
+  if( d_rm_prev ){
+    m.d_vals[d_var_num[0]] = Node::null();
+    d_rm_prev = false;
+  }
+  return false;
+}
+
 /** constructors */
 InstMatchGeneratorMulti::InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption ) :
 d_f( f ){
@@ -578,7 +647,7 @@ void InstMatchGeneratorMulti::processNewInstantiations2( QuantifiersEngine* qe,
     }
   }else{
     //m is an instantiation
-    if( qe->addInstantiation( d_f, m ) ){
+    if( qe->addInstantiation( d_f, m, false ) ){
       addedLemmas++;
       Debug("smart-multi-trigger") << "-> Produced instantiation " << m << std::endl;
     }
@@ -618,13 +687,7 @@ int InstMatchGeneratorSimple::addInstantiations( Node f, InstMatch& baseMatch, Q
   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_op ]) );
-    }
-  }else{
-    addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_func_map_trie[ d_op ]) );
-  }
+  addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_func_map_trie[ d_op ]) );
   return addedLemmas;
 }
 
@@ -646,7 +709,7 @@ void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngin
   }else{
     if( d_match_pattern[argIndex].getKind()==INST_CONSTANT ){
       int v = d_var_num[argIndex];
-      for( std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
+      for( std::map< TNode, quantifiers::TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
         Node t = it->first;
         Node prev = m.get( v );
         //using representatives, just check if equal
@@ -658,7 +721,7 @@ void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngin
       }
     }else{
       Node r = qe->getEqualityQuery()->getRepresentative( d_match_pattern[argIndex] );
-      std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.find( r );
+      std::map< TNode, quantifiers::TermArgTrie >::iterator it = tat->d_data.find( r );
       if( it!=tat->d_data.end() ){
         addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
       }
@@ -676,7 +739,7 @@ int InstMatchGeneratorSimple::addTerm( Node f, Node t, QuantifiersEngine* qe ){
       return 0;
     }
   }
-  return qe->addInstantiation( f, m ) ? 1 : 0;
+  return qe->addInstantiation( f, m, false ) ? 1 : 0;
 }
 
 }/* CVC4::theory::inst namespace */
index 56eaf2c1749bf1d7dd30b97d72fe71c84237d4d0..aa5d377132c06fd1094172e8b0512d9255870b4d 100644 (file)
@@ -42,7 +42,7 @@ public:
   /** 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;
+  virtual int addTerm( Node f, Node t, QuantifiersEngine* qe ) { return 0; }
   /** set active add */
   virtual void setActiveAdd( bool val ) {}
 };/* class IMGenerator */
@@ -50,7 +50,7 @@ public:
 class CandidateGenerator;
 
 class InstMatchGenerator : public IMGenerator {
-private:
+protected:
   bool d_needsReset;
   /** candidate generator */
   CandidateGenerator* d_cg;
@@ -63,17 +63,18 @@ private:
   InstMatchGenerator* d_next;
   /** eq class */
   Node d_eq_class;
-  /** for arithmetic matching */
-  std::map< Node, Node > d_arith_coeffs;
   /** variable numbers */
   std::map< int, int > d_var_num;
   /** initialize pattern */
   void initialize( QuantifiersEngine* qe, std::vector< InstMatchGenerator * > & gens );
+  /** children types 0 : variable, 1 : child term, -1 : ground term */
+  std::vector< int > d_children_types;
+  /** continue */
+  bool continueNextMatch( Node f, InstMatch& m, 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_ERROR,
   };
@@ -85,7 +86,8 @@ public:
   bool getMatch( Node f, Node t, InstMatch& m, QuantifiersEngine* qe );
 
   /** constructors */
-  InstMatchGenerator( Node pat, int matchOption = 0 );
+  InstMatchGenerator( Node pat );
+  InstMatchGenerator();
   /** destructor */
   ~InstMatchGenerator(){}
   /** The pattern we are producing matches for.
@@ -115,6 +117,39 @@ public:
   static InstMatchGenerator* mkInstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe );
 };/* class InstMatchGenerator */
 
+//match generator for boolean term ITEs
+class VarMatchGeneratorBooleanTerm : public InstMatchGenerator {
+public:
+  VarMatchGeneratorBooleanTerm( Node var, Node comp );
+  Node d_comp;
+  bool d_rm_prev;
+  /** reset instantiation round (call this at beginning of instantiation round) */
+  void resetInstantiationRound( QuantifiersEngine* qe ){}
+  /** reset, eqc is the equivalence class to search in (any if eqc=null) */
+  void reset( Node eqc, QuantifiersEngine* qe ){ d_eq_class = eqc; }
+  /** get the next match.  must call reset( eqc ) before this function. */
+  bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe );
+  /** add instantiations directly */
+  int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){ return 0; }
+};
+
+//match generator for purified terms (matched term is substituted into d_subs)
+class VarMatchGeneratorTermSubs : public InstMatchGenerator {
+public:
+  VarMatchGeneratorTermSubs( Node var, Node subs );
+  TNode d_var;
+  Node d_subs;
+  bool d_rm_prev;
+  /** reset instantiation round (call this at beginning of instantiation round) */
+  void resetInstantiationRound( QuantifiersEngine* qe ){}
+  /** reset, eqc is the equivalence class to search in (any if eqc=null) */
+  void reset( Node eqc, QuantifiersEngine* qe ){ d_eq_class = eqc; }
+  /** get the next match.  must call reset( eqc ) before this function. */
+  bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe );
+  /** add instantiations directly */
+  int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ) { return 0; }
+};
+
 /** smart multi-trigger implementation */
 class InstMatchGeneratorMulti : public IMGenerator {
 private:
index 25f15cd783de428e848996080902b01e8c6f7840..6a2bd5e2e113338c47e6bca637d0ddd41f6b6595 100644 (file)
@@ -347,47 +347,3 @@ Node InstStrategySimplex::getTableauxValue( ArithVar v, bool minus_delta ){
   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( f );
-    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.setValue( j, 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( !TermDb::hasInstConstAttr(n) ){
-    return n;
-  }else{
-    return n;
-  }
-}
index 9196b97030ddc139b9cd9188d2474e87d8cb3bfe..bfc0501dcd6df669c3bcd347b02a6e85f8815c20 100644 (file)
@@ -81,29 +81,6 @@ public:
 };
 
 
-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 */
-
 }
 }
 }
index 5b0fade71638623c8d87eceff4d985dfbe32fe5a..5f949789a3ad83586b37657aa45e4a09fdc96af7 100644 (file)
@@ -68,12 +68,12 @@ int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e ){
     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;
+        Trace("process-trigger") << "  Process (user) ";
+        d_user_gen[f][i]->debugPrint("process-trigger");
+        Trace("process-trigger") << "..." << std::endl;
         InstMatch baseMatch( f );
         int numInst = d_user_gen[f][i]->addInstantiations( baseMatch );
-        //if( d_user_gen[f][i]->isMultiTrigger() )
-          Trace("process-trigger") << "  Done, numInst = " << numInst << "." << std::endl;
+        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;
@@ -88,18 +88,25 @@ int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e ){
 }
 
 void InstStrategyUserPatterns::addUserPattern( Node f, Node pat ){
+  Assert( pat.getKind()==INST_PATTERN );
   //add to generators
+  bool usable = true;
   std::vector< Node > nodes;
   for( int i=0; i<(int)pat.getNumChildren(); i++ ){
     nodes.push_back( pat[i] );
+    if( pat[i].getKind()!=INST_CONSTANT && !Trigger::isUsableTrigger( pat[i], f ) ){
+      Trace("trigger-warn") << "User-provided trigger is not usable : " << pat << " because of " << pat[i] << std::endl;
+      usable = false;
+      break;
+    }
   }
-  if( Trigger::isUsableTrigger( nodes, f ) ){
+  if( usable ){
+    Trace("user-pat") << "Add user pattern: " << pat << " for " << f << std::endl;
     //extend to literal matching
     d_quantEngine->getPhaseReqTerms( f, nodes );
     //check match option
     int matchOption = 0;
-    d_user_gen[f].push_back( Trigger::mkTrigger( d_quantEngine, f, nodes, matchOption, true, Trigger::TR_MAKE_NEW,
-                                                 options::smartTriggers() ) );
+    d_user_gen[f].push_back( Trigger::mkTrigger( d_quantEngine, f, nodes, matchOption, true, Trigger::TR_MAKE_NEW, options::smartTriggers() ) );
   }
 }
 
@@ -115,10 +122,10 @@ void InstStrategyAutoGenTriggers::processResetInstantiationRound( Theory::Effort
 }
 
 int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e ){
-  if( f.getNumChildren()==3 && options::userPatternsQuant()==USER_PAT_MODE_TRUST ){
+  if( hasUserPatterns( f ) && options::userPatternsQuant()==USER_PAT_MODE_TRUST ){
     return STATUS_UNKNOWN;
   }else{
-    int peffort = ( f.getNumChildren()==3 && options::userPatternsQuant()!=USER_PAT_MODE_IGNORE ) ? 2 : 1;
+    int peffort = ( hasUserPatterns( f ) && options::userPatternsQuant()!=USER_PAT_MODE_IGNORE ) ? 2 : 1;
     //int peffort = 1;
     if( e<peffort ){
       return STATUS_UNFINISHED;
@@ -156,14 +163,12 @@ int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e )
           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->debugPrint("process-trigger");
-              Trace("process-trigger") << "..." << std::endl;
+            Trace("process-trigger") << "  Process ";
+            tr->debugPrint("process-trigger");
+            Trace("process-trigger") << "..." << std::endl;
             InstMatch baseMatch( f );
             int numInst = tr->addInstantiations( baseMatch );
-            //if( tr->isMultiTrigger() )
-              Trace("process-trigger") << "  Done, numInst = " << numInst << "." << std::endl;
+            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{
@@ -193,8 +198,8 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f, Theory::Effort effor
     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;
+    Trigger::collectPatTerms( d_quantEngine, f, d_quantEngine->getTermDatabase()->getInstConstantBody( f ), patTermsF, d_tr_strategy, d_user_no_gen[f], true );
+    Trace("auto-gen-trigger") << "Collected pat terms for " << d_quantEngine->getTermDatabase()->getInstConstantBody( f ) << ", no-patterns : " << d_user_no_gen.size() << std::endl;
     Trace("auto-gen-trigger") << "   ";
     for( int i=0; i<(int)patTermsF.size(); i++ ){
       Trace("auto-gen-trigger") << patTermsF[i] << " ";
@@ -206,7 +211,7 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f, Theory::Effort effor
     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() ){
+      if( it->second.size()==f[0].getNumChildren() && !Trigger::isPureTheoryTrigger( it->first ) ){
         d_patTerms[0][f].push_back( it->first );
         d_is_single_trigger[ it->first ] = true;
       }else{
@@ -342,6 +347,35 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f, Theory::Effort effor
   }
 }
 
+bool InstStrategyAutoGenTriggers::hasUserPatterns( Node f ) {
+  if( f.getNumChildren()==3 ){
+    std::map< Node, bool >::iterator it = d_hasUserPatterns.find( f );
+    if( it==d_hasUserPatterns.end() ){
+      bool hasPat = false;
+      for( unsigned i=0; i<f[2].getNumChildren(); i++ ){
+        if( f[2][i].getKind()==INST_PATTERN ){
+          hasPat = true;
+          break;
+        }
+      }
+      d_hasUserPatterns[f] = hasPat;
+      return hasPat;
+    }else{
+      return it->second;
+    }
+  }else{
+    return false;
+  }
+}
+
+void InstStrategyAutoGenTriggers::addUserNoPattern( Node f, Node pat ) {
+  Assert( pat.getKind()==INST_NO_PATTERN && pat.getNumChildren()==1 );
+  if( std::find( d_user_no_gen[f].begin(), d_user_no_gen[f].end(), pat[0] )==d_user_no_gen[f].end() ){
+    Trace("user-pat") << "Add user no-pattern: " << pat[0] << " for " << f << std::endl;
+    d_user_no_gen[f].push_back( pat[0] );
+  }
+}
+
 void InstStrategyFreeVariable::processResetInstantiationRound( Theory::Effort effort ){
 }
 
index 968194e49dd43f15781cdeb85f76356811d37beb..c2b4f7533136ef38ab7b0063c032593855cba257 100644 (file)
@@ -80,12 +80,18 @@ private:
   std::map< Node, bool > d_made_multi_trigger;
   //processed trigger this round
   std::map< Node, std::map< inst::Trigger*, bool > > d_processed_trigger;
+  //instantiation no patterns
+  std::map< Node, std::vector< Node > > d_user_no_gen;
 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 );
+  /** has user patterns */
+  bool hasUserPatterns( Node f );
+  /** has user patterns */
+  std::map< Node, bool > d_hasUserPatterns;
 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)
@@ -111,6 +117,8 @@ public:
   }
   /** set generate additional */
   void setGenerateAdditional( bool val ) { d_generate_additional = val; }
+  /** add pattern */
+  void addUserNoPattern( Node f, Node pat );
 };/* class InstStrategyAutoGenTriggers */
 
 class InstStrategyFreeVariable : public InstStrategy{
index 3dd4423dede68a798c240cd4324d27cab3dddc15..9c3673bc2d1a66698abb6750ba1522f81368a0ef 100644 (file)
@@ -31,7 +31,7 @@ using namespace CVC4::theory::quantifiers;
 using namespace CVC4::theory::inst;
 
 InstantiationEngine::InstantiationEngine( QuantifiersEngine* qe, bool setIncomplete ) :
-QuantifiersModule( qe ), d_isup(NULL), d_i_ag(NULL), d_setIncomplete( setIncomplete ), d_ierCounter( 0 ), d_performCheck( false ){
+QuantifiersModule( qe ), d_isup(NULL), d_i_ag(NULL), d_setIncomplete( setIncomplete ), d_ierCounter( 0 ){
 
 }
 
@@ -41,41 +41,45 @@ InstantiationEngine::~InstantiationEngine() {
 }
 
 void InstantiationEngine::finishInit(){
-  //for UF terms
   if( !options::finiteModelFind() || options::fmfInstEngine() ){
-    //if( options::cbqi() ){
-    //  addInstStrategy( new InstStrategyCheckCESolved( this, d_quantEngine ) );
-    //}
-    //these are the instantiation strategies for basic E-matching
+
+    //these are the instantiation strategies for E-matching
+    
+    //user-provided patterns
     if( options::userPatternsQuant()!=USER_PAT_MODE_IGNORE ){
       d_isup = new InstStrategyUserPatterns( d_quantEngine );
       addInstStrategy( d_isup );
     }else{
       d_isup = NULL;
     }
-    d_i_ag = new InstStrategyAutoGenTriggers( d_quantEngine, Trigger::TS_ALL, 3 );
+    
+    //auto-generated patterns
+    int tstrt = Trigger::TS_ALL;
+    if( options::triggerSelMode()==TRIGGER_SEL_MIN ){
+      tstrt = Trigger::TS_MIN_TRIGGER;
+    }else if( options::triggerSelMode()==TRIGGER_SEL_MAX ){
+      tstrt = Trigger::TS_MAX_TRIGGER;
+    }
+    d_i_ag = new InstStrategyAutoGenTriggers( d_quantEngine, tstrt, 3 );
     d_i_ag->setGenerateAdditional( true );
     addInstStrategy( d_i_ag );
-    //addInstStrategy( new InstStrategyAddFailSplits( this, ie ) );
+    
+    //full saturation : instantiate from relevant domain, then arbitrary terms
     if( !options::finiteModelFind() && options::fullSaturateQuant() ){
       addInstStrategy( new InstStrategyFreeVariable( d_quantEngine ) );
     }
-    //d_isup->setPriorityOver( d_i_ag );
-    //d_isup->setPriorityOver( i_agm );
-    //i_ag->setPriorityOver( i_agm );
   }
-  //for arithmetic
+  
+  //counterexample-based quantifier instantiation
   if( options::cbqi() ){
     addInstStrategy( new InstStrategySimplex( (arith::TheoryArith*)d_quantEngine->getTheoryEngine()->theoryOf( THEORY_ARITH ), d_quantEngine ) );
-  }
-  //for datatypes
-  //if( options::cbqi() ){
   //  addInstStrategy( new InstStrategyDatatypesValue( d_quantEngine ) );
-  //}
+  }
 }
 
 
 bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
+  unsigned lastWaiting = d_quantEngine->d_lemmas_waiting.size();
   //if counterexample-based quantifier instantiation is active
   if( options::cbqi() ){
     //check if any cbqi lemma has not been added yet
@@ -149,7 +153,7 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
       }
     }
     //do not consider another level if already added lemma at this level
-    if( d_quantEngine->hasAddedLemma() ){
+    if( d_quantEngine->d_lemmas_waiting.size()>lastWaiting ){
       d_inst_round_status = InstStrategy::STATUS_UNKNOWN;
     }
     e++;
@@ -158,14 +162,11 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
   Debug("inst-engine") << (int)d_quantEngine->d_lemmas_waiting.size() << std::endl;
   //Notice() << "All instantiators finished, # added lemmas = " << (int)d_lemmas_waiting.size() << std::endl;
   if( !d_quantEngine->hasAddedLemma() ){
-    Debug("inst-engine-stuck") << "No instantiations produced at this state." << std::endl;
     Debug("inst-engine-ctrl") << "---Fail." << std::endl;
     return false;
   }else{
-    Debug("inst-engine-ctrl") << "---Done. " << (int)d_quantEngine->d_lemmas_waiting.size() << std::endl;
-    Trace("inst-engine") << "Added lemmas = " << (int)d_quantEngine->d_lemmas_waiting.size() << std::endl;
-    //flush lemmas to output channel
-    d_quantEngine->flushLemmas( &d_quantEngine->getOutputChannel() );
+    Debug("inst-engine-ctrl") << "---Done. " << (int)(d_quantEngine->d_lemmas_waiting.size()-lastWaiting) << std::endl;
+    Trace("inst-engine") << "Added lemmas = " << (int)(d_quantEngine->d_lemmas_waiting.size()-lastWaiting)  << std::endl;
     return true;
   }
 }
@@ -175,17 +176,17 @@ bool InstantiationEngine::needsCheck( Theory::Effort e ){
     d_ierCounter++;
   }
   //determine if we should perform check, based on instWhenMode
-  d_performCheck = false;
+  bool performCheck = false;
   if( options::instWhenMode()==INST_WHEN_FULL ){
-    d_performCheck = ( e >= Theory::EFFORT_FULL );
+    performCheck = ( e >= Theory::EFFORT_FULL );
   }else if( options::instWhenMode()==INST_WHEN_FULL_DELAY ){
-    d_performCheck = ( e >= Theory::EFFORT_FULL ) && !d_quantEngine->getTheoryEngine()->needCheck();
+    performCheck = ( e >= Theory::EFFORT_FULL ) && !d_quantEngine->getTheoryEngine()->needCheck();
   }else if( options::instWhenMode()==INST_WHEN_FULL_LAST_CALL ){
-    d_performCheck = ( ( e==Theory::EFFORT_FULL  && d_ierCounter%2==0 ) || e==Theory::EFFORT_LAST_CALL );
+    performCheck = ( ( e==Theory::EFFORT_FULL  && d_ierCounter%2==0 ) || e==Theory::EFFORT_LAST_CALL );
   }else if( options::instWhenMode()==INST_WHEN_LAST_CALL ){
-    d_performCheck = ( e >= Theory::EFFORT_LAST_CALL );
+    performCheck = ( e >= Theory::EFFORT_LAST_CALL );
   }else{
-    d_performCheck = true;
+    performCheck = true;
   }
   static int ierCounter2 = 0;
   if( e==Theory::EFFORT_LAST_CALL ){
@@ -193,15 +194,14 @@ bool InstantiationEngine::needsCheck( Theory::Effort e ){
     //with bounded integers, skip every other last call,
     // since matching loops may occur with infinite quantification
     if( ierCounter2%2==0 && options::fmfBoundInt() ){
-      d_performCheck = false;
+      performCheck = false;
     }
   }
-
-  return d_performCheck;
+  return performCheck;
 }
 
-void InstantiationEngine::check( Theory::Effort e ){
-  if( d_performCheck && !d_quantEngine->hasAddedLemma() ){
+void InstantiationEngine::check( Theory::Effort e, unsigned quant_e ){
+  if( quant_e==QuantifiersEngine::QEFFORT_STANDARD ){
     Debug("inst-engine") << "IE: Check " << e << " " << d_ierCounter << std::endl;
     double clSet = 0;
     if( Trace.isOn("inst-engine") ){
@@ -211,12 +211,15 @@ void InstantiationEngine::check( Theory::Effort e ){
     ++(d_statistics.d_instantiation_rounds);
     bool quantActive = false;
     Debug("quantifiers") << "quantifiers:  check:  asserted quantifiers size="
-                         << d_quantEngine->getModel()->getNumAssertedQuantifiers() << std::endl;
+                          << d_quantEngine->getModel()->getNumAssertedQuantifiers() << std::endl;
     for( int i=0; i<(int)d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
       Node n = d_quantEngine->getModel()->getAssertedQuantifier( i );
-      //it is not active if we have found the skolemized negation is unsat
-      if( TermDb::isRewriteRule( n ) ){
+      //it is not active if it corresponds to a rewrite rule: we will process in rewrite engine
+      if( !d_quantEngine->hasOwnership( n, this ) ){
+        d_quant_active[n] = false;
+      }else if( !d_quantEngine->getModel()->isQuantifierActive( n ) ){
         d_quant_active[n] = false;
+      //it is not active if we have found the skolemized negation is unsat
       }else if( options::cbqi() && hasAddedCbqiLemma( n ) ){
         Node cel = d_quantEngine->getTermDatabase()->getCounterexampleLiteral( n );
         bool active, value;
@@ -248,7 +251,6 @@ void InstantiationEngine::check( Theory::Effort e ){
           Debug("quantifiers") << ", ce is asserted";
         }
         Debug("quantifiers") << std::endl;
-      //it is not active if it corresponds to a rewrite rule: we will process in rewrite engine
       }else{
         d_quant_active[n] = true;
         if( !TermDb::hasInstConstAttr(n) ){
@@ -298,7 +300,7 @@ void InstantiationEngine::check( Theory::Effort e ){
 }
 
 void InstantiationEngine::registerQuantifier( Node f ){
-  if( !TermDb::isRewriteRule( f ) ){
+  if( d_quantEngine->hasOwnership( f, this ) ){
     //Notice() << "do cbqi " << f << " ? " << std::endl;
     if( options::cbqi() ){
       Node ceBody = d_quantEngine->getTermDatabase()->getInstConstantBody( f );
@@ -313,7 +315,11 @@ void InstantiationEngine::registerQuantifier( Node f ){
       //add patterns
       for( int i=0; i<(int)subsPat.getNumChildren(); i++ ){
         //Notice() << "Add pattern " << subsPat[i] << " for " << f << std::endl;
-        addUserPattern( f, subsPat[i] );
+        if( subsPat[i].getKind()==INST_PATTERN ){
+          addUserPattern( f, subsPat[i] );
+        }else if( subsPat[i].getKind()==INST_NO_PATTERN ){
+          addUserNoPattern( f, subsPat[i] );
+        }
       }
     }
   }
@@ -430,6 +436,12 @@ void InstantiationEngine::addUserPattern( Node f, Node pat ){
   }
 }
 
+void InstantiationEngine::addUserNoPattern( Node f, Node pat ){
+  if( d_i_ag ){
+    d_i_ag->addUserNoPattern( f, pat );
+  }
+}
+
 InstantiationEngine::Statistics::Statistics():
   d_instantiations_user_patterns("InstantiationEngine::Instantiations_User_Patterns", 0),
   d_instantiations_auto_gen("InstantiationEngine::Instantiations_Auto_Gen", 0),
index 7a35282179dcebbf0021639bc7db1adbc39e9120..bf0bb03e12c5a9b5cb265741607ee32b92637221 100644 (file)
@@ -99,7 +99,6 @@ private:
   bool d_setIncomplete;
   /** inst round counter */
   int d_ierCounter;
-  bool d_performCheck;
   /** whether each quantifier is active */
   std::map< Node, bool > d_quant_active;
   /** whether we have added cbqi lemma */
@@ -131,13 +130,14 @@ public:
   void finishInit();
 
   bool needsCheck( Theory::Effort e );
-  void check( Theory::Effort e );
+  void check( Theory::Effort e, unsigned quant_e );
   void registerQuantifier( Node f );
   void assertNode( Node f );
   Node explain(TNode n){ return Node::null(); }
   Node getNextDecisionRequest();
   /** add user pattern */
   void addUserPattern( Node f, Node pat );
+  void addUserNoPattern( Node f, Node pat );
 public:
   /** statistics class */
   class Statistics {
index 6fb480c3d370c6009b83a39ead6378cd645878e1..a8774440eb256b87de43c9de556e77a106a4eb79 100644 (file)
@@ -33,6 +33,8 @@ sort INST_PATTERN_TYPE \
 # This node is used for specifying hints for quantifier instantiation.
 # An instantiation pattern may have more than 1 child, in which case it specifies a multi-trigger.
 operator INST_PATTERN 1: "instantiation pattern"
+operator INST_NO_PATTERN 1 "instantiation no-pattern"
+operator INST_ATTRIBUTE 1 "instantiation attribute"
 
 sort INST_PATTERN_LIST_TYPE \
     Cardinality::INTEGERS \
@@ -46,6 +48,8 @@ typerule FORALL ::CVC4::theory::quantifiers::QuantifierForallTypeRule
 typerule EXISTS ::CVC4::theory::quantifiers::QuantifierExistsTypeRule 
 typerule BOUND_VAR_LIST ::CVC4::theory::quantifiers::QuantifierBoundVarListTypeRule 
 typerule INST_PATTERN ::CVC4::theory::quantifiers::QuantifierInstPatternTypeRule 
+typerule INST_NO_PATTERN ::CVC4::theory::quantifiers::QuantifierInstNoPatternTypeRule 
+typerule INST_ATTRIBUTE ::CVC4::theory::quantifiers::QuantifierInstAttributeTypeRule 
 typerule INST_PATTERN_LIST ::CVC4::theory::quantifiers::QuantifierInstPatternListTypeRule 
 
 # for rewrite rules
index 11734c43f1c5f6304f162d3f5e076d1c9140fdb9..7321e22b4ab8d427b662118e1f540a2b5ab8e3b5 100644 (file)
@@ -98,10 +98,14 @@ bool QuantifierMacros::isMacroLiteral( Node n, bool pol ){
 
 bool QuantifierMacros::isBoundVarApplyUf( Node n ) {
   Assert( n.getKind()==APPLY_UF );
+  TypeNode tn = n.getOperator().getType();
   for( unsigned i=0; i<n.getNumChildren(); i++ ){
     if( n[i].getKind()!=BOUND_VARIABLE ){
       return false;
     }
+    if( n[i].getType()!=tn[i] ){
+      return false;
+    }
     for( unsigned j=0; j<i; j++ ){
       if( n[j]==n[i] ){
         return false;
index 4179dcbf530394638960fca383438c8f2b6e90a5..cbff2b581280e44988ae4275dc8c12f1a796a859 100644 (file)
@@ -40,7 +40,7 @@ TheoryEngineModelBuilder( qe->getTheoryEngine() ), d_curr_model( c, NULL ), d_qe
 }
 
 bool QModelBuilder::isQuantifierActive( Node f ) {
-  return !TermDb::isRewriteRule( f );
+  return d_qe->hasOwnership( f );
 }
 
 
@@ -382,8 +382,7 @@ QModelBuilderIG::Statistics::~Statistics(){
 }
 
 bool QModelBuilderIG::isQuantifierActive( Node f ){
-  return !TermDb::isRewriteRule( f ) &&
-         ( d_considerAxioms || !f.getAttribute(AxiomAttribute()) ) && d_quant_sat.find( f )==d_quant_sat.end();
+  return d_qe->hasOwnership( f ) && ( d_considerAxioms || !d_qe->getTermDatabase()->isQAttrAxiom( f ) ) && d_quant_sat.find( f )==d_quant_sat.end();
 }
 
 bool QModelBuilderIG::isTermActive( Node n ){
index d68c66535bddc219518434112812664d32f2d415..9e5a8997b9307428b51714c0363523678422d8b0 100644 (file)
@@ -35,7 +35,12 @@ using namespace CVC4::theory::inst;
 
 //Model Engine constructor
 ModelEngine::ModelEngine( context::Context* c, QuantifiersEngine* qe ) :
-QuantifiersModule( qe ){
+QuantifiersModule( qe ),
+d_incomplete_check(false),
+d_addedLemmas(0),
+d_triedLemmas(0),
+d_totalLemmas(0)
+{
 
   Trace("model-engine-debug") << "Initialize model engine, mbqi : " << options::mbqiMode() << " " << options::fmfBoundInt() << std::endl;
   if( options::mbqiMode()==MBQI_FMC || options::mbqiMode()==quantifiers::MBQI_FMC_INTERVAL ||
@@ -61,8 +66,12 @@ ModelEngine::~ModelEngine() {
   delete d_builder;
 }
 
-void ModelEngine::check( Theory::Effort e ){
-  if( e==Theory::EFFORT_LAST_CALL && !d_quantEngine->hasAddedLemma() ){
+bool ModelEngine::needsCheck( Theory::Effort e ) {
+  return e==Theory::EFFORT_LAST_CALL;
+}
+
+void ModelEngine::check( Theory::Effort e, unsigned quant_e ){
+  if( quant_e==QuantifiersEngine::QEFFORT_MODEL ){
     int addedLemmas = 0;
     bool needsBuild = true;
     FirstOrderModel* fm = d_quantEngine->getModel();
@@ -94,7 +103,8 @@ void ModelEngine::check( Theory::Effort e ){
             Trace("model-engine-debug") << "Verify uf ss is minimal..." << std::endl;
             //let the strong solver verify that the model is minimal
             //for debugging, this will if there are terms in the model that the strong solver was not notified of
-            if( ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->theoryOf( THEORY_UF ))->getStrongSolver()->debugModel( fm ) ){
+            uf::StrongSolverTheoryUF * ufss = ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->theoryOf( THEORY_UF ))->getStrongSolver();
+            if( !ufss || ufss->debugModel( fm ) ){
               Trace("model-engine-debug") << "Check model..." << std::endl;
               d_incomplete_check = false;
               //print debug
@@ -140,7 +150,6 @@ void ModelEngine::check( Theory::Effort e ){
       }
     }else{
       //otherwise, the search will continue
-      d_quantEngine->flushLemmas( &d_quantEngine->getOutputChannel() );
     }
   }
 }
index caf27f69174e680e7bfb6f86b472b120358dbe23..890af1643834f4f9be490972db94727f0ffaebca 100644 (file)
@@ -52,7 +52,8 @@ public:
   //get the builder
   QModelBuilder* getModelBuilder() { return d_builder; }
 public:
-  void check( Theory::Effort e );
+  bool needsCheck( Theory::Effort e );
+  void check( Theory::Effort e, unsigned quant_e );
   void registerQuantifier( Node f );
   void assertNode( Node f );
   Node explain(TNode n){ return Node::null(); }
index 112e052c2f3d74ee9ea6a8a93f6ebbd039eac361..993ac553667bb4f21ce6adc99940a20048c5f80c 100644 (file)
@@ -107,6 +107,25 @@ typedef enum {
   USER_PAT_MODE_IGNORE,
 } UserPatMode;
 
+typedef enum {
+  /** default for trigger selection */
+  TRIGGER_SEL_DEFAULT,
+  /** only consider minimal terms for triggers */
+  TRIGGER_SEL_MIN,
+  /** only consider maximal terms for triggers */
+  TRIGGER_SEL_MAX,
+} TriggerSelMode;
+
+typedef enum {
+  /** default : prenex quantifiers without user patterns */
+  PRENEX_NO_USER_PAT,
+  /** prenex all */
+  PRENEX_ALL,
+  /** prenex none */
+  PRENEX_NONE,
+} PrenexQuantMode;
+
+
 }/* CVC4::theory::quantifiers namespace */
 }/* CVC4::theory namespace */
 
index 1cdf5e8bdffb4c88c52bdd9052185d5bd09c032d..5e3c66d9a011fb3ae630fe8b889ddb4260c8e57a 100644 (file)
@@ -18,7 +18,7 @@ option miniscopeQuantFreeVar /--disable-miniscope-quant-fv bool :default true
  disable miniscope quantifiers for ground subformulas
 
 # Whether to prenex (nested universal) quantifiers
-option prenexQuant /--disable-prenex-quant bool :default true
+option prenexQuant --prenex-quant=MODE CVC4::theory::quantifiers::PrenexQuantMode :default CVC4::theory::quantifiers::PRENEX_NO_USER_PAT :include "theory/quantifiers/modes.h" :handler CVC4::theory::quantifiers::stringToPrenexQuantMode :handler-include "theory/quantifiers/options_handlers.h"
  disable prenexing of quantified formulas
 
 # Whether to variable-eliminate quantifiers.
@@ -26,6 +26,8 @@ option prenexQuant /--disable-prenex-quant bool :default true
 #   forall y. P( c, y )
 option varElimQuant /--disable-var-elim-quant bool :default true
  disable simple variable elimination for quantified formulas
+option dtVarExpandQuant --dt-var-exp-quant bool :default true
+ expand datatype variables bound to one constructor in quantifiers
 
 option simpleIteLiftQuant /--disable-ite-lift-quant bool :default true
  disable simple ite lifting for quantified formulas
@@ -63,6 +65,10 @@ option relevantTriggers --relevant-triggers bool :default false
  prefer triggers that are more relevant based on SInE style analysis
 option relationalTriggers --relational-triggers bool :default false
  choose relational triggers such as x = f(y), x >= f(y)
+option purifyTriggers --purify-triggers bool :default false :read-write
+ purify triggers, e.g. f( x+1 ) becomes f( y ), x mapsto y-1
+option triggerSelMode --trigger-sel CVC4::theory::quantifiers::TriggerSelMode :default CVC4::theory::quantifiers::TRIGGER_SEL_DEFAULT :read-write :include "theory/quantifiers/modes.h" :handler  CVC4::theory::quantifiers::stringToTriggerSelMode :handler-include "theory/quantifiers/options_handlers.h"
+ selection mode for triggers
 
 # Whether to consider terms in the bodies of quantifiers for matching
 option registerQuantBodyTerms --register-quant-body-terms bool :default false
@@ -72,10 +78,15 @@ option instWhenMode --inst-when=MODE CVC4::theory::quantifiers::InstWhenMode :de
  when to apply instantiation
 option instMaxLevel --inst-max-level=N int :default -1
  maximum inst level of terms used to instantiate quantified formulas with (-1 == no limit, default)
+option instLevelInputOnly --inst-level-input-only bool :default true
+ only input terms are assigned instantiation level zero
 
 option eagerInstQuant --eager-inst-quant bool :default false
  apply quantifier instantiation eagerly
 
+option instNoEntail --inst-no-entail bool :read-write :default false
+ do not consider instances of quantified formulas that are currently entailed
+
 option fullSaturateQuant --full-saturate-quant bool :default false
  when all other quantifier instantiation strategies fail, instantiate with ground terms from relevant domain, then arbitrary ground terms before answering unknown
 
@@ -139,7 +150,31 @@ option quantRewriteRules --rewrite-rules bool :default true
 option rrOneInstPerRound --rr-one-inst-per-round bool :default false
  add one instance of rewrite rule per round
 
-option dtStcInduction --dt-stc-ind bool :default false
+option quantInduction --quant-ind bool :default false
+ use all available techniques for inductive reasoning
+option dtStcInduction --dt-stc-ind bool :read-write :default false
  apply strengthening for existential quantification over datatypes based on structural induction
-
+option intWfInduction --int-wf-ind bool :read-write :default false
+ apply strengthening for integers based on well-founded induction
+option conjectureGen --conjecture-gen bool :read-write :default false
+ generate candidate conjectures for inductive proofs
+option conjectureGenPerRound --conjecture-gen-per-round=N int :default 1
+ number of conjectures to generate per instantiation round 
+option conjectureNoFilter --conjecture-no-filter bool :default false
+ do not filter conjectures
+option conjectureFilterActiveTerms --conjecture-filter-active-terms bool :read-write :default true
+ filter based on active terms
+option conjectureFilterCanonical --conjecture-filter-canonical bool :read-write :default true
+ filter based on canonicity
+option conjectureFilterModel --conjecture-filter-model bool :read-write :default true
+ filter based on model
+option conjectureGenGtEnum --conjecture-gen-gt-enum=N int :default 0
+ number of ground terms to generate for model filtering
+option conjectureUeeIntro --conjecture-gen-uee-intro bool :default false
+ more aggressive merging for universal equality engine, introduces terms
+option ceGuidedInst --cegqi bool :default false
+  counterexample guided quantifier instantiation
 endmodule
index 38567d166ce1065c815bcd84a21460598688fa31..9558aa0e0be2392d722783eed37ae108eaf23c3e 100644 (file)
@@ -152,6 +152,32 @@ ignore \n\
 + Ignore user-provided patterns. \n\
 \n\
 ";
+static const std::string triggerSelModeHelp = "\
+Trigger selection modes currently supported by the --trigger-sel option:\n\
+\n\
+default \n\
++ Default, consider all subterms of quantified formulas for trigger selection.\n\
+\n\
+min \n\
++ Consider only minimal subterms that meet criteria for triggers.\n\
+\n\
+max \n\
++ Consider only maximal subterms that meet criteria for triggers. \n\
+\n\
+";
+static const std::string prenexQuantModeHelp = "\
+Prenex quantifiers modes currently supported by the --prenex-quant option:\n\
+\n\
+default \n\
++ Default, prenex all nested quantifiers except those with user patterns.\n\
+\n\
+all \n\
++ Prenex all nested quantifiers.\n\
+\n\
+none \n\
++ Do no prenex nested quantifiers. \n\
+\n\
+";
 inline InstWhenMode stringToInstWhenMode(std::string option, std::string optarg, SmtEngine* smt) throw(OptionException) {
   if(optarg == "pre-full") {
     return INST_WHEN_PRE_FULL;
@@ -296,6 +322,39 @@ inline UserPatMode stringToUserPatMode(std::string option, std::string optarg, S
                           optarg + "'.  Try --user-pat help.");
   }
 }
+
+inline TriggerSelMode stringToTriggerSelMode(std::string option, std::string optarg, SmtEngine* smt) throw(OptionException) {
+  if(optarg ==  "default" || optarg == "all" ) {
+    return TRIGGER_SEL_DEFAULT;
+  } else if(optarg == "min") {
+    return TRIGGER_SEL_MIN;
+  } else if(optarg == "max") {
+    return TRIGGER_SEL_MAX;
+  } else if(optarg ==  "help") {
+    puts(triggerSelModeHelp.c_str());
+    exit(1);
+  } else {
+    throw OptionException(std::string("unknown option for --trigger-sel: `") +
+                          optarg + "'.  Try --trigger-sel help.");
+  }
+}
+
+inline PrenexQuantMode stringToPrenexQuantMode(std::string option, std::string optarg, SmtEngine* smt) throw(OptionException) {
+  if(optarg ==  "default" ) {
+    return PRENEX_NO_USER_PAT;
+  } else if(optarg == "all") {
+    return PRENEX_ALL;
+  } else if(optarg == "none") {
+    return PRENEX_NONE;
+  } else if(optarg ==  "help") {
+    puts(prenexQuantModeHelp.c_str());
+    exit(1);
+  } else {
+    throw OptionException(std::string("unknown option for --prenex-quant: `") +
+                          optarg + "'.  Try --prenex-quant help.");
+  }
+}
+
 }/* CVC4::theory::quantifiers namespace */
 }/* CVC4::theory namespace */
 }/* CVC4 namespace */
old mode 100644 (file)
new mode 100755 (executable)
index c6e8819..8136bf1
-/*********************                                                        */
-/*! \file quant_conflict_find.cpp
- ** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014  New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief quant conflict find class
- **
- **/
-
-#include <vector>
-
-#include "theory/quantifiers/quant_conflict_find.h"
-#include "theory/quantifiers/quant_util.h"
-#include "theory/theory_engine.h"
-#include "theory/quantifiers/options.h"
-#include "theory/quantifiers/term_database.h"
-#include "theory/quantifiers/trigger.h"
-
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::theory;
-using namespace CVC4::theory::quantifiers;
-using namespace std;
-
-namespace CVC4 {
-
-Node QcfNodeIndex::existsTerm( TNode n, std::vector< TNode >& reps, int index ) {
-  if( index==(int)reps.size() ){
-    if( d_children.empty() ){
-      return Node::null();
-    }else{
-      return d_children.begin()->first;
-    }
-  }else{
-    std::map< TNode, QcfNodeIndex >::iterator it = d_children.find( reps[index] );
-    if( it==d_children.end() ){
-      return Node::null();
-    }else{
-      return it->second.existsTerm( n, reps, index+1 );
-    }
-  }
-}
-
-Node QcfNodeIndex::addTerm( TNode n, std::vector< TNode >& reps, int index ) {
-  if( index==(int)reps.size() ){
-    if( d_children.empty() ){
-      d_children[ n ].clear();
-      return n;
-    }else{
-      return d_children.begin()->first;
-    }
-  }else{
-    return d_children[reps[index]].addTerm( n, reps, index+1 );
-  }
-}
-
-
-void QcfNodeIndex::debugPrint( const char * c, int t ) {
-  for( std::map< TNode, QcfNodeIndex >::iterator it = d_children.begin(); it != d_children.end(); ++it ){
-    if( !it->first.isNull() ){
-      for( int j=0; j<t; j++ ){ Trace(c) << "  "; }
-      Trace(c) << it->first << " : " << std::endl;
-      it->second.debugPrint( c, t+1 );
-    }
-  }
-}
-
-
-void QuantInfo::initialize( Node q, Node qn ) {
-  d_q = q;
-  for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
-    d_match.push_back( TNode::null() );
-    d_match_term.push_back( TNode::null() );
-  }
-
-  //register the variables
-  for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
-    d_var_num[q[0][i]] = i;
-    d_vars.push_back( q[0][i] );
-  }
-
-  registerNode( qn, true, true );
-
-
-  Trace("qcf-qregister") << "- Make match gen structure..." << std::endl;
-  d_mg = new MatchGen( this, qn );
-
-  if( d_mg->isValid() ){
-    /*
-    for( unsigned j=0; j<q[0].getNumChildren(); j++ ){
-      if( d_inMatchConstraint.find( q[0][j] )==d_inMatchConstraint.end() ){
-        Trace("qcf-invalid") << "QCF invalid : variable " << q[0][j] << " does not exist in a matching constraint." << std::endl;
-        d_mg->setInvalid();
-        break;
-      }
-    }
-    */
-    if( d_mg->isValid() ){
-      for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){
-        if( d_vars[j].getKind()!=BOUND_VARIABLE ){
-          d_var_mg[j] = NULL;
-          bool is_tsym = false;
-          if( !MatchGen::isHandledUfTerm( d_vars[j] ) && d_vars[j].getKind()!=ITE ){
-            is_tsym = true;
-            d_tsym_vars.push_back( j );
-          }
-          if( !is_tsym || options::qcfTConstraint() ){
-            d_var_mg[j] = new MatchGen( this, d_vars[j], true );
-          }
-          if( !d_var_mg[j] || !d_var_mg[j]->isValid() ){
-            Trace("qcf-invalid") << "QCF invalid : cannot match for " << d_vars[j] << std::endl;
-            d_mg->setInvalid();
-            break;
-          }else{
-            std::vector< int > bvars;
-            d_var_mg[j]->determineVariableOrder( this, bvars );
-          }
-        }
-      }
-      if( d_mg->isValid() ){
-        std::vector< int > bvars;
-        d_mg->determineVariableOrder( this, bvars );
-      }
-    }
-  }else{
-    Trace("qcf-invalid") << "QCF invalid : body of formula cannot be processed." << std::endl;
-  }
-  Trace("qcf-qregister-summary") << "QCF register : " << ( d_mg->isValid() ? "VALID " : "INVALID" ) << " : " << q << std::endl;
-}
-
-void QuantInfo::registerNode( Node n, bool hasPol, bool pol, bool beneathQuant ) {
-  Trace("qcf-qregister-debug2") << "Register : " << n << std::endl;
-  if( n.getKind()==FORALL ){
-    registerNode( n[1], hasPol, pol, true );
-  }else{
-    if( !MatchGen::isHandledBoolConnective( n ) ){
-      if( n.hasBoundVar() ){
-        //literals
-        if( n.getKind()==EQUAL ){
-          for( unsigned i=0; i<n.getNumChildren(); i++ ){
-            flatten( n[i], beneathQuant );
-          }
-        }else if( MatchGen::isHandledUfTerm( n ) ){
-          flatten( n, beneathQuant );
-        }else if( n.getKind()==ITE ){
-          for( unsigned i=1; i<=2; i++ ){
-            flatten( n[i], beneathQuant );
-          }
-          registerNode( n[0], false, pol, beneathQuant );
-        }else if( options::qcfTConstraint() ){
-          //a theory-specific predicate
-          for( unsigned i=0; i<n.getNumChildren(); i++ ){
-            flatten( n[i], beneathQuant );
-          }
-        }
-      }
-    }else{
-      for( unsigned i=0; i<n.getNumChildren(); i++ ){
-        bool newHasPol;
-        bool newPol;
-        QuantPhaseReq::getPolarity( n, i, hasPol, pol, newHasPol, newPol );
-        //QcfNode * qcfc = new QcfNode( d_c );
-        //qcfc->d_parent = qcf;
-        //qcf->d_child[i] = qcfc;
-        registerNode( n[i], newHasPol, newPol, beneathQuant );
-      }
-    }
-  }
-}
-
-void QuantInfo::flatten( Node n, bool beneathQuant ) {
-  Trace("qcf-qregister-debug2") << "Flatten : " << n << std::endl;
-  if( n.hasBoundVar() ){
-    if( n.getKind()==BOUND_VARIABLE ){
-      d_inMatchConstraint[n] = true;
-    }
-    //if( MatchGen::isHandledUfTerm( n ) || n.getKind()==ITE ){
-    if( d_var_num.find( n )==d_var_num.end() ){
-      Trace("qcf-qregister-debug2") << "Add FLATTEN VAR : " << n << std::endl;
-      d_var_num[n] = d_vars.size();
-      d_vars.push_back( n );
-      d_match.push_back( TNode::null() );
-      d_match_term.push_back( TNode::null() );
-      if( n.getKind()==ITE ){
-        registerNode( n, false, false );
-      }else{
-        for( unsigned i=0; i<n.getNumChildren(); i++ ){
-          flatten( n[i], beneathQuant );
-        }
-      }
-    }else{
-      Trace("qcf-qregister-debug2") << "...already processed" << std::endl;
-    }
-  }else{
-    Trace("qcf-qregister-debug2") << "...is ground." << std::endl;
-  }
-}
-
-
-void QuantInfo::reset_round( QuantConflictFind * p ) {
-  for( unsigned i=0; i<d_match.size(); i++ ){
-    d_match[i] = TNode::null();
-    d_match_term[i] = TNode::null();
-  }
-  d_curr_var_deq.clear();
-  d_tconstraints.clear();
-  //add built-in variable constraints
-  for( unsigned r=0; r<2; r++ ){
-    for( std::map< int, std::vector< Node > >::iterator it = d_var_constraint[r].begin();
-         it != d_var_constraint[r].end(); ++it ){
-      for( unsigned j=0; j<it->second.size(); j++ ){
-        Node rr = it->second[j];
-        if( !isVar( rr ) ){
-          rr = p->getRepresentative( rr );
-        }
-        if( addConstraint( p, it->first, rr, r==0 )==-1 ){
-          d_var_constraint[0].clear();
-          d_var_constraint[1].clear();
-          //quantified formula is actually equivalent to true
-          Trace("qcf-qregister") << "Quantifier is equivalent to true!!!" << std::endl;
-          d_mg->d_children.clear();
-          d_mg->d_n = NodeManager::currentNM()->mkConst( true );
-          d_mg->d_type = MatchGen::typ_ground;
-          return;
-        }
-      }
-    }
-  }
-  d_mg->reset_round( p );
-  for( std::map< int, MatchGen * >::iterator it = d_var_mg.begin(); it != d_var_mg.end(); ++it ){
-    it->second->reset_round( p );
-  }
-  //now, reset for matching
-  d_mg->reset( p, false, this );
-}
-
-int QuantInfo::getCurrentRepVar( int v ) {
-  if( v!=-1 && !d_match[v].isNull() ){
-    int vn = getVarNum( d_match[v] );
-    if( vn!=-1 ){
-      //int vr = getCurrentRepVar( vn );
-      //d_match[v] = d_vars[vr];
-      //return vr;
-      return getCurrentRepVar( vn );
-    }
-  }
-  return v;
-}
-
-TNode QuantInfo::getCurrentValue( TNode n ) {
-  int v = getVarNum( n );
-  if( v==-1 ){
-    return n;
-  }else{
-    if( d_match[v].isNull() ){
-      return n;
-    }else{
-      Assert( getVarNum( d_match[v] )!=v );
-      return getCurrentValue( d_match[v] );
-    }
-  }
-}
-
-TNode QuantInfo::getCurrentExpValue( TNode n ) {
-  int v = getVarNum( n );
-  if( v==-1 ){
-    return n;
-  }else{
-    if( d_match[v].isNull() ){
-      return n;
-    }else{
-      Assert( getVarNum( d_match[v] )!=v );
-      if( d_match_term[v].isNull() ){
-        return getCurrentValue( d_match[v] );
-      }else{
-        return d_match_term[v];
-      }
-    }
-  }
-}
-
-bool QuantInfo::getCurrentCanBeEqual( QuantConflictFind * p, int v, TNode n, bool chDiseq ) {
-  //check disequalities
-  std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( v );
-  if( itd!=d_curr_var_deq.end() ){
-    for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
-      Node cv = getCurrentValue( it->first );
-      Debug("qcf-ccbe") << "compare " << cv << " " << n << std::endl;
-      if( cv==n ){
-        return false;
-      }else if( chDiseq && !isVar( n ) && !isVar( cv ) ){
-        //they must actually be disequal if we are looking for conflicts
-        if( !p->areDisequal( n, cv ) ){
-          //TODO : check for entailed disequal
-
-          return false;
-        }
-      }
-    }
-  }
-  return true;
-}
-
-int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, bool polarity ) {
-  v = getCurrentRepVar( v );
-  int vn = getVarNum( n );
-  vn = vn==-1 ? -1 : getCurrentRepVar( vn );
-  n = getCurrentValue( n );
-  return addConstraint( p, v, n, vn, polarity, false );
-}
-
-int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, int vn, bool polarity, bool doRemove ) {
-  //for handling equalities between variables, and disequalities involving variables
-  Debug("qcf-match-debug") << "- " << (doRemove ? "un" : "" ) << "constrain : " << v << " -> " << n << " (cv=" << getCurrentValue( n ) << ")";
-  Debug("qcf-match-debug") << ", (vn=" << vn << "), polarity = " << polarity << std::endl;
-  Assert( doRemove || n==getCurrentValue( n ) );
-  Assert( doRemove || v==getCurrentRepVar( v ) );
-  Assert( doRemove || vn==getCurrentRepVar( getVarNum( n ) ) );
-  if( polarity ){
-    if( vn!=v ){
-      if( doRemove ){
-        if( vn!=-1 ){
-          //if set to this in the opposite direction, clean up opposite instead
-          //          std::map< int, TNode >::iterator itmn = d_match.find( vn );
-          if( d_match[vn]==d_vars[v] ){
-            return addConstraint( p, vn, d_vars[v], v, true, true );
-          }else{
-            //unsetting variables equal
-            std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( vn );
-            if( itd!=d_curr_var_deq.end() ){
-              //remove disequalities owned by this
-              std::vector< TNode > remDeq;
-              for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
-                if( it->second==v ){
-                  remDeq.push_back( it->first );
-                }
-              }
-              for( unsigned i=0; i<remDeq.size(); i++ ){
-                d_curr_var_deq[vn].erase( remDeq[i] );
-              }
-            }
-          }
-        }
-        d_match[v] = TNode::null();
-        return 1;
-      }else{
-        //std::map< int, TNode >::iterator itm = d_match.find( v );
-
-        if( vn!=-1 ){
-          Debug("qcf-match-debug") << "  ...Variable bound to variable" << std::endl;
-          //std::map< int, TNode >::iterator itmn = d_match.find( vn );
-          if( d_match[v].isNull() ){
-            //setting variables equal
-            bool alreadySet = false;
-            if( !d_match[vn].isNull() ){
-              alreadySet = true;
-              Assert( !isVar( d_match[vn] ) );
-            }
-
-            //copy or check disequalities
-            std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( v );
-            if( itd!=d_curr_var_deq.end() ){
-              for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
-                Node dv = getCurrentValue( it->first );
-                if( !alreadySet ){
-                  if( d_curr_var_deq[vn].find( dv )==d_curr_var_deq[vn].end() ){
-                    d_curr_var_deq[vn][dv] = v;
-                  }
-                }else{
-                  if( !p->areMatchDisequal( d_match[vn], dv ) ){
-                    Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;
-                    return -1;
-                  }
-                }
-              }
-            }
-            if( alreadySet ){
-              n = getCurrentValue( n );
-            }
-          }else{
-            if( d_match[vn].isNull() ){
-              Debug("qcf-match-debug") << " ...Reverse direction" << std::endl;
-              //set the opposite direction
-              return addConstraint( p, vn, d_vars[v], v, true, false );
-            }else{
-              Debug("qcf-match-debug") << "  -> Both variables bound, compare" << std::endl;
-              //are they currently equal
-              return p->areMatchEqual( d_match[v], d_match[vn] ) ? 0 : -1;
-            }
-          }
-        }else{
-          Debug("qcf-match-debug") << "  ...Variable bound to ground" << std::endl;
-          if( d_match[v].isNull() ){
-          }else{
-            //compare ground values
-            Debug("qcf-match-debug") << "  -> Ground value, compare " << d_match[v] << " "<< n << std::endl;
-            return p->areMatchEqual( d_match[v], n ) ? 0 : -1;
-          }
-        }
-        if( setMatch( p, v, n ) ){
-          Debug("qcf-match-debug") << "  -> success" << std::endl;
-          return 1;
-        }else{
-          Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;
-          return -1;
-        }
-      }
-    }else{
-      Debug("qcf-match-debug") << "  -> redundant, variable identity" << std::endl;
-      return 0;
-    }
-  }else{
-    if( vn==v ){
-      Debug("qcf-match-debug") << "  -> fail, variable identity" << std::endl;
-      return -1;
-    }else{
-      if( doRemove ){
-        Assert( d_curr_var_deq[v].find( n )!=d_curr_var_deq[v].end() );
-        d_curr_var_deq[v].erase( n );
-        return 1;
-      }else{
-        if( d_curr_var_deq[v].find( n )==d_curr_var_deq[v].end() ){
-          //check if it respects equality
-          //std::map< int, TNode >::iterator itm = d_match.find( v );
-          if( !d_match[v].isNull() ){
-            TNode nv = getCurrentValue( n );
-            if( !p->areMatchDisequal( nv, d_match[v] ) ){
-              Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;
-              return -1;
-            }
-          }
-          d_curr_var_deq[v][n] = v;
-          Debug("qcf-match-debug") << "  -> success" << std::endl;
-          return 1;
-        }else{
-          Debug("qcf-match-debug") << "  -> redundant disequality" << std::endl;
-          return 0;
-        }
-      }
-    }
-  }
-}
-
-bool QuantInfo::isConstrainedVar( int v ) {
-  if( d_curr_var_deq.find( v )!=d_curr_var_deq.end() && !d_curr_var_deq[v].empty() ){
-    return true;
-  }else{
-    Node vv = getVar( v );
-    //for( std::map< int, TNode >::iterator it = d_match.begin(); it != d_match.end(); ++it ){
-    for( unsigned i=0; i<d_match.size(); i++ ){
-      if( d_match[i]==vv ){
-        return true;
-      }
-    }
-    for( std::map< int, std::map< TNode, int > >::iterator it = d_curr_var_deq.begin(); it != d_curr_var_deq.end(); ++it ){
-      for( std::map< TNode, int >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
-        if( it2->first==vv ){
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-}
-
-bool QuantInfo::setMatch( QuantConflictFind * p, int v, TNode n ) {
-  if( getCurrentCanBeEqual( p, v, n ) ){
-    Debug("qcf-match-debug") << "-- bind : " << v << " -> " << n << ", checked " <<  d_curr_var_deq[v].size() << " disequalities" << std::endl;
-    d_match[v] = n;
-    return true;
-  }else{
-    return false;
-  }
-}
-
-bool QuantInfo::isMatchSpurious( QuantConflictFind * p ) {
-  for( int i=0; i<getNumVars(); i++ ){
-    //std::map< int, TNode >::iterator it = d_match.find( i );
-    if( !d_match[i].isNull() ){
-      if( !getCurrentCanBeEqual( p, i, d_match[i], p->d_effort==QuantConflictFind::effort_conflict ) ){
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-bool QuantInfo::isTConstraintSpurious( QuantConflictFind * p, std::vector< Node >& terms ) {
-  if( !d_tconstraints.empty() ){
-    //check constraints
-    for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){
-      //apply substitution to the tconstraint
-      Node cons = it->first.substitute( p->getQuantifiersEngine()->getTermDatabase()->d_vars[d_q].begin(),
-                                        p->getQuantifiersEngine()->getTermDatabase()->d_vars[d_q].end(),
-                                        terms.begin(), terms.end() );
-      cons = it->second ? cons : cons.negate();
-      if( !entailmentTest( p, cons, p->d_effort==QuantConflictFind::effort_conflict ) ){
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-bool QuantInfo::entailmentTest( QuantConflictFind * p, Node lit, bool chEnt ) {
-  Trace("qcf-tconstraint-debug") << "Check : " << lit << std::endl;
-  Node rew = Rewriter::rewrite( lit );
-  if( rew==p->d_false ){
-    Trace("qcf-tconstraint-debug") << "...constraint " << lit << " is disentailed (rewrites to false)." << std::endl;
-    return false;
-  }else if( rew!=p->d_true ){
-    //if checking for conflicts, we must be sure that the constraint is entailed
-    if( chEnt ){
-      //check if it is entailed
-      Trace("qcf-tconstraint-debug") << "Check entailment of " << rew << "..." << std::endl;
-      std::pair<bool, Node> et = p->getQuantifiersEngine()->getTheoryEngine()->entailmentCheck(THEORY_OF_TYPE_BASED, rew );
-      ++(p->d_statistics.d_entailment_checks);
-      Trace("qcf-tconstraint-debug") << "ET result : " << et.first << " " << et.second << std::endl;
-      if( !et.first ){
-        Trace("qcf-tconstraint-debug") << "...cannot show entailment of " << rew << "." << std::endl;
-        return false;
-      }else{
-        return true;
-      }
-    }else{
-      Trace("qcf-tconstraint-debug") << "...does not need to be entailed." << std::endl;
-      return true;
-    }
-  }else{
-    Trace("qcf-tconstraint-debug") << "...rewrites to true." << std::endl;
-    return true;
-  }
-}
-
-bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assigned, bool doContinue ) {
-  //assign values for variables that were unassigned (usually not necessary, but handles corner cases)
-  bool doFail = false;
-  bool success = true;
-  if( doContinue ){
-    doFail = true;
-    success = false;
-  }else{
-    //solve for interpreted symbol matches
-    //   this breaks the invariant that all introduced constraints are over existing terms
-    for( int i=(int)(d_tsym_vars.size()-1); i>=0; i-- ){
-      int index = d_tsym_vars[i];
-      TNode v = getCurrentValue( d_vars[index] );
-      int slv_v = -1;
-      if( v==d_vars[index] ){
-        slv_v = index;
-      }
-      Trace("qcf-tconstraint-debug") << "Solve " << d_vars[index] << " = " << v << " " << d_vars[index].getKind() << std::endl;
-      if( d_vars[index].getKind()==PLUS || d_vars[index].getKind()==MULT ){
-        Kind k = d_vars[index].getKind();
-        std::vector< TNode > children;
-        for( unsigned j=0; j<d_vars[index].getNumChildren(); j++ ){
-          int vn = getVarNum( d_vars[index][j] );
-          if( vn!=-1 ){
-            TNode vv = getCurrentValue( d_vars[index][j] );
-            if( vv==d_vars[index][j] ){
-              //we will assign this
-              if( slv_v==-1 ){
-                Trace("qcf-tconstraint-debug") << "...will solve for var #" << vn << std::endl;
-                slv_v = vn;
-                if( p->d_effort!=QuantConflictFind::effort_conflict ){
-                  break;
-                }
-              }else{
-                Node z = p->getZero( k );
-                if( !z.isNull() ){
-                  Trace("qcf-tconstraint-debug") << "...set " << d_vars[vn] << " = " << z << std::endl;
-                  assigned.push_back( vn );
-                  if( !setMatch( p, vn, z ) ){
-                    success = false;
-                    break;
-                  }
-                }
-              }
-            }else{
-              Trace("qcf-tconstraint-debug") << "...sum value " << vv << std::endl;
-              children.push_back( vv );
-            }
-          }else{
-            Trace("qcf-tconstraint-debug") << "...sum " << d_vars[index][j] << std::endl;
-            children.push_back( d_vars[index][j] );
-          }
-        }
-        if( success ){
-          if( slv_v!=-1 ){
-            Node lhs;
-            if( children.empty() ){
-              lhs = p->getZero( k );
-            }else if( children.size()==1 ){
-              lhs = children[0];
-            }else{
-              lhs = NodeManager::currentNM()->mkNode( k, children );
-            }
-            Node sum;
-            if( v==d_vars[index] ){
-              sum = lhs;
-            }else{
-              if( p->d_effort==QuantConflictFind::effort_conflict ){
-                Kind kn = k;
-                if( d_vars[index].getKind()==PLUS ){
-                  kn = MINUS;
-                }
-                if( kn!=k ){
-                  sum = NodeManager::currentNM()->mkNode( kn, v, lhs );
-                }
-              }
-            }
-            if( !sum.isNull() ){
-              assigned.push_back( slv_v );
-              Trace("qcf-tconstraint-debug") << "...set " << d_vars[slv_v] << " = " << sum << std::endl;
-              if( !setMatch( p, slv_v, sum ) ){
-                success = false;
-              }
-              p->d_tempCache.push_back( sum );
-            }
-          }else{
-            //must show that constraint is met
-            Node sum = NodeManager::currentNM()->mkNode( k, children );
-            Node eq = sum.eqNode( v );
-            if( !entailmentTest( p, eq ) ){
-              success = false;
-            }
-            p->d_tempCache.push_back( sum );
-          }
-        }
-      }
-
-      if( !success ){
-        break;
-      }
-    }
-    if( success ){
-      //check what is left to assign
-      d_unassigned.clear();
-      d_unassigned_tn.clear();
-      std::vector< int > unassigned[2];
-      std::vector< TypeNode > unassigned_tn[2];
-      for( int i=0; i<getNumVars(); i++ ){
-        if( d_match[i].isNull() ){
-          int rindex = d_var_mg.find( i )==d_var_mg.end() ? 1 : 0;
-          unassigned[rindex].push_back( i );
-          unassigned_tn[rindex].push_back( getVar( i ).getType() );
-          assigned.push_back( i );
-        }
-      }
-      d_unassigned_nvar = unassigned[0].size();
-      for( unsigned i=0; i<2; i++ ){
-        d_unassigned.insert( d_unassigned.end(), unassigned[i].begin(), unassigned[i].end() );
-        d_unassigned_tn.insert( d_unassigned_tn.end(), unassigned_tn[i].begin(), unassigned_tn[i].end() );
-      }
-      d_una_eqc_count.clear();
-      d_una_index = 0;
-    }
-  }
-
-  if( !d_unassigned.empty() && ( success || doContinue ) ){
-    Trace("qcf-check") << "Assign to unassigned..." << std::endl;
-    do {
-      if( doFail ){
-        Trace("qcf-check-unassign") << "Failure, try again..." << std::endl;
-      }
-      bool invalidMatch = false;
-      while( ( d_una_index>=0 && (int)d_una_index<(int)d_unassigned.size() ) || invalidMatch || doFail ){
-        invalidMatch = false;
-        if( !doFail && d_una_index==(int)d_una_eqc_count.size() ){
-          //check if it has now been assigned
-          if( d_una_index<d_unassigned_nvar ){
-            if( !isConstrainedVar( d_unassigned[d_una_index] ) ){
-              d_una_eqc_count.push_back( -1 );
-            }else{
-              d_var_mg[ d_unassigned[d_una_index] ]->reset( p, true, this );
-              d_una_eqc_count.push_back( 0 );
-            }
-          }else{
-            d_una_eqc_count.push_back( 0 );
-          }
-        }else{
-          bool failed = false;
-          if( !doFail ){
-            if( d_una_index<d_unassigned_nvar ){
-              if( !isConstrainedVar( d_unassigned[d_una_index] ) ){
-                Trace("qcf-check-unassign") << "Succeeded, variable unconstrained at " << d_una_index << std::endl;
-                d_una_index++;
-              }else if( d_var_mg[d_unassigned[d_una_index]]->getNextMatch( p, this ) ){
-                Trace("qcf-check-unassign") << "Succeeded match with mg at " << d_una_index << std::endl;
-                d_una_index++;
-              }else{
-                failed = true;
-                Trace("qcf-check-unassign") << "Failed match with mg at " << d_una_index << std::endl;
-              }
-            }else{
-              Assert( doFail || d_una_index==(int)d_una_eqc_count.size()-1 );
-              if( d_una_eqc_count[d_una_index]<(int)p->d_eqcs[d_unassigned_tn[d_una_index]].size() ){
-                int currIndex = d_una_eqc_count[d_una_index];
-                d_una_eqc_count[d_una_index]++;
-                Trace("qcf-check-unassign") << d_unassigned[d_una_index] << "->" << p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex] << std::endl;
-                if( setMatch( p, d_unassigned[d_una_index], p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex] ) ){
-                  d_match_term[d_unassigned[d_una_index]] = TNode::null();
-                  Trace("qcf-check-unassign") << "Succeeded match " << d_una_index << std::endl;
-                  d_una_index++;
-                }else{
-                  Trace("qcf-check-unassign") << "Failed match " << d_una_index << std::endl;
-                  invalidMatch = true;
-                }
-              }else{
-                failed = true;
-                Trace("qcf-check-unassign") << "No more matches " << d_una_index << std::endl;
-              }
-            }
-          }
-          if( doFail || failed ){
-            do{
-              if( !doFail ){
-                d_una_eqc_count.pop_back();
-              }else{
-                doFail = false;
-              }
-              d_una_index--;
-            }while( d_una_index>=0 && d_una_eqc_count[d_una_index]==-1 );
-          }
-        }
-      }
-      success = d_una_index>=0;
-      if( success ){
-        doFail = true;
-        Trace("qcf-check-unassign") << "  Try: " << std::endl;
-        for( unsigned i=0; i<d_unassigned.size(); i++ ){
-          int ui = d_unassigned[i];
-          if( !d_match[ui].isNull() ){
-            Trace("qcf-check-unassign") << "  Assigned #" << ui << " : " << d_vars[ui] << " -> " << d_match[ui] << std::endl;
-          }
-        }
-      }
-    }while( success && isMatchSpurious( p ) );
-  }
-  if( success ){
-    for( unsigned i=0; i<d_unassigned.size(); i++ ){
-      int ui = d_unassigned[i];
-      if( !d_match[ui].isNull() ){
-        Trace("qcf-check") << "  Assigned #" << ui << " : " << d_vars[ui] << " -> " << d_match[ui] << std::endl;
-      }
-    }
-    return true;
-  }else{
-    for( unsigned i=0; i<assigned.size(); i++ ){
-      d_match[ assigned[i] ] = TNode::null();
-    }
-    assigned.clear();
-    return false;
-  }
-}
-
-void QuantInfo::getMatch( std::vector< Node >& terms ){
-  for( unsigned i=0; i<d_q[0].getNumChildren(); i++ ){
-    //Node cv = qi->getCurrentValue( qi->d_match[i] );
-    int repVar = getCurrentRepVar( i );
-    Node cv;
-    //std::map< int, TNode >::iterator itmt = qi->d_match_term.find( repVar );
-    if( !d_match_term[repVar].isNull() ){
-      cv = d_match_term[repVar];
-    }else{
-      cv = d_match[repVar];
-    }
-    Debug("qcf-check-inst") << "INST : " << i << " -> " << cv << ", from " << d_match[i] << std::endl;
-    terms.push_back( cv );
-  }
-}
-
-void QuantInfo::revertMatch( std::vector< int >& assigned ) {
-  for( unsigned i=0; i<assigned.size(); i++ ){
-    d_match[ assigned[i] ] = TNode::null();
-  }
-}
-
-void QuantInfo::debugPrintMatch( const char * c ) {
-  for( int i=0; i<getNumVars(); i++ ){
-    Trace(c) << "  " << d_vars[i] << " -> ";
-    if( !d_match[i].isNull() ){
-      Trace(c) << d_match[i];
-    }else{
-      Trace(c) << "(unassigned) ";
-    }
-    if( !d_curr_var_deq[i].empty() ){
-      Trace(c) << ", DEQ{ ";
-      for( std::map< TNode, int >::iterator it = d_curr_var_deq[i].begin(); it != d_curr_var_deq[i].end(); ++it ){
-        Trace(c) << it->first << " ";
-      }
-      Trace(c) << "}";
-    }
-    if( !d_match_term[i].isNull() && d_match_term[i]!=d_match[i] ){
-      Trace(c) << ", EXP : " << d_match_term[i];
-    }
-    Trace(c) <<  std::endl;
-  }
-  if( !d_tconstraints.empty() ){
-    Trace(c) << "ADDITIONAL CONSTRAINTS : " << std::endl;
-    for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){
-      Trace(c) << "   " << it->first << " -> " << it->second << std::endl;
-    }
-  }
-}
-
-MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar ){
-  Trace("qcf-qregister-debug") << "Make match gen for " << n << ", isVar = " << isVar << std::endl;
-  std::vector< Node > qni_apps;
-  d_qni_size = 0;
-  if( isVar ){
-    Assert( qi->d_var_num.find( n )!=qi->d_var_num.end() );
-    if( n.getKind()==ITE ){
-      d_type = typ_ite_var;
-      d_type_not = false;
-      d_n = n;
-      d_children.push_back( MatchGen( qi, d_n[0] ) );
-      if( d_children[0].isValid() ){
-        d_type = typ_ite_var;
-        for( unsigned i=1; i<=2; i++ ){
-          Node nn = n.eqNode( n[i] );
-          d_children.push_back( MatchGen( qi, nn ) );
-          d_children[d_children.size()-1].d_qni_bound_except.push_back( 0 );
-          if( !d_children[d_children.size()-1].isValid() ){
-            setInvalid();
-            break;
-          }
-        }
-      }else{
-        d_type = typ_invalid;
-      }
-    }else{
-      d_type = isHandledUfTerm( n ) ? typ_var : typ_tsym;
-      d_qni_var_num[0] = qi->getVarNum( n );
-      d_qni_size++;
-      d_type_not = false;
-      d_n = n;
-      //Node f = getOperator( n );
-      for( unsigned j=0; j<d_n.getNumChildren(); j++ ){
-        Node nn = d_n[j];
-        Trace("qcf-qregister-debug") << "  " << d_qni_size;
-        if( qi->isVar( nn ) ){
-          int v = qi->d_var_num[nn];
-          Trace("qcf-qregister-debug") << " is var #" << v << std::endl;
-          d_qni_var_num[d_qni_size] = v;
-          //qi->addFuncParent( v, f, j );
-        }else{
-          Trace("qcf-qregister-debug") << " is gterm " << nn << std::endl;
-          d_qni_gterm[d_qni_size] = nn;
-        }
-        d_qni_size++;
-      }
-    }
-  }else{
-    if( n.hasBoundVar() ){
-      d_type_not = false;
-      d_n = n;
-      if( d_n.getKind()==NOT ){
-        d_n = d_n[0];
-        d_type_not = !d_type_not;
-      }
-
-      if( isHandledBoolConnective( d_n ) ){
-        //non-literals
-        d_type = typ_formula;
-        for( unsigned i=0; i<d_n.getNumChildren(); i++ ){
-          if( d_n.getKind()!=FORALL || i==1 ){
-            d_children.push_back( MatchGen( qi, d_n[i], false ) );
-            if( !d_children[d_children.size()-1].isValid() ){
-              setInvalid();
-              break;
-            }
-          }
-          /*
-          else if( isTop && n.getKind()==OR && d_children[d_children.size()-1].d_type==typ_var_eq ){
-            Trace("qcf-qregister-debug") << "Remove child, make built-in constraint" << std::endl;
-            //if variable equality/disequality at top level, remove immediately
-            bool cIsNot = d_children[d_children.size()-1].d_type_not;
-            Node cn = d_children[d_children.size()-1].d_n;
-            Assert( cn.getKind()==EQUAL );
-            Assert( p->d_qinfo[q].isVar( cn[0] ) || p->d_qinfo[q].isVar( cn[1] ) );
-            //make it a built-in constraint instead
-            for( unsigned i=0; i<2; i++ ){
-              if( p->d_qinfo[q].isVar( cn[i] ) ){
-                int v = p->d_qinfo[q].getVarNum( cn[i] );
-                Node cno = cn[i==0 ? 1 : 0];
-                p->d_qinfo[q].d_var_constraint[ cIsNot ? 0 : 1 ][v].push_back( cno );
-                break;
-              }
-            }
-            d_children.pop_back();
-          }
-          */
-        }
-      }else{
-        d_type = typ_invalid;
-        //literals
-        if( isHandledUfTerm( d_n ) ){
-          Assert( qi->isVar( d_n ) );
-          d_type = typ_pred;
-        }else if( d_n.getKind()==BOUND_VARIABLE ){
-          Assert( d_n.getType().isBoolean() );
-          d_type = typ_bool_var;
-        }else if( d_n.getKind()==EQUAL || options::qcfTConstraint() ){
-          for( unsigned i=0; i<d_n.getNumChildren(); i++ ){
-            if( d_n[i].hasBoundVar() ){
-              if( !qi->isVar( d_n[i] ) ){
-                Trace("qcf-qregister-debug")  << "ERROR : not var " << d_n[i] << std::endl;
-              }
-              Assert( qi->isVar( d_n[i] ) );
-              if( d_n.getKind()!=EQUAL && qi->isVar( d_n[i] ) ){
-                d_qni_var_num[i+1] = qi->d_var_num[d_n[i]];
-              }
-            }else{
-              d_qni_gterm[i] = d_n[i];
-            }
-          }
-          d_type = d_n.getKind()==EQUAL ? typ_eq : typ_tconstraint;
-          Trace("qcf-tconstraint") << "T-Constraint : " << d_n << std::endl;
-        }
-      }
-    }else{
-      //we will just evaluate
-      d_n = n;
-      d_type = typ_ground;
-    }
-    //if( d_type!=typ_invalid ){
-      //determine an efficient children ordering
-      //if( !d_children.empty() ){
-        //for( unsigned i=0; i<d_children.size(); i++ ){
-        //  d_children_order.push_back( i );
-        //}
-        //if( !d_n.isNull() && ( d_n.getKind()==OR || d_n.getKind()==AND || d_n.getKind()==IFF ) ){
-          //sort based on the type of the constraint : ground comes first, then literals, then others
-          //MatchGenSort mgs;
-          //mgs.d_mg = this;
-          //std::sort( d_children_order.begin(), d_children_order.end(), mgs );
-        //}
-      //}
-    //}
-  }
-  Trace("qcf-qregister-debug")  << "Done make match gen " << n << ", type = ";
-  debugPrintType( "qcf-qregister-debug", d_type, true );
-  Trace("qcf-qregister-debug") << std::endl;
-  //Assert( d_children.size()==d_children_order.size() );
-
-}
-
-void MatchGen::collectBoundVar( QuantInfo * qi, Node n, std::vector< int >& cbvars ) {
-  int v = qi->getVarNum( n );
-  if( v!=-1 && std::find( cbvars.begin(), cbvars.end(), v )==cbvars.end() ){
-    cbvars.push_back( v );
-  }
-  for( unsigned i=0; i<n.getNumChildren(); i++ ){
-    collectBoundVar( qi, n[i], cbvars );
-  }
-}
-
-void MatchGen::determineVariableOrder( QuantInfo * qi, std::vector< int >& bvars ) {
-  Trace("qcf-qregister-debug") << "Determine variable order " << d_n << std::endl;
-  bool isCom = d_type==typ_formula && ( d_n.getKind()==OR || d_n.getKind()==AND || d_n.getKind()==IFF );
-  std::map< int, std::vector< int > > c_to_vars;
-  std::map< int, std::vector< int > > vars_to_c;
-  std::map< int, int > vb_count;
-  std::map< int, int > vu_count;
-  std::vector< bool > assigned;
-  Trace("qcf-qregister-debug") << "Calculate bound variables..." << std::endl;
-  for( unsigned i=0; i<d_children.size(); i++ ){
-    collectBoundVar( qi, d_children[i].d_n, c_to_vars[i] );
-    assigned.push_back( false );
-    vb_count[i] = 0;
-    vu_count[i] = 0;
-    for( unsigned j=0; j<c_to_vars[i].size(); j++ ){
-      int v = c_to_vars[i][j];
-      vars_to_c[v].push_back( i );
-      if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){
-        vu_count[i]++;
-        if( !isCom ){
-          bvars.push_back( v );
-        }
-      }else{
-        vb_count[i]++;
-      }
-    }
-  }
-  if( isCom ){
-    //children that bind the least number of unbound variables go first
-    do {
-      int min_score = -1;
-      int min_score_index = -1;
-      for( unsigned i=0; i<d_children.size(); i++ ){
-        if( !assigned[i] ){
-          int score = vu_count[i];
-          if( min_score==-1 || score<min_score ){
-            min_score = score;
-            min_score_index = i;
-          }
-        }
-      }
-      Trace("qcf-qregister-debug") << "...assign child " << min_score_index << "/" << d_children.size() << std::endl;
-      Assert( min_score_index!=-1 );
-      //add to children order
-      d_children_order.push_back( min_score_index );
-      assigned[min_score_index] = true;
-      //if( vb_count[min_score_index]==0 ){
-      //  d_independent.push_back( min_score_index );
-      //}
-      //determine order internal to children
-      d_children[min_score_index].determineVariableOrder( qi, bvars );
-      Trace("qcf-qregister-debug")  << "...bind variables" << std::endl;
-      //now, make it a bound variable
-      for( unsigned i=0; i<c_to_vars[min_score_index].size(); i++ ){
-        int v = c_to_vars[min_score_index][i];
-        if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){
-          for( unsigned j=0; j<vars_to_c[v].size(); j++ ){
-            int vc = vars_to_c[v][j];
-            vu_count[vc]--;
-            vb_count[vc]++;
-          }
-          bvars.push_back( v );
-        }
-      }
-      Trace("qcf-qregister-debug") << "...done assign child " << min_score_index << std::endl;
-    }while( d_children_order.size()!=d_children.size() );
-    Trace("qcf-qregister-debug") << "Done assign variable ordering for " << d_n << std::endl;
-  }else{
-    for( unsigned i=0; i<d_children.size(); i++ ){
-      d_children_order.push_back( i );
-      d_children[i].determineVariableOrder( qi, bvars );
-    }
-  }
-}
-
-
-void MatchGen::reset_round( QuantConflictFind * p ) {
-  d_wasSet = false;
-  for( unsigned i=0; i<d_children.size(); i++ ){
-    d_children[i].reset_round( p );
-  }
-  for( std::map< int, TNode >::iterator it = d_qni_gterm.begin(); it != d_qni_gterm.end(); ++it ){
-    d_qni_gterm_rep[it->first] = p->getRepresentative( it->second );
-  }
-  if( d_type==typ_ground ){
-    int e = p->evaluate( d_n );
-    if( e==1 ){
-      d_ground_eval[0] = p->d_true;
-    }else if( e==-1 ){
-      d_ground_eval[0] = p->d_false;
-    }
-  }else if( d_type==typ_eq ){
-    for( unsigned i=0; i<d_n.getNumChildren(); i++ ){
-      if( !d_n[i].hasBoundVar() ){
-        d_ground_eval[i] = p->evaluateTerm( d_n[i] );
-      }
-    }
-  }
-  d_qni_bound_cons.clear();
-  d_qni_bound_cons_var.clear();
-  d_qni_bound.clear();
-}
-
-void MatchGen::reset( QuantConflictFind * p, bool tgt, QuantInfo * qi ) {
-  d_tgt = d_type_not ? !tgt : tgt;
-  Debug("qcf-match") << "     Reset for : " << d_n << ", type : ";
-  debugPrintType( "qcf-match", d_type );
-  Debug("qcf-match") << ", tgt = " << d_tgt << ", children = " << d_children.size() << " " << d_children_order.size() << std::endl;
-  d_qn.clear();
-  d_qni.clear();
-  d_qni_bound.clear();
-  d_child_counter = -1;
-  d_tgt_orig = d_tgt;
-
-  //set up processing matches
-  if( d_type==typ_invalid ){
-    //do nothing
-  }else if( d_type==typ_ground ){
-    if( d_ground_eval[0]==( d_tgt ? p->d_true : p->d_false ) ){
-      d_child_counter = 0;
-    }
-  }else if( d_type==typ_bool_var ){
-    //get current value of the variable
-    TNode n = qi->getCurrentValue( d_n );
-    int vn = qi->getCurrentRepVar( qi->getVarNum( n ) );
-    if( vn==-1 ){
-      //evaluate the value, see if it is compatible
-      int e = p->evaluate( n );
-      if( ( e==1 && d_tgt ) || ( e==0 && !d_tgt ) ){
-        d_child_counter = 0;
-      }
-    }else{
-      //unassigned, set match to true/false
-      d_qni_bound[0] = vn;
-      qi->setMatch( p, vn, d_tgt ? p->d_true : p->d_false );
-      d_child_counter = 0;
-    }
-    if( d_child_counter==0 ){
-      d_qn.push_back( NULL );
-    }
-  }else if( d_type==typ_var ){
-    Assert( isHandledUfTerm( d_n ) );
-    Node f = getOperator( p, d_n );
-    Debug("qcf-match-debug") << "       reset: Var will match operators of " << f << std::endl;
-    QcfNodeIndex * qni = p->getQcfNodeIndex( Node::null(), f );
-    if( qni!=NULL ){
-      d_qn.push_back( qni );
-    }
-    d_matched_basis = false;
-  }else if( d_type==typ_tsym || d_type==typ_tconstraint ){
-    for( std::map< int, int >::iterator it = d_qni_var_num.begin(); it != d_qni_var_num.end(); ++it ){
-      int repVar = qi->getCurrentRepVar( it->second );
-      if( qi->d_match[repVar].isNull() ){
-        Debug("qcf-match-debug") << "Force matching on child #" << it->first << ", which is var #" << repVar << std::endl;
-        d_qni_bound[it->first] = repVar;
-      }
-    }
-    d_qn.push_back( NULL );
-  }else if( d_type==typ_pred || d_type==typ_eq ){
-    //add initial constraint
-    Node nn[2];
-    int vn[2];
-    if( d_type==typ_pred ){
-      nn[0] = qi->getCurrentValue( d_n );
-      vn[0] = qi->getCurrentRepVar( qi->getVarNum( nn[0] ) );
-      nn[1] = p->getRepresentative( d_tgt ? p->d_true : p->d_false );
-      vn[1] = -1;
-      d_tgt = true;
-    }else{
-      for( unsigned i=0; i<2; i++ ){
-        TNode nc;
-        std::map< int, TNode >::iterator it = d_qni_gterm_rep.find( i );
-        if( it!=d_qni_gterm_rep.end() ){
-          nc = it->second;
-        }else{
-          nc = d_n[i];
-        }
-        nn[i] = qi->getCurrentValue( nc );
-        vn[i] = qi->getCurrentRepVar( qi->getVarNum( nn[i] ) );
-      }
-    }
-    bool success;
-    if( vn[0]==-1 && vn[1]==-1 ){
-      //Trace("qcf-explain") << "    reset : " << d_n << " check ground values " << nn[0] << " " << nn[1] << " (tgt=" << d_tgt << ")" << std::endl;
-      Debug("qcf-match-debug") << "       reset: check ground values " << nn[0] << " " << nn[1] << " (" << d_tgt << ")" << std::endl;
-      //just compare values
-      if( d_tgt ){
-        success = p->areMatchEqual( nn[0], nn[1] );
-      }else{
-        if( p->d_effort==QuantConflictFind::effort_conflict ){
-          success = p->areDisequal( nn[0], nn[1] );
-        }else{
-          success = p->areMatchDisequal( nn[0], nn[1] );
-        }
-      }
-    }else{
-      //otherwise, add a constraint to a variable
-      if( vn[1]!=-1 && vn[0]==-1 ){
-        //swap
-        Node t = nn[1];
-        nn[1] = nn[0];
-        nn[0] = t;
-        vn[0] = vn[1];
-        vn[1] = -1;
-      }
-      Debug("qcf-match-debug") << "       reset: add constraint " << vn[0] << " -> " << nn[1] << " (vn=" << vn[1] << ")" << std::endl;
-      //add some constraint
-      int addc = qi->addConstraint( p, vn[0], nn[1], vn[1], d_tgt, false );
-      success = addc!=-1;
-      //if successful and non-redundant, store that we need to cleanup this
-      if( addc==1 ){
-        //Trace("qcf-explain") << "       reset: " << d_n << " add constraint " << vn[0] << " -> " << nn[1] << " (vn=" << vn[1] << ")" << ", d_tgt = " << d_tgt << std::endl;
-        for( unsigned i=0; i<2; i++ ){
-          if( vn[i]!=-1 && std::find( d_qni_bound_except.begin(), d_qni_bound_except.end(), i )==d_qni_bound_except.end() ){
-            d_qni_bound[vn[i]] = vn[i];
-          }
-        }
-        d_qni_bound_cons[vn[0]] = nn[1];
-        d_qni_bound_cons_var[vn[0]] = vn[1];
-      }
-    }
-    //if successful, we will bind values to variables
-    if( success ){
-      d_qn.push_back( NULL );
-    }
-  }else{
-    if( d_children.empty() ){
-      //add dummy
-      d_qn.push_back( NULL );
-    }else{
-      if( d_tgt && d_n.getKind()==FORALL ){
-        //do nothing
-      }else{
-        //reset the first child to d_tgt
-        d_child_counter = 0;
-        getChild( d_child_counter )->reset( p, d_tgt, qi );
-      }
-    }
-  }
-  d_binding = false;
-  d_wasSet = true;
-  Debug("qcf-match") << "     reset: Finished reset for " << d_n << ", success = " << ( !d_qn.empty() || d_child_counter!=-1 ) << std::endl;
-}
-
-bool MatchGen::getNextMatch( QuantConflictFind * p, QuantInfo * qi ) {
-  Debug("qcf-match") << "     Get next match for : " << d_n << ", type = ";
-  debugPrintType( "qcf-match", d_type );
-  Debug("qcf-match") << ", children = " << d_children.size() << ", binding = " << d_binding << std::endl;
-  if( d_type==typ_invalid || d_type==typ_ground ){
-    if( d_child_counter==0 ){
-      d_child_counter = -1;
-      return true;
-    }else{
-      d_wasSet = false;
-      return false;
-    }
-  }else if( d_type==typ_var || d_type==typ_eq || d_type==typ_pred || d_type==typ_bool_var || d_type==typ_tconstraint || d_type==typ_tsym ){
-    bool success = false;
-    bool terminate = false;
-    do {
-      bool doReset = false;
-      bool doFail = false;
-      if( !d_binding ){
-        if( doMatching( p, qi ) ){
-          Debug("qcf-match-debug") << "     - Matching succeeded" << std::endl;
-          d_binding = true;
-          d_binding_it = d_qni_bound.begin();
-          doReset = true;
-          //for tconstraint, add constraint
-          if( d_type==typ_tconstraint ){
-            std::map< Node, bool >::iterator it = qi->d_tconstraints.find( d_n );
-            if( it==qi->d_tconstraints.end() ){
-              qi->d_tconstraints[d_n] = d_tgt;
-              //store that we added this constraint
-              d_qni_bound_cons[0] = d_n;
-            }else if( d_tgt!=it->second ){
-              success = false;
-              terminate = true;
-            }
-          }
-        }else{
-          Debug("qcf-match-debug") << "     - Matching failed" << std::endl;
-          success = false;
-          terminate = true;
-        }
-      }else{
-        doFail = true;
-      }
-      if( d_binding ){
-        //also need to create match for each variable we bound
-        success = true;
-        Debug("qcf-match-debug") << "     Produce matches for bound variables by " << d_n << ", type = ";
-        debugPrintType( "qcf-match-debug", d_type );
-        Debug("qcf-match-debug") << "..." << std::endl;
-
-        while( ( success && d_binding_it!=d_qni_bound.end() ) || doFail ){
-          std::map< int, MatchGen * >::iterator itm;
-          if( !doFail ){
-            Debug("qcf-match-debug") << "       check variable " << d_binding_it->second << std::endl;
-            itm = qi->d_var_mg.find( d_binding_it->second );
-          }
-          if( doFail || ( d_binding_it->first!=0 && itm!=qi->d_var_mg.end() ) ){
-            Debug("qcf-match-debug") << "       we had bound variable " << d_binding_it->second << ", reset = " << doReset << std::endl;
-            if( doReset ){
-              itm->second->reset( p, true, qi );
-            }
-            if( doFail || !itm->second->getNextMatch( p, qi ) ){
-              do {
-                if( d_binding_it==d_qni_bound.begin() ){
-                  Debug("qcf-match-debug") << "       failed." << std::endl;
-                  success = false;
-                }else{
-                  --d_binding_it;
-                  Debug("qcf-match-debug") << "       decrement..." << std::endl;
-                }
-              }while( success && ( d_binding_it->first==0 || qi->d_var_mg.find( d_binding_it->second )==qi->d_var_mg.end() ) );
-              doReset = false;
-              doFail = false;
-            }else{
-              Debug("qcf-match-debug") << "       increment..." << std::endl;
-              ++d_binding_it;
-              doReset = true;
-            }
-          }else{
-            Debug("qcf-match-debug") << "       skip..." << d_binding_it->second << std::endl;
-            ++d_binding_it;
-            doReset = true;
-          }
-        }
-        if( !success ){
-          d_binding = false;
-        }else{
-          terminate = true;
-          if( d_binding_it==d_qni_bound.begin() ){
-            d_binding = false;
-          }
-        }
-      }
-    }while( !terminate );
-    //if not successful, clean up the variables you bound
-    if( !success ){
-      if( d_type==typ_eq || d_type==typ_pred ){
-        //clean up the constraints you added
-        for( std::map< int, TNode >::iterator it = d_qni_bound_cons.begin(); it != d_qni_bound_cons.end(); ++it ){
-          if( !it->second.isNull() ){
-            Debug("qcf-match") << "       Clean up bound var " << it->first << (d_tgt ? "!" : "") << " = " << it->second << std::endl;
-            std::map< int, int >::iterator itb = d_qni_bound_cons_var.find( it->first );
-            int vn = itb!=d_qni_bound_cons_var.end() ? itb->second : -1;
-            //Trace("qcf-explain") << "       cleanup: " << d_n << " remove constraint " << it->first << " -> " << it->second << " (vn=" << vn << ")" << ", d_tgt = " << d_tgt << std::endl;
-            qi->addConstraint( p, it->first, it->second, vn, d_tgt, true );
-          }
-        }
-        d_qni_bound_cons.clear();
-        d_qni_bound_cons_var.clear();
-        d_qni_bound.clear();
-      }else{
-        //clean up the matches you set
-        for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){
-          Debug("qcf-match") << "       Clean up bound var " << it->second << std::endl;
-          Assert( it->second<qi->getNumVars() );
-          qi->d_match[ it->second ] = TNode::null();
-          qi->d_match_term[ it->second ] = TNode::null();
-        }
-        d_qni_bound.clear();
-      }
-      if( d_type==typ_tconstraint ){
-        //remove constraint if applicable
-        if( d_qni_bound_cons.find( 0 )!=d_qni_bound_cons.end() ){
-          qi->d_tconstraints.erase( d_n );
-          d_qni_bound_cons.clear();
-        }
-      }
-      /*
-      if( d_type==typ_var && p->d_effort==QuantConflictFind::effort_mc && !d_matched_basis ){
-        d_matched_basis = true;
-        Node f = getOperator( d_n );
-        TNode mbo = p->getQuantifiersEngine()->getTermDatabase()->getModelBasisOpTerm( f );
-        if( qi->setMatch( p, d_qni_var_num[0], mbo ) ){
-          success = true;
-          d_qni_bound[0] = d_qni_var_num[0];
-        }
-      }
-      */
-    }
-    Debug("qcf-match") << "    ...finished matching for " << d_n << ", success = " << success << std::endl;
-    d_wasSet = success;
-    return success;
-  }else if( d_type==typ_formula || d_type==typ_ite_var ){
-    bool success = false;
-    if( d_child_counter<0 ){
-      if( d_child_counter<-1 ){
-        success = true;
-        d_child_counter = -1;
-      }
-    }else{
-      while( !success && d_child_counter>=0 ){
-        //transition system based on d_child_counter
-        if( d_n.getKind()==OR || d_n.getKind()==AND ){
-          if( (d_n.getKind()==AND)==d_tgt ){
-            //all children must match simultaneously
-            if( getChild( d_child_counter )->getNextMatch( p, qi ) ){
-              if( d_child_counter<(int)(getNumChildren()-1) ){
-                d_child_counter++;
-                Debug("qcf-match-debug") << "       Reset child " << d_child_counter << " of " << d_n << std::endl;
-                getChild( d_child_counter )->reset( p, d_tgt, qi );
-              }else{
-                success = true;
-              }
-            }else{
-              //if( std::find( d_independent.begin(), d_independent.end(), d_child_counter )!=d_independent.end() ){
-              //  d_child_counter--;
-              //}else{
-              d_child_counter--;
-              //}
-            }
-          }else{
-            //one child must match
-            if( !getChild( d_child_counter )->getNextMatch( p, qi ) ){
-              if( d_child_counter<(int)(getNumChildren()-1) ){
-                d_child_counter++;
-                Debug("qcf-match-debug") << "       Reset child " << d_child_counter << " of " << d_n << ", one match" << std::endl;
-                getChild( d_child_counter )->reset( p, d_tgt, qi );
-              }else{
-                d_child_counter = -1;
-              }
-            }else{
-              success = true;
-            }
-          }
-        }else if( d_n.getKind()==IFF ){
-          //construct match based on both children
-          if( d_child_counter%2==0 ){
-            if( getChild( 0 )->getNextMatch( p, qi ) ){
-              d_child_counter++;
-              getChild( 1 )->reset( p, d_child_counter==1, qi );
-            }else{
-              if( d_child_counter==0 ){
-                d_child_counter = 2;
-                getChild( 0 )->reset( p, !d_tgt, qi );
-              }else{
-                d_child_counter = -1;
-              }
-            }
-          }
-          if( d_child_counter>=0 && d_child_counter%2==1 ){
-            if( getChild( 1 )->getNextMatch( p, qi ) ){
-              success = true;
-            }else{
-              d_child_counter--;
-            }
-          }
-        }else if( d_n.getKind()==ITE ){
-          if( d_child_counter%2==0 ){
-            int index1 = d_child_counter==4 ? 1 : 0;
-            if( getChild( index1 )->getNextMatch( p, qi ) ){
-              d_child_counter++;
-              getChild( d_child_counter==5 ? 2 : (d_tgt==(d_child_counter==1) ? 1 : 2) )->reset( p, d_tgt, qi );
-            }else{
-              if( d_child_counter==4 || ( d_type==typ_ite_var && d_child_counter==2 ) ){
-                d_child_counter = -1;
-              }else{
-                d_child_counter +=2;
-                getChild( d_child_counter==2 ? 0 : 1 )->reset( p, d_child_counter==2 ? !d_tgt : d_tgt, qi );
-              }
-            }
-          }
-          if( d_child_counter>=0 && d_child_counter%2==1 ){
-            int index2 = d_child_counter==5 ? 2 : (d_tgt==(d_child_counter==1) ? 1 : 2);
-            if( getChild( index2 )->getNextMatch( p, qi ) ){
-              success = true;
-            }else{
-              d_child_counter--;
-            }
-          }
-        }else if( d_n.getKind()==FORALL ){
-          if( getChild( d_child_counter )->getNextMatch( p, qi ) ){
-            success = true;
-          }else{
-            d_child_counter = -1;
-          }
-        }
-      }
-        d_wasSet = success;
-      Debug("qcf-match") << "    ...finished construct match for " << d_n << ", success = " << success << std::endl;
-      return success;
-    }
-  }
-  Debug("qcf-match") << "    ...already finished for " << d_n << std::endl;
-  return false;
-}
-
-bool MatchGen::getExplanation( QuantConflictFind * p, QuantInfo * qi, std::vector< Node >& exp ) {
-  if( d_type==typ_eq ){
-    Node n[2];
-    for( unsigned i=0; i<2; i++ ){
-      Trace("qcf-explain") << "Explain term " << d_n[i] << "..." << std::endl;
-      n[i] = getExplanationTerm( p, qi, d_n[i], exp );
-    }
-    Node eq = n[0].eqNode( n[1] );
-    if( !d_tgt_orig ){
-      eq = eq.negate();
-    }
-    exp.push_back( eq );
-    Trace("qcf-explain") << "Explanation for " << d_n << " (tgt=" << d_tgt_orig << ") is " << eq << ", set = " << d_wasSet << std::endl;
-    return true;
-  }else if( d_type==typ_pred ){
-    Trace("qcf-explain") << "Explain term " << d_n << "..." << std::endl;
-    Node n = getExplanationTerm( p, qi, d_n, exp );
-    if( !d_tgt_orig ){
-      n = n.negate();
-    }
-    exp.push_back( n );
-    Trace("qcf-explain") << "Explanation for " << d_n << " (tgt=" << d_tgt_orig << ") is " << n << ", set = " << d_wasSet << std::endl;
-    return true;
-  }else if( d_type==typ_formula ){
-    Trace("qcf-explain") << "Explanation get for " << d_n << ", counter = " << d_child_counter << ", tgt = " << d_tgt_orig << ", set = " << d_wasSet << std::endl;
-    if( d_n.getKind()==OR || d_n.getKind()==AND ){
-      if( (d_n.getKind()==AND)==d_tgt ){
-        for( unsigned i=0; i<getNumChildren(); i++ ){
-          if( !getChild( i )->getExplanation( p, qi, exp ) ){
-            return false;
-          }
-        }
-      }else{
-        return getChild( d_child_counter )->getExplanation( p, qi, exp );
-      }
-    }else if( d_n.getKind()==IFF ){
-      for( unsigned i=0; i<2; i++ ){
-        if( !getChild( i )->getExplanation( p, qi, exp ) ){
-          return false;
-        }
-      }
-    }else if( d_n.getKind()==ITE ){
-      for( unsigned i=0; i<3; i++ ){
-        bool isActive = ( ( i==0 && d_child_counter!=5 ) ||
-                          ( i==1 && d_child_counter!=( d_tgt ? 3 : 1 ) ) ||
-                          ( i==2 && d_child_counter!=( d_tgt ? 1 : 3 ) ) );
-        if( isActive ){
-          if( !getChild( i )->getExplanation( p, qi, exp ) ){
-            return false;
-          }
-        }
-      }
-    }else{
-      return false;
-    }
-    return true;
-  }else{
-    return false;
-  }
-}
-
-Node MatchGen::getExplanationTerm( QuantConflictFind * p, QuantInfo * qi, Node t, std::vector< Node >& exp ) {
-  Node v = qi->getCurrentExpValue( t );
-  if( isHandledUfTerm( t ) ){
-    for( unsigned i=0; i<t.getNumChildren(); i++ ){
-      Node vi = getExplanationTerm( p, qi, t[i], exp );
-      if( vi!=v[i] ){
-        Node eq = vi.eqNode( v[i] );
-        if( std::find( exp.begin(), exp.end(), eq )==exp.end() ){
-          Trace("qcf-explain") << "  add : " << eq << "." << std::endl;
-          exp.push_back( eq );
-        }
-      }
-    }
-  }
-  return v;
-}
-
-bool MatchGen::doMatching( QuantConflictFind * p, QuantInfo * qi ) {
-  if( !d_qn.empty() ){
-    if( d_qn[0]==NULL ){
-      d_qn.clear();
-      return true;
-    }else{
-      Assert( d_type==typ_var );
-      Assert( d_qni_size>0 );
-      bool invalidMatch;
-      do {
-        invalidMatch = false;
-        Debug("qcf-match-debug") << "       Do matching " << d_n << " " << d_qn.size() << " " << d_qni.size() << std::endl;
-        if( d_qn.size()==d_qni.size()+1 ) {
-          int index = (int)d_qni.size();
-          //initialize
-          TNode val;
-          std::map< int, int >::iterator itv = d_qni_var_num.find( index );
-          if( itv!=d_qni_var_num.end() ){
-            //get the representative variable this variable is equal to
-            int repVar = qi->getCurrentRepVar( itv->second );
-            Debug("qcf-match-debug") << "       Match " << index << " is a variable " << itv->second << ", which is repVar " << repVar << std::endl;
-            //get the value the rep variable
-            //std::map< int, TNode >::iterator itm = qi->d_match.find( repVar );
-            if( !qi->d_match[repVar].isNull() ){
-              val = qi->d_match[repVar];
-              Debug("qcf-match-debug") << "       Variable is already bound to " << val << std::endl;
-            }else{
-              //binding a variable
-              d_qni_bound[index] = repVar;
-              std::map< TNode, QcfNodeIndex >::iterator it = d_qn[index]->d_children.begin();
-              if( it != d_qn[index]->d_children.end() ) {
-                d_qni.push_back( it );
-                //set the match
-                if( qi->setMatch( p, d_qni_bound[index], it->first ) ){
-                  Debug("qcf-match-debug") << "       Binding variable" << std::endl;
-                  if( d_qn.size()<d_qni_size ){
-                    d_qn.push_back( &it->second );
-                  }
-                }else{
-                  Debug("qcf-match") << "       Binding variable, currently fail." << std::endl;
-                  invalidMatch = true;
-                }
-              }else{
-                Debug("qcf-match-debug") << "       Binding variable, fail, no more variables to bind" << std::endl;
-                d_qn.pop_back();
-              }
-            }
-          }else{
-            Debug("qcf-match-debug") << "       Match " << index << " is ground term" << std::endl;
-            Assert( d_qni_gterm.find( index )!=d_qni_gterm.end() );
-            Assert( d_qni_gterm_rep.find( index )!=d_qni_gterm_rep.end() );
-            val = d_qni_gterm_rep[index];
-            Assert( !val.isNull() );
-          }
-          if( !val.isNull() ){
-            //constrained by val
-            std::map< TNode, QcfNodeIndex >::iterator it = d_qn[index]->d_children.find( val );
-            if( it!=d_qn[index]->d_children.end() ){
-              Debug("qcf-match-debug") << "       Match" << std::endl;
-              d_qni.push_back( it );
-              if( d_qn.size()<d_qni_size ){
-                d_qn.push_back( &it->second );
-              }
-            }else{
-              Debug("qcf-match-debug") << "       Failed to match" << std::endl;
-              d_qn.pop_back();
-            }
-          }
-        }else{
-          Assert( d_qn.size()==d_qni.size() );
-          int index = d_qni.size()-1;
-          //increment if binding this variable
-          bool success = false;
-          std::map< int, int >::iterator itb = d_qni_bound.find( index );
-          if( itb!=d_qni_bound.end() ){
-            d_qni[index]++;
-            if( d_qni[index]!=d_qn[index]->d_children.end() ){
-              success = true;
-              if( qi->setMatch( p, itb->second, d_qni[index]->first ) ){
-                Debug("qcf-match-debug") << "       Bind next variable" << std::endl;
-                if( d_qn.size()<d_qni_size ){
-                  d_qn.push_back( &d_qni[index]->second );
-                }
-              }else{
-                Debug("qcf-match-debug") << "       Bind next variable, currently fail" << std::endl;
-                invalidMatch = true;
-              }
-            }else{
-              qi->d_match[ itb->second ] = TNode::null();
-              qi->d_match_term[ itb->second ] = TNode::null();
-              Debug("qcf-match-debug") << "       Bind next variable, no more variables to bind" << std::endl;
-            }
-          }else{
-            //TODO : if it equal to something else, also try that
-          }
-          //if not incrementing, move to next
-          if( !success ){
-            d_qn.pop_back();
-            d_qni.pop_back();
-          }
-        }
-      }while( ( !d_qn.empty() && d_qni.size()!=d_qni_size ) || invalidMatch );
-      if( d_qni.size()==d_qni_size ){
-        //Assert( !d_qni[d_qni.size()-1]->second.d_children.empty() );
-        //Debug("qcf-match-debug") << "       We matched " << d_qni[d_qni.size()-1]->second.d_children.begin()->first << std::endl;
-        Assert( !d_qni[d_qni.size()-1]->second.d_children.empty() );
-        TNode t = d_qni[d_qni.size()-1]->second.d_children.begin()->first;
-        Debug("qcf-match-debug") << "       " << d_n << " matched " << t << std::endl;
-        qi->d_match_term[d_qni_var_num[0]] = t;
-        //set the match terms
-        for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){
-          Debug("qcf-match-debug") << "       position " << it->first << " bounded " << it->second << " / " << qi->d_q[0].getNumChildren() << std::endl;
-          //if( it->second<(int)qi->d_q[0].getNumChildren() ){   //if it is an actual variable, we are interested in knowing the actual term
-          if( it->first>0 ){
-            Assert( !qi->d_match[ it->second ].isNull() );
-            Assert( p->areEqual( t[it->first-1], qi->d_match[ it->second ] ) );
-            qi->d_match_term[it->second] = t[it->first-1];
-          }
-          //}
-        }
-      }
-    }
-  }
-  return !d_qn.empty();
-}
-
-void MatchGen::debugPrintType( const char * c, short typ, bool isTrace ) {
-  if( isTrace ){
-    switch( typ ){
-    case typ_invalid: Trace(c) << "invalid";break;
-    case typ_ground: Trace(c) << "ground";break;
-    case typ_eq: Trace(c) << "eq";break;
-    case typ_pred: Trace(c) << "pred";break;
-    case typ_formula: Trace(c) << "formula";break;
-    case typ_var: Trace(c) << "var";break;
-    case typ_ite_var: Trace(c) << "ite_var";break;
-    case typ_bool_var: Trace(c) << "bool_var";break;
-    }
-  }else{
-    switch( typ ){
-    case typ_invalid: Debug(c) << "invalid";break;
-    case typ_ground: Debug(c) << "ground";break;
-    case typ_eq: Debug(c) << "eq";break;
-    case typ_pred: Debug(c) << "pred";break;
-    case typ_formula: Debug(c) << "formula";break;
-    case typ_var: Debug(c) << "var";break;
-    case typ_ite_var: Debug(c) << "ite_var";break;
-    case typ_bool_var: Debug(c) << "bool_var";break;
-    }
-  }
-}
-
-void MatchGen::setInvalid() {
-  d_type = typ_invalid;
-  d_children.clear();
-}
-
-bool MatchGen::isHandledBoolConnective( TNode n ) {
-  return n.getType().isBoolean() && ( n.getKind()==OR || n.getKind()==AND || n.getKind()==IFF || n.getKind()==ITE || n.getKind()==FORALL || n.getKind()==NOT );
-}
-
-bool MatchGen::isHandledUfTerm( TNode n ) {
-  //return n.getKind()==APPLY_UF || n.getKind()==STORE || n.getKind()==SELECT ||
-  //       n.getKind()==APPLY_CONSTRUCTOR || n.getKind()==APPLY_SELECTOR_TOTAL || n.getKind()==APPLY_TESTER;
-  return inst::Trigger::isAtomicTriggerKind( n.getKind() );  
-}
-
-Node MatchGen::getOperator( QuantConflictFind * p, Node n ) {
-  if( isHandledUfTerm( n ) ){
-    return p->getQuantifiersEngine()->getTermDatabase()->getOperator( n );
-  }else{
-    return Node::null();
-  }
-}
-
-bool MatchGen::isHandled( TNode n ) {
-  if( n.getKind()!=BOUND_VARIABLE && n.hasBoundVar() ){
-    if( !isHandledBoolConnective( n ) && !isHandledUfTerm( n ) && n.getKind()!=EQUAL && n.getKind()!=ITE ){
-      return false;
-    }
-    for( unsigned i=0; i<n.getNumChildren(); i++ ){
-      if( !isHandled( n[i] ) ){
-        return false;
-      }
-    }
-  }
-  return true;
-}
-
-
-QuantConflictFind::QuantConflictFind( QuantifiersEngine * qe, context::Context* c ) :
-QuantifiersModule( qe ),
-d_c( c ),
-d_conflict( c, false ),
-d_qassert( c ) {
-  d_fid_count = 0;
-  d_true = NodeManager::currentNM()->mkConst<bool>(true);
-  d_false = NodeManager::currentNM()->mkConst<bool>(false);
-}
-
-Node QuantConflictFind::mkEqNode( Node a, Node b ) {
-  if( a.getType().isBoolean() ){
-    return a.iffNode( b );
-  }else{
-    return a.eqNode( b );
-  }
-}
-
-//-------------------------------------------------- registration
-
-void QuantConflictFind::registerQuantifier( Node q ) {
-  if( !TermDb::isRewriteRule( q ) ){
-    d_quants.push_back( q );
-    d_quant_id[q] = d_quants.size();
-    Trace("qcf-qregister") << "Register ";
-    debugPrintQuant( "qcf-qregister", q );
-    Trace("qcf-qregister") << " : " << q << std::endl;
-    //make QcfNode structure
-    Trace("qcf-qregister") << "- Get relevant equality/disequality pairs, calculate flattening..." << std::endl;
-    d_qinfo[q].initialize( q, q[1] );
-
-    //debug print
-    Trace("qcf-qregister") << "- Flattened structure is :" << std::endl;
-    Trace("qcf-qregister") << "    ";
-    debugPrintQuantBody( "qcf-qregister", q, q[1] );
-    Trace("qcf-qregister") << std::endl;
-    if( d_qinfo[q].d_vars.size()>q[0].getNumChildren() ){
-      Trace("qcf-qregister") << "  with additional constraints : " << std::endl;
-      for( unsigned j=q[0].getNumChildren(); j<d_qinfo[q].d_vars.size(); j++ ){
-        Trace("qcf-qregister") << "    ?x" << j << " = ";
-        debugPrintQuantBody( "qcf-qregister", q, d_qinfo[q].d_vars[j], false );
-        Trace("qcf-qregister") << std::endl;
-      }
-    }
-
-    Trace("qcf-qregister") << "Done registering quantifier." << std::endl;
-  }
-}
-
-int QuantConflictFind::evaluate( Node n, bool pref, bool hasPref ) {
-  int ret = 0;
-  if( n.getKind()==EQUAL ){
-    Node n1 = evaluateTerm( n[0] );
-    Node n2 = evaluateTerm( n[1] );
-    Debug("qcf-eval") << "Evaluate : Normalize " << n << " to " << n1 << " = " << n2 << std::endl;
-    if( areEqual( n1, n2 ) ){
-      ret = 1;
-    }else if( areDisequal( n1, n2 ) ){
-      ret = -1;
-    }
-    //else if( d_effort>QuantConflictFind::effort_conflict ){
-    //  ret = -1;
-    //}
-  }else if( MatchGen::isHandledUfTerm( n ) ){  //predicate
-    Node nn = evaluateTerm( n );
-    Debug("qcf-eval") << "Evaluate : Normalize " << nn << " to " << n << std::endl;
-    if( areEqual( nn, d_true ) ){
-      ret = 1;
-    }else if( areEqual( nn, d_false ) ){
-      ret = -1;
-    }
-    //else if( d_effort>QuantConflictFind::effort_conflict ){
-    //  ret = -1;
-    //}
-  }else if( n.getKind()==NOT ){
-    return -evaluate( n[0] );
-  }else if( n.getKind()==ITE ){
-    int cev1 = evaluate( n[0] );
-    int cevc[2] = { 0, 0 };
-    for( unsigned i=0; i<2; i++ ){
-      if( ( i==0 && cev1!=-1 ) || ( i==1 && cev1!=1 ) ){
-        cevc[i] = evaluate( n[i+1] );
-        if( cev1!=0 ){
-          ret = cevc[i];
-          break;
-        }else if( cevc[i]==0 ){
-          break;
-        }
-      }
-    }
-    if( ret==0 && cevc[0]!=0 && cevc[0]==cevc[1] ){
-      ret = cevc[0];
-    }
-  }else if( n.getKind()==IFF ){
-    int cev1 = evaluate( n[0] );
-    if( cev1!=0 ){
-      int cev2 = evaluate( n[1] );
-      if( cev2!=0 ){
-        ret = cev1==cev2 ? 1 : -1;
-      }
-    }
-
-  }else{
-    int ssval = 0;
-    if( n.getKind()==OR ){
-      ssval = 1;
-    }else if( n.getKind()==AND ){
-      ssval = -1;
-    }
-    bool isUnk = false;
-    for( unsigned i=0; i<n.getNumChildren(); i++ ){
-      int cev = evaluate( n[i] );
-      if( cev==ssval ){
-        ret = ssval;
-        break;
-      }else if( cev==0 ){
-        isUnk = true;
-      }
-    }
-    if( ret==0 && !isUnk ){
-      ret = -ssval;
-    }
-  }
-  Debug("qcf-eval") << "Evaluate " << n << " to " << ret << std::endl;
-  return ret;
-}
-
-short QuantConflictFind::getMaxQcfEffort() {
-  if( options::qcfMode()==QCF_CONFLICT_ONLY ){
-    return effort_conflict;
-  }else if( options::qcfMode()==QCF_PROP_EQ ){
-    return effort_prop_eq;
-  }else if( options::qcfMode()==QCF_MC ){
-    return effort_mc;
-  }else{
-    return 0;
-  }
-}
-
-bool QuantConflictFind::areMatchEqual( TNode n1, TNode n2 ) {
-  //if( d_effort==QuantConflictFind::effort_mc ){
-  //  return n1==n2 || !areDisequal( n1, n2 );
-  //}else{
-  return n1==n2;
-  //}
-}
-
-bool QuantConflictFind::areMatchDisequal( TNode n1, TNode n2 ) {
-  //if( d_effort==QuantConflictFind::effort_conflict ){
-  //  return areDisequal( n1, n2 );
-  //}else{
-  return n1!=n2;
-  //}
-}
-
-//-------------------------------------------------- handling assertions / eqc
-
-void QuantConflictFind::assertNode( Node q ) {
-  if( !TermDb::isRewriteRule( q ) ){
-    Trace("qcf-proc") << "QCF : assertQuantifier : ";
-    debugPrintQuant("qcf-proc", q);
-    Trace("qcf-proc") << std::endl;
-    d_qassert.push_back( q );
-    //set the eqRegistries that this depends on to true
-    //for( std::map< EqRegistry *, bool >::iterator it = d_qinfo[q].d_rel_eqr.begin(); it != d_qinfo[q].d_rel_eqr.end(); ++it ){
-    //  it->first->d_active.set( true );
-    //}
-  }
-}
-
-eq::EqualityEngine * QuantConflictFind::getEqualityEngine() {
-  //return ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->theoryOf( theory::THEORY_UF ))->getEqualityEngine();
-  return d_quantEngine->getTheoryEngine()->getMasterEqualityEngine();
-}
-bool QuantConflictFind::areEqual( Node n1, Node n2 ) {
-  return getEqualityEngine()->hasTerm( n1 ) && getEqualityEngine()->hasTerm( n2 ) && getEqualityEngine()->areEqual( n1,n2 );
-}
-bool QuantConflictFind::areDisequal( Node n1, Node n2 ) {
-  return n1!=n2 && getEqualityEngine()->hasTerm( n1 ) && getEqualityEngine()->hasTerm( n2 ) && getEqualityEngine()->areDisequal( n1,n2, false );
-}
-Node QuantConflictFind::getRepresentative( Node n ) {
-  if( getEqualityEngine()->hasTerm( n ) ){
-    return getEqualityEngine()->getRepresentative( n );
-  }else{
-    return n;
-  }
-}
-Node QuantConflictFind::evaluateTerm( Node n ) {
-  if( MatchGen::isHandledUfTerm( n ) ){
-    Node f = MatchGen::getOperator( this, n );
-    Node nn;
-    computeUfTerms( f );
-    if( getEqualityEngine()->hasTerm( n ) ){
-      computeArgReps( n );
-      nn = d_uf_terms[f].existsTerm( n, d_arg_reps[n] );
-    }else{
-      std::vector< TNode > args;
-      for( unsigned i=0; i<n.getNumChildren(); i++ ){
-        Node c = evaluateTerm( n[i] );
-        args.push_back( c );
-      }
-      nn = d_uf_terms[f].existsTerm( n, args );
-    }
-    if( !nn.isNull() ){
-      Debug("qcf-eval") << "GT: Term " << nn << " for " << n << " hasTerm = " << getEqualityEngine()->hasTerm( n )  << std::endl;
-      return getRepresentative( nn );
-    }else{
-      Debug("qcf-eval") << "GT: No term for " << n << " hasTerm = " << getEqualityEngine()->hasTerm( n )  << std::endl;
-      return n;
-    }
-  }else if( n.getKind()==ITE ){
-    int v = evaluate( n[0], false, false );
-    if( v==1 ){
-      return evaluateTerm( n[1] );
-    }else if( v==-1 ){
-      return evaluateTerm( n[2] );
-    }
-  }
-  return getRepresentative( n );
-}
-
-/*
-QuantConflictFind::EqcInfo * QuantConflictFind::getEqcInfo( Node n, bool doCreate ) {
-  std::map< Node, EqcInfo * >::iterator it2 = d_eqc_info.find( n );
-  if( it2==d_eqc_info.end() ){
-    if( doCreate ){
-      EqcInfo * eqci = new EqcInfo( d_c );
-      d_eqc_info[n] = eqci;
-      return eqci;
-    }else{
-      return NULL;
-    }
-  }
-  return it2->second;
-}
-*/
-
-QcfNodeIndex * QuantConflictFind::getQcfNodeIndex( Node eqc, Node f ) {
-  computeUfTerms( f );
-  std::map< TNode, QcfNodeIndex >::iterator itut = d_eqc_uf_terms.find( f );
-  if( itut==d_eqc_uf_terms.end() ){
-    return NULL;
-  }else{
-    if( eqc.isNull() ){
-      return &itut->second;
-    }else{
-      std::map< TNode, QcfNodeIndex >::iterator itute = itut->second.d_children.find( eqc );
-      if( itute!=itut->second.d_children.end() ){
-        return &itute->second;
-      }else{
-        return NULL;
-      }
-    }
-  }
-}
-
-QcfNodeIndex * QuantConflictFind::getQcfNodeIndex( Node f ) {
-  computeUfTerms( f );
-  std::map< TNode, QcfNodeIndex >::iterator itut = d_uf_terms.find( f );
-  if( itut!=d_uf_terms.end() ){
-    return &itut->second;
-  }else{
-    return NULL;
-  }
-}
-
-/** new node */
-void QuantConflictFind::newEqClass( Node n ) {
-  //Trace("qcf-proc-debug") << "QCF : newEqClass : " << n << std::endl;
-  //Trace("qcf-proc2-debug") << "QCF : finished newEqClass : " << n << std::endl;
-}
-
-/** merge */
-void QuantConflictFind::merge( Node a, Node b ) {
-  /*
-  if( b.getKind()==EQUAL ){
-    if( a==d_true ){
-      //will merge anyways
-      //merge( b[0], b[1] );
-    }else if( a==d_false ){
-      assertDisequal( b[0], b[1] );
-    }
-  }else{
-    Trace("qcf-proc") << "QCF : merge : " << a << " " << b << std::endl;
-    EqcInfo * eqc_b = getEqcInfo( b, false );
-    EqcInfo * eqc_a = NULL;
-    if( eqc_b ){
-      eqc_a = getEqcInfo( a );
-      //move disequalities of b into a
-      for( NodeBoolMap::iterator it = eqc_b->d_diseq.begin(); it != eqc_b->d_diseq.end(); ++it ){
-        if( (*it).second ){
-          Node n = (*it).first;
-          EqcInfo * eqc_n = getEqcInfo( n, false );
-          Assert( eqc_n );
-          if( !eqc_n->isDisequal( a ) ){
-            Assert( !eqc_a->isDisequal( n ) );
-            eqc_n->setDisequal( a );
-            eqc_a->setDisequal( n );
-            //setEqual( eqc_a, eqc_b, a, n, false );
-          }
-          eqc_n->setDisequal( b, false );
-        }
-      }
-      ////move all previous EqcRegistry's regarding equalities within b
-      //for( NodeBoolMap::iterator it = eqc_b->d_rel_eqr_e.begin(); it != eqc_b->d_rel_eqr_e.end(); ++it ){
-      //  if( (*it).second ){
-      //    eqc_a->d_rel_eqr_e[(*it).first] = true;
-      //  }
-      //}
-    }
-    //process new equalities
-    //setEqual( eqc_a, eqc_b, a, b, true );
-    Trace("qcf-proc2") << "QCF : finished merge : " << a << " " << b << std::endl;
-  }
-  */
-}
-
-/** assert disequal */
-void QuantConflictFind::assertDisequal( Node a, Node b ) {
-  /*
-  a = getRepresentative( a );
-  b = getRepresentative( b );
-  Trace("qcf-proc") << "QCF : assert disequal : " << a << " " << b << std::endl;
-  EqcInfo * eqc_a = getEqcInfo( a );
-  EqcInfo * eqc_b = getEqcInfo( b );
-  if( !eqc_a->isDisequal( b ) ){
-    Assert( !eqc_b->isDisequal( a ) );
-    eqc_b->setDisequal( a );
-    eqc_a->setDisequal( b );
-    //setEqual( eqc_a, eqc_b, a, b, false );
-  }
-  Trace("qcf-proc2") << "QCF : finished assert disequal : " << a << " " << b << std::endl;
-  */
-}
-
-//-------------------------------------------------- check function
-
-void QuantConflictFind::reset_round( Theory::Effort level ) {
-  d_needs_computeRelEqr = true;
-}
-
-/** check */
-void QuantConflictFind::check( Theory::Effort level ) {
-  Trace("qcf-check") << "QCF : check : " << level << std::endl;
-  if( d_conflict ){
-    Trace("qcf-check2") << "QCF : finished check : already in conflict." << std::endl;
-    if( level>=Theory::EFFORT_FULL ){
-      Trace("qcf-warn") << "ALREADY IN CONFLICT? " << level << std::endl;
-      //Assert( false );
-    }
-  }else{
-    int addedLemmas = 0;
-    if( d_performCheck ){
-      ++(d_statistics.d_inst_rounds);
-      double clSet = 0;
-      int prevEt = 0;
-      if( Trace.isOn("qcf-engine") ){
-        prevEt = d_statistics.d_entailment_checks.getData();
-        clSet = double(clock())/double(CLOCKS_PER_SEC);
-        Trace("qcf-engine") << "---Conflict Find Engine Round, effort = " << level << "---" << std::endl;
-      }
-      computeRelevantEqr();
-
-      //determine order for quantified formulas
-      std::vector< Node > qorder;
-      std::map< Node, bool > qassert;
-      //mark which are asserted
-      for( unsigned i=0; i<d_qassert.size(); i++ ){
-        qassert[d_qassert[i]] = true;
-      }
-      //add which ones are specified in the order
-      for( unsigned i=0; i<d_quant_order.size(); i++ ){
-        Node n = d_quant_order[i];
-        if( std::find( qorder.begin(), qorder.end(), n )==qorder.end() && qassert.find( n )!=qassert.end() ){
-          qorder.push_back( n );
-        }
-      }
-      d_quant_order.clear();
-      d_quant_order.insert( d_quant_order.begin(), qorder.begin(), qorder.end() );
-      //add remaining
-      for( unsigned i=0; i<d_qassert.size(); i++ ){
-        Node n = d_qassert[i];
-        if( std::find( qorder.begin(), qorder.end(), n )==qorder.end() ){
-          qorder.push_back( n );
-        }
-      }
-
-      if( Trace.isOn("qcf-debug") ){
-        Trace("qcf-debug") << std::endl;
-        debugPrint("qcf-debug");
-        Trace("qcf-debug") << std::endl;
-      }
-      short end_e = getMaxQcfEffort();
-      for( short e = effort_conflict; e<=end_e; e++ ){
-        d_effort = e;
-        Trace("qcf-check") << "Checking quantified formulas at effort " << e << "..." << std::endl;
-        for( unsigned j=0; j<qorder.size(); j++ ){
-          Node q = qorder[j];
-          QuantInfo * qi = &d_qinfo[q];
-
-          Assert( d_qinfo.find( q )!=d_qinfo.end() );
-          if( qi->d_mg->isValid() ){
-            Trace("qcf-check") << "Check quantified formula ";
-            debugPrintQuant("qcf-check", q);
-            Trace("qcf-check") << " : " << q << "..." << std::endl;
-
-            Trace("qcf-check-debug") << "Reset round..." << std::endl;
-            qi->reset_round( this );
-            //try to make a matches making the body false
-            Trace("qcf-check-debug") << "Get next match..." << std::endl;
-            while( qi->d_mg->getNextMatch( this, qi ) ){
-              Trace("qcf-check") << "*** Produced match at effort " << e << " : " << std::endl;
-              qi->debugPrintMatch("qcf-check");
-              Trace("qcf-check") << std::endl;
-              std::vector< int > assigned;
-              if( !qi->isMatchSpurious( this ) ){
-                if( qi->completeMatch( this, assigned ) ){
-                  /*
-                  if( options::qcfExp() && d_effort==effort_conflict ){
-                    std::vector< Node > exp;
-                    if( qi->d_mg->getExplanation( this, qi, exp ) ){
-                      Trace("qcf-check-exp") << "Base explanation is : " << std::endl;
-                      for( unsigned c=0; c<exp.size(); c++ ){
-                        Trace("qcf-check-exp") << "  " << exp[c] << std::endl;
-                      }
-                      std::vector< TNode > c_exp;
-                      eq::EqualityEngine* ee = ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->theoryOf( THEORY_UF ))->getEqualityEngine() ;
-                      for( unsigned c=0; c<exp.size(); c++ ){
-                        bool pol = exp[c].getKind()!=NOT;
-                        TNode lit = pol ? exp[c] : exp[c][0];
-                        Trace("qcf-check-exp") << "Explain " << lit << ", polarity " << pol << std::endl;
-                        if( lit.getKind()==EQUAL ){
-                          if( !pol && !ee->areDisequal( lit[0], lit[1], true ) ){
-                            exit( 98 );
-                          }else if( pol && !ee->areEqual( lit[0], lit[1] ) ){
-                            exit( 99 );
-                          }
-                          ee->explainEquality( lit[0], lit[1], pol, c_exp );
-                        }else{
-                          if( !ee->areEqual( lit, pol ? d_true : d_false ) ){
-                            exit( pol ? 96 : 97 );
-                          }
-                          ee->explainPredicate( lit, pol, c_exp );
-                        }
-                      }
-                      std::vector< Node > c_lem;
-                      Trace("qcf-check-exp") << "Actual explanation is : " << std::endl;
-                      for( unsigned c=0; c<c_exp.size(); c++ ){
-                        Trace("qcf-check-exp") << "  " << c_exp[c] << std::endl;
-                        Node ccc = c_exp[c].negate();
-                        if( std::find( c_lem.begin(), c_lem.end(), ccc )==c_lem.end() ){
-                          c_lem.push_back( ccc );
-                        }
-                      }
-
-                      c_lem.push_back( q.negate() );
-                      Node conf = NodeManager::currentNM()->mkNode( OR, c_lem );
-                      Trace("qcf-conflict") << "QCF conflict : " << conf << std::endl;
-                      d_quantEngine->addLemma( conf, false );
-                      d_conflict.set( true );
-                      ++(d_statistics.d_conflict_inst);
-                      ++addedLemmas;
-                      break;
-                    }
-                  }
-                  */
-                  std::vector< Node > terms;
-                  qi->getMatch( terms );
-                  if( !qi->isTConstraintSpurious( this, terms ) ){
-                    if( Debug.isOn("qcf-check-inst") ){
-                      //if( e==effort_conflict ){
-                      Node inst = d_quantEngine->getInstantiation( q, terms );
-                      Debug("qcf-check-inst") << "Check instantiation " << inst << "..." << std::endl;
-                      Assert( evaluate( inst )!=1 );
-                      Assert( evaluate( inst )==-1 || e>effort_conflict );
-                      //}
-                    }
-                    if( d_quantEngine->addInstantiation( q, terms, false ) ){
-                      Trace("qcf-check") << "   ... Added instantiation" << std::endl;
-                      Trace("qcf-inst") << "*** Was from effort " << e << " : " << std::endl;
-                      qi->debugPrintMatch("qcf-inst");
-                      Trace("qcf-inst") << std::endl;
-                      ++addedLemmas;
-                      if( e==effort_conflict ){
-                        d_quant_order.insert( d_quant_order.begin(), q );
-                        d_conflict.set( true );
-                        ++(d_statistics.d_conflict_inst);
-                        break;
-                      }else if( e==effort_prop_eq ){
-                        ++(d_statistics.d_prop_inst);
-                      }
-                    }else{
-                      Trace("qcf-check") << "   ... Failed to add instantiation" << std::endl;
-                      //Assert( false );
-                    }
-                  }
-                  //clean up assigned
-                  qi->revertMatch( assigned );
-                  d_tempCache.clear();
-                }else{
-                  Trace("qcf-check") << "   ... Spurious instantiation (cannot assign unassigned variables)" << std::endl;
-                }
-              }else{
-                Trace("qcf-check") << "   ... Spurious instantiation (match is inconsistent)" << std::endl;
-              }
-            }
-            if( d_conflict ){
-              break;
-            }
-          }
-        }
-        if( addedLemmas>0 ){
-          d_quantEngine->flushLemmas();
-          break;
-        }
-      }
-      if( Trace.isOn("qcf-engine") ){
-        double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
-        Trace("qcf-engine") << "Finished conflict find engine, time = " << (clSet2-clSet);
-        if( addedLemmas>0 ){
-          Trace("qcf-engine") << ", effort = " << ( d_effort==effort_conflict ? "conflict" : ( d_effort==effort_prop_eq ? "prop_eq" : "mc" ) );
-          Trace("qcf-engine") << ", addedLemmas = " << addedLemmas;
-        }
-        Trace("qcf-engine") << std::endl;
-        int currEt = d_statistics.d_entailment_checks.getData();
-        if( currEt!=prevEt ){
-          Trace("qcf-engine") << "  Entailment checks = " << ( currEt - prevEt ) << std::endl;
-        }
-      }
-    }
-    Trace("qcf-check2") << "QCF : finished check : " << level << std::endl;
-  }
-}
-
-bool QuantConflictFind::needsCheck( Theory::Effort level ) {
-  d_performCheck = false;
-  if( options::quantConflictFind() && !d_conflict ){
-    if( level==Theory::EFFORT_LAST_CALL ){
-      d_performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_LAST_CALL;
-    }else if( level==Theory::EFFORT_FULL ){
-      d_performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_DEFAULT;
-    }else if( level==Theory::EFFORT_STANDARD ){
-      d_performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_STD;
-    }
-  }
-  return d_performCheck;
-}
-
-void QuantConflictFind::computeRelevantEqr() {
-  if( d_needs_computeRelEqr ){
-    d_needs_computeRelEqr = false;
-    Trace("qcf-check") << "Compute relevant equalities..." << std::endl;
-    d_uf_terms.clear();
-    d_eqc_uf_terms.clear();
-    d_eqcs.clear();
-    d_model_basis.clear();
-    d_arg_reps.clear();
-    //double clSet = 0;
-    //if( Trace.isOn("qcf-opt") ){
-    //  clSet = double(clock())/double(CLOCKS_PER_SEC);
-    //}
-
-    //long nTermst = 0;
-    //long nTerms = 0;
-    //long nEqc = 0;
-
-    //which nodes are irrelevant for disequality matches
-    std::map< TNode, bool > irrelevant_dnode;
-    //now, store matches
-    eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( getEqualityEngine() );
-    while( !eqcs_i.isFinished() ){
-      //nEqc++;
-      Node r = (*eqcs_i);
-      TypeNode rtn = r.getType();
-      if( options::qcfMode()==QCF_MC ){
-        std::map< TypeNode, std::vector< TNode > >::iterator itt = d_eqcs.find( rtn );
-        if( itt==d_eqcs.end() ){
-          Node mb = getQuantifiersEngine()->getTermDatabase()->getModelBasisTerm( rtn );
-          if( !getEqualityEngine()->hasTerm( mb ) ){
-            Trace("qcf-warn") << "WARNING: Model basis term does not exist!" << std::endl;
-            Assert( false );
-          }
-          Node mbr = getRepresentative( mb );
-          if( mbr!=r ){
-            d_eqcs[rtn].push_back( mbr );
-          }
-          d_eqcs[rtn].push_back( r );
-          d_model_basis[rtn] = mb;
-        }else{
-          itt->second.push_back( r );
-        }
-      }else{
-        d_eqcs[rtn].push_back( r );
-      }
-      /*
-      eq::EqClassIterator eqc_i = eq::EqClassIterator( r, getEqualityEngine() );
-      while( !eqc_i.isFinished() ){
-        TNode n = (*eqc_i);
-        if( n.hasBoundVar() ){
-          std::cout << "BAD TERM IN DB : " << n << std::endl;
-          exit( 199 );
-        }
-        ++eqc_i;
-      }
-
-      */
-
-      //if( r.getType().isInteger() ){
-      //  Trace("qcf-mv") << "Model value for eqc(" << r << ") : " << d_quantEngine->getValuation().getModelValue( r ) << std::endl;
-      //}
-      //EqcInfo * eqcir = getEqcInfo( r, false );
-      //get relevant nodes that we are disequal from
-      /*
-      std::vector< Node > deqc;
-      if( eqcir ){
-        for( NodeBoolMap::iterator it = eqcir->d_diseq.begin(); it != eqcir->d_diseq.end(); ++it ){
-          if( (*it).second ){
-            //Node rd = (*it).first;
-            //if( rd!=getRepresentative( rd ) ){
-            //  std::cout << "Bad rep!" << std::endl;
-            //  exit( 0 );
-            //}
-            deqc.push_back( (*it).first );
-          }
-        }
-      }
-      */
-      //process disequalities
-      /*
-      eq::EqClassIterator eqc_i = eq::EqClassIterator( r, getEqualityEngine() );
-      while( !eqc_i.isFinished() ){
-        TNode n = (*eqc_i);
-        if( n.getKind()!=EQUAL ){
-          nTermst++;
-          //node_to_rep[n] = r;
-          //if( n.getNumChildren()>0 ){
-          //  if( n.getKind()!=APPLY_UF ){
-          //    std::cout << n.getKind() << " " << n.getOperator() << " " << n << std::endl;
-          //  }
-          //}
-          if( !quantifiers::TermDb::hasBoundVarAttr( n ) ){    //temporary
-
-            bool isRedundant;
-            std::map< TNode, std::vector< TNode > >::iterator it_na;
-            TNode fn;
-            if( MatchGen::isHandledUfTerm( n ) ){
-              Node f = MatchGen::getOperator( this, n );
-              computeArgReps( n );
-              it_na = d_arg_reps.find( n );
-              Assert( it_na!=d_arg_reps.end() );
-              Node nadd = d_eqc_uf_terms[f].d_children[r].addTerm( n, d_arg_reps[n] );
-              isRedundant = (nadd!=n);
-              d_uf_terms[f].addTerm( n, d_arg_reps[n] );
-            }else{
-              isRedundant = false;
-            }
-            nTerms += isRedundant ? 0 : 1;
-          }else{
-            if( Debug.isOn("qcf-nground") ){
-              Debug("qcf-nground") << "Non-ground term in eqc : " << n << std::endl;
-              Assert( false );
-            }
-          }
-        }
-        ++eqc_i;
-      }
-      */
-      ++eqcs_i;
-    }
-    /*
-    if( Trace.isOn("qcf-opt") ){
-      double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
-      Trace("qcf-opt") << "Compute rel eqc : " << std::endl;
-      Trace("qcf-opt") << "   " << nEqc << " equivalence classes. " << std::endl;
-      Trace("qcf-opt") << "   " << nTerms << " / " << nTermst << " terms." << std::endl;
-      Trace("qcf-opt") << "   Time : " << (clSet2-clSet) << std::endl;
-    }
-    */
-  }
-}
-
-void QuantConflictFind::computeArgReps( TNode n ) {
-  if( d_arg_reps.find( n )==d_arg_reps.end() ){
-    Assert( MatchGen::isHandledUfTerm( n ) );
-    for( unsigned j=0; j<n.getNumChildren(); j++ ){
-      d_arg_reps[n].push_back( getRepresentative( n[j] ) );
-    }
-  }
-}
-
-void QuantConflictFind::computeUfTerms( TNode f ) {
-  if( d_uf_terms.find( f )==d_uf_terms.end() ){
-    d_uf_terms[f].clear();
-    unsigned nt = d_quantEngine->getTermDatabase()->getNumGroundTerms( f );
-    for( unsigned i=0; i<nt; i++ ){
-      Node n = d_quantEngine->getTermDatabase()->d_op_map[f][i];
-      if( getEqualityEngine()->hasTerm( n ) && !n.getAttribute(NoMatchAttribute()) ){
-        Node r = getRepresentative( n );
-        computeArgReps( n );
-        d_eqc_uf_terms[f].d_children[r].addTerm( n, d_arg_reps[n] );
-        d_uf_terms[f].addTerm( n, d_arg_reps[n] );
-      }
-    }
-  }
-}
-
-//-------------------------------------------------- debugging
-
-
-void QuantConflictFind::debugPrint( const char * c ) {
-  //print the equivalance classes
-  Trace(c) << "----------EQ classes" << std::endl;
-  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( getEqualityEngine() );
-  while( !eqcs_i.isFinished() ){
-    Node n = (*eqcs_i);
-    //if( !n.getType().isInteger() ){
-    Trace(c) << "  - " << n << " : {";
-    eq::EqClassIterator eqc_i = eq::EqClassIterator( n, getEqualityEngine() );
-    bool pr = false;
-    while( !eqc_i.isFinished() ){
-      Node nn = (*eqc_i);
-      if( nn.getKind()!=EQUAL && nn!=n ){
-        Trace(c) << (pr ? "," : "" ) << " " << nn;
-        pr = true;
-      }
-      ++eqc_i;
-    }
-    Trace(c) << (pr ? " " : "" ) << "}" << std::endl;
-    /*
-    EqcInfo * eqcn = getEqcInfo( n, false );
-    if( eqcn ){
-      Trace(c) << "    DEQ : {";
-      pr = false;
-      for( NodeBoolMap::iterator it = eqcn->d_diseq.begin(); it != eqcn->d_diseq.end(); ++it ){
-        if( (*it).second ){
-          Trace(c) << (pr ? "," : "" ) << " " << (*it).first;
-          pr = true;
-        }
-      }
-      Trace(c) << (pr ? " " : "" ) << "}" << std::endl;
-    }
-    //}
-    */
-    ++eqcs_i;
-  }
-}
-
-void QuantConflictFind::debugPrintQuant( const char * c, Node q ) {
-  Trace(c) << "Q" << d_quant_id[q];
-}
-
-void QuantConflictFind::debugPrintQuantBody( const char * c, Node q, Node n, bool doVarNum ) {
-  if( n.getNumChildren()==0 ){
-    Trace(c) << n;
-  }else if( doVarNum && d_qinfo[q].d_var_num.find( n )!=d_qinfo[q].d_var_num.end() ){
-    Trace(c) << "?x" << d_qinfo[q].d_var_num[n];
-  }else{
-    Trace(c) << "(";
-    if( n.getKind()==APPLY_UF ){
-      Trace(c) << n.getOperator();
-    }else{
-      Trace(c) << n.getKind();
-    }
-    for( unsigned i=0; i<n.getNumChildren(); i++ ){
-      Trace(c) << " ";
-      debugPrintQuantBody( c, q, n[i] );
-    }
-    Trace(c) << ")";
-  }
-}
-
-QuantConflictFind::Statistics::Statistics():
-  d_inst_rounds("QuantConflictFind::Inst_Rounds", 0),
-  d_conflict_inst("QuantConflictFind::Instantiations_Conflict_Find", 0 ),
-  d_prop_inst("QuantConflictFind::Instantiations_Prop", 0 ),
-  d_entailment_checks("QuantConflictFind::Entailment_Checks",0)
-{
-  StatisticsRegistry::registerStat(&d_inst_rounds);
-  StatisticsRegistry::registerStat(&d_conflict_inst);
-  StatisticsRegistry::registerStat(&d_prop_inst);
-  StatisticsRegistry::registerStat(&d_entailment_checks);
-}
-
-QuantConflictFind::Statistics::~Statistics(){
-  StatisticsRegistry::unregisterStat(&d_inst_rounds);
-  StatisticsRegistry::unregisterStat(&d_conflict_inst);
-  StatisticsRegistry::unregisterStat(&d_prop_inst);
-  StatisticsRegistry::unregisterStat(&d_entailment_checks);
-}
-
-TNode QuantConflictFind::getZero( Kind k ) {
-  std::map< Kind, Node >::iterator it = d_zero.find( k );
-  if( it==d_zero.end() ){
-    Node nn;
-    if( k==PLUS ){
-      nn = NodeManager::currentNM()->mkConst( Rational(0) );
-    }
-    d_zero[k] = nn;
-    return nn;
-  }else{
-    return it->second;
-  }
-}
-
-
-}
+/*********************                                                        */\r
+/*! \file quant_conflict_find.cpp\r
+ ** \verbatim\r
+ ** Original author: Andrew Reynolds\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 project.\r
+ ** Copyright (c) 2009-2014  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 quant conflict find class\r
+ **\r
+ **/\r
+\r
+#include <vector>\r
+\r
+#include "theory/quantifiers/quant_conflict_find.h"\r
+#include "theory/quantifiers/quant_util.h"\r
+#include "theory/theory_engine.h"\r
+#include "theory/quantifiers/options.h"\r
+#include "theory/quantifiers/term_database.h"\r
+#include "theory/quantifiers/trigger.h"\r
+\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::theory;\r
+using namespace CVC4::theory::quantifiers;\r
+using namespace std;\r
+\r
+namespace CVC4 {\r
+\r
+\r
+\r
+void QuantInfo::initialize( Node q, Node qn ) {\r
+  d_q = q;\r
+  for( unsigned i=0; i<q[0].getNumChildren(); i++ ){\r
+    d_match.push_back( TNode::null() );\r
+    d_match_term.push_back( TNode::null() );\r
+  }\r
+\r
+  //register the variables\r
+  for( unsigned i=0; i<q[0].getNumChildren(); i++ ){\r
+    d_var_num[q[0][i]] = i;\r
+    d_vars.push_back( q[0][i] );\r
+  }\r
+\r
+  registerNode( qn, true, true );\r
+\r
+\r
+  Trace("qcf-qregister") << "- Make match gen structure..." << std::endl;\r
+  d_mg = new MatchGen( this, qn );\r
+\r
+  if( d_mg->isValid() ){\r
+    /*\r
+    for( unsigned j=0; j<q[0].getNumChildren(); j++ ){\r
+      if( d_inMatchConstraint.find( q[0][j] )==d_inMatchConstraint.end() ){\r
+        Trace("qcf-invalid") << "QCF invalid : variable " << q[0][j] << " does not exist in a matching constraint." << std::endl;\r
+        d_mg->setInvalid();\r
+        break;\r
+      }\r
+    }\r
+    */\r
+    if( d_mg->isValid() ){\r
+      for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){\r
+        if( d_vars[j].getKind()!=BOUND_VARIABLE ){\r
+          d_var_mg[j] = NULL;\r
+          bool is_tsym = false;\r
+          if( !MatchGen::isHandledUfTerm( d_vars[j] ) && d_vars[j].getKind()!=ITE ){\r
+            is_tsym = true;\r
+            d_tsym_vars.push_back( j );\r
+          }\r
+          if( !is_tsym || options::qcfTConstraint() ){\r
+            d_var_mg[j] = new MatchGen( this, d_vars[j], true );\r
+          }\r
+          if( !d_var_mg[j] || !d_var_mg[j]->isValid() ){\r
+            Trace("qcf-invalid") << "QCF invalid : cannot match for " << d_vars[j] << std::endl;\r
+            d_mg->setInvalid();\r
+            break;\r
+          }else{\r
+            std::vector< int > bvars;\r
+            d_var_mg[j]->determineVariableOrder( this, bvars );\r
+          }\r
+        }\r
+      }\r
+      if( d_mg->isValid() ){\r
+        std::vector< int > bvars;\r
+        d_mg->determineVariableOrder( this, bvars );\r
+      }\r
+    }\r
+  }else{\r
+    Trace("qcf-invalid") << "QCF invalid : body of formula cannot be processed." << std::endl;\r
+  }\r
+  Trace("qcf-qregister-summary") << "QCF register : " << ( d_mg->isValid() ? "VALID " : "INVALID" ) << " : " << q << std::endl;\r
+}\r
+\r
+void QuantInfo::registerNode( Node n, bool hasPol, bool pol, bool beneathQuant ) {\r
+  Trace("qcf-qregister-debug2") << "Register : " << n << std::endl;\r
+  if( n.getKind()==FORALL ){\r
+    registerNode( n[1], hasPol, pol, true );\r
+  }else{\r
+    if( !MatchGen::isHandledBoolConnective( n ) ){\r
+      if( n.hasBoundVar() ){\r
+        //literals\r
+        if( n.getKind()==EQUAL ){\r
+          for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+            flatten( n[i], beneathQuant );\r
+          }\r
+        }else if( MatchGen::isHandledUfTerm( n ) ){\r
+          flatten( n, beneathQuant );\r
+        }else if( n.getKind()==ITE ){\r
+          for( unsigned i=1; i<=2; i++ ){\r
+            flatten( n[i], beneathQuant );\r
+          }\r
+          registerNode( n[0], false, pol, beneathQuant );\r
+        }else if( options::qcfTConstraint() ){\r
+          //a theory-specific predicate\r
+          for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+            flatten( n[i], beneathQuant );\r
+          }\r
+        }\r
+      }\r
+    }else{\r
+      for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+        bool newHasPol;\r
+        bool newPol;\r
+        QuantPhaseReq::getPolarity( n, i, hasPol, pol, newHasPol, newPol );\r
+        //QcfNode * qcfc = new QcfNode( d_c );\r
+        //qcfc->d_parent = qcf;\r
+        //qcf->d_child[i] = qcfc;\r
+        registerNode( n[i], newHasPol, newPol, beneathQuant );\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+void QuantInfo::flatten( Node n, bool beneathQuant ) {\r
+  Trace("qcf-qregister-debug2") << "Flatten : " << n << std::endl;\r
+  if( n.hasBoundVar() ){\r
+    if( n.getKind()==BOUND_VARIABLE ){\r
+      d_inMatchConstraint[n] = true;\r
+    }\r
+    //if( MatchGen::isHandledUfTerm( n ) || n.getKind()==ITE ){\r
+    if( d_var_num.find( n )==d_var_num.end() ){\r
+      Trace("qcf-qregister-debug2") << "Add FLATTEN VAR : " << n << std::endl;\r
+      d_var_num[n] = d_vars.size();\r
+      d_vars.push_back( n );\r
+      d_match.push_back( TNode::null() );\r
+      d_match_term.push_back( TNode::null() );\r
+      if( n.getKind()==ITE ){\r
+        registerNode( n, false, false );\r
+      }else{\r
+        for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+          flatten( n[i], beneathQuant );\r
+        }\r
+      }\r
+    }else{\r
+      Trace("qcf-qregister-debug2") << "...already processed" << std::endl;\r
+    }\r
+  }else{\r
+    Trace("qcf-qregister-debug2") << "...is ground." << std::endl;\r
+  }\r
+}\r
+\r
+\r
+void QuantInfo::reset_round( QuantConflictFind * p ) {\r
+  for( unsigned i=0; i<d_match.size(); i++ ){\r
+    d_match[i] = TNode::null();\r
+    d_match_term[i] = TNode::null();\r
+  }\r
+  d_curr_var_deq.clear();\r
+  d_tconstraints.clear();\r
+  //add built-in variable constraints\r
+  for( unsigned r=0; r<2; r++ ){\r
+    for( std::map< int, std::vector< Node > >::iterator it = d_var_constraint[r].begin();\r
+         it != d_var_constraint[r].end(); ++it ){\r
+      for( unsigned j=0; j<it->second.size(); j++ ){\r
+        Node rr = it->second[j];\r
+        if( !isVar( rr ) ){\r
+          rr = p->getRepresentative( rr );\r
+        }\r
+        if( addConstraint( p, it->first, rr, r==0 )==-1 ){\r
+          d_var_constraint[0].clear();\r
+          d_var_constraint[1].clear();\r
+          //quantified formula is actually equivalent to true\r
+          Trace("qcf-qregister") << "Quantifier is equivalent to true!!!" << std::endl;\r
+          d_mg->d_children.clear();\r
+          d_mg->d_n = NodeManager::currentNM()->mkConst( true );\r
+          d_mg->d_type = MatchGen::typ_ground;\r
+          return;\r
+        }\r
+      }\r
+    }\r
+  }\r
+  d_mg->reset_round( p );\r
+  for( std::map< int, MatchGen * >::iterator it = d_var_mg.begin(); it != d_var_mg.end(); ++it ){\r
+    it->second->reset_round( p );\r
+  }\r
+  //now, reset for matching\r
+  d_mg->reset( p, false, this );\r
+}\r
+\r
+int QuantInfo::getCurrentRepVar( int v ) {\r
+  if( v!=-1 && !d_match[v].isNull() ){\r
+    int vn = getVarNum( d_match[v] );\r
+    if( vn!=-1 ){\r
+      //int vr = getCurrentRepVar( vn );\r
+      //d_match[v] = d_vars[vr];\r
+      //return vr;\r
+      return getCurrentRepVar( vn );\r
+    }\r
+  }\r
+  return v;\r
+}\r
+\r
+TNode QuantInfo::getCurrentValue( TNode n ) {\r
+  int v = getVarNum( n );\r
+  if( v==-1 ){\r
+    return n;\r
+  }else{\r
+    if( d_match[v].isNull() ){\r
+      return n;\r
+    }else{\r
+      Assert( getVarNum( d_match[v] )!=v );\r
+      return getCurrentValue( d_match[v] );\r
+    }\r
+  }\r
+}\r
+\r
+TNode QuantInfo::getCurrentExpValue( TNode n ) {\r
+  int v = getVarNum( n );\r
+  if( v==-1 ){\r
+    return n;\r
+  }else{\r
+    if( d_match[v].isNull() ){\r
+      return n;\r
+    }else{\r
+      Assert( getVarNum( d_match[v] )!=v );\r
+      if( d_match_term[v].isNull() ){\r
+        return getCurrentValue( d_match[v] );\r
+      }else{\r
+        return d_match_term[v];\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+bool QuantInfo::getCurrentCanBeEqual( QuantConflictFind * p, int v, TNode n, bool chDiseq ) {\r
+  //check disequalities\r
+  std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( v );\r
+  if( itd!=d_curr_var_deq.end() ){\r
+    for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){\r
+      Node cv = getCurrentValue( it->first );\r
+      Debug("qcf-ccbe") << "compare " << cv << " " << n << std::endl;\r
+      if( cv==n ){\r
+        return false;\r
+      }else if( chDiseq && !isVar( n ) && !isVar( cv ) ){\r
+        //they must actually be disequal if we are looking for conflicts\r
+        if( !p->areDisequal( n, cv ) ){\r
+          //TODO : check for entailed disequal\r
+\r
+          return false;\r
+        }\r
+      }\r
+    }\r
+  }\r
+  return true;\r
+}\r
+\r
+int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, bool polarity ) {\r
+  v = getCurrentRepVar( v );\r
+  int vn = getVarNum( n );\r
+  vn = vn==-1 ? -1 : getCurrentRepVar( vn );\r
+  n = getCurrentValue( n );\r
+  return addConstraint( p, v, n, vn, polarity, false );\r
+}\r
+\r
+int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, int vn, bool polarity, bool doRemove ) {\r
+  //for handling equalities between variables, and disequalities involving variables\r
+  Debug("qcf-match-debug") << "- " << (doRemove ? "un" : "" ) << "constrain : " << v << " -> " << n << " (cv=" << getCurrentValue( n ) << ")";\r
+  Debug("qcf-match-debug") << ", (vn=" << vn << "), polarity = " << polarity << std::endl;\r
+  Assert( doRemove || n==getCurrentValue( n ) );\r
+  Assert( doRemove || v==getCurrentRepVar( v ) );\r
+  Assert( doRemove || vn==getCurrentRepVar( getVarNum( n ) ) );\r
+  if( polarity ){\r
+    if( vn!=v ){\r
+      if( doRemove ){\r
+        if( vn!=-1 ){\r
+          //if set to this in the opposite direction, clean up opposite instead\r
+          //          std::map< int, TNode >::iterator itmn = d_match.find( vn );\r
+          if( d_match[vn]==d_vars[v] ){\r
+            return addConstraint( p, vn, d_vars[v], v, true, true );\r
+          }else{\r
+            //unsetting variables equal\r
+            std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( vn );\r
+            if( itd!=d_curr_var_deq.end() ){\r
+              //remove disequalities owned by this\r
+              std::vector< TNode > remDeq;\r
+              for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){\r
+                if( it->second==v ){\r
+                  remDeq.push_back( it->first );\r
+                }\r
+              }\r
+              for( unsigned i=0; i<remDeq.size(); i++ ){\r
+                d_curr_var_deq[vn].erase( remDeq[i] );\r
+              }\r
+            }\r
+          }\r
+        }\r
+        d_match[v] = TNode::null();\r
+        return 1;\r
+      }else{\r
+        //std::map< int, TNode >::iterator itm = d_match.find( v );\r
+\r
+        if( vn!=-1 ){\r
+          Debug("qcf-match-debug") << "  ...Variable bound to variable" << std::endl;\r
+          //std::map< int, TNode >::iterator itmn = d_match.find( vn );\r
+          if( d_match[v].isNull() ){\r
+            //setting variables equal\r
+            bool alreadySet = false;\r
+            if( !d_match[vn].isNull() ){\r
+              alreadySet = true;\r
+              Assert( !isVar( d_match[vn] ) );\r
+            }\r
+\r
+            //copy or check disequalities\r
+            std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( v );\r
+            if( itd!=d_curr_var_deq.end() ){\r
+              for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){\r
+                Node dv = getCurrentValue( it->first );\r
+                if( !alreadySet ){\r
+                  if( d_curr_var_deq[vn].find( dv )==d_curr_var_deq[vn].end() ){\r
+                    d_curr_var_deq[vn][dv] = v;\r
+                  }\r
+                }else{\r
+                  if( !p->areMatchDisequal( d_match[vn], dv ) ){\r
+                    Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;\r
+                    return -1;\r
+                  }\r
+                }\r
+              }\r
+            }\r
+            if( alreadySet ){\r
+              n = getCurrentValue( n );\r
+            }\r
+          }else{\r
+            if( d_match[vn].isNull() ){\r
+              Debug("qcf-match-debug") << " ...Reverse direction" << std::endl;\r
+              //set the opposite direction\r
+              return addConstraint( p, vn, d_vars[v], v, true, false );\r
+            }else{\r
+              Debug("qcf-match-debug") << "  -> Both variables bound, compare" << std::endl;\r
+              //are they currently equal\r
+              return p->areMatchEqual( d_match[v], d_match[vn] ) ? 0 : -1;\r
+            }\r
+          }\r
+        }else{\r
+          Debug("qcf-match-debug") << "  ...Variable bound to ground" << std::endl;\r
+          if( d_match[v].isNull() ){\r
+          }else{\r
+            //compare ground values\r
+            Debug("qcf-match-debug") << "  -> Ground value, compare " << d_match[v] << " "<< n << std::endl;\r
+            return p->areMatchEqual( d_match[v], n ) ? 0 : -1;\r
+          }\r
+        }\r
+        if( setMatch( p, v, n ) ){\r
+          Debug("qcf-match-debug") << "  -> success" << std::endl;\r
+          return 1;\r
+        }else{\r
+          Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;\r
+          return -1;\r
+        }\r
+      }\r
+    }else{\r
+      Debug("qcf-match-debug") << "  -> redundant, variable identity" << std::endl;\r
+      return 0;\r
+    }\r
+  }else{\r
+    if( vn==v ){\r
+      Debug("qcf-match-debug") << "  -> fail, variable identity" << std::endl;\r
+      return -1;\r
+    }else{\r
+      if( doRemove ){\r
+        Assert( d_curr_var_deq[v].find( n )!=d_curr_var_deq[v].end() );\r
+        d_curr_var_deq[v].erase( n );\r
+        return 1;\r
+      }else{\r
+        if( d_curr_var_deq[v].find( n )==d_curr_var_deq[v].end() ){\r
+          //check if it respects equality\r
+          //std::map< int, TNode >::iterator itm = d_match.find( v );\r
+          if( !d_match[v].isNull() ){\r
+            TNode nv = getCurrentValue( n );\r
+            if( !p->areMatchDisequal( nv, d_match[v] ) ){\r
+              Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;\r
+              return -1;\r
+            }\r
+          }\r
+          d_curr_var_deq[v][n] = v;\r
+          Debug("qcf-match-debug") << "  -> success" << std::endl;\r
+          return 1;\r
+        }else{\r
+          Debug("qcf-match-debug") << "  -> redundant disequality" << std::endl;\r
+          return 0;\r
+        }\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+bool QuantInfo::isConstrainedVar( int v ) {\r
+  if( d_curr_var_deq.find( v )!=d_curr_var_deq.end() && !d_curr_var_deq[v].empty() ){\r
+    return true;\r
+  }else{\r
+    Node vv = getVar( v );\r
+    //for( std::map< int, TNode >::iterator it = d_match.begin(); it != d_match.end(); ++it ){\r
+    for( unsigned i=0; i<d_match.size(); i++ ){\r
+      if( d_match[i]==vv ){\r
+        return true;\r
+      }\r
+    }\r
+    for( std::map< int, std::map< TNode, int > >::iterator it = d_curr_var_deq.begin(); it != d_curr_var_deq.end(); ++it ){\r
+      for( std::map< TNode, int >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){\r
+        if( it2->first==vv ){\r
+          return true;\r
+        }\r
+      }\r
+    }\r
+    return false;\r
+  }\r
+}\r
+\r
+bool QuantInfo::setMatch( QuantConflictFind * p, int v, TNode n ) {\r
+  if( getCurrentCanBeEqual( p, v, n ) ){\r
+    Debug("qcf-match-debug") << "-- bind : " << v << " -> " << n << ", checked " <<  d_curr_var_deq[v].size() << " disequalities" << std::endl;\r
+    d_match[v] = n;\r
+    return true;\r
+  }else{\r
+    return false;\r
+  }\r
+}\r
+\r
+bool QuantInfo::isMatchSpurious( QuantConflictFind * p ) {\r
+  for( int i=0; i<getNumVars(); i++ ){\r
+    //std::map< int, TNode >::iterator it = d_match.find( i );\r
+    if( !d_match[i].isNull() ){\r
+      if( !getCurrentCanBeEqual( p, i, d_match[i], p->d_effort==QuantConflictFind::effort_conflict ) ){\r
+        return true;\r
+      }\r
+    }\r
+  }\r
+  return false;\r
+}\r
+\r
+bool QuantInfo::isTConstraintSpurious( QuantConflictFind * p, std::vector< Node >& terms ) {\r
+  if( !d_tconstraints.empty() ){\r
+    //check constraints\r
+    for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){\r
+      //apply substitution to the tconstraint\r
+      Node cons = it->first.substitute( p->getQuantifiersEngine()->getTermDatabase()->d_vars[d_q].begin(),\r
+                                        p->getQuantifiersEngine()->getTermDatabase()->d_vars[d_q].end(),\r
+                                        terms.begin(), terms.end() );\r
+      cons = it->second ? cons : cons.negate();\r
+      if( !entailmentTest( p, cons, p->d_effort==QuantConflictFind::effort_conflict ) ){\r
+        return true;\r
+      }\r
+    }\r
+  }\r
+  return false;\r
+}\r
+\r
+bool QuantInfo::entailmentTest( QuantConflictFind * p, Node lit, bool chEnt ) {\r
+  Trace("qcf-tconstraint-debug") << "Check : " << lit << std::endl;\r
+  Node rew = Rewriter::rewrite( lit );\r
+  if( rew==p->d_false ){\r
+    Trace("qcf-tconstraint-debug") << "...constraint " << lit << " is disentailed (rewrites to false)." << std::endl;\r
+    return false;\r
+  }else if( rew!=p->d_true ){\r
+    //if checking for conflicts, we must be sure that the constraint is entailed\r
+    if( chEnt ){\r
+      //check if it is entailed\r
+      Trace("qcf-tconstraint-debug") << "Check entailment of " << rew << "..." << std::endl;\r
+      std::pair<bool, Node> et = p->getQuantifiersEngine()->getTheoryEngine()->entailmentCheck(THEORY_OF_TYPE_BASED, rew );\r
+      ++(p->d_statistics.d_entailment_checks);\r
+      Trace("qcf-tconstraint-debug") << "ET result : " << et.first << " " << et.second << std::endl;\r
+      if( !et.first ){\r
+        Trace("qcf-tconstraint-debug") << "...cannot show entailment of " << rew << "." << std::endl;\r
+        return false;\r
+      }else{\r
+        return true;\r
+      }\r
+    }else{\r
+      Trace("qcf-tconstraint-debug") << "...does not need to be entailed." << std::endl;\r
+      return true;\r
+    }\r
+  }else{\r
+    Trace("qcf-tconstraint-debug") << "...rewrites to true." << std::endl;\r
+    return true;\r
+  }\r
+}\r
+\r
+bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assigned, bool doContinue ) {\r
+  //assign values for variables that were unassigned (usually not necessary, but handles corner cases)\r
+  bool doFail = false;\r
+  bool success = true;\r
+  if( doContinue ){\r
+    doFail = true;\r
+    success = false;\r
+  }else{\r
+    //solve for interpreted symbol matches\r
+    //   this breaks the invariant that all introduced constraints are over existing terms\r
+    for( int i=(int)(d_tsym_vars.size()-1); i>=0; i-- ){\r
+      int index = d_tsym_vars[i];\r
+      TNode v = getCurrentValue( d_vars[index] );\r
+      int slv_v = -1;\r
+      if( v==d_vars[index] ){\r
+        slv_v = index;\r
+      }\r
+      Trace("qcf-tconstraint-debug") << "Solve " << d_vars[index] << " = " << v << " " << d_vars[index].getKind() << std::endl;\r
+      if( d_vars[index].getKind()==PLUS || d_vars[index].getKind()==MULT ){\r
+        Kind k = d_vars[index].getKind();\r
+        std::vector< TNode > children;\r
+        for( unsigned j=0; j<d_vars[index].getNumChildren(); j++ ){\r
+          int vn = getVarNum( d_vars[index][j] );\r
+          if( vn!=-1 ){\r
+            TNode vv = getCurrentValue( d_vars[index][j] );\r
+            if( vv==d_vars[index][j] ){\r
+              //we will assign this\r
+              if( slv_v==-1 ){\r
+                Trace("qcf-tconstraint-debug") << "...will solve for var #" << vn << std::endl;\r
+                slv_v = vn;\r
+                if( p->d_effort!=QuantConflictFind::effort_conflict ){\r
+                  break;\r
+                }\r
+              }else{\r
+                Node z = p->getZero( k );\r
+                if( !z.isNull() ){\r
+                  Trace("qcf-tconstraint-debug") << "...set " << d_vars[vn] << " = " << z << std::endl;\r
+                  assigned.push_back( vn );\r
+                  if( !setMatch( p, vn, z ) ){\r
+                    success = false;\r
+                    break;\r
+                  }\r
+                }\r
+              }\r
+            }else{\r
+              Trace("qcf-tconstraint-debug") << "...sum value " << vv << std::endl;\r
+              children.push_back( vv );\r
+            }\r
+          }else{\r
+            Trace("qcf-tconstraint-debug") << "...sum " << d_vars[index][j] << std::endl;\r
+            children.push_back( d_vars[index][j] );\r
+          }\r
+        }\r
+        if( success ){\r
+          if( slv_v!=-1 ){\r
+            Node lhs;\r
+            if( children.empty() ){\r
+              lhs = p->getZero( k );\r
+            }else if( children.size()==1 ){\r
+              lhs = children[0];\r
+            }else{\r
+              lhs = NodeManager::currentNM()->mkNode( k, children );\r
+            }\r
+            Node sum;\r
+            if( v==d_vars[index] ){\r
+              sum = lhs;\r
+            }else{\r
+              if( p->d_effort==QuantConflictFind::effort_conflict ){\r
+                Kind kn = k;\r
+                if( d_vars[index].getKind()==PLUS ){\r
+                  kn = MINUS;\r
+                }\r
+                if( kn!=k ){\r
+                  sum = NodeManager::currentNM()->mkNode( kn, v, lhs );\r
+                }\r
+              }\r
+            }\r
+            if( !sum.isNull() ){\r
+              assigned.push_back( slv_v );\r
+              Trace("qcf-tconstraint-debug") << "...set " << d_vars[slv_v] << " = " << sum << std::endl;\r
+              if( !setMatch( p, slv_v, sum ) ){\r
+                success = false;\r
+              }\r
+              p->d_tempCache.push_back( sum );\r
+            }\r
+          }else{\r
+            //must show that constraint is met\r
+            Node sum = NodeManager::currentNM()->mkNode( k, children );\r
+            Node eq = sum.eqNode( v );\r
+            if( !entailmentTest( p, eq ) ){\r
+              success = false;\r
+            }\r
+            p->d_tempCache.push_back( sum );\r
+          }\r
+        }\r
+      }\r
+\r
+      if( !success ){\r
+        break;\r
+      }\r
+    }\r
+    if( success ){\r
+      //check what is left to assign\r
+      d_unassigned.clear();\r
+      d_unassigned_tn.clear();\r
+      std::vector< int > unassigned[2];\r
+      std::vector< TypeNode > unassigned_tn[2];\r
+      for( int i=0; i<getNumVars(); i++ ){\r
+        if( d_match[i].isNull() ){\r
+          int rindex = d_var_mg.find( i )==d_var_mg.end() ? 1 : 0;\r
+          unassigned[rindex].push_back( i );\r
+          unassigned_tn[rindex].push_back( getVar( i ).getType() );\r
+          assigned.push_back( i );\r
+        }\r
+      }\r
+      d_unassigned_nvar = unassigned[0].size();\r
+      for( unsigned i=0; i<2; i++ ){\r
+        d_unassigned.insert( d_unassigned.end(), unassigned[i].begin(), unassigned[i].end() );\r
+        d_unassigned_tn.insert( d_unassigned_tn.end(), unassigned_tn[i].begin(), unassigned_tn[i].end() );\r
+      }\r
+      d_una_eqc_count.clear();\r
+      d_una_index = 0;\r
+    }\r
+  }\r
+\r
+  if( !d_unassigned.empty() && ( success || doContinue ) ){\r
+    Trace("qcf-check") << "Assign to unassigned..." << std::endl;\r
+    do {\r
+      if( doFail ){\r
+        Trace("qcf-check-unassign") << "Failure, try again..." << std::endl;\r
+      }\r
+      bool invalidMatch = false;\r
+      while( ( d_una_index>=0 && (int)d_una_index<(int)d_unassigned.size() ) || invalidMatch || doFail ){\r
+        invalidMatch = false;\r
+        if( !doFail && d_una_index==(int)d_una_eqc_count.size() ){\r
+          //check if it has now been assigned\r
+          if( d_una_index<d_unassigned_nvar ){\r
+            if( !isConstrainedVar( d_unassigned[d_una_index] ) ){\r
+              d_una_eqc_count.push_back( -1 );\r
+            }else{\r
+              d_var_mg[ d_unassigned[d_una_index] ]->reset( p, true, this );\r
+              d_una_eqc_count.push_back( 0 );\r
+            }\r
+          }else{\r
+            d_una_eqc_count.push_back( 0 );\r
+          }\r
+        }else{\r
+          bool failed = false;\r
+          if( !doFail ){\r
+            if( d_una_index<d_unassigned_nvar ){\r
+              if( !isConstrainedVar( d_unassigned[d_una_index] ) ){\r
+                Trace("qcf-check-unassign") << "Succeeded, variable unconstrained at " << d_una_index << std::endl;\r
+                d_una_index++;\r
+              }else if( d_var_mg[d_unassigned[d_una_index]]->getNextMatch( p, this ) ){\r
+                Trace("qcf-check-unassign") << "Succeeded match with mg at " << d_una_index << std::endl;\r
+                d_una_index++;\r
+              }else{\r
+                failed = true;\r
+                Trace("qcf-check-unassign") << "Failed match with mg at " << d_una_index << std::endl;\r
+              }\r
+            }else{\r
+              Assert( doFail || d_una_index==(int)d_una_eqc_count.size()-1 );\r
+              if( d_una_eqc_count[d_una_index]<(int)p->d_eqcs[d_unassigned_tn[d_una_index]].size() ){\r
+                int currIndex = d_una_eqc_count[d_una_index];\r
+                d_una_eqc_count[d_una_index]++;\r
+                Trace("qcf-check-unassign") << d_unassigned[d_una_index] << "->" << p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex] << std::endl;\r
+                if( setMatch( p, d_unassigned[d_una_index], p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex] ) ){\r
+                  d_match_term[d_unassigned[d_una_index]] = TNode::null();\r
+                  Trace("qcf-check-unassign") << "Succeeded match " << d_una_index << std::endl;\r
+                  d_una_index++;\r
+                }else{\r
+                  Trace("qcf-check-unassign") << "Failed match " << d_una_index << std::endl;\r
+                  invalidMatch = true;\r
+                }\r
+              }else{\r
+                failed = true;\r
+                Trace("qcf-check-unassign") << "No more matches " << d_una_index << std::endl;\r
+              }\r
+            }\r
+          }\r
+          if( doFail || failed ){\r
+            do{\r
+              if( !doFail ){\r
+                d_una_eqc_count.pop_back();\r
+              }else{\r
+                doFail = false;\r
+              }\r
+              d_una_index--;\r
+            }while( d_una_index>=0 && d_una_eqc_count[d_una_index]==-1 );\r
+          }\r
+        }\r
+      }\r
+      success = d_una_index>=0;\r
+      if( success ){\r
+        doFail = true;\r
+        Trace("qcf-check-unassign") << "  Try: " << std::endl;\r
+        for( unsigned i=0; i<d_unassigned.size(); i++ ){\r
+          int ui = d_unassigned[i];\r
+          if( !d_match[ui].isNull() ){\r
+            Trace("qcf-check-unassign") << "  Assigned #" << ui << " : " << d_vars[ui] << " -> " << d_match[ui] << std::endl;\r
+          }\r
+        }\r
+      }\r
+    }while( success && isMatchSpurious( p ) );\r
+  }\r
+  if( success ){\r
+    for( unsigned i=0; i<d_unassigned.size(); i++ ){\r
+      int ui = d_unassigned[i];\r
+      if( !d_match[ui].isNull() ){\r
+        Trace("qcf-check") << "  Assigned #" << ui << " : " << d_vars[ui] << " -> " << d_match[ui] << std::endl;\r
+      }\r
+    }\r
+    return true;\r
+  }else{\r
+    for( unsigned i=0; i<assigned.size(); i++ ){\r
+      d_match[ assigned[i] ] = TNode::null();\r
+    }\r
+    assigned.clear();\r
+    return false;\r
+  }\r
+}\r
+\r
+void QuantInfo::getMatch( std::vector< Node >& terms ){\r
+  for( unsigned i=0; i<d_q[0].getNumChildren(); i++ ){\r
+    //Node cv = qi->getCurrentValue( qi->d_match[i] );\r
+    int repVar = getCurrentRepVar( i );\r
+    Node cv;\r
+    //std::map< int, TNode >::iterator itmt = qi->d_match_term.find( repVar );\r
+    if( !d_match_term[repVar].isNull() ){\r
+      cv = d_match_term[repVar];\r
+    }else{\r
+      cv = d_match[repVar];\r
+    }\r
+    Debug("qcf-check-inst") << "INST : " << i << " -> " << cv << ", from " << d_match[i] << std::endl;\r
+    terms.push_back( cv );\r
+  }\r
+}\r
+\r
+void QuantInfo::revertMatch( std::vector< int >& assigned ) {\r
+  for( unsigned i=0; i<assigned.size(); i++ ){\r
+    d_match[ assigned[i] ] = TNode::null();\r
+  }\r
+}\r
+\r
+void QuantInfo::debugPrintMatch( const char * c ) {\r
+  for( int i=0; i<getNumVars(); i++ ){\r
+    Trace(c) << "  " << d_vars[i] << " -> ";\r
+    if( !d_match[i].isNull() ){\r
+      Trace(c) << d_match[i];\r
+    }else{\r
+      Trace(c) << "(unassigned) ";\r
+    }\r
+    if( !d_curr_var_deq[i].empty() ){\r
+      Trace(c) << ", DEQ{ ";\r
+      for( std::map< TNode, int >::iterator it = d_curr_var_deq[i].begin(); it != d_curr_var_deq[i].end(); ++it ){\r
+        Trace(c) << it->first << " ";\r
+      }\r
+      Trace(c) << "}";\r
+    }\r
+    if( !d_match_term[i].isNull() && d_match_term[i]!=d_match[i] ){\r
+      Trace(c) << ", EXP : " << d_match_term[i];\r
+    }\r
+    Trace(c) <<  std::endl;\r
+  }\r
+  if( !d_tconstraints.empty() ){\r
+    Trace(c) << "ADDITIONAL CONSTRAINTS : " << std::endl;\r
+    for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){\r
+      Trace(c) << "   " << it->first << " -> " << it->second << std::endl;\r
+    }\r
+  }\r
+}\r
+\r
+MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar ){\r
+  Trace("qcf-qregister-debug") << "Make match gen for " << n << ", isVar = " << isVar << std::endl;\r
+  std::vector< Node > qni_apps;\r
+  d_qni_size = 0;\r
+  if( isVar ){\r
+    Assert( qi->d_var_num.find( n )!=qi->d_var_num.end() );\r
+    if( n.getKind()==ITE ){\r
+      d_type = typ_ite_var;\r
+      d_type_not = false;\r
+      d_n = n;\r
+      d_children.push_back( MatchGen( qi, d_n[0] ) );\r
+      if( d_children[0].isValid() ){\r
+        d_type = typ_ite_var;\r
+        for( unsigned i=1; i<=2; i++ ){\r
+          Node nn = n.eqNode( n[i] );\r
+          d_children.push_back( MatchGen( qi, nn ) );\r
+          d_children[d_children.size()-1].d_qni_bound_except.push_back( 0 );\r
+          if( !d_children[d_children.size()-1].isValid() ){\r
+            setInvalid();\r
+            break;\r
+          }\r
+        }\r
+      }else{\r
+        d_type = typ_invalid;\r
+      }\r
+    }else{\r
+      d_type = isHandledUfTerm( n ) ? typ_var : typ_tsym;\r
+      d_qni_var_num[0] = qi->getVarNum( n );\r
+      d_qni_size++;\r
+      d_type_not = false;\r
+      d_n = n;\r
+      //Node f = getOperator( n );\r
+      for( unsigned j=0; j<d_n.getNumChildren(); j++ ){\r
+        Node nn = d_n[j];\r
+        Trace("qcf-qregister-debug") << "  " << d_qni_size;\r
+        if( qi->isVar( nn ) ){\r
+          int v = qi->d_var_num[nn];\r
+          Trace("qcf-qregister-debug") << " is var #" << v << std::endl;\r
+          d_qni_var_num[d_qni_size] = v;\r
+          //qi->addFuncParent( v, f, j );\r
+        }else{\r
+          Trace("qcf-qregister-debug") << " is gterm " << nn << std::endl;\r
+          d_qni_gterm[d_qni_size] = nn;\r
+        }\r
+        d_qni_size++;\r
+      }\r
+    }\r
+  }else{\r
+    if( n.hasBoundVar() ){\r
+      d_type_not = false;\r
+      d_n = n;\r
+      if( d_n.getKind()==NOT ){\r
+        d_n = d_n[0];\r
+        d_type_not = !d_type_not;\r
+      }\r
+\r
+      if( isHandledBoolConnective( d_n ) ){\r
+        //non-literals\r
+        d_type = typ_formula;\r
+        for( unsigned i=0; i<d_n.getNumChildren(); i++ ){\r
+          if( d_n.getKind()!=FORALL || i==1 ){\r
+            d_children.push_back( MatchGen( qi, d_n[i], false ) );\r
+            if( !d_children[d_children.size()-1].isValid() ){\r
+              setInvalid();\r
+              break;\r
+            }\r
+          }\r
+          /*\r
+          else if( isTop && n.getKind()==OR && d_children[d_children.size()-1].d_type==typ_var_eq ){\r
+            Trace("qcf-qregister-debug") << "Remove child, make built-in constraint" << std::endl;\r
+            //if variable equality/disequality at top level, remove immediately\r
+            bool cIsNot = d_children[d_children.size()-1].d_type_not;\r
+            Node cn = d_children[d_children.size()-1].d_n;\r
+            Assert( cn.getKind()==EQUAL );\r
+            Assert( p->d_qinfo[q].isVar( cn[0] ) || p->d_qinfo[q].isVar( cn[1] ) );\r
+            //make it a built-in constraint instead\r
+            for( unsigned i=0; i<2; i++ ){\r
+              if( p->d_qinfo[q].isVar( cn[i] ) ){\r
+                int v = p->d_qinfo[q].getVarNum( cn[i] );\r
+                Node cno = cn[i==0 ? 1 : 0];\r
+                p->d_qinfo[q].d_var_constraint[ cIsNot ? 0 : 1 ][v].push_back( cno );\r
+                break;\r
+              }\r
+            }\r
+            d_children.pop_back();\r
+          }\r
+          */\r
+        }\r
+      }else{\r
+        d_type = typ_invalid;\r
+        //literals\r
+        if( isHandledUfTerm( d_n ) ){\r
+          Assert( qi->isVar( d_n ) );\r
+          d_type = typ_pred;\r
+        }else if( d_n.getKind()==BOUND_VARIABLE ){\r
+          Assert( d_n.getType().isBoolean() );\r
+          d_type = typ_bool_var;\r
+        }else if( d_n.getKind()==EQUAL || options::qcfTConstraint() ){\r
+          for( unsigned i=0; i<d_n.getNumChildren(); i++ ){\r
+            if( d_n[i].hasBoundVar() ){\r
+              if( !qi->isVar( d_n[i] ) ){\r
+                Trace("qcf-qregister-debug")  << "ERROR : not var " << d_n[i] << std::endl;\r
+              }\r
+              Assert( qi->isVar( d_n[i] ) );\r
+              if( d_n.getKind()!=EQUAL && qi->isVar( d_n[i] ) ){\r
+                d_qni_var_num[i+1] = qi->d_var_num[d_n[i]];\r
+              }\r
+            }else{\r
+              d_qni_gterm[i] = d_n[i];\r
+            }\r
+          }\r
+          d_type = d_n.getKind()==EQUAL ? typ_eq : typ_tconstraint;\r
+          Trace("qcf-tconstraint") << "T-Constraint : " << d_n << std::endl;\r
+        }\r
+      }\r
+    }else{\r
+      //we will just evaluate\r
+      d_n = n;\r
+      d_type = typ_ground;\r
+    }\r
+    //if( d_type!=typ_invalid ){\r
+      //determine an efficient children ordering\r
+      //if( !d_children.empty() ){\r
+        //for( unsigned i=0; i<d_children.size(); i++ ){\r
+        //  d_children_order.push_back( i );\r
+        //}\r
+        //if( !d_n.isNull() && ( d_n.getKind()==OR || d_n.getKind()==AND || d_n.getKind()==IFF ) ){\r
+          //sort based on the type of the constraint : ground comes first, then literals, then others\r
+          //MatchGenSort mgs;\r
+          //mgs.d_mg = this;\r
+          //std::sort( d_children_order.begin(), d_children_order.end(), mgs );\r
+        //}\r
+      //}\r
+    //}\r
+  }\r
+  Trace("qcf-qregister-debug")  << "Done make match gen " << n << ", type = ";\r
+  debugPrintType( "qcf-qregister-debug", d_type, true );\r
+  Trace("qcf-qregister-debug") << std::endl;\r
+  //Assert( d_children.size()==d_children_order.size() );\r
+\r
+}\r
+\r
+void MatchGen::collectBoundVar( QuantInfo * qi, Node n, std::vector< int >& cbvars ) {\r
+  int v = qi->getVarNum( n );\r
+  if( v!=-1 && std::find( cbvars.begin(), cbvars.end(), v )==cbvars.end() ){\r
+    cbvars.push_back( v );\r
+  }\r
+  for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+    collectBoundVar( qi, n[i], cbvars );\r
+  }\r
+}\r
+\r
+void MatchGen::determineVariableOrder( QuantInfo * qi, std::vector< int >& bvars ) {\r
+  Trace("qcf-qregister-debug") << "Determine variable order " << d_n << std::endl;\r
+  bool isCom = d_type==typ_formula && ( d_n.getKind()==OR || d_n.getKind()==AND || d_n.getKind()==IFF );\r
+  std::map< int, std::vector< int > > c_to_vars;\r
+  std::map< int, std::vector< int > > vars_to_c;\r
+  std::map< int, int > vb_count;\r
+  std::map< int, int > vu_count;\r
+  std::vector< bool > assigned;\r
+  Trace("qcf-qregister-debug") << "Calculate bound variables..." << std::endl;\r
+  for( unsigned i=0; i<d_children.size(); i++ ){\r
+    collectBoundVar( qi, d_children[i].d_n, c_to_vars[i] );\r
+    assigned.push_back( false );\r
+    vb_count[i] = 0;\r
+    vu_count[i] = 0;\r
+    for( unsigned j=0; j<c_to_vars[i].size(); j++ ){\r
+      int v = c_to_vars[i][j];\r
+      vars_to_c[v].push_back( i );\r
+      if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){\r
+        vu_count[i]++;\r
+        if( !isCom ){\r
+          bvars.push_back( v );\r
+        }\r
+      }else{\r
+        vb_count[i]++;\r
+      }\r
+    }\r
+  }\r
+  if( isCom ){\r
+    //children that bind the least number of unbound variables go first\r
+    do {\r
+      int min_score = -1;\r
+      int min_score_index = -1;\r
+      for( unsigned i=0; i<d_children.size(); i++ ){\r
+        if( !assigned[i] ){\r
+          int score = vu_count[i];\r
+          if( min_score==-1 || score<min_score ){\r
+            min_score = score;\r
+            min_score_index = i;\r
+          }\r
+        }\r
+      }\r
+      Trace("qcf-qregister-debug") << "...assign child " << min_score_index << "/" << d_children.size() << std::endl;\r
+      Assert( min_score_index!=-1 );\r
+      //add to children order\r
+      d_children_order.push_back( min_score_index );\r
+      assigned[min_score_index] = true;\r
+      //if( vb_count[min_score_index]==0 ){\r
+      //  d_independent.push_back( min_score_index );\r
+      //}\r
+      //determine order internal to children\r
+      d_children[min_score_index].determineVariableOrder( qi, bvars );\r
+      Trace("qcf-qregister-debug")  << "...bind variables" << std::endl;\r
+      //now, make it a bound variable\r
+      for( unsigned i=0; i<c_to_vars[min_score_index].size(); i++ ){\r
+        int v = c_to_vars[min_score_index][i];\r
+        if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){\r
+          for( unsigned j=0; j<vars_to_c[v].size(); j++ ){\r
+            int vc = vars_to_c[v][j];\r
+            vu_count[vc]--;\r
+            vb_count[vc]++;\r
+          }\r
+          bvars.push_back( v );\r
+        }\r
+      }\r
+      Trace("qcf-qregister-debug") << "...done assign child " << min_score_index << std::endl;\r
+    }while( d_children_order.size()!=d_children.size() );\r
+    Trace("qcf-qregister-debug") << "Done assign variable ordering for " << d_n << std::endl;\r
+  }else{\r
+    for( unsigned i=0; i<d_children.size(); i++ ){\r
+      d_children_order.push_back( i );\r
+      d_children[i].determineVariableOrder( qi, bvars );\r
+    }\r
+  }\r
+}\r
+\r
+\r
+void MatchGen::reset_round( QuantConflictFind * p ) {\r
+  d_wasSet = false;\r
+  for( unsigned i=0; i<d_children.size(); i++ ){\r
+    d_children[i].reset_round( p );\r
+  }\r
+  for( std::map< int, TNode >::iterator it = d_qni_gterm.begin(); it != d_qni_gterm.end(); ++it ){\r
+    d_qni_gterm_rep[it->first] = p->getRepresentative( it->second );\r
+  }\r
+  if( d_type==typ_ground ){\r
+    int e = p->evaluate( d_n );\r
+    if( e==1 ){\r
+      d_ground_eval[0] = p->d_true;\r
+    }else if( e==-1 ){\r
+      d_ground_eval[0] = p->d_false;\r
+    }\r
+  }else if( d_type==typ_eq ){\r
+    for( unsigned i=0; i<d_n.getNumChildren(); i++ ){\r
+      if( !d_n[i].hasBoundVar() ){\r
+        d_ground_eval[i] = p->evaluateTerm( d_n[i] );\r
+      }\r
+    }\r
+  }\r
+  d_qni_bound_cons.clear();\r
+  d_qni_bound_cons_var.clear();\r
+  d_qni_bound.clear();\r
+}\r
+\r
+void MatchGen::reset( QuantConflictFind * p, bool tgt, QuantInfo * qi ) {\r
+  d_tgt = d_type_not ? !tgt : tgt;\r
+  Debug("qcf-match") << "     Reset for : " << d_n << ", type : ";\r
+  debugPrintType( "qcf-match", d_type );\r
+  Debug("qcf-match") << ", tgt = " << d_tgt << ", children = " << d_children.size() << " " << d_children_order.size() << std::endl;\r
+  d_qn.clear();\r
+  d_qni.clear();\r
+  d_qni_bound.clear();\r
+  d_child_counter = -1;\r
+  d_tgt_orig = d_tgt;\r
+\r
+  //set up processing matches\r
+  if( d_type==typ_invalid ){\r
+    //do nothing\r
+  }else if( d_type==typ_ground ){\r
+    if( d_ground_eval[0]==( d_tgt ? p->d_true : p->d_false ) ){\r
+      d_child_counter = 0;\r
+    }\r
+  }else if( d_type==typ_bool_var ){\r
+    //get current value of the variable\r
+    TNode n = qi->getCurrentValue( d_n );\r
+    int vn = qi->getCurrentRepVar( qi->getVarNum( n ) );\r
+    if( vn==-1 ){\r
+      //evaluate the value, see if it is compatible\r
+      int e = p->evaluate( n );\r
+      if( ( e==1 && d_tgt ) || ( e==0 && !d_tgt ) ){\r
+        d_child_counter = 0;\r
+      }\r
+    }else{\r
+      //unassigned, set match to true/false\r
+      d_qni_bound[0] = vn;\r
+      qi->setMatch( p, vn, d_tgt ? p->d_true : p->d_false );\r
+      d_child_counter = 0;\r
+    }\r
+    if( d_child_counter==0 ){\r
+      d_qn.push_back( NULL );\r
+    }\r
+  }else if( d_type==typ_var ){\r
+    Assert( isHandledUfTerm( d_n ) );\r
+    Node f = getOperator( p, d_n );\r
+    Debug("qcf-match-debug") << "       reset: Var will match operators of " << f << std::endl;\r
+    TermArgTrie * qni = p->getTermDatabase()->getTermArgTrie( Node::null(), f );\r
+    if( qni!=NULL ){\r
+      d_qn.push_back( qni );\r
+    }\r
+    d_matched_basis = false;\r
+  }else if( d_type==typ_tsym || d_type==typ_tconstraint ){\r
+    for( std::map< int, int >::iterator it = d_qni_var_num.begin(); it != d_qni_var_num.end(); ++it ){\r
+      int repVar = qi->getCurrentRepVar( it->second );\r
+      if( qi->d_match[repVar].isNull() ){\r
+        Debug("qcf-match-debug") << "Force matching on child #" << it->first << ", which is var #" << repVar << std::endl;\r
+        d_qni_bound[it->first] = repVar;\r
+      }\r
+    }\r
+    d_qn.push_back( NULL );\r
+  }else if( d_type==typ_pred || d_type==typ_eq ){\r
+    //add initial constraint\r
+    Node nn[2];\r
+    int vn[2];\r
+    if( d_type==typ_pred ){\r
+      nn[0] = qi->getCurrentValue( d_n );\r
+      vn[0] = qi->getCurrentRepVar( qi->getVarNum( nn[0] ) );\r
+      nn[1] = p->getRepresentative( d_tgt ? p->d_true : p->d_false );\r
+      vn[1] = -1;\r
+      d_tgt = true;\r
+    }else{\r
+      for( unsigned i=0; i<2; i++ ){\r
+        TNode nc;\r
+        std::map< int, TNode >::iterator it = d_qni_gterm_rep.find( i );\r
+        if( it!=d_qni_gterm_rep.end() ){\r
+          nc = it->second;\r
+        }else{\r
+          nc = d_n[i];\r
+        }\r
+        nn[i] = qi->getCurrentValue( nc );\r
+        vn[i] = qi->getCurrentRepVar( qi->getVarNum( nn[i] ) );\r
+      }\r
+    }\r
+    bool success;\r
+    if( vn[0]==-1 && vn[1]==-1 ){\r
+      //Trace("qcf-explain") << "    reset : " << d_n << " check ground values " << nn[0] << " " << nn[1] << " (tgt=" << d_tgt << ")" << std::endl;\r
+      Debug("qcf-match-debug") << "       reset: check ground values " << nn[0] << " " << nn[1] << " (" << d_tgt << ")" << std::endl;\r
+      //just compare values\r
+      if( d_tgt ){\r
+        success = p->areMatchEqual( nn[0], nn[1] );\r
+      }else{\r
+        if( p->d_effort==QuantConflictFind::effort_conflict ){\r
+          success = p->areDisequal( nn[0], nn[1] );\r
+        }else{\r
+          success = p->areMatchDisequal( nn[0], nn[1] );\r
+        }\r
+      }\r
+    }else{\r
+      //otherwise, add a constraint to a variable\r
+      if( vn[1]!=-1 && vn[0]==-1 ){\r
+        //swap\r
+        Node t = nn[1];\r
+        nn[1] = nn[0];\r
+        nn[0] = t;\r
+        vn[0] = vn[1];\r
+        vn[1] = -1;\r
+      }\r
+      Debug("qcf-match-debug") << "       reset: add constraint " << vn[0] << " -> " << nn[1] << " (vn=" << vn[1] << ")" << std::endl;\r
+      //add some constraint\r
+      int addc = qi->addConstraint( p, vn[0], nn[1], vn[1], d_tgt, false );\r
+      success = addc!=-1;\r
+      //if successful and non-redundant, store that we need to cleanup this\r
+      if( addc==1 ){\r
+        //Trace("qcf-explain") << "       reset: " << d_n << " add constraint " << vn[0] << " -> " << nn[1] << " (vn=" << vn[1] << ")" << ", d_tgt = " << d_tgt << std::endl;\r
+        for( unsigned i=0; i<2; i++ ){\r
+          if( vn[i]!=-1 && std::find( d_qni_bound_except.begin(), d_qni_bound_except.end(), i )==d_qni_bound_except.end() ){\r
+            d_qni_bound[vn[i]] = vn[i];\r
+          }\r
+        }\r
+        d_qni_bound_cons[vn[0]] = nn[1];\r
+        d_qni_bound_cons_var[vn[0]] = vn[1];\r
+      }\r
+    }\r
+    //if successful, we will bind values to variables\r
+    if( success ){\r
+      d_qn.push_back( NULL );\r
+    }\r
+  }else{\r
+    if( d_children.empty() ){\r
+      //add dummy\r
+      d_qn.push_back( NULL );\r
+    }else{\r
+      if( d_tgt && d_n.getKind()==FORALL ){\r
+        //do nothing\r
+      }else{\r
+        //reset the first child to d_tgt\r
+        d_child_counter = 0;\r
+        getChild( d_child_counter )->reset( p, d_tgt, qi );\r
+      }\r
+    }\r
+  }\r
+  d_binding = false;\r
+  d_wasSet = true;\r
+  Debug("qcf-match") << "     reset: Finished reset for " << d_n << ", success = " << ( !d_qn.empty() || d_child_counter!=-1 ) << std::endl;\r
+}\r
+\r
+bool MatchGen::getNextMatch( QuantConflictFind * p, QuantInfo * qi ) {\r
+  Debug("qcf-match") << "     Get next match for : " << d_n << ", type = ";\r
+  debugPrintType( "qcf-match", d_type );\r
+  Debug("qcf-match") << ", children = " << d_children.size() << ", binding = " << d_binding << std::endl;\r
+  if( d_type==typ_invalid || d_type==typ_ground ){\r
+    if( d_child_counter==0 ){\r
+      d_child_counter = -1;\r
+      return true;\r
+    }else{\r
+      d_wasSet = false;\r
+      return false;\r
+    }\r
+  }else if( d_type==typ_var || d_type==typ_eq || d_type==typ_pred || d_type==typ_bool_var || d_type==typ_tconstraint || d_type==typ_tsym ){\r
+    bool success = false;\r
+    bool terminate = false;\r
+    do {\r
+      bool doReset = false;\r
+      bool doFail = false;\r
+      if( !d_binding ){\r
+        if( doMatching( p, qi ) ){\r
+          Debug("qcf-match-debug") << "     - Matching succeeded" << std::endl;\r
+          d_binding = true;\r
+          d_binding_it = d_qni_bound.begin();\r
+          doReset = true;\r
+          //for tconstraint, add constraint\r
+          if( d_type==typ_tconstraint ){\r
+            std::map< Node, bool >::iterator it = qi->d_tconstraints.find( d_n );\r
+            if( it==qi->d_tconstraints.end() ){\r
+              qi->d_tconstraints[d_n] = d_tgt;\r
+              //store that we added this constraint\r
+              d_qni_bound_cons[0] = d_n;\r
+            }else if( d_tgt!=it->second ){\r
+              success = false;\r
+              terminate = true;\r
+            }\r
+          }\r
+        }else{\r
+          Debug("qcf-match-debug") << "     - Matching failed" << std::endl;\r
+          success = false;\r
+          terminate = true;\r
+        }\r
+      }else{\r
+        doFail = true;\r
+      }\r
+      if( d_binding ){\r
+        //also need to create match for each variable we bound\r
+        success = true;\r
+        Debug("qcf-match-debug") << "     Produce matches for bound variables by " << d_n << ", type = ";\r
+        debugPrintType( "qcf-match-debug", d_type );\r
+        Debug("qcf-match-debug") << "..." << std::endl;\r
+\r
+        while( ( success && d_binding_it!=d_qni_bound.end() ) || doFail ){\r
+          std::map< int, MatchGen * >::iterator itm;\r
+          if( !doFail ){\r
+            Debug("qcf-match-debug") << "       check variable " << d_binding_it->second << std::endl;\r
+            itm = qi->d_var_mg.find( d_binding_it->second );\r
+          }\r
+          if( doFail || ( d_binding_it->first!=0 && itm!=qi->d_var_mg.end() ) ){\r
+            Debug("qcf-match-debug") << "       we had bound variable " << d_binding_it->second << ", reset = " << doReset << std::endl;\r
+            if( doReset ){\r
+              itm->second->reset( p, true, qi );\r
+            }\r
+            if( doFail || !itm->second->getNextMatch( p, qi ) ){\r
+              do {\r
+                if( d_binding_it==d_qni_bound.begin() ){\r
+                  Debug("qcf-match-debug") << "       failed." << std::endl;\r
+                  success = false;\r
+                }else{\r
+                  --d_binding_it;\r
+                  Debug("qcf-match-debug") << "       decrement..." << std::endl;\r
+                }\r
+              }while( success && ( d_binding_it->first==0 || qi->d_var_mg.find( d_binding_it->second )==qi->d_var_mg.end() ) );\r
+              doReset = false;\r
+              doFail = false;\r
+            }else{\r
+              Debug("qcf-match-debug") << "       increment..." << std::endl;\r
+              ++d_binding_it;\r
+              doReset = true;\r
+            }\r
+          }else{\r
+            Debug("qcf-match-debug") << "       skip..." << d_binding_it->second << std::endl;\r
+            ++d_binding_it;\r
+            doReset = true;\r
+          }\r
+        }\r
+        if( !success ){\r
+          d_binding = false;\r
+        }else{\r
+          terminate = true;\r
+          if( d_binding_it==d_qni_bound.begin() ){\r
+            d_binding = false;\r
+          }\r
+        }\r
+      }\r
+    }while( !terminate );\r
+    //if not successful, clean up the variables you bound\r
+    if( !success ){\r
+      if( d_type==typ_eq || d_type==typ_pred ){\r
+        //clean up the constraints you added\r
+        for( std::map< int, TNode >::iterator it = d_qni_bound_cons.begin(); it != d_qni_bound_cons.end(); ++it ){\r
+          if( !it->second.isNull() ){\r
+            Debug("qcf-match") << "       Clean up bound var " << it->first << (d_tgt ? "!" : "") << " = " << it->second << std::endl;\r
+            std::map< int, int >::iterator itb = d_qni_bound_cons_var.find( it->first );\r
+            int vn = itb!=d_qni_bound_cons_var.end() ? itb->second : -1;\r
+            //Trace("qcf-explain") << "       cleanup: " << d_n << " remove constraint " << it->first << " -> " << it->second << " (vn=" << vn << ")" << ", d_tgt = " << d_tgt << std::endl;\r
+            qi->addConstraint( p, it->first, it->second, vn, d_tgt, true );\r
+          }\r
+        }\r
+        d_qni_bound_cons.clear();\r
+        d_qni_bound_cons_var.clear();\r
+        d_qni_bound.clear();\r
+      }else{\r
+        //clean up the matches you set\r
+        for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){\r
+          Debug("qcf-match") << "       Clean up bound var " << it->second << std::endl;\r
+          Assert( it->second<qi->getNumVars() );\r
+          qi->d_match[ it->second ] = TNode::null();\r
+          qi->d_match_term[ it->second ] = TNode::null();\r
+        }\r
+        d_qni_bound.clear();\r
+      }\r
+      if( d_type==typ_tconstraint ){\r
+        //remove constraint if applicable\r
+        if( d_qni_bound_cons.find( 0 )!=d_qni_bound_cons.end() ){\r
+          qi->d_tconstraints.erase( d_n );\r
+          d_qni_bound_cons.clear();\r
+        }\r
+      }\r
+      /*\r
+      if( d_type==typ_var && p->d_effort==QuantConflictFind::effort_mc && !d_matched_basis ){\r
+        d_matched_basis = true;\r
+        Node f = getOperator( d_n );\r
+        TNode mbo = p->getQuantifiersEngine()->getTermDatabase()->getModelBasisOpTerm( f );\r
+        if( qi->setMatch( p, d_qni_var_num[0], mbo ) ){\r
+          success = true;\r
+          d_qni_bound[0] = d_qni_var_num[0];\r
+        }\r
+      }\r
+      */\r
+    }\r
+    Debug("qcf-match") << "    ...finished matching for " << d_n << ", success = " << success << std::endl;\r
+    d_wasSet = success;\r
+    return success;\r
+  }else if( d_type==typ_formula || d_type==typ_ite_var ){\r
+    bool success = false;\r
+    if( d_child_counter<0 ){\r
+      if( d_child_counter<-1 ){\r
+        success = true;\r
+        d_child_counter = -1;\r
+      }\r
+    }else{\r
+      while( !success && d_child_counter>=0 ){\r
+        //transition system based on d_child_counter\r
+        if( d_n.getKind()==OR || d_n.getKind()==AND ){\r
+          if( (d_n.getKind()==AND)==d_tgt ){\r
+            //all children must match simultaneously\r
+            if( getChild( d_child_counter )->getNextMatch( p, qi ) ){\r
+              if( d_child_counter<(int)(getNumChildren()-1) ){\r
+                d_child_counter++;\r
+                Debug("qcf-match-debug") << "       Reset child " << d_child_counter << " of " << d_n << std::endl;\r
+                getChild( d_child_counter )->reset( p, d_tgt, qi );\r
+              }else{\r
+                success = true;\r
+              }\r
+            }else{\r
+              //if( std::find( d_independent.begin(), d_independent.end(), d_child_counter )!=d_independent.end() ){\r
+              //  d_child_counter--;\r
+              //}else{\r
+              d_child_counter--;\r
+              //}\r
+            }\r
+          }else{\r
+            //one child must match\r
+            if( !getChild( d_child_counter )->getNextMatch( p, qi ) ){\r
+              if( d_child_counter<(int)(getNumChildren()-1) ){\r
+                d_child_counter++;\r
+                Debug("qcf-match-debug") << "       Reset child " << d_child_counter << " of " << d_n << ", one match" << std::endl;\r
+                getChild( d_child_counter )->reset( p, d_tgt, qi );\r
+              }else{\r
+                d_child_counter = -1;\r
+              }\r
+            }else{\r
+              success = true;\r
+            }\r
+          }\r
+        }else if( d_n.getKind()==IFF ){\r
+          //construct match based on both children\r
+          if( d_child_counter%2==0 ){\r
+            if( getChild( 0 )->getNextMatch( p, qi ) ){\r
+              d_child_counter++;\r
+              getChild( 1 )->reset( p, d_child_counter==1, qi );\r
+            }else{\r
+              if( d_child_counter==0 ){\r
+                d_child_counter = 2;\r
+                getChild( 0 )->reset( p, !d_tgt, qi );\r
+              }else{\r
+                d_child_counter = -1;\r
+              }\r
+            }\r
+          }\r
+          if( d_child_counter>=0 && d_child_counter%2==1 ){\r
+            if( getChild( 1 )->getNextMatch( p, qi ) ){\r
+              success = true;\r
+            }else{\r
+              d_child_counter--;\r
+            }\r
+          }\r
+        }else if( d_n.getKind()==ITE ){\r
+          if( d_child_counter%2==0 ){\r
+            int index1 = d_child_counter==4 ? 1 : 0;\r
+            if( getChild( index1 )->getNextMatch( p, qi ) ){\r
+              d_child_counter++;\r
+              getChild( d_child_counter==5 ? 2 : (d_tgt==(d_child_counter==1) ? 1 : 2) )->reset( p, d_tgt, qi );\r
+            }else{\r
+              if( d_child_counter==4 || ( d_type==typ_ite_var && d_child_counter==2 ) ){\r
+                d_child_counter = -1;\r
+              }else{\r
+                d_child_counter +=2;\r
+                getChild( d_child_counter==2 ? 0 : 1 )->reset( p, d_child_counter==2 ? !d_tgt : d_tgt, qi );\r
+              }\r
+            }\r
+          }\r
+          if( d_child_counter>=0 && d_child_counter%2==1 ){\r
+            int index2 = d_child_counter==5 ? 2 : (d_tgt==(d_child_counter==1) ? 1 : 2);\r
+            if( getChild( index2 )->getNextMatch( p, qi ) ){\r
+              success = true;\r
+            }else{\r
+              d_child_counter--;\r
+            }\r
+          }\r
+        }else if( d_n.getKind()==FORALL ){\r
+          if( getChild( d_child_counter )->getNextMatch( p, qi ) ){\r
+            success = true;\r
+          }else{\r
+            d_child_counter = -1;\r
+          }\r
+        }\r
+      }\r
+        d_wasSet = success;\r
+      Debug("qcf-match") << "    ...finished construct match for " << d_n << ", success = " << success << std::endl;\r
+      return success;\r
+    }\r
+  }\r
+  Debug("qcf-match") << "    ...already finished for " << d_n << std::endl;\r
+  return false;\r
+}\r
+\r
+bool MatchGen::getExplanation( QuantConflictFind * p, QuantInfo * qi, std::vector< Node >& exp ) {\r
+  if( d_type==typ_eq ){\r
+    Node n[2];\r
+    for( unsigned i=0; i<2; i++ ){\r
+      Trace("qcf-explain") << "Explain term " << d_n[i] << "..." << std::endl;\r
+      n[i] = getExplanationTerm( p, qi, d_n[i], exp );\r
+    }\r
+    Node eq = n[0].eqNode( n[1] );\r
+    if( !d_tgt_orig ){\r
+      eq = eq.negate();\r
+    }\r
+    exp.push_back( eq );\r
+    Trace("qcf-explain") << "Explanation for " << d_n << " (tgt=" << d_tgt_orig << ") is " << eq << ", set = " << d_wasSet << std::endl;\r
+    return true;\r
+  }else if( d_type==typ_pred ){\r
+    Trace("qcf-explain") << "Explain term " << d_n << "..." << std::endl;\r
+    Node n = getExplanationTerm( p, qi, d_n, exp );\r
+    if( !d_tgt_orig ){\r
+      n = n.negate();\r
+    }\r
+    exp.push_back( n );\r
+    Trace("qcf-explain") << "Explanation for " << d_n << " (tgt=" << d_tgt_orig << ") is " << n << ", set = " << d_wasSet << std::endl;\r
+    return true;\r
+  }else if( d_type==typ_formula ){\r
+    Trace("qcf-explain") << "Explanation get for " << d_n << ", counter = " << d_child_counter << ", tgt = " << d_tgt_orig << ", set = " << d_wasSet << std::endl;\r
+    if( d_n.getKind()==OR || d_n.getKind()==AND ){\r
+      if( (d_n.getKind()==AND)==d_tgt ){\r
+        for( unsigned i=0; i<getNumChildren(); i++ ){\r
+          if( !getChild( i )->getExplanation( p, qi, exp ) ){\r
+            return false;\r
+          }\r
+        }\r
+      }else{\r
+        return getChild( d_child_counter )->getExplanation( p, qi, exp );\r
+      }\r
+    }else if( d_n.getKind()==IFF ){\r
+      for( unsigned i=0; i<2; i++ ){\r
+        if( !getChild( i )->getExplanation( p, qi, exp ) ){\r
+          return false;\r
+        }\r
+      }\r
+    }else if( d_n.getKind()==ITE ){\r
+      for( unsigned i=0; i<3; i++ ){\r
+        bool isActive = ( ( i==0 && d_child_counter!=5 ) ||\r
+                          ( i==1 && d_child_counter!=( d_tgt ? 3 : 1 ) ) ||\r
+                          ( i==2 && d_child_counter!=( d_tgt ? 1 : 3 ) ) );\r
+        if( isActive ){\r
+          if( !getChild( i )->getExplanation( p, qi, exp ) ){\r
+            return false;\r
+          }\r
+        }\r
+      }\r
+    }else{\r
+      return false;\r
+    }\r
+    return true;\r
+  }else{\r
+    return false;\r
+  }\r
+}\r
+\r
+Node MatchGen::getExplanationTerm( QuantConflictFind * p, QuantInfo * qi, Node t, std::vector< Node >& exp ) {\r
+  Node v = qi->getCurrentExpValue( t );\r
+  if( isHandledUfTerm( t ) ){\r
+    for( unsigned i=0; i<t.getNumChildren(); i++ ){\r
+      Node vi = getExplanationTerm( p, qi, t[i], exp );\r
+      if( vi!=v[i] ){\r
+        Node eq = vi.eqNode( v[i] );\r
+        if( std::find( exp.begin(), exp.end(), eq )==exp.end() ){\r
+          Trace("qcf-explain") << "  add : " << eq << "." << std::endl;\r
+          exp.push_back( eq );\r
+        }\r
+      }\r
+    }\r
+  }\r
+  return v;\r
+}\r
+\r
+bool MatchGen::doMatching( QuantConflictFind * p, QuantInfo * qi ) {\r
+  if( !d_qn.empty() ){\r
+    if( d_qn[0]==NULL ){\r
+      d_qn.clear();\r
+      return true;\r
+    }else{\r
+      Assert( d_type==typ_var );\r
+      Assert( d_qni_size>0 );\r
+      bool invalidMatch;\r
+      do {\r
+        invalidMatch = false;\r
+        Debug("qcf-match-debug") << "       Do matching " << d_n << " " << d_qn.size() << " " << d_qni.size() << std::endl;\r
+        if( d_qn.size()==d_qni.size()+1 ) {\r
+          int index = (int)d_qni.size();\r
+          //initialize\r
+          TNode val;\r
+          std::map< int, int >::iterator itv = d_qni_var_num.find( index );\r
+          if( itv!=d_qni_var_num.end() ){\r
+            //get the representative variable this variable is equal to\r
+            int repVar = qi->getCurrentRepVar( itv->second );\r
+            Debug("qcf-match-debug") << "       Match " << index << " is a variable " << itv->second << ", which is repVar " << repVar << std::endl;\r
+            //get the value the rep variable\r
+            //std::map< int, TNode >::iterator itm = qi->d_match.find( repVar );\r
+            if( !qi->d_match[repVar].isNull() ){\r
+              val = qi->d_match[repVar];\r
+              Debug("qcf-match-debug") << "       Variable is already bound to " << val << std::endl;\r
+            }else{\r
+              //binding a variable\r
+              d_qni_bound[index] = repVar;\r
+              std::map< TNode, TermArgTrie >::iterator it = d_qn[index]->d_data.begin();\r
+              if( it != d_qn[index]->d_data.end() ) {\r
+                d_qni.push_back( it );\r
+                //set the match\r
+                if( qi->setMatch( p, d_qni_bound[index], it->first ) ){\r
+                  Debug("qcf-match-debug") << "       Binding variable" << std::endl;\r
+                  if( d_qn.size()<d_qni_size ){\r
+                    d_qn.push_back( &it->second );\r
+                  }\r
+                }else{\r
+                  Debug("qcf-match") << "       Binding variable, currently fail." << std::endl;\r
+                  invalidMatch = true;\r
+                }\r
+              }else{\r
+                Debug("qcf-match-debug") << "       Binding variable, fail, no more variables to bind" << std::endl;\r
+                d_qn.pop_back();\r
+              }\r
+            }\r
+          }else{\r
+            Debug("qcf-match-debug") << "       Match " << index << " is ground term" << std::endl;\r
+            Assert( d_qni_gterm.find( index )!=d_qni_gterm.end() );\r
+            Assert( d_qni_gterm_rep.find( index )!=d_qni_gterm_rep.end() );\r
+            val = d_qni_gterm_rep[index];\r
+            Assert( !val.isNull() );\r
+          }\r
+          if( !val.isNull() ){\r
+            //constrained by val\r
+            std::map< TNode, TermArgTrie >::iterator it = d_qn[index]->d_data.find( val );\r
+            if( it!=d_qn[index]->d_data.end() ){\r
+              Debug("qcf-match-debug") << "       Match" << std::endl;\r
+              d_qni.push_back( it );\r
+              if( d_qn.size()<d_qni_size ){\r
+                d_qn.push_back( &it->second );\r
+              }\r
+            }else{\r
+              Debug("qcf-match-debug") << "       Failed to match" << std::endl;\r
+              d_qn.pop_back();\r
+            }\r
+          }\r
+        }else{\r
+          Assert( d_qn.size()==d_qni.size() );\r
+          int index = d_qni.size()-1;\r
+          //increment if binding this variable\r
+          bool success = false;\r
+          std::map< int, int >::iterator itb = d_qni_bound.find( index );\r
+          if( itb!=d_qni_bound.end() ){\r
+            d_qni[index]++;\r
+            if( d_qni[index]!=d_qn[index]->d_data.end() ){\r
+              success = true;\r
+              if( qi->setMatch( p, itb->second, d_qni[index]->first ) ){\r
+                Debug("qcf-match-debug") << "       Bind next variable" << std::endl;\r
+                if( d_qn.size()<d_qni_size ){\r
+                  d_qn.push_back( &d_qni[index]->second );\r
+                }\r
+              }else{\r
+                Debug("qcf-match-debug") << "       Bind next variable, currently fail" << std::endl;\r
+                invalidMatch = true;\r
+              }\r
+            }else{\r
+              qi->d_match[ itb->second ] = TNode::null();\r
+              qi->d_match_term[ itb->second ] = TNode::null();\r
+              Debug("qcf-match-debug") << "       Bind next variable, no more variables to bind" << std::endl;\r
+            }\r
+          }else{\r
+            //TODO : if it equal to something else, also try that\r
+          }\r
+          //if not incrementing, move to next\r
+          if( !success ){\r
+            d_qn.pop_back();\r
+            d_qni.pop_back();\r
+          }\r
+        }\r
+      }while( ( !d_qn.empty() && d_qni.size()!=d_qni_size ) || invalidMatch );\r
+      if( d_qni.size()==d_qni_size ){\r
+        //Assert( !d_qni[d_qni.size()-1]->second.d_data.empty() );\r
+        //Debug("qcf-match-debug") << "       We matched " << d_qni[d_qni.size()-1]->second.d_children.begin()->first << std::endl;\r
+        Assert( !d_qni[d_qni.size()-1]->second.d_data.empty() );\r
+        TNode t = d_qni[d_qni.size()-1]->second.d_data.begin()->first;\r
+        Debug("qcf-match-debug") << "       " << d_n << " matched " << t << std::endl;\r
+        qi->d_match_term[d_qni_var_num[0]] = t;\r
+        //set the match terms\r
+        for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){\r
+          Debug("qcf-match-debug") << "       position " << it->first << " bounded " << it->second << " / " << qi->d_q[0].getNumChildren() << std::endl;\r
+          //if( it->second<(int)qi->d_q[0].getNumChildren() ){   //if it is an actual variable, we are interested in knowing the actual term\r
+          if( it->first>0 ){\r
+            Assert( !qi->d_match[ it->second ].isNull() );\r
+            Assert( p->areEqual( t[it->first-1], qi->d_match[ it->second ] ) );\r
+            qi->d_match_term[it->second] = t[it->first-1];\r
+          }\r
+          //}\r
+        }\r
+      }\r
+    }\r
+  }\r
+  return !d_qn.empty();\r
+}\r
+\r
+void MatchGen::debugPrintType( const char * c, short typ, bool isTrace ) {\r
+  if( isTrace ){\r
+    switch( typ ){\r
+    case typ_invalid: Trace(c) << "invalid";break;\r
+    case typ_ground: Trace(c) << "ground";break;\r
+    case typ_eq: Trace(c) << "eq";break;\r
+    case typ_pred: Trace(c) << "pred";break;\r
+    case typ_formula: Trace(c) << "formula";break;\r
+    case typ_var: Trace(c) << "var";break;\r
+    case typ_ite_var: Trace(c) << "ite_var";break;\r
+    case typ_bool_var: Trace(c) << "bool_var";break;\r
+    }\r
+  }else{\r
+    switch( typ ){\r
+    case typ_invalid: Debug(c) << "invalid";break;\r
+    case typ_ground: Debug(c) << "ground";break;\r
+    case typ_eq: Debug(c) << "eq";break;\r
+    case typ_pred: Debug(c) << "pred";break;\r
+    case typ_formula: Debug(c) << "formula";break;\r
+    case typ_var: Debug(c) << "var";break;\r
+    case typ_ite_var: Debug(c) << "ite_var";break;\r
+    case typ_bool_var: Debug(c) << "bool_var";break;\r
+    }\r
+  }\r
+}\r
+\r
+void MatchGen::setInvalid() {\r
+  d_type = typ_invalid;\r
+  d_children.clear();\r
+}\r
+\r
+bool MatchGen::isHandledBoolConnective( TNode n ) {\r
+  return n.getType().isBoolean() && ( n.getKind()==OR || n.getKind()==AND || n.getKind()==IFF || n.getKind()==ITE || n.getKind()==FORALL || n.getKind()==NOT );\r
+}\r
+\r
+bool MatchGen::isHandledUfTerm( TNode n ) {\r
+  //return n.getKind()==APPLY_UF || n.getKind()==STORE || n.getKind()==SELECT ||\r
+  //       n.getKind()==APPLY_CONSTRUCTOR || n.getKind()==APPLY_SELECTOR_TOTAL || n.getKind()==APPLY_TESTER;\r
+  return inst::Trigger::isAtomicTriggerKind( n.getKind() );  \r
+}\r
+\r
+Node MatchGen::getOperator( QuantConflictFind * p, Node n ) {\r
+  if( isHandledUfTerm( n ) ){\r
+    return p->getQuantifiersEngine()->getTermDatabase()->getOperator( n );\r
+  }else{\r
+    return Node::null();\r
+  }\r
+}\r
+\r
+bool MatchGen::isHandled( TNode n ) {\r
+  if( n.getKind()!=BOUND_VARIABLE && n.hasBoundVar() ){\r
+    if( !isHandledBoolConnective( n ) && !isHandledUfTerm( n ) && n.getKind()!=EQUAL && n.getKind()!=ITE ){\r
+      return false;\r
+    }\r
+    for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+      if( !isHandled( n[i] ) ){\r
+        return false;\r
+      }\r
+    }\r
+  }\r
+  return true;\r
+}\r
+\r
+\r
+QuantConflictFind::QuantConflictFind( QuantifiersEngine * qe, context::Context* c ) :\r
+QuantifiersModule( qe ),\r
+d_c( c ),\r
+d_conflict( c, false ),\r
+d_qassert( c ) {\r
+  d_fid_count = 0;\r
+  d_true = NodeManager::currentNM()->mkConst<bool>(true);\r
+  d_false = NodeManager::currentNM()->mkConst<bool>(false);\r
+}\r
+\r
+Node QuantConflictFind::mkEqNode( Node a, Node b ) {\r
+  if( a.getType().isBoolean() ){\r
+    return a.iffNode( b );\r
+  }else{\r
+    return a.eqNode( b );\r
+  }\r
+}\r
+\r
+//-------------------------------------------------- registration\r
+\r
+void QuantConflictFind::registerQuantifier( Node q ) {\r
+  if( d_quantEngine->hasOwnership( q, this ) ){\r
+    d_quants.push_back( q );\r
+    d_quant_id[q] = d_quants.size();\r
+    Trace("qcf-qregister") << "Register ";\r
+    debugPrintQuant( "qcf-qregister", q );\r
+    Trace("qcf-qregister") << " : " << q << std::endl;\r
+    //make QcfNode structure\r
+    Trace("qcf-qregister") << "- Get relevant equality/disequality pairs, calculate flattening..." << std::endl;\r
+    d_qinfo[q].initialize( q, q[1] );\r
+\r
+    //debug print\r
+    Trace("qcf-qregister") << "- Flattened structure is :" << std::endl;\r
+    Trace("qcf-qregister") << "    ";\r
+    debugPrintQuantBody( "qcf-qregister", q, q[1] );\r
+    Trace("qcf-qregister") << std::endl;\r
+    if( d_qinfo[q].d_vars.size()>q[0].getNumChildren() ){\r
+      Trace("qcf-qregister") << "  with additional constraints : " << std::endl;\r
+      for( unsigned j=q[0].getNumChildren(); j<d_qinfo[q].d_vars.size(); j++ ){\r
+        Trace("qcf-qregister") << "    ?x" << j << " = ";\r
+        debugPrintQuantBody( "qcf-qregister", q, d_qinfo[q].d_vars[j], false );\r
+        Trace("qcf-qregister") << std::endl;\r
+      }\r
+    }\r
+\r
+    Trace("qcf-qregister") << "Done registering quantifier." << std::endl;\r
+  }\r
+}\r
+\r
+int QuantConflictFind::evaluate( Node n, bool pref, bool hasPref ) {\r
+  int ret = 0;\r
+  if( n.getKind()==EQUAL ){\r
+    Node n1 = evaluateTerm( n[0] );\r
+    Node n2 = evaluateTerm( n[1] );\r
+    Debug("qcf-eval") << "Evaluate : Normalize " << n << " to " << n1 << " = " << n2 << std::endl;\r
+    if( areEqual( n1, n2 ) ){\r
+      ret = 1;\r
+    }else if( areDisequal( n1, n2 ) ){\r
+      ret = -1;\r
+    }\r
+    //else if( d_effort>QuantConflictFind::effort_conflict ){\r
+    //  ret = -1;\r
+    //}\r
+  }else if( MatchGen::isHandledUfTerm( n ) ){  //predicate\r
+    Node nn = evaluateTerm( n );\r
+    Debug("qcf-eval") << "Evaluate : Normalize " << nn << " to " << n << std::endl;\r
+    if( areEqual( nn, d_true ) ){\r
+      ret = 1;\r
+    }else if( areEqual( nn, d_false ) ){\r
+      ret = -1;\r
+    }\r
+    //else if( d_effort>QuantConflictFind::effort_conflict ){\r
+    //  ret = -1;\r
+    //}\r
+  }else if( n.getKind()==NOT ){\r
+    return -evaluate( n[0] );\r
+  }else if( n.getKind()==ITE ){\r
+    int cev1 = evaluate( n[0] );\r
+    int cevc[2] = { 0, 0 };\r
+    for( unsigned i=0; i<2; i++ ){\r
+      if( ( i==0 && cev1!=-1 ) || ( i==1 && cev1!=1 ) ){\r
+        cevc[i] = evaluate( n[i+1] );\r
+        if( cev1!=0 ){\r
+          ret = cevc[i];\r
+          break;\r
+        }else if( cevc[i]==0 ){\r
+          break;\r
+        }\r
+      }\r
+    }\r
+    if( ret==0 && cevc[0]!=0 && cevc[0]==cevc[1] ){\r
+      ret = cevc[0];\r
+    }\r
+  }else if( n.getKind()==IFF ){\r
+    int cev1 = evaluate( n[0] );\r
+    if( cev1!=0 ){\r
+      int cev2 = evaluate( n[1] );\r
+      if( cev2!=0 ){\r
+        ret = cev1==cev2 ? 1 : -1;\r
+      }\r
+    }\r
+\r
+  }else{\r
+    int ssval = 0;\r
+    if( n.getKind()==OR ){\r
+      ssval = 1;\r
+    }else if( n.getKind()==AND ){\r
+      ssval = -1;\r
+    }\r
+    bool isUnk = false;\r
+    for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+      int cev = evaluate( n[i] );\r
+      if( cev==ssval ){\r
+        ret = ssval;\r
+        break;\r
+      }else if( cev==0 ){\r
+        isUnk = true;\r
+      }\r
+    }\r
+    if( ret==0 && !isUnk ){\r
+      ret = -ssval;\r
+    }\r
+  }\r
+  Debug("qcf-eval") << "Evaluate " << n << " to " << ret << std::endl;\r
+  return ret;\r
+}\r
+\r
+short QuantConflictFind::getMaxQcfEffort() {\r
+  if( options::qcfMode()==QCF_CONFLICT_ONLY ){\r
+    return effort_conflict;\r
+  }else if( options::qcfMode()==QCF_PROP_EQ ){\r
+    return effort_prop_eq;\r
+  }else if( options::qcfMode()==QCF_MC ){\r
+    return effort_mc;\r
+  }else{\r
+    return 0;\r
+  }\r
+}\r
+\r
+bool QuantConflictFind::areMatchEqual( TNode n1, TNode n2 ) {\r
+  //if( d_effort==QuantConflictFind::effort_mc ){\r
+  //  return n1==n2 || !areDisequal( n1, n2 );\r
+  //}else{\r
+  return n1==n2;\r
+  //}\r
+}\r
+\r
+bool QuantConflictFind::areMatchDisequal( TNode n1, TNode n2 ) {\r
+  //if( d_effort==QuantConflictFind::effort_conflict ){\r
+  //  return areDisequal( n1, n2 );\r
+  //}else{\r
+  return n1!=n2;\r
+  //}\r
+}\r
+\r
+//-------------------------------------------------- handling assertions / eqc\r
+\r
+void QuantConflictFind::assertNode( Node q ) {\r
+  if( d_quantEngine->hasOwnership( q, this ) ){\r
+    Trace("qcf-proc") << "QCF : assertQuantifier : ";\r
+    debugPrintQuant("qcf-proc", q);\r
+    Trace("qcf-proc") << std::endl;\r
+    d_qassert.push_back( q );\r
+    //set the eqRegistries that this depends on to true\r
+    //for( std::map< EqRegistry *, bool >::iterator it = d_qinfo[q].d_rel_eqr.begin(); it != d_qinfo[q].d_rel_eqr.end(); ++it ){\r
+    //  it->first->d_active.set( true );\r
+    //}\r
+  }\r
+}\r
+\r
+Node QuantConflictFind::evaluateTerm( Node n ) {\r
+  if( MatchGen::isHandledUfTerm( n ) ){\r
+    Node f = MatchGen::getOperator( this, n );\r
+    Node nn;\r
+    if( getEqualityEngine()->hasTerm( n ) ){\r
+      nn = getTermDatabase()->existsTerm( f, n );\r
+    }else{\r
+      std::vector< TNode > args;\r
+      for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+        Node c = evaluateTerm( n[i] );\r
+        args.push_back( c );\r
+      }\r
+      nn = getTermDatabase()->d_func_map_trie[f].existsTerm( args );\r
+    }\r
+    if( !nn.isNull() ){\r
+      Debug("qcf-eval") << "GT: Term " << nn << " for " << n << " hasTerm = " << getEqualityEngine()->hasTerm( n )  << std::endl;\r
+      return getRepresentative( nn );\r
+    }else{\r
+      Debug("qcf-eval") << "GT: No term for " << n << " hasTerm = " << getEqualityEngine()->hasTerm( n )  << std::endl;\r
+      return n;\r
+    }\r
+  }else if( n.getKind()==ITE ){\r
+    int v = evaluate( n[0], false, false );\r
+    if( v==1 ){\r
+      return evaluateTerm( n[1] );\r
+    }else if( v==-1 ){\r
+      return evaluateTerm( n[2] );\r
+    }\r
+  }\r
+  return getRepresentative( n );\r
+}\r
+\r
+/** new node */\r
+void QuantConflictFind::newEqClass( Node n ) {\r
+  //Trace("qcf-proc-debug") << "QCF : newEqClass : " << n << std::endl;\r
+  //Trace("qcf-proc2-debug") << "QCF : finished newEqClass : " << n << std::endl;\r
+}\r
+\r
+/** merge */\r
+void QuantConflictFind::merge( Node a, Node b ) {\r
+\r
+}\r
+\r
+/** assert disequal */\r
+void QuantConflictFind::assertDisequal( Node a, Node b ) {\r
+\r
+}\r
+\r
+//-------------------------------------------------- check function\r
+\r
+bool QuantConflictFind::needsCheck( Theory::Effort level ) {\r
+  bool performCheck = false;\r
+  if( options::quantConflictFind() && !d_conflict ){\r
+    if( level==Theory::EFFORT_LAST_CALL ){\r
+      performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_LAST_CALL;\r
+    }else if( level==Theory::EFFORT_FULL ){\r
+      performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_DEFAULT;\r
+    }else if( level==Theory::EFFORT_STANDARD ){\r
+      performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_STD;\r
+    }\r
+  }\r
+  return performCheck;\r
+}\r
+\r
+void QuantConflictFind::reset_round( Theory::Effort level ) {\r
+  d_needs_computeRelEqr = true;\r
+}\r
+\r
+/** check */\r
+void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {\r
+  if( quant_e==QuantifiersEngine::QEFFORT_CONFLICT ){\r
+    Trace("qcf-check") << "QCF : check : " << level << std::endl;\r
+    if( d_conflict ){\r
+      Trace("qcf-check2") << "QCF : finished check : already in conflict." << std::endl;\r
+      if( level>=Theory::EFFORT_FULL ){\r
+        Trace("qcf-warn") << "ALREADY IN CONFLICT? " << level << std::endl;\r
+        //Assert( false );\r
+      }\r
+    }else{\r
+      int addedLemmas = 0;\r
+      ++(d_statistics.d_inst_rounds);\r
+      double clSet = 0;\r
+      int prevEt = 0;\r
+      if( Trace.isOn("qcf-engine") ){\r
+        prevEt = d_statistics.d_entailment_checks.getData();\r
+        clSet = double(clock())/double(CLOCKS_PER_SEC);\r
+        Trace("qcf-engine") << "---Conflict Find Engine Round, effort = " << level << "---" << std::endl;\r
+      }\r
+      computeRelevantEqr();\r
+\r
+      //determine order for quantified formulas\r
+      std::vector< Node > qorder;\r
+      std::map< Node, bool > qassert;\r
+      //mark which are asserted\r
+      for( unsigned i=0; i<d_qassert.size(); i++ ){\r
+        qassert[d_qassert[i]] = true;\r
+      }\r
+      //add which ones are specified in the order\r
+      for( unsigned i=0; i<d_quant_order.size(); i++ ){\r
+        Node n = d_quant_order[i];\r
+        if( std::find( qorder.begin(), qorder.end(), n )==qorder.end() && qassert.find( n )!=qassert.end() ){\r
+          qorder.push_back( n );\r
+        }\r
+      }\r
+      d_quant_order.clear();\r
+      d_quant_order.insert( d_quant_order.begin(), qorder.begin(), qorder.end() );\r
+      //add remaining\r
+      for( unsigned i=0; i<d_qassert.size(); i++ ){\r
+        Node n = d_qassert[i];\r
+        if( std::find( qorder.begin(), qorder.end(), n )==qorder.end() ){\r
+          qorder.push_back( n );\r
+        }\r
+      }\r
+\r
+      if( Trace.isOn("qcf-debug") ){\r
+        Trace("qcf-debug") << std::endl;\r
+        debugPrint("qcf-debug");\r
+        Trace("qcf-debug") << std::endl;\r
+      }\r
+      short end_e = getMaxQcfEffort();\r
+      for( short e = effort_conflict; e<=end_e; e++ ){\r
+        d_effort = e;\r
+        Trace("qcf-check") << "Checking quantified formulas at effort " << e << "..." << std::endl;\r
+        for( unsigned j=0; j<qorder.size(); j++ ){\r
+          Node q = qorder[j];\r
+          QuantInfo * qi = &d_qinfo[q];\r
+\r
+          Assert( d_qinfo.find( q )!=d_qinfo.end() );\r
+          if( qi->d_mg->isValid() ){\r
+            Trace("qcf-check") << "Check quantified formula ";\r
+            debugPrintQuant("qcf-check", q);\r
+            Trace("qcf-check") << " : " << q << "..." << std::endl;\r
+\r
+            Trace("qcf-check-debug") << "Reset round..." << std::endl;\r
+            qi->reset_round( this );\r
+            //try to make a matches making the body false\r
+            Trace("qcf-check-debug") << "Get next match..." << std::endl;\r
+            while( qi->d_mg->getNextMatch( this, qi ) ){\r
+              Trace("qcf-inst") << "*** Produced match at effort " << e << " : " << std::endl;\r
+              qi->debugPrintMatch("qcf-inst");\r
+              Trace("qcf-inst") << std::endl;\r
+              std::vector< int > assigned;\r
+              if( !qi->isMatchSpurious( this ) ){\r
+                if( qi->completeMatch( this, assigned ) ){\r
+                  std::vector< Node > terms;\r
+                  qi->getMatch( terms );\r
+                  if( !qi->isTConstraintSpurious( this, terms ) ){\r
+                    if( Debug.isOn("qcf-check-inst") ){\r
+                      //if( e==effort_conflict ){\r
+                      Node inst = d_quantEngine->getInstantiation( q, terms );\r
+                      Debug("qcf-check-inst") << "Check instantiation " << inst << "..." << std::endl;\r
+                      Assert( evaluate( inst )!=1 );\r
+                      Assert( evaluate( inst )==-1 || e>effort_conflict );\r
+                      //}\r
+                    }\r
+                    if( d_quantEngine->addInstantiation( q, terms, false ) ){\r
+                      Trace("qcf-check") << "   ... Added instantiation" << std::endl;\r
+                      Trace("qcf-inst") << "*** Was from effort " << e << " : " << std::endl;\r
+                      qi->debugPrintMatch("qcf-inst");\r
+                      Trace("qcf-inst") << std::endl;\r
+                      ++addedLemmas;\r
+                      if( e==effort_conflict ){\r
+                        d_quant_order.insert( d_quant_order.begin(), q );\r
+                        d_conflict.set( true );\r
+                        ++(d_statistics.d_conflict_inst);\r
+                        break;\r
+                      }else if( e==effort_prop_eq ){\r
+                        ++(d_statistics.d_prop_inst);\r
+                      }\r
+                    }else{\r
+                      Trace("qcf-inst") << "   ... Failed to add instantiation" << std::endl;\r
+                      //Assert( false );\r
+                    }\r
+                  }\r
+                  //clean up assigned\r
+                  qi->revertMatch( assigned );\r
+                  d_tempCache.clear();\r
+                }else{\r
+                  Trace("qcf-inst") << "   ... Spurious instantiation (cannot assign unassigned variables)" << std::endl;\r
+                }\r
+              }else{\r
+                Trace("qcf-inst") << "   ... Spurious instantiation (match is inconsistent)" << std::endl;\r
+              }\r
+            }\r
+            if( d_conflict ){\r
+              break;\r
+            }\r
+          }\r
+        }\r
+        if( addedLemmas>0 ){\r
+          break;\r
+        }\r
+      }\r
+      if( Trace.isOn("qcf-engine") ){\r
+        double clSet2 = double(clock())/double(CLOCKS_PER_SEC);\r
+        Trace("qcf-engine") << "Finished conflict find engine, time = " << (clSet2-clSet);\r
+        if( addedLemmas>0 ){\r
+          Trace("qcf-engine") << ", effort = " << ( d_effort==effort_conflict ? "conflict" : ( d_effort==effort_prop_eq ? "prop_eq" : "mc" ) );\r
+          Trace("qcf-engine") << ", addedLemmas = " << addedLemmas;\r
+        }\r
+        Trace("qcf-engine") << std::endl;\r
+        int currEt = d_statistics.d_entailment_checks.getData();\r
+        if( currEt!=prevEt ){\r
+          Trace("qcf-engine") << "  Entailment checks = " << ( currEt - prevEt ) << std::endl;\r
+        }\r
+      }\r
+      Trace("qcf-check2") << "QCF : finished check : " << level << std::endl;\r
+    }\r
+  }\r
+}\r
+\r
+void QuantConflictFind::computeRelevantEqr() {\r
+  if( d_needs_computeRelEqr ){\r
+    d_needs_computeRelEqr = false;\r
+    Trace("qcf-check") << "Compute relevant equalities..." << std::endl;\r
+    //d_uf_terms.clear();\r
+    //d_eqc_uf_terms.clear();\r
+    d_eqcs.clear();\r
+    d_model_basis.clear();\r
+    //d_arg_reps.clear();\r
+    //double clSet = 0;\r
+    //if( Trace.isOn("qcf-opt") ){\r
+    //  clSet = double(clock())/double(CLOCKS_PER_SEC);\r
+    //}\r
+\r
+    //long nTermst = 0;\r
+    //long nTerms = 0;\r
+    //long nEqc = 0;\r
+\r
+    //which nodes are irrelevant for disequality matches\r
+    std::map< TNode, bool > irrelevant_dnode;\r
+    //now, store matches\r
+    eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( getEqualityEngine() );\r
+    while( !eqcs_i.isFinished() ){\r
+      //nEqc++;\r
+      Node r = (*eqcs_i);\r
+      TypeNode rtn = r.getType();\r
+      if( options::qcfMode()==QCF_MC ){\r
+        std::map< TypeNode, std::vector< TNode > >::iterator itt = d_eqcs.find( rtn );\r
+        if( itt==d_eqcs.end() ){\r
+          Node mb = getQuantifiersEngine()->getTermDatabase()->getModelBasisTerm( rtn );\r
+          if( !getEqualityEngine()->hasTerm( mb ) ){\r
+            Trace("qcf-warn") << "WARNING: Model basis term does not exist!" << std::endl;\r
+            Assert( false );\r
+          }\r
+          Node mbr = getRepresentative( mb );\r
+          if( mbr!=r ){\r
+            d_eqcs[rtn].push_back( mbr );\r
+          }\r
+          d_eqcs[rtn].push_back( r );\r
+          d_model_basis[rtn] = mb;\r
+        }else{\r
+          itt->second.push_back( r );\r
+        }\r
+      }else{\r
+        d_eqcs[rtn].push_back( r );\r
+      }\r
+      ++eqcs_i;\r
+    }\r
+    /*\r
+    if( Trace.isOn("qcf-opt") ){\r
+      double clSet2 = double(clock())/double(CLOCKS_PER_SEC);\r
+      Trace("qcf-opt") << "Compute rel eqc : " << std::endl;\r
+      Trace("qcf-opt") << "   " << nEqc << " equivalence classes. " << std::endl;\r
+      Trace("qcf-opt") << "   " << nTerms << " / " << nTermst << " terms." << std::endl;\r
+      Trace("qcf-opt") << "   Time : " << (clSet2-clSet) << std::endl;\r
+    }\r
+    */\r
+  }\r
+}\r
+\r
+\r
+//-------------------------------------------------- debugging\r
+\r
+\r
+void QuantConflictFind::debugPrint( const char * c ) {\r
+  //print the equivalance classes\r
+  Trace(c) << "----------EQ classes" << std::endl;\r
+  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( getEqualityEngine() );\r
+  while( !eqcs_i.isFinished() ){\r
+    Node n = (*eqcs_i);\r
+    //if( !n.getType().isInteger() ){\r
+    Trace(c) << "  - " << n << " : {";\r
+    eq::EqClassIterator eqc_i = eq::EqClassIterator( n, getEqualityEngine() );\r
+    bool pr = false;\r
+    while( !eqc_i.isFinished() ){\r
+      Node nn = (*eqc_i);\r
+      if( nn.getKind()!=EQUAL && nn!=n ){\r
+        Trace(c) << (pr ? "," : "" ) << " " << nn;\r
+        pr = true;\r
+      }\r
+      ++eqc_i;\r
+    }\r
+    Trace(c) << (pr ? " " : "" ) << "}" << std::endl;\r
+    /*\r
+    EqcInfo * eqcn = getEqcInfo( n, false );\r
+    if( eqcn ){\r
+      Trace(c) << "    DEQ : {";\r
+      pr = false;\r
+      for( NodeBoolMap::iterator it = eqcn->d_diseq.begin(); it != eqcn->d_diseq.end(); ++it ){\r
+        if( (*it).second ){\r
+          Trace(c) << (pr ? "," : "" ) << " " << (*it).first;\r
+          pr = true;\r
+        }\r
+      }\r
+      Trace(c) << (pr ? " " : "" ) << "}" << std::endl;\r
+    }\r
+    //}\r
+    */\r
+    ++eqcs_i;\r
+  }\r
+}\r
+\r
+void QuantConflictFind::debugPrintQuant( const char * c, Node q ) {\r
+  Trace(c) << "Q" << d_quant_id[q];\r
+}\r
+\r
+void QuantConflictFind::debugPrintQuantBody( const char * c, Node q, Node n, bool doVarNum ) {\r
+  if( n.getNumChildren()==0 ){\r
+    Trace(c) << n;\r
+  }else if( doVarNum && d_qinfo[q].d_var_num.find( n )!=d_qinfo[q].d_var_num.end() ){\r
+    Trace(c) << "?x" << d_qinfo[q].d_var_num[n];\r
+  }else{\r
+    Trace(c) << "(";\r
+    if( n.getKind()==APPLY_UF ){\r
+      Trace(c) << n.getOperator();\r
+    }else{\r
+      Trace(c) << n.getKind();\r
+    }\r
+    for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+      Trace(c) << " ";\r
+      debugPrintQuantBody( c, q, n[i] );\r
+    }\r
+    Trace(c) << ")";\r
+  }\r
+}\r
+\r
+QuantConflictFind::Statistics::Statistics():\r
+  d_inst_rounds("QuantConflictFind::Inst_Rounds", 0),\r
+  d_conflict_inst("QuantConflictFind::Instantiations_Conflict_Find", 0 ),\r
+  d_prop_inst("QuantConflictFind::Instantiations_Prop", 0 ),\r
+  d_entailment_checks("QuantConflictFind::Entailment_Checks",0)\r
+{\r
+  StatisticsRegistry::registerStat(&d_inst_rounds);\r
+  StatisticsRegistry::registerStat(&d_conflict_inst);\r
+  StatisticsRegistry::registerStat(&d_prop_inst);\r
+  StatisticsRegistry::registerStat(&d_entailment_checks);\r
+}\r
+\r
+QuantConflictFind::Statistics::~Statistics(){\r
+  StatisticsRegistry::unregisterStat(&d_inst_rounds);\r
+  StatisticsRegistry::unregisterStat(&d_conflict_inst);\r
+  StatisticsRegistry::unregisterStat(&d_prop_inst);\r
+  StatisticsRegistry::unregisterStat(&d_entailment_checks);\r
+}\r
+\r
+TNode QuantConflictFind::getZero( Kind k ) {\r
+  std::map< Kind, Node >::iterator it = d_zero.find( k );\r
+  if( it==d_zero.end() ){\r
+    Node nn;\r
+    if( k==PLUS ){\r
+      nn = NodeManager::currentNM()->mkConst( Rational(0) );\r
+    }\r
+    d_zero[k] = nn;\r
+    return nn;\r
+  }else{\r
+    return it->second;\r
+  }\r
+}\r
+\r
+\r
+}\r
old mode 100644 (file)
new mode 100755 (executable)
index 0464c04..81f31fa
-/*********************                                                        */
-/*! \file quant_conflict_find.h
- ** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014  New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief quantifiers conflict find class
- **/
-
-#include "cvc4_private.h"
-
-#ifndef QUANT_CONFLICT_FIND
-#define QUANT_CONFLICT_FIND
-
-#include "context/cdhashmap.h"
-#include "context/cdchunk_list.h"
-#include "theory/quantifiers_engine.h"
-
-namespace CVC4 {
-namespace theory {
-namespace quantifiers {
-
-class QcfNode;
-
-class QuantConflictFind;
-
-class QcfNodeIndex {
-public:
-  std::map< TNode, QcfNodeIndex > d_children;
-  void clear() { d_children.clear(); }
-  void debugPrint( const char * c, int t );
-  Node existsTerm( TNode n, std::vector< TNode >& reps, int index = 0 );
-  Node addTerm( TNode n, std::vector< TNode >& reps, int index = 0 );
-};
-
-class QuantInfo;
-
-//match generator
-class MatchGen {
-  friend class QuantInfo;
-private:
-  //current children information
-  int d_child_counter;
-  //children of this object
-  std::vector< int > d_children_order;
-  unsigned getNumChildren() { return d_children.size(); }
-  MatchGen * getChild( int i ) { return &d_children[d_children_order[i]]; }
-  //MatchGen * getChild( int i ) { return &d_children[i]; }
-  //current matching information
-  std::vector< QcfNodeIndex * > d_qn;
-  std::vector< std::map< TNode, QcfNodeIndex >::iterator > d_qni;
-  bool doMatching( QuantConflictFind * p, QuantInfo * qi );
-  //for matching : each index is either a variable or a ground term
-  unsigned d_qni_size;
-  std::map< int, int > d_qni_var_num;
-  std::map< int, TNode > d_qni_gterm;
-  std::map< int, TNode > d_qni_gterm_rep;
-  std::map< int, int > d_qni_bound;
-  std::vector< int > d_qni_bound_except;
-  std::map< int, TNode > d_qni_bound_cons;
-  std::map< int, int > d_qni_bound_cons_var;
-  std::map< int, int >::iterator d_binding_it;
-  //std::vector< int > d_independent;
-  bool d_matched_basis;
-  bool d_binding;
-  //int getVarBindingVar();
-  std::map< int, Node > d_ground_eval;
-  //determine variable order
-  void determineVariableOrder( QuantInfo * qi, std::vector< int >& bvars );
-  void collectBoundVar( QuantInfo * qi, Node n, std::vector< int >& cbvars );
-public:
-  //type of the match generator
-  enum {
-    typ_invalid,
-    typ_ground,
-    typ_pred,
-    typ_eq,
-    typ_formula,
-    typ_var,
-    typ_ite_var,
-    typ_bool_var,
-    typ_tconstraint,
-    typ_tsym,
-  };
-  void debugPrintType( const char * c, short typ, bool isTrace = false );
-public:
-  MatchGen() : d_type( typ_invalid ){}
-  MatchGen( QuantInfo * qi, Node n, bool isVar = false );
-  bool d_tgt;
-  bool d_tgt_orig;
-  bool d_wasSet;
-  Node d_n;
-  std::vector< MatchGen > d_children;
-  short d_type;
-  bool d_type_not;
-  void reset_round( QuantConflictFind * p );
-  void reset( QuantConflictFind * p, bool tgt, QuantInfo * qi );
-  bool getNextMatch( QuantConflictFind * p, QuantInfo * qi );
-  bool getExplanation( QuantConflictFind * p, QuantInfo * qi, std::vector< Node >& exp );
-  Node getExplanationTerm( QuantConflictFind * p, QuantInfo * qi, Node t, std::vector< Node >& exp );
-  bool isValid() { return d_type!=typ_invalid; }
-  void setInvalid();
-
-  // is this term treated as UF application?
-  static bool isHandledBoolConnective( TNode n );
-  static bool isHandledUfTerm( TNode n );
-  static Node getOperator( QuantConflictFind * p, Node n );
-  //can this node be handled by the algorithm
-  static bool isHandled( TNode n );
-};
-
-//info for quantifiers
-class QuantInfo {
-private:
-  void registerNode( Node n, bool hasPol, bool pol, bool beneathQuant = false );
-  void flatten( Node n, bool beneathQuant );
-private: //for completing match
-  std::vector< int > d_unassigned;
-  std::vector< TypeNode > d_unassigned_tn;
-  int d_unassigned_nvar;
-  int d_una_index;
-  std::vector< int > d_una_eqc_count;
-public:
-  QuantInfo() : d_mg( NULL ) {}
-  ~QuantInfo() { delete d_mg; }
-  std::vector< TNode > d_vars;
-  std::map< TNode, int > d_var_num;
-  std::vector< int > d_tsym_vars;
-  std::map< TNode, bool > d_inMatchConstraint;
-  std::map< int, std::vector< Node > > d_var_constraint[2];
-  int getVarNum( TNode v ) { return d_var_num.find( v )!=d_var_num.end() ? d_var_num[v] : -1; }
-  bool isVar( TNode v ) { return d_var_num.find( v )!=d_var_num.end(); }
-  int getNumVars() { return (int)d_vars.size(); }
-  TNode getVar( int i ) { return d_vars[i]; }
-
-  MatchGen * d_mg;
-  Node d_q;
-  std::map< int, MatchGen * > d_var_mg;
-  void reset_round( QuantConflictFind * p );
-public:
-  //initialize
-  void initialize( Node q, Node qn );
-  //current constraints
-  std::vector< TNode > d_match;
-  std::vector< TNode > d_match_term;
-  std::map< int, std::map< TNode, int > > d_curr_var_deq;
-  std::map< Node, bool > d_tconstraints;
-  int getCurrentRepVar( int v );
-  TNode getCurrentValue( TNode n );
-  TNode getCurrentExpValue( TNode n );
-  bool getCurrentCanBeEqual( QuantConflictFind * p, int v, TNode n, bool chDiseq = false );
-  int addConstraint( QuantConflictFind * p, int v, TNode n, bool polarity );
-  int addConstraint( QuantConflictFind * p, int v, TNode n, int vn, bool polarity, bool doRemove );
-  bool setMatch( QuantConflictFind * p, int v, TNode n );
-  bool isMatchSpurious( QuantConflictFind * p );
-  bool isTConstraintSpurious( QuantConflictFind * p, std::vector< Node >& terms );
-  bool entailmentTest( QuantConflictFind * p, Node lit, bool chEnt = true );
-  bool completeMatch( QuantConflictFind * p, std::vector< int >& assigned, bool doContinue = false );
-  void revertMatch( std::vector< int >& assigned );
-  void debugPrintMatch( const char * c );
-  bool isConstrainedVar( int v );
-public:
-  void getMatch( std::vector< Node >& terms );
-};
-
-class QuantConflictFind : public QuantifiersModule
-{
-  friend class QcfNodeIndex;
-  friend class MatchGen;
-  friend class QuantInfo;
-  typedef context::CDChunkList<Node> NodeList;
-  typedef context::CDHashMap<Node, bool, NodeHashFunction> NodeBoolMap;
-private:
-  context::Context* d_c;
-  context::CDO< bool > d_conflict;
-  bool d_performCheck;
-  std::vector< Node > d_quant_order;
-  std::map< Kind, Node > d_zero;
-  //for storing nodes created during t-constraint solving (prevents memory leaks)
-  std::vector< Node > d_tempCache;
-private:
-  std::map< Node, Node > d_op_node;
-  int d_fid_count;
-  std::map< Node, int > d_fid;
-  Node mkEqNode( Node a, Node b );
-public:  //for ground terms
-  Node d_true;
-  Node d_false;
-  TNode getZero( Kind k );
-private:
-  Node evaluateTerm( Node n );
-  int evaluate( Node n, bool pref = false, bool hasPref = false );
-private:
-  //currently asserted quantifiers
-  NodeList d_qassert;
-  std::map< Node, QuantInfo > d_qinfo;
-private:  //for equivalence classes
-  eq::EqualityEngine * getEqualityEngine();
-  bool areDisequal( Node n1, Node n2 );
-  bool areEqual( Node n1, Node n2 );
-  Node getRepresentative( Node n );
-
-/*
-  class EqcInfo {
-  public:
-    EqcInfo( context::Context* c ) : d_diseq( c ) {}
-    NodeBoolMap d_diseq;
-    bool isDisequal( Node n ) { return d_diseq.find( n )!=d_diseq.end() && d_diseq[n]; }
-    void setDisequal( Node n, bool val = true ) { d_diseq[n] = val; }
-    //NodeBoolMap& getRelEqr( int index ) { return index==0 ? d_rel_eqr_e : d_rel_eqr_d; }
-  };
-  std::map< Node, EqcInfo * > d_eqc_info;
-  EqcInfo * getEqcInfo( Node n, bool doCreate = true );
-*/
-  // operator -> index(terms)
-  std::map< TNode, QcfNodeIndex > d_uf_terms;
-  // operator -> index(eqc -> terms)
-  std::map< TNode, QcfNodeIndex > d_eqc_uf_terms;
-  //get qcf node index
-  QcfNodeIndex * getQcfNodeIndex( Node eqc, Node f );
-  QcfNodeIndex * getQcfNodeIndex( Node f );
-  // type -> list(eqc)
-  std::map< TypeNode, std::vector< TNode > > d_eqcs;
-  std::map< TypeNode, Node > d_model_basis;
-  //mapping from UF terms to representatives of their arguments
-  std::map< TNode, std::vector< TNode > > d_arg_reps;
-  //compute arg reps
-  void computeArgReps( TNode n );
-  //compute
-  void computeUfTerms( TNode f );
-public:
-  enum {
-    effort_conflict,
-    effort_prop_eq,
-    effort_mc,
-  };
-  short d_effort;
-  void setEffort( int e ) { d_effort = e; }
-  static short getMaxQcfEffort();
-  bool areMatchEqual( TNode n1, TNode n2 );
-  bool areMatchDisequal( TNode n1, TNode n2 );
-public:
-  QuantConflictFind( QuantifiersEngine * qe, context::Context* c );
-  /** register quantifier */
-  void registerQuantifier( Node q );
-public:
-  /** assert quantifier */
-  void assertNode( Node q );
-  /** new node */
-  void newEqClass( Node n );
-  /** merge */
-  void merge( Node a, Node b );
-  /** assert disequal */
-  void assertDisequal( Node a, Node b );
-  /** reset round */
-  void reset_round( Theory::Effort level );
-  /** check */
-  void check( Theory::Effort level );
-  /** needs check */
-  bool needsCheck( Theory::Effort level );
-private:
-  bool d_needs_computeRelEqr;
-public:
-  void computeRelevantEqr();
-private:
-  void debugPrint( const char * c );
-  //for debugging
-  std::vector< Node > d_quants;
-  std::map< Node, int > d_quant_id;
-  void debugPrintQuant( const char * c, Node q );
-  void debugPrintQuantBody( const char * c, Node q, Node n, bool doVarNum = true );
-public:
-  /** statistics class */
-  class Statistics {
-  public:
-    IntStat d_inst_rounds;
-    IntStat d_conflict_inst;
-    IntStat d_prop_inst;
-    IntStat d_entailment_checks;
-    Statistics();
-    ~Statistics();
-  };
-  Statistics d_statistics;
-  /** Identify this module */
-  std::string identify() const { return "QcfEngine"; }
-};
-
-}
-}
-}
-
-#endif
+/*********************                                                        */\r
+/*! \file quant_conflict_find.h\r
+ ** \verbatim\r
+ ** Original author: Andrew Reynolds\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 project.\r
+ ** Copyright (c) 2009-2014  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 quantifiers conflict find class\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef QUANT_CONFLICT_FIND\r
+#define QUANT_CONFLICT_FIND\r
+\r
+#include "context/cdhashmap.h"\r
+#include "context/cdchunk_list.h"\r
+#include "theory/quantifiers_engine.h"\r
+#include "theory/quantifiers/term_database.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+namespace quantifiers {\r
+\r
+class QuantConflictFind;\r
+class QuantInfo;\r
+\r
+//match generator\r
+class MatchGen {\r
+  friend class QuantInfo;\r
+private:\r
+  //current children information\r
+  int d_child_counter;\r
+  //children of this object\r
+  std::vector< int > d_children_order;\r
+  unsigned getNumChildren() { return d_children.size(); }\r
+  MatchGen * getChild( int i ) { return &d_children[d_children_order[i]]; }\r
+  //MatchGen * getChild( int i ) { return &d_children[i]; }\r
+  //current matching information\r
+  std::vector< TermArgTrie * > d_qn;\r
+  std::vector< std::map< TNode, TermArgTrie >::iterator > d_qni;\r
+  bool doMatching( QuantConflictFind * p, QuantInfo * qi );\r
+  //for matching : each index is either a variable or a ground term\r
+  unsigned d_qni_size;\r
+  std::map< int, int > d_qni_var_num;\r
+  std::map< int, TNode > d_qni_gterm;\r
+  std::map< int, TNode > d_qni_gterm_rep;\r
+  std::map< int, int > d_qni_bound;\r
+  std::vector< int > d_qni_bound_except;\r
+  std::map< int, TNode > d_qni_bound_cons;\r
+  std::map< int, int > d_qni_bound_cons_var;\r
+  std::map< int, int >::iterator d_binding_it;\r
+  //std::vector< int > d_independent;\r
+  bool d_matched_basis;\r
+  bool d_binding;\r
+  //int getVarBindingVar();\r
+  std::map< int, Node > d_ground_eval;\r
+  //determine variable order\r
+  void determineVariableOrder( QuantInfo * qi, std::vector< int >& bvars );\r
+  void collectBoundVar( QuantInfo * qi, Node n, std::vector< int >& cbvars );\r
+public:\r
+  //type of the match generator\r
+  enum {\r
+    typ_invalid,\r
+    typ_ground,\r
+    typ_pred,\r
+    typ_eq,\r
+    typ_formula,\r
+    typ_var,\r
+    typ_ite_var,\r
+    typ_bool_var,\r
+    typ_tconstraint,\r
+    typ_tsym,\r
+  };\r
+  void debugPrintType( const char * c, short typ, bool isTrace = false );\r
+public:\r
+  MatchGen() : d_type( typ_invalid ){}\r
+  MatchGen( QuantInfo * qi, Node n, bool isVar = false );\r
+  bool d_tgt;\r
+  bool d_tgt_orig;\r
+  bool d_wasSet;\r
+  Node d_n;\r
+  std::vector< MatchGen > d_children;\r
+  short d_type;\r
+  bool d_type_not;\r
+  void reset_round( QuantConflictFind * p );\r
+  void reset( QuantConflictFind * p, bool tgt, QuantInfo * qi );\r
+  bool getNextMatch( QuantConflictFind * p, QuantInfo * qi );\r
+  bool getExplanation( QuantConflictFind * p, QuantInfo * qi, std::vector< Node >& exp );\r
+  Node getExplanationTerm( QuantConflictFind * p, QuantInfo * qi, Node t, std::vector< Node >& exp );\r
+  bool isValid() { return d_type!=typ_invalid; }\r
+  void setInvalid();\r
+\r
+  // is this term treated as UF application?\r
+  static bool isHandledBoolConnective( TNode n );\r
+  static bool isHandledUfTerm( TNode n );\r
+  static Node getOperator( QuantConflictFind * p, Node n );\r
+  //can this node be handled by the algorithm\r
+  static bool isHandled( TNode n );\r
+};\r
+\r
+//info for quantifiers\r
+class QuantInfo {\r
+private:\r
+  void registerNode( Node n, bool hasPol, bool pol, bool beneathQuant = false );\r
+  void flatten( Node n, bool beneathQuant );\r
+private: //for completing match\r
+  std::vector< int > d_unassigned;\r
+  std::vector< TypeNode > d_unassigned_tn;\r
+  int d_unassigned_nvar;\r
+  int d_una_index;\r
+  std::vector< int > d_una_eqc_count;\r
+public:\r
+  QuantInfo() : d_mg( NULL ) {}\r
+  ~QuantInfo() { delete d_mg; }\r
+  std::vector< TNode > d_vars;\r
+  std::map< TNode, int > d_var_num;\r
+  std::vector< int > d_tsym_vars;\r
+  std::map< TNode, bool > d_inMatchConstraint;\r
+  std::map< int, std::vector< Node > > d_var_constraint[2];\r
+  int getVarNum( TNode v ) { return d_var_num.find( v )!=d_var_num.end() ? d_var_num[v] : -1; }\r
+  bool isVar( TNode v ) { return d_var_num.find( v )!=d_var_num.end(); }\r
+  int getNumVars() { return (int)d_vars.size(); }\r
+  TNode getVar( int i ) { return d_vars[i]; }\r
+\r
+  MatchGen * d_mg;\r
+  Node d_q;\r
+  std::map< int, MatchGen * > d_var_mg;\r
+  void reset_round( QuantConflictFind * p );\r
+public:\r
+  //initialize\r
+  void initialize( Node q, Node qn );\r
+  //current constraints\r
+  std::vector< TNode > d_match;\r
+  std::vector< TNode > d_match_term;\r
+  std::map< int, std::map< TNode, int > > d_curr_var_deq;\r
+  std::map< Node, bool > d_tconstraints;\r
+  int getCurrentRepVar( int v );\r
+  TNode getCurrentValue( TNode n );\r
+  TNode getCurrentExpValue( TNode n );\r
+  bool getCurrentCanBeEqual( QuantConflictFind * p, int v, TNode n, bool chDiseq = false );\r
+  int addConstraint( QuantConflictFind * p, int v, TNode n, bool polarity );\r
+  int addConstraint( QuantConflictFind * p, int v, TNode n, int vn, bool polarity, bool doRemove );\r
+  bool setMatch( QuantConflictFind * p, int v, TNode n );\r
+  bool isMatchSpurious( QuantConflictFind * p );\r
+  bool isTConstraintSpurious( QuantConflictFind * p, std::vector< Node >& terms );\r
+  bool entailmentTest( QuantConflictFind * p, Node lit, bool chEnt = true );\r
+  bool completeMatch( QuantConflictFind * p, std::vector< int >& assigned, bool doContinue = false );\r
+  void revertMatch( std::vector< int >& assigned );\r
+  void debugPrintMatch( const char * c );\r
+  bool isConstrainedVar( int v );\r
+public:\r
+  void getMatch( std::vector< Node >& terms );\r
+};\r
+\r
+class QuantConflictFind : public QuantifiersModule\r
+{\r
+  friend class MatchGen;\r
+  friend class QuantInfo;\r
+  typedef context::CDChunkList<Node> NodeList;\r
+  typedef context::CDHashMap<Node, bool, NodeHashFunction> NodeBoolMap;\r
+private:\r
+  context::Context* d_c;\r
+  context::CDO< bool > d_conflict;\r
+  std::vector< Node > d_quant_order;\r
+  std::map< Kind, Node > d_zero;\r
+  //for storing nodes created during t-constraint solving (prevents memory leaks)\r
+  std::vector< Node > d_tempCache;\r
+private:\r
+  std::map< Node, Node > d_op_node;\r
+  int d_fid_count;\r
+  std::map< Node, int > d_fid;\r
+  Node mkEqNode( Node a, Node b );\r
+public:  //for ground terms\r
+  Node d_true;\r
+  Node d_false;\r
+  TNode getZero( Kind k );\r
+private:\r
+  Node evaluateTerm( Node n );\r
+  int evaluate( Node n, bool pref = false, bool hasPref = false );\r
+private:\r
+  //currently asserted quantifiers\r
+  NodeList d_qassert;\r
+  std::map< Node, QuantInfo > d_qinfo;\r
+private:  //for equivalence classes\r
+  // type -> list(eqc)\r
+  std::map< TypeNode, std::vector< TNode > > d_eqcs;\r
+  std::map< TypeNode, Node > d_model_basis;\r
+public:\r
+  enum {\r
+    effort_conflict,\r
+    effort_prop_eq,\r
+    effort_mc,\r
+  };\r
+  short d_effort;\r
+  void setEffort( int e ) { d_effort = e; }\r
+  static short getMaxQcfEffort();\r
+  bool areMatchEqual( TNode n1, TNode n2 );\r
+  bool areMatchDisequal( TNode n1, TNode n2 );\r
+public:\r
+  QuantConflictFind( QuantifiersEngine * qe, context::Context* c );\r
+  /** register quantifier */\r
+  void registerQuantifier( Node q );\r
+public:\r
+  /** assert quantifier */\r
+  void assertNode( Node q );\r
+  /** new node */\r
+  void newEqClass( Node n );\r
+  /** merge */\r
+  void merge( Node a, Node b );\r
+  /** assert disequal */\r
+  void assertDisequal( Node a, Node b );\r
+  /** needs check */\r
+  bool needsCheck( Theory::Effort level );\r
+  /** reset round */\r
+  void reset_round( Theory::Effort level );\r
+  /** check */\r
+  void check( Theory::Effort level, unsigned quant_e );\r
+private:\r
+  bool d_needs_computeRelEqr;\r
+public:\r
+  void computeRelevantEqr();\r
+private:\r
+  void debugPrint( const char * c );\r
+  //for debugging\r
+  std::vector< Node > d_quants;\r
+  std::map< Node, int > d_quant_id;\r
+  void debugPrintQuant( const char * c, Node q );\r
+  void debugPrintQuantBody( const char * c, Node q, Node n, bool doVarNum = true );\r
+public:\r
+  /** statistics class */\r
+  class Statistics {\r
+  public:\r
+    IntStat d_inst_rounds;\r
+    IntStat d_conflict_inst;\r
+    IntStat d_prop_inst;\r
+    IntStat d_entailment_checks;\r
+    Statistics();\r
+    ~Statistics();\r
+  };\r
+  Statistics d_statistics;\r
+  /** Identify this module */\r
+  std::string identify() const { return "QcfEngine"; }\r
+};\r
+\r
+}\r
+}\r
+}\r
+\r
+#endif\r
index a5de6ffa9dfbba5ae73b802de32af2cc7db12c09..48608cb4ed690dab3786042a57ad3ac536df978b 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "theory/quantifiers/quantifiers_attributes.h"
 #include "theory/quantifiers/options.h"
+#include "theory/quantifiers/term_database.h"
 
 using namespace std;
 using namespace CVC4;
@@ -22,24 +23,35 @@ 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 if( attr=="rr_priority" ){
-      //Trace("quant-attr") << "Set rr priority " << n << std::endl;
-      //RrPriorityAttribute rra;
-
-    }
-  }else{
-    for( size_t i=0; i<n.getNumChildren(); i++ ){
-      setUserAttribute( attr, n[i] );
-    }
+void QuantifiersAttributes::setUserAttribute( const std::string& attr, Node n, std::vector<Node> node_values, std::string str_value ){
+  Trace("quant-attr-debug") << "Set " << attr << " " << n << std::endl;
+  if( attr=="axiom" ){
+    Trace("quant-attr-debug") << "Set axiom " << n << std::endl;
+    AxiomAttribute aa;
+    n.setAttribute( aa, true );
+  }else if( attr=="conjecture" ){
+    Trace("quant-attr-debug") << "Set conjecture " << n << std::endl;
+    ConjectureAttribute ca;
+    n.setAttribute( ca, true );
+  }else if( attr=="sygus" ){
+    Trace("quant-attr-debug") << "Set sygus " << n << std::endl;
+    SygusAttribute ca;
+    n.setAttribute( ca, true );
+  }else if( attr=="synthesis" ){
+    Trace("quant-attr-debug") << "Set synthesis " << n << std::endl;
+    SynthesisAttribute ca;
+    n.setAttribute( ca, true );
+  }else if( attr=="quant-inst-max-level" ){
+    Assert( node_values.size()==1 );
+    uint64_t lvl = node_values[0].getConst<Rational>().getNumerator().getLong();
+    Trace("quant-attr-debug") << "Set instantiation level " << n << " to " << lvl << std::endl;
+    QuantInstLevelAttribute qila;
+    n.setAttribute( qila, lvl );
+  }else if( attr=="rr-priority" ){
+    Assert( node_values.size()==1 );
+    uint64_t lvl = node_values[0].getConst<Rational>().getNumerator().getLong();
+    Trace("quant-attr-debug") << "Set rewrite rule priority " << n << " to " << lvl << std::endl;
+    RrPriorityAttribute rrpa;
+    n.setAttribute( rrpa, lvl );
   }
 }
index cf9620a07b535c5973bdf792ff503823a08bdd20..bad58eef850f49b319f79c643616d0bd7fe8b4f7 100644 (file)
@@ -26,14 +26,6 @@ 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;
-
 /** Attribute priority for rewrite rules */
 //struct RrPriorityAttributeId {};
 //typedef expr::Attribute< RrPriorityAttributeId, uint64_t > RrPriorityAttribute;
@@ -44,7 +36,7 @@ struct QuantifiersAttributes
     *   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 );
+  static void setUserAttribute( const std::string& attr, Node n, std::vector<Node> node_values, std::string str_value );
 };
 
 
index eb14b0abee7b2b9b310b28b7b8ff515a9c496c99..fb7ff679bdef4b7664f925d69af2bc42195da0ea 100644 (file)
@@ -159,7 +159,13 @@ RewriteResponse QuantifiersRewriter::preRewrite(TNode in) {
     }
     Node body = in[1];
     bool doRewrite = false;
+    std::vector< Node > ipl;
     while( body.getNumChildren()>=2 && body.getKind()==in.getKind() ){
+      if( body.getNumChildren()==3 ){
+        for( unsigned i=0; i<body[2].getNumChildren(); i++ ){
+          ipl.push_back( body[2][i] );
+        }
+      }
       for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
         args.push_back( body[0][i] );
       }
@@ -171,7 +177,12 @@ RewriteResponse QuantifiersRewriter::preRewrite(TNode in) {
       children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST,args) );
       children.push_back( body );
       if( in.getNumChildren()==3 ){
-        children.push_back( in[2] );
+        for( unsigned i=0; i<in[2].getNumChildren(); i++ ){
+          ipl.push_back( in[2][i] );
+        }
+      }
+      if( !ipl.empty() ){
+        children.push_back( NodeManager::currentNM()->mkNode( INST_PATTERN_LIST, ipl ) );
       }
       Node n = NodeManager::currentNM()->mkNode( in.getKind(), children );
       if( in!=n ){
@@ -357,7 +368,7 @@ Node QuantifiersRewriter::computeVarElimination( Node body, std::vector< Node >&
   for( std::map< Node, bool >::iterator it = qpr.d_phase_reqs.begin(); it != qpr.d_phase_reqs.end(); ++it ){
     //Notice() << "   " << it->first << " -> " << ( it->second ? "true" : "false" ) << std::endl;
     if( it->first.getKind()==EQUAL ){
-      if( it->second ){
+      if( it->second && options::varElimQuant() ){
         for( int i=0; i<2; i++ ){
           int j = i==0 ? 1 : 0;
           std::vector< Node >::iterator ita = std::find( args.begin(), args.end(), it->first[i] );
@@ -377,6 +388,33 @@ Node QuantifiersRewriter::computeVarElimination( Node body, std::vector< Node >&
         }
       }
     }
+    else if( it->first.getKind()==APPLY_TESTER ){
+      if( options::dtVarExpandQuant() && it->second && it->first[0].getKind()==BOUND_VARIABLE ){
+        Trace("dt-var-expand") << "Expand datatype variable based on : " << it->first << std::endl;
+        std::vector< Node >::iterator ita = std::find( args.begin(), args.end(), it->first[0] );
+        if( ita!=args.end() ){
+          vars.push_back( it->first[0] );
+          Expr testerExpr = it->first.getOperator().toExpr();
+          int index = Datatype::indexOf( testerExpr );
+          const Datatype& dt = Datatype::datatypeOf(testerExpr);
+          const DatatypeConstructor& c = dt[index];
+          std::vector< Node > newChildren;
+          newChildren.push_back( Node::fromExpr( c.getConstructor() ) );
+          std::vector< Node > newVars;
+          for( unsigned j=0; j<c.getNumArgs(); j++ ){
+            TypeNode tn = TypeNode::fromType( c[j].getSelector().getType() );
+            tn = tn[1];
+            Node v = NodeManager::currentNM()->mkBoundVar( tn );
+            newChildren.push_back( v );
+            newVars.push_back( v );
+          }
+          subs.push_back( NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, newChildren ) );
+          Trace("dt-var-expand") << "...apply substitution " << subs[0] << "/" << vars[0] << std::endl;
+          args.erase( ita );
+          args.insert( args.end(), newVars.begin(), newVars.end() );
+        }
+      }
+    }
   }
   if( !vars.empty() ){
     Trace("var-elim-quant") << "VE " << vars.size() << "/" << args.size() << std::endl;
@@ -539,7 +577,7 @@ Node QuantifiersRewriter::computeCNF( Node n, std::vector< Node >& args, NodeBui
 
 Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, bool pol ){
   if( body.getKind()==FORALL ){
-    if( pol ){
+    if( pol && ( options::prenexQuant()==PRENEX_ALL || body.getNumChildren()==2 ) ){
       std::vector< Node > terms;
       std::vector< Node > subs;
       //for doing prenexing of same-signed quantifiers
@@ -912,9 +950,9 @@ bool QuantifiersRewriter::doOperation( Node f, bool isNested, int computeOption
   }else if( computeOption==COMPUTE_SIMPLE_ITE_LIFT ){
     return options::simpleIteLiftQuant();
   }else if( computeOption==COMPUTE_PRENEX ){
-    return options::prenexQuant() && !options::aggressiveMiniscopeQuant();
+    return options::prenexQuant()!=PRENEX_NONE && !options::aggressiveMiniscopeQuant();
   }else if( computeOption==COMPUTE_VAR_ELIMINATION ){
-    return options::varElimQuant();
+    return options::varElimQuant() || options::dtVarExpandQuant();
   }else if( computeOption==COMPUTE_CNF ){
     return false;//return options::cnfQuant() ; FIXME
   }else if( computeOption==COMPUTE_SPLIT ){
@@ -1079,7 +1117,7 @@ Node QuantifiersRewriter::rewriteRewriteRule( Node r ) {
   NodeBuilder<> patternListB(kind::INST_PATTERN_LIST);
   //the entire rewrite rule is the first pattern
   if( options::quantRewriteRules() ){
-    patternListB << NodeManager::currentNM()->mkNode( INST_PATTERN, r );
+    patternListB << NodeManager::currentNM()->mkNode( INST_ATTRIBUTE, r );
   }
   patternListB << static_cast<Node>(patternB);
   forallB << static_cast<Node>(patternListB);
@@ -1142,8 +1180,10 @@ Node QuantifiersRewriter::preSkolemizeQuantifiers( Node n, bool polarity, std::v
       //process body
       Node nn = preSkolemizeQuantifiers( n[1], polarity, fvTypes, fvs );
       std::vector< Node > sk;
+      Node sub;
+      std::vector< unsigned > sub_vars;
       //return skolemized body
-      return TermDb::mkSkolemizedBody( n, nn, fvTypes, fvs, sk );
+      return TermDb::mkSkolemizedBody( n, nn, fvTypes, fvs, sk, sub, sub_vars );
     }
   }else{
     //check if it contains a quantifier as a subterm
index 1b13d772ee38a405f0f7e36b2330bed06223eb72..05e33c7b2cb487f71a191757551f318bec5fbd53 100644 (file)
@@ -39,7 +39,7 @@ struct PrioritySort {
 
 RewriteEngine::RewriteEngine( context::Context* c, QuantifiersEngine* qe ) : QuantifiersModule(qe) {
   d_true = NodeManager::currentNM()->mkConst( true );
-  d_needsSort = true;
+  d_needsSort = false;
 }
 
 double RewriteEngine::getPriority( Node f ) {
@@ -61,8 +61,14 @@ double RewriteEngine::getPriority( Node f ) {
   //return deterministic ? 0.0 : 1.0;
 }
 
-void RewriteEngine::check( Theory::Effort e ) {
-  if( e==Theory::EFFORT_FULL ){
+bool RewriteEngine::needsCheck( Theory::Effort e ){
+  return e==Theory::EFFORT_FULL;
+  //return e>=Theory::EFFORT_LAST_CALL;
+}
+
+void RewriteEngine::check( Theory::Effort e, unsigned quant_e ) {
+  if( quant_e==QuantifiersEngine::QEFFORT_STANDARD ){
+  //if( e==Theory::EFFORT_FULL ){  
     Trace("rewrite-engine") << "---Rewrite Engine Round, effort = " << e << "---" << std::endl;
     //if( e==Theory::EFFORT_LAST_CALL ){
     //  if( !d_quantEngine->getModel()->isModelSet() ){
@@ -102,7 +108,6 @@ void RewriteEngine::check( Theory::Effort e ) {
 
     }else{
       //otherwise, the search will continue
-      d_quantEngine->flushLemmas( &d_quantEngine->getOutputChannel() );
     }
   }
 }
index d2108bf3e61e01aafa48ef55510976dd368b39f9..1703a9bfc353513217c987acc84e83ece16750d9 100644 (file)
@@ -54,7 +54,8 @@ private:
 public:
   RewriteEngine( context::Context* c, QuantifiersEngine* qe );
 
-  void check( Theory::Effort e );
+  bool needsCheck( Theory::Effort e );
+  void check( Theory::Effort e, unsigned quant_e );
   void registerQuantifier( Node f );
   void assertNode( Node n );  
   /** Identify this module */
index 9ea9ee9626f104d501b453323497e20fe2afa3d1..9c1eeb9b472d5910d43ab3662e534527b8f1b13a 100644 (file)
@@ -21,6 +21,8 @@
 #include "theory/quantifiers/theory_quantifiers.h"
 #include "util/datatype.h"
 #include "theory/datatypes/datatypes_rewriter.h"
+#include "theory/quantifiers/ce_guided_instantiation.h"
+#include "theory/quantifiers/rewrite_engine.h"
 
 using namespace std;
 using namespace CVC4;
@@ -31,25 +33,39 @@ using namespace CVC4::theory::quantifiers;
 
 using namespace CVC4::theory::inst;
 
-bool TermArgTrie::addTerm2( QuantifiersEngine* qe, Node n, int argIndex ){
-  if( argIndex<(int)n.getNumChildren() ){
-    Node r = qe->getEqualityQuery()->getRepresentative( n[ argIndex ] );
-    std::map< Node, TermArgTrie >::iterator it = d_data.find( r );
+TNode TermArgTrie::existsTerm( std::vector< TNode >& reps, int argIndex ) {
+  if( argIndex==(int)reps.size() ){
+    if( d_data.empty() ){
+      return Node::null();
+    }else{
+      return d_data.begin()->first;
+    }
+  }else{
+    std::map< TNode, TermArgTrie >::iterator it = d_data.find( reps[argIndex] );
     if( it==d_data.end() ){
-      d_data[r].addTerm2( qe, n, argIndex+1 );
+      return Node::null();
+    }else{
+      return it->second.existsTerm( reps, argIndex+1 );
+    }
+  }
+}
+
+bool TermArgTrie::addTerm( TNode n, std::vector< TNode >& reps, int argIndex ){
+  if( argIndex==(int)reps.size() ){
+    if( d_data.empty() ){
+      //store n in d_data (this should be interpretted as the "data" and not as a reference to a child)
+      d_data[n].clear();
       return true;
     }else{
-      return it->second.addTerm2( qe, n, argIndex+1 );
+      return false;
     }
   }else{
-    //store n in d_data (this should be interpretted as the "data" and not as a reference to a child)
-    d_data[n].d_data.clear();
-    return false;
+    return d_data[reps[argIndex]].addTerm( n, reps, argIndex+1 );
   }
 }
 
 void TermArgTrie::debugPrint( const char * c, Node n, unsigned depth ) {
-  for( std::map< Node, TermArgTrie >::iterator it = d_data.begin(); it != d_data.end(); ++it ){
+  for( std::map< TNode, TermArgTrie >::iterator it = d_data.begin(); it != d_data.end(); ++it ){
     for( unsigned i=0; i<depth; i++ ){ Debug(c) << "  "; }
     Debug(c) << it->first << std::endl;
     it->second.debugPrint( c, n, depth+1 );
@@ -57,7 +73,8 @@ void TermArgTrie::debugPrint( const char * c, Node n, unsigned depth ) {
 }
 
 TermDb::TermDb( context::Context* c, context::UserContext* u, QuantifiersEngine* qe ) : d_quantEngine( qe ), d_op_ccount( u ) {
-
+  d_true = NodeManager::currentNM()->mkConst( true );
+  d_false = NodeManager::currentNM()->mkConst( false );
 }
 
 /** ground terms */
@@ -129,8 +146,6 @@ void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant ){
               for( size_t i=0; i<d_op_triggers[op].size(); i++ ){
                 addedLemmas += d_op_triggers[op][i]->addTerm( n );
               }
-              //Message() << "Terms, added lemmas: " << addedLemmas << std::endl;
-              d_quantEngine->flushLemmas( &d_quantEngine->getOutputChannel() );
             }
           }
         }
@@ -143,65 +158,193 @@ void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant ){
   }
 }
 
- void TermDb::reset( Theory::Effort effort ){
+void TermDb::computeArgReps( TNode n ) {
+  if( d_arg_reps.find( n )==d_arg_reps.end() ){
+    eq::EqualityEngine * ee = d_quantEngine->getTheoryEngine()->getMasterEqualityEngine();
+    for( unsigned j=0; j<n.getNumChildren(); j++ ){
+      TNode r = ee->hasTerm( n[j] ) ? ee->getRepresentative( n[j] ) : n[j];
+      d_arg_reps[n].push_back( r );
+    }
+  }
+}
+
+void TermDb::computeUfEqcTerms( TNode f ) {
+  if( d_func_map_eqc_trie.find( f )==d_func_map_eqc_trie.end() ){
+    d_func_map_eqc_trie[f].clear();
+    eq::EqualityEngine * ee = d_quantEngine->getTheoryEngine()->getMasterEqualityEngine();
+    for( unsigned i=0; i<d_op_map[f].size(); i++ ){
+      TNode n = d_op_map[f][i];
+      if( !n.getAttribute(NoMatchAttribute()) ){
+        computeArgReps( n );
+        TNode r = ee->hasTerm( n ) ? ee->getRepresentative( n ) : n;
+        d_func_map_eqc_trie[f].d_data[r].addTerm( n, d_arg_reps[n] );
+      }
+    }
+  }
+}
+
+TNode TermDb::evaluateTerm( TNode n, std::map< TNode, TNode >& subs, bool subsRep ) {
+  Trace("term-db-eval") << "evaluate term : " << n << std::endl;
+  eq::EqualityEngine * ee = d_quantEngine->getTheoryEngine()->getMasterEqualityEngine();
+  if( ee->hasTerm( n ) ){
+    Trace("term-db-eval") << "...exists in ee, return rep " << std::endl;
+    return ee->getRepresentative( n );
+  }else if( n.getKind()==BOUND_VARIABLE ){
+    Assert( subs.find( n )!=subs.end() );
+    Trace("term-db-eval") << "...substitution is : " << subs[n] << std::endl;
+    if( subsRep ){
+      Assert( ee->hasTerm( subs[n] ) );
+      Assert( ee->getRepresentative( subs[n] )==subs[n] );
+      return subs[n];
+    }else{
+      return evaluateTerm( subs[n], subs, subsRep );
+    }
+  }else{
+    if( n.hasOperator() ){
+      TNode f = getOperator( n );
+      if( !f.isNull() ){
+        std::vector< TNode > args;
+        for( unsigned i=0; i<n.getNumChildren(); i++ ){
+          TNode c = evaluateTerm( n[i], subs, subsRep );
+          if( c.isNull() ){
+            return TNode::null();
+          }
+          Trace("term-db-eval") << "Got child : " << c << std::endl;
+          args.push_back( c );
+        }
+        Trace("term-db-eval") << "Get term from DB" << std::endl;
+        TNode nn = d_func_map_trie[f].existsTerm( args );
+        Trace("term-db-eval") << "Got term " << nn << std::endl;
+        if( !nn.isNull() ){
+          if( ee->hasTerm( nn ) ){
+            Trace("term-db-eval") << "return rep " << std::endl;
+            return ee->getRepresentative( nn );
+          }else{
+            //Assert( false );
+          }
+        }
+      }
+    }
+    return TNode::null();
+  }
+}
+
+TNode TermDb::evaluateTerm( TNode n ) {
+  eq::EqualityEngine * ee = d_quantEngine->getTheoryEngine()->getMasterEqualityEngine();
+  if( ee->hasTerm( n ) ){
+    return ee->getRepresentative( n );
+  }else if( n.getKind()!=BOUND_VARIABLE ){
+    if( n.hasOperator() ){
+      TNode f = getOperator( n );
+      if( !f.isNull() ){
+        std::vector< TNode > args;
+        for( unsigned i=0; i<n.getNumChildren(); i++ ){
+          TNode c = evaluateTerm( n[i] );
+          if( c.isNull() ){
+            return TNode::null();
+          }
+          args.push_back( c );
+        }
+        TNode nn = d_func_map_trie[f].existsTerm( args );
+        if( !nn.isNull() ){
+          if( ee->hasTerm( nn ) ){
+            return ee->getRepresentative( nn );
+          }else{
+            //Assert( false );
+          }
+        }
+      }
+    }
+  }
+  return TNode::null();
+}
+
+bool TermDb::isEntailed( TNode n, std::map< TNode, TNode >& subs, bool subsRep, bool pol ) {
+  Trace("term-db-eval") << "Check entailed : " << n << ", pol = " << pol << std::endl;
+  Assert( n.getType().isBoolean() );
+  if( n.getKind()==EQUAL ){
+    TNode n1 = evaluateTerm( n[0], subs, subsRep );
+    if( !n1.isNull() ){
+      TNode n2 = evaluateTerm( n[1], subs, subsRep );
+      if( !n2.isNull() ){
+        eq::EqualityEngine * ee = d_quantEngine->getTheoryEngine()->getMasterEqualityEngine();
+        Assert( ee->hasTerm( n1 ) );
+        Assert( ee->hasTerm( n2 ) );
+        if( pol ){
+          return n1==n2 || ee->areEqual( n1, n2 );
+        }else{
+          return n1!=n2 && ee->areDisequal( n1, n2, false );
+        }
+      }
+    }
+  }else if( n.getKind()==APPLY_UF ){
+    TNode n1 = evaluateTerm( n, subs, subsRep );
+    if( !n1.isNull() ){
+      eq::EqualityEngine * ee = d_quantEngine->getTheoryEngine()->getMasterEqualityEngine();
+      Assert( ee->hasTerm( n1 ) );
+      TNode n2 = pol ? d_true : d_false;
+      if( ee->hasTerm( n2 ) ){
+        return ee->areEqual( n1, n2 );
+      }
+    }
+  }else if( n.getKind()==NOT ){
+    return isEntailed( n[0], subs, subsRep, !pol );
+  }else if( n.getKind()==OR || n.getKind()==AND ){
+    bool simPol = ( pol && n.getKind()==OR ) || ( !pol && n.getKind()==AND );
+    for( unsigned i=0; i<n.getNumChildren(); i++ ){
+      if( isEntailed( n[i], subs, subsRep, pol ) ){
+        if( simPol ){
+          return true;
+        }
+      }else{
+        if( !simPol ){
+          return false;
+        }
+      }
+    }
+    return !simPol;
+  }else if( n.getKind()==IFF || n.getKind()==ITE ){
+    for( unsigned i=0; i<2; i++ ){
+      if( isEntailed( n[0], subs, subsRep, i==0 ) ){
+        unsigned ch = ( n.getKind()==IFF || i==0 ) ? 1 : 2;
+        bool reqPol = ( n.getKind()==ITE || i==0 ) ? pol : !pol;
+        return isEntailed( n[ch], subs, subsRep, reqPol );
+      }
+    }
+  }
+  return false;
+}
+
+void TermDb::reset( Theory::Effort effort ){
    int nonCongruentCount = 0;
    int congruentCount = 0;
    int alreadyCongruentCount = 0;
+   d_op_nonred_count.clear();
+   d_arg_reps.clear();
+   d_func_map_trie.clear();
+   d_func_map_eqc_trie.clear();
    //rebuild d_func/pred_map_trie for each operation, this will calculate all congruent terms
    for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){
      d_op_nonred_count[ it->first ] = 0;
      if( !it->second.empty() ){
-       if( it->second[0].getType().isBoolean() ){
-         d_pred_map_trie[ 0 ][ it->first ].d_data.clear();
-         d_pred_map_trie[ 1 ][ it->first ].d_data.clear();
-       }else{
-         d_func_map_trie[ it->first ].d_data.clear();
-         for( int i=0; i<(int)it->second.size(); i++ ){
-           Node n = it->second[i];
-           computeModelBasisArgAttribute( n );
-           if( !n.getAttribute(NoMatchAttribute()) ){
-             if( !d_func_map_trie[ it->first ].addTerm( d_quantEngine, n ) ){
-               NoMatchAttribute nma;
-               n.setAttribute(nma,true);
-               Debug("term-db-cong") << n << " is redundant." << std::endl;
-               congruentCount++;
-             }else{
-               nonCongruentCount++;
-               d_op_nonred_count[ it->first ]++;
-             }
-           }else{
+       for( unsigned i=0; i<it->second.size(); i++ ){
+         Node n = it->second[i];
+         computeModelBasisArgAttribute( n );
+         if( !n.getAttribute(NoMatchAttribute()) ){
+           computeArgReps( n );
+           if( !d_func_map_trie[ it->first ].addTerm( n, d_arg_reps[n] ) ){
+             NoMatchAttribute nma;
+             n.setAttribute(nma,true);
+             Debug("term-db-cong") << n << " is redundant." << std::endl;
              congruentCount++;
-             alreadyCongruentCount++;
-           }
-         }
-       }
-     }
-   }
-   for( int i=0; i<2; i++ ){
-     Node n = NodeManager::currentNM()->mkConst( i==1 );
-     if( d_quantEngine->getEqualityQuery()->getEngine()->hasTerm( n ) ){
-       eq::EqClassIterator eqc( d_quantEngine->getEqualityQuery()->getEngine()->getRepresentative( n ),
-                                d_quantEngine->getEqualityQuery()->getEngine() );
-       while( !eqc.isFinished() ){
-         Node en = (*eqc);
-         computeModelBasisArgAttribute( en );
-         if( en.getKind()==APPLY_UF && !TermDb::hasInstConstAttr(en) ){
-           if( !en.getAttribute(NoMatchAttribute()) ){
-             Node op = getOperator( en );
-             if( !d_pred_map_trie[i][op].addTerm( d_quantEngine, en ) ){
-               NoMatchAttribute nma;
-               en.setAttribute(nma,true);
-               Debug("term-db-cong") << en << " is redundant." << std::endl;
-               congruentCount++;
-             }else{
-               nonCongruentCount++;
-               d_op_nonred_count[ op ]++;
-             }
            }else{
-             alreadyCongruentCount++;
+             nonCongruentCount++;
+             d_op_nonred_count[ it->first ]++;
            }
+         }else{
+           congruentCount++;
+           alreadyCongruentCount++;
          }
-         ++eqc;
        }
      }
    }
@@ -219,6 +362,39 @@ void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant ){
    }
 }
 
+TermArgTrie * TermDb::getTermArgTrie( Node f ) {
+  std::map< Node, TermArgTrie >::iterator itut = d_func_map_trie.find( f );
+  if( itut!=d_func_map_trie.end() ){
+    return &itut->second;
+  }else{
+    return NULL;
+  }
+}
+
+TermArgTrie * TermDb::getTermArgTrie( Node eqc, Node f ) {
+  computeUfEqcTerms( f );
+  std::map< Node, TermArgTrie >::iterator itut = d_func_map_eqc_trie.find( f );
+  if( itut==d_func_map_eqc_trie.end() ){
+    return NULL;
+  }else{
+    if( eqc.isNull() ){
+      return &itut->second;
+    }else{
+      std::map< TNode, TermArgTrie >::iterator itute = itut->second.d_data.find( eqc );
+      if( itute!=itut->second.d_data.end() ){
+        return &itute->second;
+      }else{
+        return NULL;
+      }
+    }
+  }
+}
+
+TNode TermDb::existsTerm( Node f, Node n ) {
+  computeArgReps( n );
+  return d_func_map_trie[f].existsTerm( d_arg_reps[n] );
+}
+
 Node TermDb::getModelBasisTerm( TypeNode tn, int i ){
   if( d_model_basis_term.find( tn )==d_model_basis_term.end() ){
     Node mbt;
@@ -448,14 +624,15 @@ void getSelfSel( const DatatypeConstructor& dc, Node n, TypeNode ntn, std::vecto
 
 
 Node TermDb::mkSkolemizedBody( Node f, Node n, std::vector< TypeNode >& argTypes, std::vector< TNode >& fvs,
-                               std::vector< Node >& sk ) {
+                               std::vector< Node >& sk, Node& sub, std::vector< unsigned >& sub_vars ) {
+  Assert( sk.empty() || sk.size()==f[0].getNumChildren() );
   //calculate the variables and substitution
   std::vector< TNode > ind_vars;
   std::vector< unsigned > ind_var_indicies;
   std::vector< TNode > vars;
   std::vector< unsigned > var_indicies;
   for( unsigned i=0; i<f[0].getNumChildren(); i++ ){
-    if( options::dtStcInduction() && datatypes::DatatypesRewriter::isTermDatatype( f[0][i] ) ){
+    if( isInductionTerm( f[0][i] ) ){
       ind_vars.push_back( f[0][i] );
       ind_var_indicies.push_back( i );
     }else{
@@ -463,19 +640,23 @@ Node TermDb::mkSkolemizedBody( Node f, Node n, std::vector< TypeNode >& argTypes
       var_indicies.push_back( i );
     }
     Node s;
-    //make the new function symbol
-    if( argTypes.empty() ){
-      s = NodeManager::currentNM()->mkSkolem( "skv", f[0][i].getType(), "created during skolemization" );
+    //make the new function symbol or use existing
+    if( i>=sk.size() ){
+      if( argTypes.empty() ){
+        s = NodeManager::currentNM()->mkSkolem( "skv", f[0][i].getType(), "created during skolemization" );
+      }else{
+        TypeNode typ = NodeManager::currentNM()->mkFunctionType( argTypes, f[0][i].getType() );
+        Node op = NodeManager::currentNM()->mkSkolem( "skop", typ, "op created during pre-skolemization" );
+        //DOTHIS: set attribute on op, marking that it should not be selected as trigger
+        std::vector< Node > funcArgs;
+        funcArgs.push_back( op );
+        funcArgs.insert( funcArgs.end(), fvs.begin(), fvs.end() );
+        s = NodeManager::currentNM()->mkNode( kind::APPLY_UF, funcArgs );
+      }
+      sk.push_back( s );
     }else{
-      TypeNode typ = NodeManager::currentNM()->mkFunctionType( argTypes, f[0][i].getType() );
-      Node op = NodeManager::currentNM()->mkSkolem( "skop", typ, "op created during pre-skolemization" );
-      //DOTHIS: set attribute on op, marking that it should not be selected as trigger
-      std::vector< Node > funcArgs;
-      funcArgs.push_back( op );
-      funcArgs.insert( funcArgs.end(), fvs.begin(), fvs.end() );
-      s = NodeManager::currentNM()->mkNode( kind::APPLY_UF, funcArgs );
+      Assert( sk[i].getType()==f[0][i].getType() );
     }
-    sk.push_back( s );
   }
   Node ret;
   if( vars.empty() ){
@@ -489,44 +670,57 @@ Node TermDb::mkSkolemizedBody( Node f, Node n, std::vector< TypeNode >& argTypes
     ret = n.substitute( vars.begin(), vars.end(), var_sk.begin(), var_sk.end() );
   }
   if( !ind_vars.empty() ){
-    Trace("stc-ind") << "Ind strengthen : (not " << f << ")" << std::endl;
-    Trace("stc-ind") << "Skolemized is : " << ret << std::endl;
-    Node nret;
+    Trace("sk-ind") << "Ind strengthen : (not " << f << ")" << std::endl;
+    Trace("sk-ind") << "Skolemized is : " << ret << std::endl;
     Node n_str_ind;
     TypeNode tn = ind_vars[0].getType();
-    if( datatypes::DatatypesRewriter::isTypeDatatype(tn) ){
-      Node k = sk[ind_var_indicies[0]];
+    Node k = sk[ind_var_indicies[0]];
+    Node nret = ret.substitute( ind_vars[0], k );
+    //note : everything is under a negation
+    //the following constructs ~( R( x, k ) => ~P( x ) )
+    if( options::dtStcInduction() && datatypes::DatatypesRewriter::isTypeDatatype(tn) ){
       const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
       std::vector< Node > disj;
       for( unsigned i=0; i<dt.getNumConstructors(); i++ ){
-       std::vector< Node > selfSel;
-       getSelfSel( dt[i], k, tn, selfSel );
-       std::vector< Node > conj;
-       conj.push_back( NodeManager::currentNM()->mkNode( APPLY_TESTER, Node::fromExpr( dt[i].getTester() ), k ).negate() );
-       for( unsigned j=0; j<selfSel.size(); j++ ){
-         conj.push_back( ret.substitute( ind_vars[0], selfSel[j] ).negate() );
-       }
-       disj.push_back( conj.size()==1 ? conj[0] : NodeManager::currentNM()->mkNode( OR, conj ) );
+        std::vector< Node > selfSel;
+        getSelfSel( dt[i], k, tn, selfSel );
+        std::vector< Node > conj;
+        conj.push_back( NodeManager::currentNM()->mkNode( APPLY_TESTER, Node::fromExpr( dt[i].getTester() ), k ).negate() );
+        for( unsigned j=0; j<selfSel.size(); j++ ){
+          conj.push_back( ret.substitute( ind_vars[0], selfSel[j] ).negate() );
+        }
+        disj.push_back( conj.size()==1 ? conj[0] : NodeManager::currentNM()->mkNode( OR, conj ) );
       }
       Assert( !disj.empty() );
       n_str_ind = disj.size()==1 ? disj[0] : NodeManager::currentNM()->mkNode( AND, disj );
-      Trace("stc-ind") << "Strengthening is : " << n_str_ind << std::endl;
-      nret = ret.substitute( ind_vars[0], k );
+    }else if( options::intWfInduction() && tn.isInteger() ){
+      Node icond = NodeManager::currentNM()->mkNode( GEQ, k, NodeManager::currentNM()->mkConst( Rational(0) ) );
+      Node iret = ret.substitute( ind_vars[0], NodeManager::currentNM()->mkNode( MINUS, k, NodeManager::currentNM()->mkConst( Rational(1) ) ) ).negate();
+      n_str_ind = NodeManager::currentNM()->mkNode( OR, icond.negate(), iret );
+      n_str_ind = NodeManager::currentNM()->mkNode( AND, icond, n_str_ind );
     }else{
-      Trace("stc-ind") << "Unknown induction for term : " << ind_vars[0] << ", type = " << tn << std::endl;
+      Trace("sk-ind") << "Unknown induction for term : " << ind_vars[0] << ", type = " << tn << std::endl;
       Assert( false );
     }
-    
+    Trace("sk-ind") << "Strengthening is : " << n_str_ind << std::endl;
+
     std::vector< Node > rem_ind_vars;
     rem_ind_vars.insert( rem_ind_vars.end(), ind_vars.begin()+1, ind_vars.end() );
     if( !rem_ind_vars.empty() ){
       Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, rem_ind_vars );
       nret = NodeManager::currentNM()->mkNode( FORALL, bvl, nret );
+      nret = Rewriter::rewrite( nret );
+      sub = nret;
+      sub_vars.insert( sub_vars.end(), ind_var_indicies.begin()+1, ind_var_indicies.end() );
       n_str_ind = NodeManager::currentNM()->mkNode( FORALL, bvl, n_str_ind.negate() ).negate();
     }
     ret = NodeManager::currentNM()->mkNode( OR, nret, n_str_ind );
   }
   Trace("quantifiers-sk") << "mkSkolem body for " << f << " returns : " << ret << std::endl;
+  //if it has an instantiation level, set the skolemized body to that level
+  if( f.hasAttribute(InstLevelAttribute()) ){
+    theory::QuantifiersEngine::setInstantiationLevelAttr( ret, f.getAttribute(InstLevelAttribute()) );
+  }
   return ret;
 }
 
@@ -535,7 +729,17 @@ Node TermDb::getSkolemizedBody( Node f ){
   if( d_skolem_body.find( f )==d_skolem_body.end() ){
     std::vector< TypeNode > fvTypes;
     std::vector< TNode > fvs;
-    d_skolem_body[ f ] = mkSkolemizedBody( f, f[1], fvTypes, fvs, d_skolem_constants[f] );
+    Node sub;
+    std::vector< unsigned > sub_vars;
+    d_skolem_body[ f ] = mkSkolemizedBody( f, f[1], fvTypes, fvs, d_skolem_constants[f], sub, sub_vars );
+    //store sub quantifier information
+    if( !sub.isNull() ){
+      //if we are skolemizing one at a time, we already know the skolem constants of the sub-quantified formula, store them
+      Assert( d_skolem_constants[sub].empty() );
+      for( unsigned i=0; i<sub_vars.size(); i++ ){
+        d_skolem_constants[sub].push_back( d_skolem_constants[f][sub_vars[i]] );
+      }
+    }
     Assert( d_skolem_constants[f].size()==f[0].getNumChildren() );
     if( options::sortInference() ){
       for( unsigned i=0; i<d_skolem_constants[f].size(); i++ ){
@@ -547,6 +751,27 @@ Node TermDb::getSkolemizedBody( Node f ){
   return d_skolem_body[ f ];
 }
 
+Node TermDb::getEnumerateTerm( TypeNode tn, unsigned index ) {
+  std::map< TypeNode, unsigned >::iterator it = d_typ_enum_map.find( tn );
+  unsigned teIndex;
+  if( it==d_typ_enum_map.end() ){
+    teIndex = (int)d_typ_enum.size();
+    d_typ_enum_map[tn] = teIndex;
+    d_typ_enum.push_back( TypeEnumerator(tn) );
+  }else{
+    teIndex = it->second;
+  }
+  while( index>=d_enum_terms[tn].size() ){
+    if( d_typ_enum[teIndex].isFinished() ){
+      return Node::null();
+    }
+    d_enum_terms[tn].push_back( *d_typ_enum[teIndex] );
+    ++d_typ_enum[teIndex];
+  }
+  return d_enum_terms[tn][index];
+}
+
+
 Node TermDb::getFreeVariableForInstConstant( Node n ){
   TypeNode tn = n.getType();
   if( d_free_vars.find( tn )==d_free_vars.end() ){
@@ -752,6 +977,17 @@ void TermDb::registerTrigger( theory::inst::Trigger* tr, Node op ){
   }
 }
 
+bool TermDb::isInductionTerm( Node n ) {
+  if( options::dtStcInduction() && datatypes::DatatypesRewriter::isTermDatatype( n ) ){
+    return true;
+  }
+  if( options::intWfInduction() && n.getType().isInteger() ){
+    return true;
+  }
+  return false;
+}
+
+
 bool TermDb::isRewriteRule( Node q ) {
   return !getRewriteRule( q ).isNull();
 }
@@ -763,3 +999,113 @@ Node TermDb::getRewriteRule( Node q ) {
     return Node::null();
   }
 }
+
+
+void TermDb::computeAttributes( Node q ) {
+  if( q.getNumChildren()==3 ){
+    for( unsigned i=0; i<q[2].getNumChildren(); i++ ){
+      Trace("quant-attr-debug") << "Check : " << q[2][i] << " " << q[2][i].getKind() << std::endl;
+      if( q[2][i].getKind()==INST_ATTRIBUTE ){
+        Node avar = q[2][i][0];
+        if( avar.getAttribute(AxiomAttribute()) ){
+          Trace("quant-attr") << "Attribute : axiom : " << q << std::endl;
+          d_qattr_axiom[q] = true;
+        }
+        if( avar.getAttribute(ConjectureAttribute()) ){
+          Trace("quant-attr") << "Attribute : conjecture : " << q << std::endl;
+          d_qattr_conjecture[q] = true;
+        }
+        if( avar.getAttribute(SygusAttribute()) ){
+          //should be nested existential
+          Assert( q[1].getKind()==NOT );
+          Assert( q[1][0].getKind()==FORALL );
+          Trace("quant-attr") << "Attribute : sygus : " << q << std::endl;
+          d_qattr_sygus[q] = true;
+          if( d_quantEngine->getCegInstantiation()==NULL ){
+            Trace("quant-warn") << "WARNING : ceg instantiation is null, and we have : " << q << std::endl;
+          }
+          d_quantEngine->setOwner( q, d_quantEngine->getCegInstantiation() );
+        }
+        if( avar.getAttribute(SynthesisAttribute()) ){
+          Trace("quant-attr") << "Attribute : synthesis : " << q << std::endl;
+          d_qattr_synthesis[q] = true;
+          if( d_quantEngine->getCegInstantiation()==NULL ){
+            Trace("quant-warn") << "WARNING : ceg instantiation is null, and we have : " << q << std::endl;
+          }
+          d_quantEngine->setOwner( q, d_quantEngine->getCegInstantiation() );
+        }
+        if( avar.hasAttribute(QuantInstLevelAttribute()) ){
+          d_qattr_qinstLevel[q] = avar.getAttribute(QuantInstLevelAttribute());
+          Trace("quant-attr") << "Attribute : quant inst level " << d_qattr_qinstLevel[q] << " : " << q << std::endl;
+        }
+        if( avar.hasAttribute(RrPriorityAttribute()) ){
+          d_qattr_rr_priority[q] = avar.getAttribute(RrPriorityAttribute());
+          Trace("quant-attr") << "Attribute : rr priority " << d_qattr_rr_priority[q] << " : " << q << std::endl;
+        }
+        if( avar.getKind()==REWRITE_RULE ){
+          Trace("quant-attr") << "Attribute : rewrite rule : " << q << std::endl;
+          Assert( i==0 );
+          if( d_quantEngine->getRewriteEngine()==NULL ){
+            Trace("quant-warn") << "WARNING : rewrite engine is null, and we have : " << q << std::endl;
+          }
+          //set rewrite engine as owner
+          d_quantEngine->setOwner( q, d_quantEngine->getRewriteEngine() );
+        }
+      }
+    }
+  }
+}
+
+bool TermDb::isQAttrConjecture( Node q ) {
+  std::map< Node, bool >::iterator it = d_qattr_conjecture.find( q );
+  if( it==d_qattr_conjecture.end() ){
+    return false;
+  }else{
+    return it->second;
+  }
+}
+
+bool TermDb::isQAttrAxiom( Node q ) {
+  std::map< Node, bool >::iterator it = d_qattr_axiom.find( q );
+  if( it==d_qattr_axiom.end() ){
+    return false;
+  }else{
+    return it->second;
+  }
+}
+
+bool TermDb::isQAttrSygus( Node q ) {
+  std::map< Node, bool >::iterator it = d_qattr_sygus.find( q );
+  if( it==d_qattr_sygus.end() ){
+    return false;
+  }else{
+    return it->second;
+  }
+}
+
+bool TermDb::isQAttrSynthesis( Node q ) {
+  std::map< Node, bool >::iterator it = d_qattr_synthesis.find( q );
+  if( it==d_qattr_synthesis.end() ){
+    return false;
+  }else{
+    return it->second;
+  }
+}
+
+int TermDb::getQAttrQuantInstLevel( Node q ) {
+  std::map< Node, int >::iterator it = d_qattr_qinstLevel.find( q );
+  if( it==d_qattr_qinstLevel.end() ){
+    return -1;
+  }else{
+    return it->second;
+  }
+}
+
+int TermDb::getQAttrRewriteRulePriority( Node q ) {
+  std::map< Node, int >::iterator it = d_qattr_rr_priority.find( q );
+  if( it==d_qattr_rr_priority.end() ){
+    return -1;
+  }else{
+    return it->second;
+  }
+}
index c839d08d72ff547266d7da7dd80e3380782b6af9..25ef9c81c4ff2423c734af6b830cf6ba67621f0c 100644 (file)
 
 #include "expr/attribute.h"
 #include "theory/theory.h"
+#include "theory/type_enumerator.h"
 
 #include <map>
 
 namespace CVC4 {
 namespace theory {
 
+/** 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;
+  
+/** Attribute true for quantifiers that are SyGus conjectures */
+struct SygusAttributeId {};
+typedef expr::Attribute< SygusAttributeId, bool > SygusAttribute;
+
+/** Attribute true for quantifiers that are synthesis conjectures */
+struct SynthesisAttributeId {};
+typedef expr::Attribute< SynthesisAttributeId, bool > SynthesisAttribute;
+
 /** Attribute true for nodes that should not be used for matching */
 struct NoMatchAttributeId {};
 /** use the special for boolean flag */
@@ -55,6 +72,13 @@ typedef expr::Attribute<ModelBasisArgAttributeId, uint64_t> ModelBasisArgAttribu
 struct BoundIntLitAttributeId {};
 typedef expr::Attribute<BoundIntLitAttributeId, uint64_t> BoundIntLitAttribute;
 
+//for quantifier instantiation level
+struct QuantInstLevelAttributeId {};
+typedef expr::Attribute<QuantInstLevelAttributeId, uint64_t> QuantInstLevelAttribute;
+
+//rewrite-rule priority
+struct RrPriorityAttributeId {};
+typedef expr::Attribute<RrPriorityAttributeId, uint64_t> RrPriorityAttribute;
 
 class QuantifiersEngine;
 
@@ -69,14 +93,14 @@ namespace rrinst{
 namespace quantifiers {
 
 class TermArgTrie {
-private:
-  bool addTerm2( QuantifiersEngine* qe, Node n, int argIndex );
 public:
   /** the data */
-  std::map< Node, TermArgTrie > d_data;
+  std::map< TNode, TermArgTrie > d_data;
 public:
-  bool addTerm( QuantifiersEngine* qe, Node n ) { return addTerm2( qe, n, 0 ); }
+  TNode existsTerm( std::vector< TNode >& reps, int argIndex = 0 );
+  bool addTerm( TNode n, std::vector< TNode >& reps, int argIndex = 0 );
   void debugPrint( const char * c, Node n, unsigned depth = 0 );
+  void clear() { d_data.clear(); }
 };/* class TermArgTrie */
 
 
@@ -103,6 +127,9 @@ private:
 public:
   TermDb( context::Context* c, context::UserContext* u, QuantifiersEngine* qe );
   ~TermDb(){}
+  /** boolean terms */
+  Node d_true;
+  Node d_false;
   /** ground terms */
   unsigned getNumGroundTerms( Node f );
   /** count number of non-redundant ground terms per operator */
@@ -111,16 +138,34 @@ public:
   std::map< Node, std::vector< Node > > d_op_map;
   /** map from APPLY_UF functions to trie */
   std::map< Node, TermArgTrie > d_func_map_trie;
-  /** map from APPLY_UF predicates to trie */
-  std::map< Node, TermArgTrie > d_pred_map_trie[2];
+  std::map< Node, TermArgTrie > d_func_map_eqc_trie;
+  /**mapping from UF terms to representatives of their arguments */
+  std::map< TNode, std::vector< TNode > > d_arg_reps;
   /** map from type nodes to terms of that type */
   std::map< TypeNode, std::vector< Node > > d_type_map;
   /** add a term to the database */
   void addTerm( Node n, std::set< Node >& added, bool withinQuant = false );
   /** reset (calculate which terms are active) */
   void reset( Theory::Effort effort );
-  /** get operation */
+  /** get operator*/
   Node getOperator( Node n );
+  /** get term arg index */
+  TermArgTrie * getTermArgTrie( Node f );
+  TermArgTrie * getTermArgTrie( Node eqc, Node f );
+  /** exists term */
+  TNode existsTerm( Node f, Node n );
+  /** compute arg reps */
+  void computeArgReps( TNode n );
+  /** compute uf eqc terms */
+  void computeUfEqcTerms( TNode f );
+  /** evaluate a term under a substitution.  Return representative in EE if possible.
+   * subsRep is whether subs contains only representatives
+   */
+  TNode evaluateTerm( TNode n, std::map< TNode, TNode >& subs, bool subsRep );
+  /** same as above, but without substitution */
+  TNode evaluateTerm( TNode n );
+  /** is entailed (incomplete check) */
+  bool isEntailed( TNode n, std::map< TNode, TNode >& subs, bool subsRep, bool pol );
 public:
   /** parent structure (for efficient E-matching):
       n -> op -> index -> L
@@ -197,6 +242,8 @@ public:
 public:
   //get bound variables in n
   static void getBoundVars( Node n, std::vector< Node >& bvs);
+  
+  
 //for skolem
 private:
   /** map from universal quantifiers to their skolemized body */
@@ -206,10 +253,23 @@ public:
   std::map< Node, std::vector< Node > > d_skolem_constants;
   /** make the skolemized body f[e/x] */
   static Node mkSkolemizedBody( Node f, Node n, std::vector< TypeNode >& fvTypes, std::vector< TNode >& fvs,
-                                std::vector< Node >& sk );
+                                std::vector< Node >& sk, Node& sub, std::vector< unsigned >& sub_vars );
   /** get the skolemized body */
   Node getSkolemizedBody( Node f);
-
+  /** is induction variable */
+  static bool isInductionTerm( Node n );
+  
+//for ground term enumeration
+private:  
+  /** ground terms enumerated for types */
+  std::map< TypeNode, std::vector< Node > > d_enum_terms;
+  //type enumerators
+  std::map< TypeNode, unsigned > d_typ_enum_map;
+  std::vector< TypeEnumerator > d_typ_enum;
+public:
+  //get nth term for type
+  Node getEnumerateTerm( TypeNode tn, unsigned index );  
+  
 //miscellaneous
 public:
   /** map from universal quantifiers to the list of variables */
@@ -245,11 +305,38 @@ public:
   int isInstanceOf( Node n1, Node n2 );
   /** filter all nodes that have instances */
   void filterInstances( std::vector< Node >& nodes );
-public:
+
+  
+public: //general queries concerning quantified formulas wrt modules
   /** is quantifier treated as a rewrite rule? */
   static bool isRewriteRule( Node q );
   /** get the rewrite rule associated with the quanfied formula */
   static Node getRewriteRule( Node q );
+  
+//attributes
+private:
+  std::map< Node, bool > d_qattr_conjecture;
+  std::map< Node, bool > d_qattr_axiom;
+  std::map< Node, bool > d_qattr_sygus;
+  std::map< Node, bool > d_qattr_synthesis;
+  std::map< Node, int > d_qattr_rr_priority;
+  std::map< Node, int > d_qattr_qinstLevel;
+  //record attributes
+  void computeAttributes( Node q );
+public:
+  /** is conjecture */
+  bool isQAttrConjecture( Node q );
+  /** is axiom */
+  bool isQAttrAxiom( Node q );
+  /** is sygus conjecture */
+  bool isQAttrSygus( Node q );
+  /** is synthesis conjecture */
+  bool isQAttrSynthesis( Node q );
+  /** get instantiation level */
+  int getQAttrQuantInstLevel( Node q );
+  /** get rewrite rule priority */
+  int getQAttrRewriteRulePriority( Node q );
+  
 };/* class TermDb */
 
 }/* CVC4::theory::quantifiers namespace */
index 4ba3c499d7e90b44017e94ac24d441e4bc81d33b..f7c4c745f81d153957627d9107d0192042d96461 100644 (file)
@@ -42,6 +42,10 @@ TheoryQuantifiers::TheoryQuantifiers(Context* c, context::UserContext* u, Output
   d_baseDecLevel = -1;
   out.handleUserAttribute( "axiom", this );
   out.handleUserAttribute( "conjecture", this );
+  out.handleUserAttribute( "sygus", this );
+  out.handleUserAttribute( "synthesis", this );
+  out.handleUserAttribute( "quant-inst-max-level", this );
+  out.handleUserAttribute( "rr-priority", this );
 }
 
 TheoryQuantifiers::~TheoryQuantifiers() {
@@ -107,6 +111,10 @@ void TheoryQuantifiers::collectModelInfo(TheoryModel* m, bool fullModel) {
 }
 
 void TheoryQuantifiers::check(Effort e) {
+  if (done() && !fullEffort(e)) {
+    return;
+  }
+
   CodeTimer codeTimer(d_theoryTime);
 
   Trace("quantifiers-check") << "quantifiers::check(" << e << ")" << std::endl;
@@ -193,6 +201,6 @@ bool TheoryQuantifiers::restart(){
   }
 }
 
-void TheoryQuantifiers::setUserAttribute( const std::string& attr, Node n ){
-  QuantifiersAttributes::setUserAttribute( attr, n );
+void TheoryQuantifiers::setUserAttribute(const std::string& attr, Node n, std::vector<Node> node_values, std::string str_value){
+  QuantifiersAttributes::setUserAttribute( attr, n, node_values, str_value );
 }
index ffd3c4c598cf93eecb610a1c0eabb9da280fde4a..6febc84178e0110efe8ad16e3b8464fbb34a0f8d 100644 (file)
@@ -69,7 +69,7 @@ public:
   void shutdown() { }
   std::string identify() const { return std::string("TheoryQuantifiers"); }
   bool flipDecision();
-  void setUserAttribute( const std::string& attr, Node n );
+  void setUserAttribute(const std::string& attr, Node n, std::vector<Node> node_values, std::string str_value);
   eq::EqualityEngine* getMasterEqualityEngine() { return d_masterEqualityEngine; }
   bool ppDontRewriteSubterm(TNode atom) { return atom.getKind() == kind::FORALL || atom.getKind() == kind::EXISTS; }
 private:
index e4b1732ddade6e83eb5c297d2f63c111aa4885f1..5d86c29c042aaac10163dc45b78963897ef3c4fc 100644 (file)
@@ -88,6 +88,21 @@ struct QuantifierInstPatternTypeRule {
   }
 };/* struct QuantifierInstPatternTypeRule */
 
+struct QuantifierInstNoPatternTypeRule {
+  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+    throw(TypeCheckingExceptionPrivate) {
+    Assert(n.getKind() == kind::INST_NO_PATTERN );
+    return nodeManager->instPatternType();
+  }
+};/* struct QuantifierInstNoPatternTypeRule */
+
+struct QuantifierInstAttributeTypeRule {
+  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+    throw(TypeCheckingExceptionPrivate) {
+    Assert(n.getKind() == kind::INST_ATTRIBUTE );
+    return nodeManager->instPatternType();
+  }
+};/* struct QuantifierInstAttributeTypeRule */
 
 struct QuantifierInstPatternListTypeRule {
   inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
@@ -95,7 +110,7 @@ struct QuantifierInstPatternListTypeRule {
     Assert(n.getKind() == kind::INST_PATTERN_LIST );
     if( check ){
       for( int i=0; i<(int)n.getNumChildren(); i++ ){
-        if( n[i].getKind()!=kind::INST_PATTERN ){
+        if( n[i].getKind()!=kind::INST_PATTERN && n[i].getKind()!=kind::INST_NO_PATTERN && n[i].getKind()!=kind::INST_ATTRIBUTE ){
           throw TypeCheckingExceptionPrivate(n, "argument of inst pattern list is not inst pattern");
         }
       }
@@ -141,7 +156,6 @@ public:
   }
 };/* class RewriteRuleTypeRule */
 
-
 class RRRewriteTypeRule {
 public:
 
index c6ee480577012e4b1fcad159a2bda0b5087f593e..b2b8e7197d7aabdf3968bbf6871fd78d0b8b9aee 100644 (file)
@@ -188,19 +188,7 @@ Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >&
   }
 
   //check for duplicate?
-  if( trOption==TR_MAKE_NEW ){
-    //static int trNew = 0;
-    //static int trOld = 0;
-    //Trigger* t = qe->getTermDatabase()->getTrigger( trNodes );
-    //if( t ){
-    //  trOld++;
-    //}else{
-    //  trNew++;
-    //}
-    //if( (trNew+trOld)%100==0 ){
-    //  Notice() << "Trigger new old = " << trNew << " " << trOld << std::endl;
-    //}
-  }else{
+  if( trOption!=TR_MAKE_NEW ){
     Trigger* t = qe->getTriggerDatabase()->getTrigger( trNodes );
     if( t ){
       if( trOption==TR_GET_OLD ){
@@ -215,21 +203,13 @@ Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >&
   qe->getTriggerDatabase()->addTrigger( trNodes, t );
   return t;
 }
+
 Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, Node n, int matchOption, bool keepAll, int trOption, bool smartTriggers ){
   std::vector< Node > nodes;
   nodes.push_back( n );
   return mkTrigger( qe, f, nodes, matchOption, keepAll, trOption, smartTriggers );
 }
 
-bool Trigger::isUsableTrigger( std::vector< Node >& nodes, Node f ){
-  for( int i=0; i<(int)nodes.size(); i++ ){
-    if( !isUsableTrigger( nodes[i], f ) ){
-      return false;
-    }
-  }
-  return true;
-}
-
 bool Trigger::isUsable( Node n, Node f ){
   if( quantifiers::TermDb::getInstConstAttr(n)==f ){
     if( isAtomicTrigger( n ) ){
@@ -243,9 +223,7 @@ bool Trigger::isUsable( Node n, Node f ){
       return true;
     }else{
       std::map< Node, Node > coeffs;
-      if( isArithmeticTrigger( f, n, coeffs ) ){
-        return true;
-      }else if( isBooleanTermTrigger( n ) ){
+      if( isBooleanTermTrigger( n ) ){
         return true;
       }
     }
@@ -324,7 +302,7 @@ bool Trigger::isUsableTrigger( Node n, Node f ){
 
 bool Trigger::isAtomicTrigger( Node n ){
   Kind k = n.getKind();
-  return ( k==APPLY_UF && !n.getOperator().getAttribute(NoMatchAttribute()) ) || 
+  return ( k==APPLY_UF && !n.getOperator().getAttribute(NoMatchAttribute()) ) ||
          ( k!=APPLY_UF && isAtomicTriggerKind( k ) );
 }
 bool Trigger::isAtomicTriggerKind( Kind k ) {
@@ -347,7 +325,7 @@ bool Trigger::isSimpleTrigger( Node n ){
 }
 
 
-bool Trigger::collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt, bool pol, bool hasPol ){
+bool Trigger::collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt, std::vector< Node >& exclude, bool pol, bool hasPol ){
   if( patMap.find( n )==patMap.end() ){
     patMap[ n ] = false;
     bool newHasPol = n.getKind()==IFF ? false : hasPol;
@@ -359,14 +337,17 @@ bool Trigger::collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map<
         bool retVal = false;
         for( int i=0; i<(int)n.getNumChildren(); i++ ){
           bool newHasPol2 = (n.getKind()==ITE && i==0) ? false : newHasPol;
-          if( collectPatTerms2( qe, f, n[i], patMap, tstrt, newPol, newHasPol2 ) ){
+          if( collectPatTerms2( qe, f, n[i], patMap, tstrt, exclude, newPol, newHasPol2 ) ){
             retVal = true;
           }
         }
         if( retVal ){
           return true;
         }else{
-          Node nu = getIsUsableTrigger( n, f, pol, hasPol );
+          Node nu;
+          if( std::find( exclude.begin(), exclude.end(), n )==exclude.end() ){
+            nu = getIsUsableTrigger( n, f, pol, hasPol );
+          }
           if( !nu.isNull() ){
             patMap[ nu ] = true;
             return true;
@@ -377,7 +358,10 @@ bool Trigger::collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map<
       }
     }else{
       bool retVal = false;
-      Node nu = getIsUsableTrigger( n, f, pol, hasPol );
+      Node nu;
+      if( std::find( exclude.begin(), exclude.end(), n )==exclude.end() ){
+        nu = getIsUsableTrigger( n, f, pol, hasPol );
+      }
       if( !nu.isNull() ){
         patMap[ nu ] = true;
         if( tstrt==TS_MAX_TRIGGER ){
@@ -389,7 +373,7 @@ bool Trigger::collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map<
       if( n.getKind()!=FORALL ){
         for( int i=0; i<(int)n.getNumChildren(); i++ ){
           bool newHasPol2 = (n.getKind()==ITE && i==0) ? false : newHasPol;
-          if( collectPatTerms2( qe, f, n[i], patMap, tstrt, newPol, newHasPol2 ) ){
+          if( collectPatTerms2( qe, f, n[i], patMap, tstrt, exclude, newPol, newHasPol2 ) ){
             retVal = true;
           }
         }
@@ -401,12 +385,41 @@ bool Trigger::collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map<
   }
 }
 
-void Trigger::collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, bool filterInst ){
+bool Trigger::isBooleanTermTrigger( Node n ) {
+  if( n.getKind()==ITE ){
+    //check for boolean term converted to ITE
+    if( n[0].getKind()==INST_CONSTANT &&
+        n[1].getKind()==CONST_BITVECTOR &&
+        n[2].getKind()==CONST_BITVECTOR ){
+      if( ((BitVectorType)n[1].getType().toType()).getSize()==1 &&
+          n[1].getConst<BitVector>().toInteger()==1 &&
+          n[2].getConst<BitVector>().toInteger()==0 ){
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+bool Trigger::isPureTheoryTrigger( Node n ) {
+  if( n.getKind()==APPLY_UF || n.getKind()==VARIABLE || n.getKind()==SKOLEM ){  //|| !quantifiers::TermDb::hasInstConstAttr( n ) ){
+    return false;
+  }else{
+    for( unsigned i=0; i<n.getNumChildren(); i++ ){
+      if( !isPureTheoryTrigger( n[i] ) ){
+        return false;
+      }
+    }
+    return true;
+  }
+}
+
+void Trigger::collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, std::vector< Node >& exclude, bool filterInst ){
   std::map< Node, bool > patMap;
   if( filterInst ){
     //immediately do not consider any term t for which another term is an instance of t
     std::vector< Node > patTerms2;
-    collectPatTerms( qe, f, n, patTerms2, TS_ALL, false );
+    collectPatTerms( qe, f, n, patTerms2, TS_ALL, exclude, false );
     std::vector< Node > temp;
     temp.insert( temp.begin(), patTerms2.begin(), patTerms2.end() );
     qe->getTermDatabase()->filterInstances( temp );
@@ -434,7 +447,7 @@ void Trigger::collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vecto
       }
     }
   }
-  collectPatTerms2( qe, f, n, patMap, tstrt, true, true );
+  collectPatTerms2( qe, f, n, patMap, tstrt, exclude, true, true );
   for( std::map< Node, bool >::iterator it = patMap.begin(); it != patMap.end(); ++it ){
     if( it->second ){
       patTerms.push_back( it->first );
@@ -442,65 +455,91 @@ void Trigger::collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vecto
   }
 }
 
-bool Trigger::isArithmeticTrigger( Node f, Node n, std::map< Node, Node >& coeffs ){
-  if( n.getKind()==PLUS ){
-    Assert( coeffs.empty() );
-    NodeBuilder<> t(kind::PLUS);
-    for( int i=0; i<(int)n.getNumChildren(); i++ ){
+Node Trigger::getInversionVariable( Node n ) {
+  if( n.getKind()==INST_CONSTANT ){
+    return n;
+  }else if( n.getKind()==PLUS || n.getKind()==MULT ){
+    Node ret;
+    for( unsigned i=0; i<n.getNumChildren(); i++ ){
       if( quantifiers::TermDb::hasInstConstAttr(n[i]) ){
-        if( n[i].getKind()==INST_CONSTANT ){
-          if( quantifiers::TermDb::getInstConstAttr(n[i])==f ){
-            coeffs[ n[i] ] = Node::null();
-          }else{
-            coeffs.clear();
-            return false;
+        if( ret.isNull() ){
+          ret = getInversionVariable( n[i] );
+          if( ret.isNull() ){
+            Trace("var-trigger-debug") << "No : multiple variables " << n << std::endl;
+            return Node::null();
+          }
+        }else{
+          return Node::null();
+        }
+      }else if( n.getKind()==MULT ){
+        if( !n[i].isConst() ){
+          Trace("var-trigger-debug") << "No : non-linear coefficient " << n << std::endl;
+          return Node::null();
+        }else if( n.getType().isInteger() ){
+          Rational r = n[i].getConst<Rational>();
+          if( r!=Rational(-1) && r!=Rational(1) ){
+            Trace("var-trigger-debug") << "No : not integer coefficient " << n << std::endl;
+            return Node::null();
           }
-        }else if( !isArithmeticTrigger( f, n[i], coeffs ) ){
-          coeffs.clear();
-          return false;
         }
-      }else{
-        t << n[i];
       }
     }
-    if( t.getNumChildren()==0 ){
-      coeffs[ Node::null() ] = NodeManager::currentNM()->mkConst( Rational(0) );
-    }else if( t.getNumChildren()==1 ){
-      coeffs[ Node::null() ]  = t.getChild( 0 );
-    }else{
-      coeffs[ Node::null() ]  = t;
-    }
-    return true;
-  }else if( n.getKind()==MULT ){
-    if( n[0].getKind()==INST_CONSTANT && quantifiers::TermDb::getInstConstAttr(n[0])==f ){
-      if( !quantifiers::TermDb::hasInstConstAttr(n[1]) ){
-        coeffs[ n[0] ] = n[1];
-        return true;
-      }
-    }else if( n[1].getKind()==INST_CONSTANT && quantifiers::TermDb::getInstConstAttr(n[1])==f ){
-      if( !quantifiers::TermDb::hasInstConstAttr(n[0]) ){
-        coeffs[ n[1] ] = n[0];
-        return true;
+    return ret;
+  }else{
+    Trace("var-trigger-debug") << "No : unsupported operator " << n << "." << std::endl;
+  }
+  return Node::null();
+}
+
+Node Trigger::getInversion( Node n, Node x ) {
+  if( n.getKind()==INST_CONSTANT ){
+    return x;
+  }else if( n.getKind()==PLUS || n.getKind()==MULT ){
+    int cindex = -1;
+    for( unsigned i=0; i<n.getNumChildren(); i++ ){
+      if( !quantifiers::TermDb::hasInstConstAttr(n[i]) ){
+        if( n.getKind()==PLUS ){
+          x = NodeManager::currentNM()->mkNode( MINUS, x, n[i] );
+        }else if( n.getKind()==MULT ){
+          Assert( n[i].isConst() );
+          Node coeff = NodeManager::currentNM()->mkConst( Rational(1) / n[i].getConst<Rational>() );
+          x = NodeManager::currentNM()->mkNode( MULT, x, coeff );
+        }
+      }else{
+        Assert( cindex==-1 );
+        cindex = i;
       }
     }
+    Assert( cindex!=-1 );
+    return getInversion( n[cindex], x );
   }
-  return false;
+  return Node::null();
 }
 
-bool Trigger::isBooleanTermTrigger( Node n ) {
-  if( n.getKind()==ITE ){
-    //check for boolean term converted to ITE
-    if( n[0].getKind()==INST_CONSTANT &&
-        n[1].getKind()==CONST_BITVECTOR &&
-        n[2].getKind()==CONST_BITVECTOR ){
-      if( ((BitVectorType)n[1].getType().toType()).getSize()==1 &&
-          n[1].getConst<BitVector>().toInteger()==1 &&
-          n[2].getConst<BitVector>().toInteger()==0 ){
-        return true;
+InstMatchGenerator* Trigger::getInstMatchGenerator( Node n ) {
+  if( n.getKind()==INST_CONSTANT ){
+    return NULL;
+  }else{
+    Trace("var-trigger-debug") << "Is " << n << " a variable trigger?" << std::endl;
+    if( isBooleanTermTrigger( n ) ){
+      VarMatchGeneratorBooleanTerm* vmg = new VarMatchGeneratorBooleanTerm( n[0], n[1] );
+      Trace("var-trigger") << "Boolean term trigger : " << n << ", var = " << n[0] << std::endl;
+      return vmg;
+    }else{
+      Node x;
+      if( options::purifyTriggers() ){
+        x = getInversionVariable( n );
+      }
+      if( !x.isNull() ){
+        Node s = getInversion( n, x );
+        VarMatchGeneratorTermSubs* vmg = new VarMatchGeneratorTermSubs( x, s );
+        Trace("var-trigger") << "Term substitution trigger : " << n << ", var = " << x << ", subs = " << s << std::endl;
+        return vmg;
+      }else{
+        return new InstMatchGenerator( n );
       }
     }
   }
-  return false;
 }
 
 Trigger* TriggerTrie::getTrigger2( std::vector< Node >& nodes ){
index 17da6f0d56f72804a518785560d24674d69d86ea..75ada4f8323065eb6e2319f8c65608e9f27a5bd4 100644 (file)
@@ -30,6 +30,7 @@ class QuantifiersEngine;
 namespace inst {
 
 class IMGenerator;
+class InstMatchGenerator;
 
 //a collect of nodes representing a trigger
 class Trigger {
@@ -93,7 +94,7 @@ private:
   static bool isUsable( Node n, Node f );
   static Node getIsUsableTrigger( Node n, Node f, bool pol = true, bool hasPol = false );
   /** collect all APPLY_UF pattern terms for f in n */
-  static bool collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt, bool pol, bool hasPol );
+  static bool collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt, std::vector< Node >& exclude, bool pol, bool hasPol );
 public:
   //different strategies for choosing trigger terms
   enum {
@@ -101,17 +102,19 @@ public:
     TS_MIN_TRIGGER,
     TS_ALL,
   };
-  static void collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, bool filterInst = false );
+  static void collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, std::vector< Node >& exclude, bool filterInst = false );
 public:
   /** is usable trigger */
-  static bool isUsableTrigger( std::vector< Node >& nodes, Node f );
   static bool isUsableTrigger( Node n, Node f );
   static bool isAtomicTrigger( Node n );
   static bool isAtomicTriggerKind( Kind k );
   static bool isSimpleTrigger( Node n );
-  /** get pattern arithmetic */
-  static bool isArithmeticTrigger( Node f, Node n, std::map< Node, Node >& coeffs );
   static bool isBooleanTermTrigger( Node n );
+  static bool isPureTheoryTrigger( Node n );
+  /** return data structure for producing matches for this trigger. */
+  static InstMatchGenerator* getInstMatchGenerator( Node n );
+  static Node getInversionVariable( Node n );
+  static Node getInversion( Node n, Node x );
 
   inline void toStream(std::ostream& out) const {
     /*
index c55ffa2a6611a7d1a5e756f79521ec90ad48ffda..d17899cf2c51c81b2f42ec5f8119fb6c8b8d96ab 100644 (file)
@@ -30,6 +30,8 @@
 #include "theory/quantifiers/bounded_integers.h"
 #include "theory/quantifiers/rewrite_engine.h"
 #include "theory/quantifiers/quant_conflict_find.h"
+#include "theory/quantifiers/conjecture_generator.h"
+#include "theory/quantifiers/ce_guided_instantiation.h"
 #include "theory/quantifiers/relevant_domain.h"
 #include "theory/uf/options.h"
 #include "theory/uf/theory_uf.h"
@@ -41,6 +43,34 @@ using namespace CVC4::context;
 using namespace CVC4::theory;
 using namespace CVC4::theory::inst;
 
+
+eq::EqualityEngine * QuantifiersModule::getEqualityEngine() {
+  return d_quantEngine->getTheoryEngine()->getMasterEqualityEngine();
+}
+
+bool QuantifiersModule::areEqual( TNode n1, TNode n2 ) {
+  eq::EqualityEngine * ee = getEqualityEngine();
+  return n1==n2 || ( ee->hasTerm( n1 ) && ee->hasTerm( n2 ) && ee->areEqual( n1, n2 ) );
+}
+
+bool QuantifiersModule::areDisequal( TNode n1, TNode n2 ) {
+  eq::EqualityEngine * ee = getEqualityEngine();
+  return n1!=n2 && ee->hasTerm( n1 ) && ee->hasTerm( n2 ) && ee->areDisequal( n1, n2, false );
+}
+
+TNode QuantifiersModule::getRepresentative( TNode n ) {
+  eq::EqualityEngine * ee = getEqualityEngine();
+  if( ee->hasTerm( n ) ){
+    return ee->getRepresentative( n );
+  }else{
+    return n;
+  }
+}
+
+quantifiers::TermDb * QuantifiersModule::getTermDatabase() {
+  return d_quantEngine->getTermDatabase();
+}
+
 QuantifiersEngine::QuantifiersEngine(context::Context* c, context::UserContext* u, TheoryEngine* te):
 d_te( te ),
 d_lemmas_produced_c(u){
@@ -83,6 +113,12 @@ d_lemmas_produced_c(u){
   }else{
     d_qcf = NULL;
   }
+  if( options::conjectureGen() ){
+    d_sg_gen = new quantifiers::ConjectureGenerator( this, c );
+    d_modules.push_back( d_sg_gen );
+  }else{
+    d_sg_gen = NULL;
+  }
   if( !options::finiteModelFind() || options::fmfInstEngine() ){
     //the instantiation must set incomplete flag unless finite model finding is turned on
     d_inst_engine = new quantifiers::InstantiationEngine( this, !options::finiteModelFind() );
@@ -109,6 +145,12 @@ d_lemmas_produced_c(u){
   }else{
     d_rr_engine = NULL;
   }
+  if( options::ceGuidedInst() ){
+    d_ceg_inst = new quantifiers::CegInstantiation( this, c );
+    d_modules.push_back( d_ceg_inst );
+  }else{
+    d_ceg_inst = NULL;
+  }
 
   //options
   d_total_inst_count_debug = 0;
@@ -157,58 +199,111 @@ void QuantifiersEngine::finishInit(){
   }
 }
 
+QuantifiersModule * QuantifiersEngine::getOwner( Node q ) { 
+  std::map< Node, QuantifiersModule * >::iterator it = d_owner.find( q );
+  if( it==d_owner.end() ){
+    return NULL;
+  }else{
+    return it->second;
+  }
+}
+
+void QuantifiersEngine::setOwner( Node q, QuantifiersModule * m ) {
+  QuantifiersModule * mo = getOwner( q );
+  if( mo!=m ){
+    if( mo!=NULL ){
+      Trace("quant-warn") << "WARNING: setting owner of " << q << " to " << ( m ? m->identify() : "null" ) << ", but already has owner " << mo->identify() << "!" << std::endl;
+    }
+    d_owner[q] = m; 
+  }
+}
+
+bool QuantifiersEngine::hasOwnership( Node q, QuantifiersModule * m ) {
+  QuantifiersModule * mo = getOwner( q );
+  return mo==m || mo==NULL;
+}
+
 void QuantifiersEngine::check( Theory::Effort e ){
   CodeTimer codeTimer(d_time);
-  bool needsCheck = e>=Theory::EFFORT_LAST_CALL;  //always need to check at or above last call
-  for( int i=0; i<(int)d_modules.size(); i++ ){
-    if( d_modules[i]->needsCheck( e ) ){
-      needsCheck = true;
+  bool needsCheck = false;
+  bool needsBuildModel = false;
+  std::vector< QuantifiersModule* > qm;
+  if( d_model->getNumAssertedQuantifiers()>0 ){
+    needsCheck = e>=Theory::EFFORT_LAST_CALL;  //always need to check at or above last call
+    for( int i=0; i<(int)d_modules.size(); i++ ){
+      if( d_modules[i]->needsCheck( e ) ){
+        qm.push_back( d_modules[i] );
+        needsCheck = true;
+      }
     }
   }
   if( needsCheck ){
     Trace("quant-engine") << "Quantifiers Engine check, level = " << e << std::endl;
+    Trace("quant-engine-debug") << "  modules to check : ";
+    for( unsigned i=0; i<qm.size(); i++ ){
+      Trace("quant-engine-debug") << qm[i]->identify() << " ";
+    }
+    Trace("quant-engine-debug") << std::endl;
+    Trace("quant-engine-debug") << "  # quantified formulas = " << d_model->getNumAssertedQuantifiers() << std::endl;
+    Trace("quant-engine-debug") << "  Theory engine finished : " << !d_te->needCheck() << std::endl;
+
     if( !getMasterEqualityEngine()->consistent() ){
       Trace("quant-engine") << "Master equality engine not consistent, return." << std::endl;
       return;
     }
-    Trace("quant-engine-debug") << "Resetting modules..." << std::endl;
+    Trace("quant-engine-debug") << "Resetting all modules..." << std::endl;
     //reset relevant information
+    d_conflict = false;
     d_hasAddedLemma = false;
+
+    //flush previous lemmas (for instance, if was interupted)
+    flushLemmas();
+    if( d_hasAddedLemma ){
+      return;
+    }
+
     d_term_db->reset( e );
     d_eq_query->reset();
     if( d_rel_dom ){
       d_rel_dom->reset();
     }
+    d_model->reset_round();
     for( int i=0; i<(int)d_modules.size(); i++ ){
       d_modules[i]->reset_round( e );
     }
-    Trace("quant-engine-debug") << "Done resetting modules." << std::endl;
+    Trace("quant-engine-debug") << "Done resetting all modules." << std::endl;
 
     if( e==Theory::EFFORT_LAST_CALL ){
-      //if effort is last call, try to minimize model first
-      if( options::finiteModelFind() ){
-        //first, check if we can minimize the model further
-        if( !((uf::TheoryUF*)getTheoryEngine()->theoryOf( THEORY_UF ))->getStrongSolver()->minimize() ){
-          return;
-        }
+      //if effort is last call, try to minimize model first FIXME: remove?
+      uf::StrongSolverTheoryUF * ufss = ((uf::TheoryUF*)getTheoryEngine()->theoryOf( THEORY_UF ))->getStrongSolver();
+      if( ufss && !ufss->minimize() ){
+        return;
       }
       ++(d_statistics.d_instantiation_rounds_lc);
     }else if( e==Theory::EFFORT_FULL ){
       ++(d_statistics.d_instantiation_rounds);
     }
-    Trace("quant-engine-debug") << "Check with modules..." << std::endl;
-    for( int i=0; i<(int)d_modules.size(); i++ ){
-      Trace("quant-engine-debug") << "Check " << d_modules[i]->identify().c_str() << "..." << std::endl;
-      d_modules[i]->check( e );
+
+    Trace("quant-engine-debug") << "Check modules that needed check..." << std::endl;
+    for( unsigned quant_e = QEFFORT_CONFLICT; quant_e<=QEFFORT_MODEL; quant_e++ ){
+      for( int i=0; i<(int)qm.size(); i++ ){
+        Trace("quant-engine-debug") << "Check " << qm[i]->identify().c_str() << " at effort " << quant_e << "..." << std::endl;
+        qm[i]->check( e, quant_e );
+      }
+      //flush all current lemmas
+      flushLemmas();
+      //if we have added one, stop
+      if( d_hasAddedLemma ){
+        break;
+      }
     }
-    Trace("quant-engine-debug") << "Done check with modules." << std::endl;
+    Trace("quant-engine-debug") << "Done check modules that needed check." << std::endl;
+
     //build the model if not done so already
     //  this happens if no quantifiers are currently asserted and no model-building module is enabled
     if( e==Theory::EFFORT_LAST_CALL && !d_hasAddedLemma ){
       if( options::produceModels() && !d_model->isModelSet() ){
-        Trace("quant-engine-debug") << "Build the model..." << std::endl;
-        d_te->getModelBuilder()->buildModel( d_model, true );
-        Trace("quant-engine-debug") << "Done building the model." << std::endl;
+        needsBuildModel = true;
       }
       if( Trace.isOn("inst-per-quant") ){
         for( std::map< Node, int >::iterator it = d_total_inst_debug.begin(); it != d_total_inst_debug.end(); ++it ){
@@ -224,15 +319,22 @@ void QuantifiersEngine::check( Theory::Effort e ){
       }
     }
     Trace("quant-engine") << "Finished quantifiers engine check." << std::endl;
+  }else{
+    if( e==Theory::EFFORT_LAST_CALL && options::produceModels() ){
+      needsBuildModel = true;
+    }
+  }
+
+  if( needsBuildModel ){
+    Trace("quant-engine-debug") << "Build the model..." << std::endl;
+    d_te->getModelBuilder()->buildModel( d_model, true );
+    Trace("quant-engine-debug") << "Done building the model." << std::endl;
   }
 }
 
 void QuantifiersEngine::registerQuantifier( Node f ){
   if( std::find( d_quants.begin(), d_quants.end(), f )==d_quants.end() ){
     Trace("quant") << "QuantifiersEngine : Register quantifier ";
-    if( d_term_db->isRewriteRule( f ) ){
-      Trace("quant") << " (rewrite rule)";
-    }
     Trace("quant") << " : " << f << std::endl;
     d_quants.push_back( f );
 
@@ -240,6 +342,11 @@ void QuantifiersEngine::registerQuantifier( Node f ){
     Assert( f.getKind()==FORALL );
     //make instantiation constants for f
     d_term_db->makeInstantiationConstantsFor( f );
+    d_term_db->computeAttributes( f );
+    QuantifiersModule * qm = getOwner( f );
+    if( qm!=NULL ){
+      Trace("quant") << "   Owner : " << qm->identify() << std::endl;
+    }
     //register with quantifier relevance
     if( d_quant_rel ){
       d_quant_rel->registerQuantifier( f );
@@ -261,7 +368,7 @@ void QuantifiersEngine::registerQuantifier( Node f ){
 void QuantifiersEngine::registerPattern( std::vector<Node> & pattern) {
   for(std::vector<Node>::iterator p = pattern.begin(); p != pattern.end(); ++p){
     std::set< Node > added;
-    getTermDatabase()->addTerm(*p,added);
+    getTermDatabase()->addTerm( *p, added );
   }
 }
 
@@ -314,6 +421,10 @@ Node QuantifiersEngine::getNextDecisionRequest(){
 void QuantifiersEngine::addTermToDatabase( Node n, bool withinQuant ){
   std::set< Node > added;
   getTermDatabase()->addTerm( n, added, withinQuant );
+  //maybe have triggered instantiations if we are doing eager instantiation
+  if( options::eagerInstQuant() ){
+    flushLemmas();
+  }
   //added contains also the Node that just have been asserted in this branch
   if( d_quant_rel ){
     for( std::set< Node >::iterator i=added.begin(), end=added.end(); i!=end; i++ ){
@@ -338,6 +449,7 @@ bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& vars, std
   Assert( f.getKind()==FORALL );
   Assert( vars.size()==terms.size() );
   Node body = getInstantiation( f, vars, terms );
+  Trace("inst-assert") << "(assert " << body << ")" << std::endl;
   //make the lemma
   NodeBuilder<> nb(kind::OR);
   nb << f.notNode() << body;
@@ -372,7 +484,7 @@ bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& vars, std
           }
         }
       }
-      setInstantiationLevelAttr( body, f[1], maxInstLevel+1, terms );
+      setInstantiationLevelAttr( body, f[1], maxInstLevel+1 );
     }
     Trace("inst-debug") << "*** Lemma is " << lem << std::endl;
     ++(d_statistics.d_instantiations);
@@ -383,22 +495,54 @@ bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& vars, std
   }
 }
 
-void QuantifiersEngine::setInstantiationLevelAttr( Node n, Node qn, uint64_t level, std::vector< Node >& inst_terms ){
+void QuantifiersEngine::setInstantiationLevelAttr( Node n, Node qn, uint64_t level ){
+  Trace("inst-level-debug2") << "IL : " << n << " " << qn << " " << level << std::endl;
   //if not from the vector of terms we instantiatied
-  if( std::find( inst_terms.begin(), inst_terms.end(), n )==inst_terms.end() ){
+  if( qn.getKind()!=BOUND_VARIABLE && n!=qn ){
     //if this is a new term, without an instantiation level
-    if( n!=qn && !n.hasAttribute(InstLevelAttribute()) ){
+    if( !n.hasAttribute(InstLevelAttribute()) ){
       InstLevelAttribute ila;
       n.setAttribute(ila,level);
+      Trace("inst-level-debug") << "Set instantiation level " << n << " to " << level << std::endl;
     }
-    Assert( qn.getKind()!=BOUND_VARIABLE );
     Assert( n.getNumChildren()==qn.getNumChildren() );
     for( int i=0; i<(int)n.getNumChildren(); i++ ){
-      setInstantiationLevelAttr( n[i], qn[i], level, inst_terms );
+      setInstantiationLevelAttr( n[i], qn[i], level );
+    }
+  }
+}
+
+void QuantifiersEngine::setInstantiationLevelAttr( Node n, uint64_t level ){
+  if( !n.hasAttribute(InstLevelAttribute()) ){
+    InstLevelAttribute ila;
+    n.setAttribute(ila,level);
+    Trace("inst-level-debug") << "Set instantiation level " << n << " to " << level << std::endl;
+  }
+  for( int i=0; i<(int)n.getNumChildren(); i++ ){
+    setInstantiationLevelAttr( n[i], level );
+  }
+}
+
+bool QuantifiersEngine::isTermEligibleForInstantiation( Node n, Node f, bool print ) {
+  if( n.hasAttribute(InstLevelAttribute()) ){
+    int fml = d_term_db->getQAttrQuantInstLevel( f );
+    unsigned ml = fml>=0 ? fml : options::instMaxLevel();
+
+    if( n.getAttribute(InstLevelAttribute())>ml ){
+      Trace("inst-add-debug") << "Term " << n << " has instantiation level " << n.getAttribute(InstLevelAttribute());
+      Trace("inst-add-debug") << ", which is more than maximum allowed level " << ml << " for this quantified formula." << std::endl;
+      return false;
+    }
+  }else{
+    if( options::instLevelInputOnly() ){
+      Trace("inst-add-debug") << "Term " << n << " does not have an instantiation level." << std::endl;
+      return false;
     }
   }
+  return true;
 }
 
+
 Node QuantifiersEngine::getSubstitute( Node n, std::vector< Node >& terms ){
   if( n.getKind()==INST_CONSTANT ){
     Debug("check-inst") << "Substitute inst constant : " << n << std::endl;
@@ -511,7 +655,14 @@ bool QuantifiersEngine::addLemma( Node lem, bool doCache ){
   }
 }
 
+void QuantifiersEngine::addRequirePhase( Node lit, bool req ){
+  d_phase_req_waiting[lit] = req;
+}
+
 bool QuantifiersEngine::addInstantiation( Node f, InstMatch& m, bool mkRep, bool modEq, bool modInst ){
+  // For resource-limiting (also does a time check).
+  getOutputChannel().safePoint();
+
   std::vector< Node > terms;
   //make sure there are values for each variable we are instantiating
   for( size_t i=0; i<f[0].getNumChildren(); i++ ){
@@ -536,24 +687,32 @@ bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& terms, bo
     if( mkRep ){
       //pick the best possible representative for instantiation, based on past use and simplicity of term
       terms[i] = d_eq_query->getInternalRepresentative( terms[i], f, i );
-      //Trace("inst-add-debug") << " (" << terms[i] << ")";
+      Trace("inst-add-debug2") << " (" << terms[i] << ")";
     }
   }
   Trace("inst-add-debug") << std::endl;
 
+  //check based on instantiation level
   if( options::instMaxLevel()!=-1 ){
     for( unsigned i=0; i<terms.size(); i++ ){
-      if( terms[i].hasAttribute(InstLevelAttribute()) &&
-          (int)terms[i].getAttribute(InstLevelAttribute())>options::instMaxLevel() ){
-        Trace("inst-add-debug") << "Term " << terms[i] << " has instantiation level " << terms[i].getAttribute(InstLevelAttribute());
-        Trace("inst-add-debug") << ", which is more than maximum allowed level " << options::instMaxLevel() << std::endl;
+      if( !isTermEligibleForInstantiation( terms[i], f, true ) ){
         return false;
       }
     }
   }
+  //check for entailment
+  if( options::instNoEntail() ){
+    std::map< TNode, TNode > subs;
+    for( unsigned i=0; i<terms.size(); i++ ){
+      subs[f[0][i]] = terms[i];
+    }
+    if( d_term_db->isEntailed( f[1], subs, false, true ) ){
+      Trace("inst-add-debug") << " -> Currently entailed." << std::endl;
+      return false;
+    }
+  }
 
   //check for duplication
-  ///*
   bool alreadyExists = false;
   if( options::incrementalSolving() ){
     Trace("inst-add-debug") << "Adding into context-dependent inst trie, modEq = " << modEq << ", modInst = " << modInst << std::endl;
@@ -575,9 +734,10 @@ bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& terms, bo
     ++(d_statistics.d_inst_duplicate_eq);
     return false;
   }
-  //*/
+
 
   //add the instantiation
+  Trace("inst-add-debug") << "Constructing instantiation..." << std::endl;
   bool addedInst = addInstantiation( f, d_term_db->d_vars[f], terms );
   //report the result
   if( addedInst ){
@@ -608,18 +768,21 @@ bool QuantifiersEngine::addSplitEquality( Node n1, Node n2, bool reqPhase, bool
   return addSplit( fm );
 }
 
-void QuantifiersEngine::flushLemmas( OutputChannel* out ){
+void QuantifiersEngine::flushLemmas(){
   if( !d_lemmas_waiting.empty() ){
-    if( !out ){
-      out = &getOutputChannel();
-    }
     //take default output channel if none is provided
     d_hasAddedLemma = true;
     for( int i=0; i<(int)d_lemmas_waiting.size(); i++ ){
-      out->lemma( d_lemmas_waiting[i], false, true );
+      getOutputChannel().lemma( d_lemmas_waiting[i], false, true );
     }
     d_lemmas_waiting.clear();
   }
+  if( !d_phase_req_waiting.empty() ){
+    for( std::map< Node, bool >::iterator it = d_phase_req_waiting.begin(); it != d_phase_req_waiting.end(); ++it ){
+      getOutputChannel().requirePhase( it->first, it->second );
+    }
+    d_phase_req_waiting.clear();
+  }
 }
 
 void QuantifiersEngine::getPhaseReqTerms( Node f, std::vector< Node >& nodes ){
@@ -793,7 +956,6 @@ Node EqualityQueryQuantifiersEngine::getInternalRepresentative( Node a, Node f,
         //if cbqi is active, do not choose instantiation constant terms
         if( !options::cbqi() || !quantifiers::TermDb::hasInstConstAttr(eqc[i]) ){
           int score = getRepScore( eqc[i], f, index );
-          //score prefers earliest use of this term as a representative
           if( r_best.isNull() || ( score>=0 && ( r_best_score<0 || score<r_best_score ) ) ){
             r_best = eqc[i];
             r_best_score = score;
@@ -809,7 +971,8 @@ Node EqualityQueryQuantifiersEngine::getInternalRepresentative( Node a, Node f,
         }
       }
       //now, make sure that no other member of the class is an instance
-      r_best = getInstance( r_best, eqc );
+      std::hash_map<TNode, Node, TNodeHashFunction> cache;
+      r_best = getInstance( r_best, eqc, cache );
       //store that this representative was chosen at this point
       if( d_rep_score.find( r_best )==d_rep_score.end() ){
         d_rep_score[ r_best ] = d_reset_count;
@@ -916,17 +1079,20 @@ void EqualityQueryQuantifiersEngine::getEquivalenceClass( Node a, std::vector< N
 
 //helper functions
 
-Node EqualityQueryQuantifiersEngine::getInstance( Node n, std::vector< Node >& eqc ){
+Node EqualityQueryQuantifiersEngine::getInstance( Node n, const std::vector< Node >& eqc, std::hash_map<TNode, Node, TNodeHashFunction>& cache ){
+  if(cache.find(n) != cache.end()) {
+    return cache[n];
+  }
   for( size_t i=0; i<n.getNumChildren(); i++ ){
-    Node nn = getInstance( n[i], eqc );
+    Node nn = getInstance( n[i], eqc, cache );
     if( !nn.isNull() ){
-      return nn;
+      return cache[n] = nn;
     }
   }
   if( std::find( eqc.begin(), eqc.end(), n )!=eqc.end() ){
-    return n;
+    return cache[n] = n;
   }else{
-    return Node::null();
+    return cache[n] = Node::null();
   }
 }
 
@@ -945,8 +1111,21 @@ int getDepth( Node n ){
   }
 }
 
+//smaller the score, the better
 int EqualityQueryQuantifiersEngine::getRepScore( Node n, Node f, int index ){
-  return d_rep_score.find( n )==d_rep_score.end() ? -1 : d_rep_score[n];          //initial
+  int s;
+  if( options::instMaxLevel()!=-1 ){
+    //score prefer lowest instantiation level
+    if( n.hasAttribute(InstLevelAttribute()) ){
+      s = n.getAttribute(InstLevelAttribute());
+    }else{
+      s = options::instLevelInputOnly() ? -1 : 0;
+    }
+  }else{
+    //score prefers earliest use of this term as a representative
+    s = d_rep_score.find( n )==d_rep_score.end() ? -1 : d_rep_score[n];
+  }
+  return s;
   //return ( d_rep_score.find( n )==d_rep_score.end() ? 100 : 0 ) + getDepth( n );    //term depth
 }
 
index 7786e0b70b03879e972f4a0c1c216e64d649f66f..b5a02df60d790f0c39f28aa153c69beaba863e22 100644 (file)
@@ -37,6 +37,10 @@ namespace theory {
 
 class QuantifiersEngine;
 
+namespace quantifiers {
+  class TermDb;
+}
+
 class QuantifiersModule {
 protected:
   QuantifiersEngine* d_quantEngine;
@@ -52,7 +56,7 @@ public:
   /* reset at a round */
   virtual void reset_round( Theory::Effort e ){}
   /* Call during quantifier engine's check */
-  virtual void check( Theory::Effort e ) = 0;
+  virtual void check( Theory::Effort e, unsigned quant_e ) = 0;
   /* Called for new quantifiers */
   virtual void registerQuantifier( Node q ) = 0;
   virtual void assertNode( Node n ) = 0;
@@ -61,10 +65,15 @@ public:
   virtual Node explain(TNode n) { return TNode::null(); }
   /** Identify this module (for debugging, dynamic configuration, etc..) */
   virtual std::string identify() const = 0;
+public:
+  eq::EqualityEngine * getEqualityEngine();
+  bool areDisequal( TNode n1, TNode n2 );
+  bool areEqual( TNode n1, TNode n2 );
+  TNode getRepresentative( TNode n );
+  quantifiers::TermDb * getTermDatabase();
 };/* class QuantifiersModule */
 
 namespace quantifiers {
-  class TermDb;
   class FirstOrderModel;
   //modules
   class InstantiationEngine;
@@ -73,6 +82,8 @@ namespace quantifiers {
   class QuantConflictFind;
   class RewriteEngine;
   class RelevantDomain;
+  class ConjectureGenerator;
+  class CegInstantiation;
 }/* CVC4::theory::quantifiers */
 
 namespace inst {
@@ -112,6 +123,16 @@ private:
   quantifiers::QuantConflictFind* d_qcf;
   /** rewrite rules utility */
   quantifiers::RewriteEngine * d_rr_engine;
+  /** subgoal generator */
+  quantifiers::ConjectureGenerator * d_sg_gen;
+  /** ceg instantiation */
+  quantifiers::CegInstantiation * d_ceg_inst;
+public: //effort levels
+  enum {
+    QEFFORT_CONFLICT,
+    QEFFORT_STANDARD,
+    QEFFORT_MODEL,
+  };
 private:
   /** list of all quantifiers seen */
   std::vector< Node > d_quants;
@@ -120,8 +141,12 @@ private:
   BoolMap d_lemmas_produced_c;
   /** lemmas waiting */
   std::vector< Node > d_lemmas_waiting;
+  /** phase requirements waiting */
+  std::map< Node, bool > d_phase_req_waiting;
   /** has added lemma this round */
   bool d_hasAddedLemma;
+  /** has a conflict been found */
+  bool d_conflict;
   /** list of all instantiations produced for each quantifier */
   std::map< Node, inst::InstMatchTrie > d_inst_match_trie;
   std::map< Node, inst::CDInstMatchTrie* > d_c_inst_match_trie;
@@ -147,10 +172,6 @@ public:
   /** get equality query object for the given type. The default is the
       generic one */
   EqualityQueryQuantifiersEngine* getEqualityQuery();
-  /** get instantiation engine */
-  quantifiers::InstantiationEngine* getInstantiationEngine() { return d_inst_engine; }
-  /** get model engine */
-  quantifiers::ModelEngine* getModelEngine() { return d_model_engine; }
   /** get default sat context for quantifiers engine */
   context::Context* getSatContext();
   /** get default sat context for quantifiers engine */
@@ -167,10 +188,31 @@ public:
   QuantPhaseReq* getPhaseRequirements( Node f ) { return d_phase_reqs.find( f )==d_phase_reqs.end() ? NULL : d_phase_reqs[f]; }
   /** get phase requirement terms */
   void getPhaseReqTerms( Node f, std::vector< Node >& nodes );
+public:  //modules
+  /** get instantiation engine */
+  quantifiers::InstantiationEngine* getInstantiationEngine() { return d_inst_engine; }
+  /** get model engine */
+  quantifiers::ModelEngine* getModelEngine() { return d_model_engine; }
   /** get bounded integers utility */
   quantifiers::BoundedIntegers * getBoundedIntegers() { return d_bint; }
   /** Conflict find mechanism for quantifiers */
   quantifiers::QuantConflictFind* getConflictFind() { return d_qcf; }
+  /** rewrite rules utility */
+  quantifiers::RewriteEngine * getRewriteEngine() { return d_rr_engine; }
+  /** subgoal generator */
+  quantifiers::ConjectureGenerator * getConjectureGenerator() { return d_sg_gen; }
+  /** ceg instantiation */
+  quantifiers::CegInstantiation * getCegInstantiation() { return d_ceg_inst; }
+private:
+  /** owner of quantified formulas */
+  std::map< Node, QuantifiersModule * > d_owner;
+public:
+  /** get owner */
+  QuantifiersModule * getOwner( Node q );
+  /** set owner */
+  void setOwner( Node q, QuantifiersModule * m );
+  /** considers */
+  bool hasOwnership( Node q, QuantifiersModule * m = NULL );
 public:
   /** initialize */
   void finishInit();
@@ -192,7 +234,9 @@ private:
   /** instantiate f with arguments terms */
   bool addInstantiation( Node f, std::vector< Node >& vars, std::vector< Node >& terms );
   /** set instantiation level attr */
-  void setInstantiationLevelAttr( Node n, Node qn, uint64_t level, std::vector< Node >& inst_terms );
+  static void setInstantiationLevelAttr( Node n, Node qn, uint64_t level );
+  /** flush lemmas */
+  void flushLemmas();
 public:
   /** get instantiation */
   Node getInstantiation( Node f, std::vector< Node >& vars, std::vector< Node >& terms );
@@ -206,6 +250,8 @@ public:
   bool existsInstantiation( Node f, InstMatch& m, bool modEq = true, bool modInst = false );
   /** add lemma lem */
   bool addLemma( Node lem, bool doCache = true );
+  /** add require phase */
+  void addRequirePhase( Node lit, bool req );
   /** do instantiation specified by m */
   bool addInstantiation( Node f, InstMatch& m, bool mkRep = true, bool modEq = false, bool modInst = false );
   /** add instantiation */
@@ -216,10 +262,12 @@ public:
   bool addSplitEquality( Node n1, Node n2, bool reqPhase = false, bool reqPhasePol = true );
   /** has added lemma */
   bool hasAddedLemma() { return !d_lemmas_waiting.empty() || d_hasAddedLemma; }
-  /** flush lemmas */
-  void flushLemmas( OutputChannel* out = NULL );
   /** get number of waiting lemmas */
   int getNumLemmasWaiting() { return (int)d_lemmas_waiting.size(); }
+  /** set instantiation level attr */
+  static void setInstantiationLevelAttr( Node n, uint64_t level );
+  /** is term eligble for instantiation? */
+  bool isTermEligibleForInstantiation( Node n, Node f, bool print = false );
 public:
   /** get number of quantifiers */
   int getNumQuantifiers() { return (int)d_quants.size(); }
@@ -278,7 +326,7 @@ private:
   bool d_liberal;
 private:
   /** node contains */
-  Node getInstance( Node n, std::vector< Node >& eqc );
+  Node getInstance( Node n, const std::vector< Node >& eqc, std::hash_map<TNode, Node, TNodeHashFunction>& cache );
   /** get score */
   int getRepScore( Node n, Node f, int index );
 public:
index 9542725493f83ae94642cb8ddce0df3b4404baa6..ee14d6fc15b9da25c3a08f2cd92a661de5031fd6 100644 (file)
@@ -38,8 +38,9 @@ int RepSet::getNumRepresentatives( TypeNode tn ) const{
 }
 
 void RepSet::add( TypeNode tn, Node n ){
-  d_tmap[ n ] = (int)d_type_reps[tn].size();
   Trace("rsi-debug") << "Add rep #" << d_type_reps[tn].size() << " for " << tn << " : " << n << std::endl;
+  Assert( n.getType().isSubtypeOf( tn ) );
+  d_tmap[ n ] = (int)d_type_reps[tn].size();
   d_type_reps[tn].push_back( n );
 }
 
index 1c95e78e4b2ef5e38cae0968bd4663b01f13dd7d..6f4b5129d77cd44365b1ee415bcb93d490bcd0bf 100644 (file)
@@ -11,4 +11,10 @@ option setsPropagate --sets-propagate bool :default true
 option setsEagerLemmas --sets-eager-lemmas bool :default true
  add lemmas even at regular effort
 
+expert-option setsCare1 --sets-care1 bool :default false
+ generate one lemma at a time for care graph
+
+option setsPropFull --sets-prop-full bool :default true
+ additional propagation at full effort
+
 endmodule
index a4f3f6a6db5a234c8dd65572b510a0bf1ce79ed5..dc5feecda4313d075ab1f40d4ea42f9f7ebeaeb2 100644 (file)
@@ -35,11 +35,11 @@ public:
   }
   void postCheckInvariants() const {
     Debug("sets-scrutinize") << "[sets-scrutinize] postCheckInvariants()" << std::endl;
-    
+
     // assume not in conflict, and complete:
     // - try building model
     // - check it
-    
+
     TheorySetsPrivate::SettermElementsMap settermElementsMap;
     TNode true_atom = NodeManager::currentNM()->mkConst<bool>(true);
     std::set<Node> terms;
index b59beac8d2fbb2a115acedf017f3619853e89ef0..106ad6e5627ae2130c0ad3df9eb2780e7ebcd02e 100644 (file)
@@ -39,6 +39,9 @@ void TheorySets::addSharedTerm(TNode n) {
 }
 
 void TheorySets::check(Effort e) {
+  if (done() && !fullEffort(e)) {
+    return;
+  }
   d_internal->check(e);
 }
 
@@ -54,6 +57,14 @@ Node TheorySets::explain(TNode node) {
   return d_internal->explain(node);
 }
 
+EqualityStatus TheorySets::getEqualityStatus(TNode a, TNode b) {
+  return d_internal->getEqualityStatus(a, b);
+}
+
+Node TheorySets::getModelValue(TNode node) {
+  return d_internal->getModelValue(node);
+}
+
 void TheorySets::preRegisterTerm(TNode node) {
   d_internal->preRegisterTerm(node);
 }
index a168323896025c5f6ac108dde8711c6f8abe295e..6136fc8f8f767e728d3843c657774d1358d64a81 100644 (file)
@@ -58,6 +58,10 @@ public:
 
   Node explain(TNode);
 
+  EqualityStatus getEqualityStatus(TNode a, TNode b);
+
+  Node getModelValue(TNode);
+
   std::string identify() const { return "THEORY_SETS"; }
 
   void preRegisterTerm(TNode node);
index cae6064095bcdd7e313c72a2af3bd9b8e78664af..57b761500e87189b258cfac907d5d61699c3a44a 100644 (file)
@@ -418,32 +418,192 @@ void TheorySetsPrivate::addSharedTerm(TNode n) {
   d_equalityEngine.addTriggerTerm(n, THEORY_SETS);
 }
 
+void TheorySetsPrivate::dumpAssertionsHumanified() const
+{
+    std::string tag = "sets-assertions";
+
+    if(Trace.isOn(tag)) { /* condition can't be !Trace.isOn, that's why this empty block */ }
+    else { return; }
+
+    context::CDList<Assertion>::const_iterator it = d_external.facts_begin(), it_end = d_external.facts_end();
+
+    std::map<TNode, std::set<TNode> > equalities;
+    std::set< pair<TNode, TNode> > disequalities;
+    std::map<TNode, std::pair<std::set<TNode>, std::set<TNode> > > members;
+    static std::map<TNode, int> numbering;
+    static int number = 0;
+
+    for (unsigned i = 0; it != it_end; ++ it, ++i) {
+      TNode ass = (*it).assertion;
+      // Trace("sets-care-dump") << AssertCommand(ass.toExpr()) << endl;
+      bool polarity = ass.getKind() != kind::NOT;
+      ass = polarity ? ass : ass[0];
+      Assert( ass.getNumChildren() == 2);
+      TNode left = d_equalityEngine.getRepresentative(ass[0]);
+      TNode right = d_equalityEngine.getRepresentative(ass[1]);
+      if(numbering[left] == 0) numbering[left] = ++number;
+      if(numbering[right] == 0) numbering[right] = ++number;
+      equalities[left].insert(ass[0]);
+      equalities[right].insert(ass[1]);
+      if(ass.getKind() == kind::EQUAL) {
+        if(polarity) {
+          Assert(left == right);
+        } else {
+          if(left > right) std::swap(left, right);
+          disequalities.insert(make_pair(left, right));
+        }
+      } else if(ass.getKind() == kind::MEMBER) {
+        (polarity ? members[right].first : members[right].second).insert(left);
+      }
+    }
+#define FORIT(it, container) for(typeof((container).begin()) it=(container).begin(); (it) != (container).end(); ++(it))
+    FORIT(kt, equalities) {
+      Trace(tag) << " Eq class of t" << numbering[(*kt).first] << ": " << std::endl;
+      FORIT(jt, (*kt).second) {
+        TNode S = (*jt);
+        if( S.getKind() != kind::UNION && S.getKind() != kind::INTERSECTION && S.getKind() != kind::SETMINUS) {
+          Trace(tag) << "    " << *jt << ((*jt).getType().isSet() ? "\n": " ");
+        } else {
+          Trace(tag) << "    ";
+          if(S[0].isConst() || numbering.find(d_equalityEngine.getRepresentative(S[0])) == numbering.end()) {
+            Trace(tag) << S[0];
+          } else {
+            Trace(tag) << "t" << numbering[d_equalityEngine.getRepresentative(S[0])];
+          }
+          Trace(tag) << " " << (S.getKind() == kind::UNION ? "|" : (S.getKind() == kind::INTERSECTION ? "&" : "-")) << " ";
+          if(S[1].isConst() || numbering.find(d_equalityEngine.getRepresentative(S[1])) == numbering.end()) {
+            Trace(tag) << S[1];
+          } else {
+            Trace(tag) << "t" << numbering[d_equalityEngine.getRepresentative(S[1])];
+          }
+          Trace(tag) << std::endl;
+        }
+      }
+      Trace(tag) << std::endl;
+    }
+    FORIT(kt, disequalities) Trace(tag) << "NOT(t"<<numbering[(*kt).first]<<" = t" <<numbering[(*kt).second] <<")"<< std::endl;
+    FORIT(kt, members) {
+      if( (*kt).second.first.size() > 0) {
+        Trace(tag) << "IN t" << numbering[(*kt).first] << ": ";
+        FORIT(jt, (*kt).second.first) {
+          TNode x = (*jt);
+          if(x.isConst() || numbering.find(d_equalityEngine.getRepresentative(x)) == numbering.end()) {
+            Trace(tag) << x << ", ";
+          } else {
+            Trace(tag) << "t" << numbering[d_equalityEngine.getRepresentative(x)] << ", ";
+          }
+        }
+        Trace(tag) << std::endl;
+      }
+      if( (*kt).second.second.size() > 0) {
+        Trace(tag) << "NOT IN t" << numbering[(*kt).first] << ": ";
+        FORIT(jt, (*kt).second.second) {
+          TNode x = (*jt);
+          if(x.isConst() || numbering.find(d_equalityEngine.getRepresentative(x)) == numbering.end()) {
+            Trace(tag) << x << ", ";
+          } else {
+            Trace(tag) << "t" << numbering[d_equalityEngine.getRepresentative(x)] << ", ";
+          }
+        }
+        Trace(tag) << std::endl;
+      }
+    }
+    Trace(tag) << std::endl;
+#undef FORIT
+}
 
 void TheorySetsPrivate::computeCareGraph() {
   Debug("sharing") << "Theory::computeCareGraph<" << d_external.identify() << ">()" << endl;
-  for (unsigned i = 0; i < d_external.d_sharedTerms.size(); ++ i) {
+
+  if(Trace.isOn("sets-assertions")) {
+    // dump our understanding of assertions
+    dumpAssertionsHumanified();
+  }
+
+  CVC4_UNUSED unsigned edgesAddedCnt = 0;
+
+  unsigned i_st = 0;
+  if(options::setsCare1()) { i_st = d_ccg_i; }
+  for (unsigned i = i_st; i < d_external.d_sharedTerms.size(); ++ i) {
     TNode a = d_external.d_sharedTerms[i];
     TypeNode aType = a.getType();
-    for (unsigned j = i + 1; j < d_external.d_sharedTerms.size(); ++ j) {
+
+    unsigned j_st = i + 1;
+    if(options::setsCare1()) { if(i == d_ccg_i) j_st = d_ccg_j + 1; }
+
+    for (unsigned j = j_st; j < d_external.d_sharedTerms.size(); ++ j) {
       TNode b = d_external.d_sharedTerms[j];
       if (b.getType() != aType) {
         // We don't care about the terms of different types
         continue;
       }
+
       switch (d_external.d_valuation.getEqualityStatus(a, b)) {
       case EQUALITY_TRUE_AND_PROPAGATED:
+        // If we know about it, we should have propagated it, so we can skip
+        Trace("sets-care") << "[sets-care] Know: " << EQUAL(a, b) << std::endl;
+        break;
       case EQUALITY_FALSE_AND_PROPAGATED:
         // If we know about it, we should have propagated it, so we can skip
+        Trace("sets-care") << "[sets-care] Know: " << NOT(EQUAL(a, b)) << std::endl;
         break;
-      default:
+      case EQUALITY_FALSE:
+      case EQUALITY_TRUE:
+        Assert(false, "ERROR: Equality status true/false but not propagated (sets care graph computation).");
+        break;
+      case EQUALITY_TRUE_IN_MODEL:
+        d_external.addCarePair(a, b);
+        if(Trace.isOn("sharing")) {
+          ++edgesAddedCnt;
+        }
+       if(Debug.isOn("sets-care")) {
+         Debug("sets-care") << "[sets-care] Requesting split between" << a << " and "
+                            << b << "." << std::endl << "[sets-care] "
+                            << "  Both current have value "
+                            << d_external.d_valuation.getModelValue(a) << std::endl;
+       }
+      case EQUALITY_FALSE_IN_MODEL:
+        if(Trace.isOn("sets-care-performance-test")) {
+          // TODO: delete these lines, only for performance testing for now
+          d_external.addCarePair(a, b);
+        }
+        break;
+      case EQUALITY_UNKNOWN:
         // Let's split on it
         d_external.addCarePair(a, b);
+        if(options::setsCare1()) {
+          d_ccg_i = i;
+          d_ccg_j = j;
+          return;
+        }
         break;
+      default:
+       Unreachable();
       }
     }
   }
+  Trace("sharing") << "TheorySetsPrivate::computeCareGraph(): size = " << edgesAddedCnt << std::endl;
 }
 
+EqualityStatus TheorySetsPrivate::getEqualityStatus(TNode a, TNode b) {
+  Assert(d_equalityEngine.hasTerm(a) && d_equalityEngine.hasTerm(b));
+  if (d_equalityEngine.areEqual(a, b)) {
+    // The terms are implied to be equal
+    return EQUALITY_TRUE;
+  }
+  if (d_equalityEngine.areDisequal(a, b, false)) {
+    // The terms are implied to be dis-equal
+    return EQUALITY_FALSE;
+  }
+  if( d_external.d_valuation.getModelValue(a) == d_external.d_valuation.getModelValue(b) ) {
+    // Ther term are true in current model
+    return EQUALITY_TRUE_IN_MODEL;
+  }
+  return EQUALITY_FALSE_IN_MODEL;
+  // }
+  // //TODO: can we be more precise sometimes?
+  // return EQUALITY_UNKNOWN;
+}
 
 /******************** Model generation ********************/
 /******************** Model generation ********************/
@@ -584,6 +744,21 @@ Node TheorySetsPrivate::elementsToShape(Elements elements, TypeNode setType) con
     return cur;
   }
 }
+Node TheorySetsPrivate::elementsToShape(set<Node> elements, TypeNode setType) const
+{
+  NodeManager* nm = NodeManager::currentNM();
+
+  if(elements.size() == 0) {
+    return nm->mkConst(EmptySet(nm->toType(setType)));
+  } else {
+    typeof(elements.begin()) it = elements.begin();
+    Node cur = SINGLETON(*it);
+    while( ++it != elements.end() ) {
+      cur = nm->mkNode(kind::UNION, cur, SINGLETON(*it));
+    }
+    return cur;
+  }
+}
 
 void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel)
 {
@@ -690,6 +865,11 @@ void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel)
 #endif
 }
 
+Node TheorySetsPrivate::getModelValue(TNode n)
+{
+  CodeTimer codeTimer(d_statistics.d_getModelValueTime);
+  return d_termInfoManager->getModelValue(n);
+}
 
 /********************** Helper functions ***************************/
 /********************** Helper functions ***************************/
@@ -736,14 +916,23 @@ Node mkAnd(const std::vector<TNode>& conjunctions) {
 
 
 TheorySetsPrivate::Statistics::Statistics() :
-  d_checkTime("theory::sets::time") {
-
+  d_checkTime("theory::sets::time")
+  , d_getModelValueTime("theory::sets::getModelValueTime")
+  , d_memberLemmas("theory::sets::lemmas::member", 0)
+  , d_disequalityLemmas("theory::sets::lemmas::disequality", 0)
+{
   StatisticsRegistry::registerStat(&d_checkTime);
+  StatisticsRegistry::registerStat(&d_getModelValueTime);
+  StatisticsRegistry::registerStat(&d_memberLemmas);
+  StatisticsRegistry::registerStat(&d_disequalityLemmas);
 }
 
 
 TheorySetsPrivate::Statistics::~Statistics() {
   StatisticsRegistry::unregisterStat(&d_checkTime);
+  StatisticsRegistry::unregisterStat(&d_getModelValueTime);
+  StatisticsRegistry::unregisterStat(&d_memberLemmas);
+  StatisticsRegistry::unregisterStat(&d_disequalityLemmas);
 }
 
 
@@ -813,11 +1002,13 @@ void TheorySetsPrivate::addToPending(Node n) {
     if(n.getKind() == kind::MEMBER) {
       Debug("sets-pending") << "[sets-pending] \u2514 added to member queue"
                             << std::endl;
+      ++d_statistics.d_memberLemmas;
       d_pending.push(n);
     } else {
       Debug("sets-pending") << "[sets-pending] \u2514 added to equality queue"
                             << std::endl;
       Assert(n.getKind() == kind::EQUAL);
+      ++d_statistics.d_disequalityLemmas;
       d_pendingDisequal.push(n);
     }
     d_external.d_out->lemma(getLemma());
@@ -882,6 +1073,9 @@ TheorySetsPrivate::TheorySetsPrivate(TheorySets& external,
   d_pending(c),
   d_pendingDisequal(c),
   d_pendingEverInserted(u),
+  d_modelCache(c),
+  d_ccg_i(c),
+  d_ccg_j(c),
   d_scrutinize(NULL)
 {
   d_termInfoManager = new TermInfoManager(*this, c, &d_equalityEngine);
@@ -906,8 +1100,44 @@ TheorySetsPrivate::~TheorySetsPrivate()
     Assert(d_scrutinize != NULL);
     delete d_scrutinize;
   }
-}
+}/* TheorySetsPrivate::~TheorySetsPrivate() */
+
+void TheorySetsPrivate::propagate(Theory::Effort effort) {
+  if(effort != Theory::EFFORT_FULL || !options::setsPropFull()) {
+    return;
+  }
+
+  // build a model
+  Trace("sets-prop-full") << "[sets-prop-full] propagate(FULL_EFFORT)" << std::endl;
+  if(Trace.isOn("sets-assertions")) {
+    dumpAssertionsHumanified();
+  }
+
+  const CDNodeSet& terms = (d_termInfoManager->d_terms);
+  for(typeof(terms.begin()) it = terms.begin(); it != terms.end(); ++it) {
+    Node node = (*it);
+    Kind k = node.getKind();
+    if(k == kind::UNION && node[0].getKind() == kind::SINGLETON ) {
+
+      if(holds(MEMBER(node[0][0], node[1]))) {
+        Trace("sets-prop-full") << "[sets-prop-full] " << MEMBER(node[0][0], node[1])
+                                << " => " << EQUAL(node[1], node) << std::endl;
+        learnLiteral(EQUAL(node[1], node), MEMBER(node[0][0], node[1]));
+      }
+
+    } else if(k == kind::UNION && node[1].getKind() == kind::SINGLETON ) {
+
+      if(holds(MEMBER(node[1][0], node[0]))) {
+        Trace("sets-prop-full") << "[sets-prop-full] " << MEMBER(node[1][0], node[0])
+                                << " => " << EQUAL(node[0], node) << std::endl;
+        learnLiteral(EQUAL(node[0], node), MEMBER(node[1][0], node[0]));
+      }
+
+    }
+  }
 
+  finishPropagation();
+}
 
 bool TheorySetsPrivate::propagate(TNode literal) {
   Debug("sets-prop") << " propagate(" << literal  << ")" << std::endl;
@@ -925,13 +1155,14 @@ bool TheorySetsPrivate::propagate(TNode literal) {
   }
 
   return ok;
-}/* TheorySetsPropagate::propagate(TNode) */
+}/* TheorySetsPrivate::propagate(TNode) */
 
 
 void TheorySetsPrivate::setMasterEqualityEngine(eq::EqualityEngine* eq) {
   d_equalityEngine.setMasterEqualityEngine(eq);
 }
 
+
 void TheorySetsPrivate::conflict(TNode a, TNode b)
 {
   if (a.getKind() == kind::CONST_BOOLEAN) {
@@ -970,6 +1201,7 @@ Node TheorySetsPrivate::explain(TNode literal)
   return mkAnd(assumptions);
 }
 
+
 void TheorySetsPrivate::preRegisterTerm(TNode node)
 {
   Debug("sets") << "TheorySetsPrivate::preRegisterTerm(" << node << ")"
@@ -1112,6 +1344,8 @@ void TheorySetsPrivate::TermInfoManager::notifyMembership(TNode fact) {
 
   d_info[S]->addToElementList(x, polarity);
   d_info[x]->addToSetList(S, polarity);
+
+  d_theory.d_modelCache.clear();
 }
 
 const CDTNodeList* TheorySetsPrivate::TermInfoManager::getParents(TNode x) {
@@ -1265,8 +1499,38 @@ void TheorySetsPrivate::TermInfoManager::mergeTerms(TNode a, TNode b) {
               (*itb).second->setsContainingThisElement );
   mergeLists( (*ita).second->setsNotContainingThisElement,
               (*itb).second->setsNotContainingThisElement );
+
+  d_theory.d_modelCache.clear();
 }
 
+Node TheorySetsPrivate::TermInfoManager::getModelValue(TNode n)
+{
+  if(d_terms.find(n) == d_terms.end()) {
+    return Node();
+  }
+  Assert(n.getType().isSet());
+  set<Node> elements, elements_const;
+  Node S = d_eqEngine->getRepresentative(n);
+  typeof(d_theory.d_modelCache.begin()) it = d_theory.d_modelCache.find(S);
+  if(it != d_theory.d_modelCache.end()) {
+    return (*it).second;
+  }
+  const CDTNodeList* l = getMembers(S);
+  for(typeof(l->begin()) it = l->begin(); it != l->end(); ++it) {
+    TNode n = *it;
+    elements.insert(d_eqEngine->getRepresentative(n));
+  }
+  BOOST_FOREACH(TNode e, elements) {
+    if(e.isConst()) {
+      elements_const.insert(e);
+    } else {
+      elements_const.insert(d_theory.d_external.d_valuation.getModelValue(e));
+    }
+  }
+  Node v = d_theory.elementsToShape(elements_const, n.getType());
+  d_theory.d_modelCache[n] = v;
+  return v;
+}
 
 }/* CVC4::theory::sets namespace */
 }/* CVC4::theory namespace */
index 78a415529ae0bb3e431cab99e0a42989765eccbe..5369870737ddccef34f641b8c2665532a245e86d 100644 (file)
@@ -47,7 +47,7 @@ public:
                     context::UserContext* u);
 
   ~TheorySetsPrivate();
-  
+
   void setMasterEqualityEngine(eq::EqualityEngine* eq);
 
   void addSharedTerm(TNode);
@@ -60,9 +60,13 @@ public:
 
   Node explain(TNode);
 
+  EqualityStatus getEqualityStatus(TNode a, TNode b);
+
+  Node getModelValue(TNode);
+
   void preRegisterTerm(TNode node);
 
-  void propagate(Theory::Effort) { /* we don't depend on this call */ }
+  void propagate(Theory::Effort);
 
 private:
   TheorySets& d_external;
@@ -70,6 +74,9 @@ private:
   class Statistics {
   public:
     TimerStat d_checkTime;
+    TimerStat d_getModelValueTime;
+    IntStat d_memberLemmas;
+    IntStat d_disequalityLemmas;
 
     Statistics();
     ~Statistics();
@@ -107,8 +114,9 @@ private:
     TheorySetsPrivate& d_theory;
     context::Context* d_context;
     eq::EqualityEngine* d_eqEngine;
-
+  public:
     CDNodeSet d_terms;
+  private:
     std::hash_map<TNode, TheorySetsTermInfo*, TNodeHashFunction> d_info;
 
     void mergeLists(CDTNodeList* la, const CDTNodeList* lb) const;
@@ -123,6 +131,7 @@ private:
     void notifyMembership(TNode fact);
     const CDTNodeList* getParents(TNode x);
     const CDTNodeList* getMembers(TNode S);
+    Node getModelValue(TNode n);
     const CDTNodeList* getNonMembers(TNode S);
     void addTerm(TNode n);
     void mergeTerms(TNode a, TNode b);
@@ -174,11 +183,19 @@ private:
   typedef std::hash_map<TNode, Elements, TNodeHashFunction> SettermElementsMap;
   const Elements& getElements(TNode setterm, SettermElementsMap& settermElementsMap) const;
   Node elementsToShape(Elements elements, TypeNode setType) const;
+  Node elementsToShape(std::set<Node> elements, TypeNode setType) const;
   bool checkModel(const SettermElementsMap& settermElementsMap, TNode S) const;
 
+  context::CDHashMap <Node, Node, NodeHashFunction> d_modelCache;
+
+
+  // sharing related
+  context::CDO<unsigned>  d_ccg_i, d_ccg_j;
+
   // more debugging stuff
   friend class TheorySetsScrutinize;
   TheorySetsScrutinize* d_scrutinize;
+  void dumpAssertionsHumanified() const;  /** do some formatting to make them more readable */
 };/* class TheorySetsPrivate */
 
 
index eb270202ae19ef1cb9740cc862a5cc29ead88fd7..6754bbb9ee2bc9bf35eb43a28e0afcfebb068ff2 100644 (file)
@@ -100,7 +100,7 @@ struct MemberTypeRule {
       }
       TypeNode elementType = n[0].getType(check);
       if(elementType != setType.getSetElementType()) {
-        throw TypeCheckingExceptionPrivate(n, "set in operating on sets of different types");
+        throw TypeCheckingExceptionPrivate(n, "member operating on sets of different types");
       }
     }
     return nodeManager->booleanType();
index 4266c02f5b132ced41db6d2d461e7d63c80e4ee7..0f68d120765c9b7674c5116d1e519392aa4a989b 100644 (file)
@@ -88,6 +88,11 @@ operator REGEXP_LOOP 2:3 "regexp loop"
 operator REGEXP_EMPTY 0 "regexp empty"
 operator REGEXP_SIGMA 0 "regexp all characters"
 
+#internal
+operator REGEXP_RV 1 "regexp rv (internal use only)"
+typerule REGEXP_RV ::CVC4::theory::strings::RegExpRVTypeRule
+
+#typerules
 typerule REGEXP_CONCAT ::CVC4::theory::strings::RegExpConcatTypeRule
 typerule REGEXP_UNION ::CVC4::theory::strings::RegExpUnionTypeRule
 typerule REGEXP_INTER ::CVC4::theory::strings::RegExpInterTypeRule
index 369278994bab3ec09d2ab34fd9952e93826681e8..e769eb712dfae991246eb4a17cdf5a407899132c 100644 (file)
@@ -1183,8 +1183,19 @@ void RegExpOpr::getCharSet( Node r, std::set<unsigned> &pcset, SetNodes &pvset )
   }
 }
 
+bool RegExpOpr::isPairNodesInSet(std::set< PairNodes > &s, Node n1, Node n2) {
+  for(std::set< PairNodes >::const_iterator itr = s.begin();
+      itr != s.end(); ++itr) {
+    if(itr->first == n1 && itr->second == n2 ||
+       itr->first == n2 && itr->second == n1) {
+      return true;
+    }
+  }
+  return false;
+}
 
 Node RegExpOpr::intersectInternal( Node r1, Node r2, std::map< unsigned, std::set< PairNodes > > cache, bool &spflag ) {
+  Trace("regexp-intersect") << "Starting INTERSECT:\n  "<< mkString(r1) << ",\n  " << mkString(r2) << std::endl;
   if(spflag) {
     //TODO: var
     return Node::null();
@@ -1230,11 +1241,18 @@ Node RegExpOpr::intersectInternal( Node r1, Node r2, std::map< unsigned, std::se
             spflag = true;
           }
         }
+        if(Trace.isOn("regexp-debug")) {
+          Trace("regexp-debug") << "Try CSET( " << cset.size() << " ) = ";
+          for(std::set<unsigned>::const_iterator itr = cset.begin();
+            itr != cset.end(); itr++) {
+            Trace("regexp-debug") << *itr << ", ";
+          }
+          Trace("regexp-debug") << std::endl;
+        }
         for(std::set<unsigned>::const_iterator itr = cset.begin();
           itr != cset.end(); itr++) {
           CVC4::String c( CVC4::String::convertUnsignedIntToChar(*itr) );
-          std::pair< Node, Node > p(r1, r2);
-          if(cache[ *itr ].find(p) == cache[ *itr ].end()) {
+          if(!isPairNodesInSet(cache[ *itr ], r1, r2)) {
             Node r1l = derivativeSingle(r1, c);
             Node r2l = derivativeSingle(r2, c);
             std::map< unsigned, std::set< PairNodes > > cache2(cache);
@@ -1263,10 +1281,208 @@ Node RegExpOpr::intersectInternal( Node r1, Node r2, std::map< unsigned, std::se
   Trace("regexp-intersect") << "INTERSECT( " << mkString(r1) << ", " << mkString(r2) << " ) = " << mkString(rNode) << std::endl;
   return rNode;
 }
+
+bool RegExpOpr::containC2(unsigned cnt, Node n) {
+  if(n.getKind() == kind::REGEXP_RV) {
+    unsigned y = n[0].getConst<Rational>().getNumerator().toUnsignedInt();
+    return cnt == y;
+  } else if(n.getKind() == kind::REGEXP_CONCAT) {
+    for( unsigned i=0; i<n.getNumChildren(); i++ ) {
+      if(containC2(cnt, n[i])) {
+        return true;
+      }
+    }
+  } else if(n.getKind() == kind::REGEXP_STAR) {
+    return containC2(cnt, n[0]);
+  } else if(n.getKind() == kind::REGEXP_UNION) {
+    for( unsigned i=0; i<n.getNumChildren(); i++ ) {
+      if(containC2(cnt, n[i])) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+Node RegExpOpr::convert1(unsigned cnt, Node n) {
+  Trace("regexp-debug") << "Converting " << n << " at " << cnt << "... " << std::endl;
+  Node r1, r2;
+  convert2(cnt, n, r1, r2);
+  Trace("regexp-debug") << "... getting r1=" << r1 << ", and r2=" << r2 << std::endl;
+  Node ret = NodeManager::currentNM()->mkNode(kind::REGEXP_CONCAT, 
+     NodeManager::currentNM()->mkNode(kind::REGEXP_STAR, r1), r2);
+  ret = Rewriter::rewrite( ret );
+  Trace("regexp-debug") << "... done convert at " << cnt << ", with return " << ret << std::endl;
+  return ret;
+}
+void RegExpOpr::convert2(unsigned cnt, Node n, Node &r1, Node &r2) {
+  if(n == d_emptyRegexp) {
+    r1 = d_emptyRegexp;
+    r2 = d_emptyRegexp;
+  } else if(n == d_emptySingleton) {
+    r1 = d_emptySingleton;
+    r2 = d_emptySingleton;
+  } else if(n.getKind() == kind::REGEXP_RV) {
+    unsigned y = n[0].getConst<Rational>().getNumerator().toUnsignedInt();
+    r1 = d_emptySingleton;
+    if(cnt == y) {
+      r2 = d_emptyRegexp;
+    } else {
+      r2 = n;
+    }
+  } else if(n.getKind() == kind::REGEXP_CONCAT) {
+    //TODO
+    //convert2 x (r@(Seq l r1))
+    //   | contains x r1 = let (r2,r3) = convert2 x r1
+    //                     in (Seq l r2, r3)
+    //   | otherwise = (Empty, r)
+    bool flag = true;
+    std::vector<Node> vr1, vr2;
+    for( unsigned i=0; i<n.getNumChildren(); i++ ) {
+      if(containC2(cnt, n[i])) {
+        Node t1, t2;
+        convert2(cnt, n[i], t1, t2);
+        vr1.push_back(t1);
+        r1 = vr1.size()==0 ? d_emptyRegexp : vr1.size()==1 ? vr1[0] :
+             NodeManager::currentNM()->mkNode(kind::REGEXP_CONCAT, vr1);
+        vr2.push_back(t2);
+        for( unsigned j=i+1; j<n.getNumChildren(); j++ ) {
+          vr2.push_back(n[j]);
+        }
+        r2 = vr2.size()==0 ? d_emptyRegexp : vr2.size()==1 ? vr2[0] :
+             NodeManager::currentNM()->mkNode(kind::REGEXP_CONCAT, vr2);
+        flag = false;
+        break;
+      } else {
+        vr1.push_back(n[i]);
+      }
+    }
+    if(flag) {
+      r1 = d_emptySingleton;
+      r2 = n;
+    }
+  } else if(n.getKind() == kind::REGEXP_UNION) {
+    std::vector<Node> vr1, vr2;
+    for( unsigned i=0; i<n.getNumChildren(); i++ ) {
+      Node t1, t2;
+      convert2(cnt, n[i], t1, t2);
+      vr1.push_back(t1);
+      vr2.push_back(t2);
+    }
+    r1 = NodeManager::currentNM()->mkNode(kind::REGEXP_UNION, vr1);
+    r2 = NodeManager::currentNM()->mkNode(kind::REGEXP_UNION, vr2);
+  } else if(n.getKind() == kind::STRING_TO_REGEXP) {
+      r1 = d_emptySingleton;
+      r2 = n;
+  } else {
+    //is it possible?
+  }
+}
+Node RegExpOpr::intersectInternal2( Node r1, Node r2, std::map< PairNodes, Node > cache, bool &spflag, unsigned cnt ) {
+  Trace("regexp-intersect") << "Starting INTERSECT:\n  "<< mkString(r1) << ",\n  " << mkString(r2) << std::endl;
+  //if(Trace.isOn("regexp-debug")) {
+  //  Trace("regexp-debug") << "... with cache:\n";
+  //  for(std::map< PairNodes, Node >::const_iterator itr=cache.begin();
+  //      itr!=cache.end();itr++) {
+  //        Trace("regexp-debug") << "(" << itr->first.first << "," << itr->first.second << ")->" << itr->second << std::endl;
+  //      }
+  //}
+  if(spflag) {
+    //TODO: var
+    return Node::null();
+  }
+  std::pair < Node, Node > p(r1, r2);
+  std::map < std::pair< Node, Node >, Node >::const_iterator itr = d_inter_cache.find(p);
+  Node rNode;
+  if(itr != d_inter_cache.end()) {
+    rNode = itr->second;
+  } else {
+    if(r1 == d_emptyRegexp || r2 == d_emptyRegexp) {
+      rNode = d_emptyRegexp;
+    } else if(r1 == d_emptySingleton || r2 == d_emptySingleton) {
+      Node exp;
+      int r = delta((r1 == d_emptySingleton ? r2 : r1), exp);
+      if(r == 0) {
+        //TODO: variable
+        spflag = true;
+      } else if(r == 1) {
+        rNode = d_emptySingleton;
+      } else {
+        rNode = d_emptyRegexp;
+      }
+    } else if(r1 == r2) {
+      rNode = convert1(cnt, r1);
+    } else {
+      PairNodes p(r1, r2);
+      std::map< PairNodes, Node >::const_iterator itrcache = cache.find(p);
+      if(itrcache != cache.end()) {
+        rNode = itrcache->second;
+      } else {
+        if(checkConstRegExp(r1) && checkConstRegExp(r2)) {
+          std::vector< unsigned > cset;
+          std::set< unsigned > cset1, cset2;
+          std::set< Node > vset1, vset2;
+          firstChars(r1, cset1, vset1);
+          firstChars(r2, cset2, vset2);
+          std::set_intersection(cset1.begin(), cset1.end(), cset2.begin(), cset1.end(),
+               std::inserter(cset, cset.begin()));
+          std::vector< Node > vec_nodes;
+          Node delta_exp;
+          int flag = delta(r1, delta_exp);
+          int flag2 = delta(r2, delta_exp);
+          if(flag != 2 && flag2 != 2) {
+            if(flag == 1 && flag2 == 1) {
+              vec_nodes.push_back(d_emptySingleton);
+            } else {
+              //TODO
+              spflag = true;
+            }
+          }
+          if(Trace.isOn("regexp-debug")) {
+            Trace("regexp-debug") << "Try CSET( " << cset.size() << " ) = ";
+            for(std::vector<unsigned>::const_iterator itr = cset.begin();
+              itr != cset.end(); itr++) {
+              CVC4::String c( CVC4::String::convertUnsignedIntToChar(*itr) );
+              Trace("regexp-debug") << c << ", ";
+            }
+            Trace("regexp-debug") << std::endl;
+          }
+          for(std::vector<unsigned>::const_iterator itr = cset.begin();
+            itr != cset.end(); itr++) {
+            CVC4::String c( CVC4::String::convertUnsignedIntToChar(*itr) );
+            Node r1l = derivativeSingle(r1, c);
+            Node r2l = derivativeSingle(r2, c);
+            std::map< PairNodes, Node > cache2(cache);
+            PairNodes p(r1, r2);
+            cache2[ p ] = NodeManager::currentNM()->mkNode(kind::REGEXP_RV, NodeManager::currentNM()->mkConst(CVC4::Rational(cnt)));
+            Node rt = intersectInternal2(r1l, r2l, cache2, spflag, cnt+1);
+            rt = convert1(cnt, rt);
+            if(spflag) {
+              //TODO:
+              return Node::null();
+            }
+            rt = Rewriter::rewrite( NodeManager::currentNM()->mkNode(kind::REGEXP_CONCAT,
+              NodeManager::currentNM()->mkNode(kind::STRING_TO_REGEXP, NodeManager::currentNM()->mkConst(c)), rt) );
+            vec_nodes.push_back(rt);
+          }
+          rNode = vec_nodes.size()==0 ? d_emptyRegexp : vec_nodes.size()==1 ? vec_nodes[0] :
+              NodeManager::currentNM()->mkNode(kind::REGEXP_UNION, vec_nodes);
+          rNode = Rewriter::rewrite( rNode );
+        } else {
+          //TODO: non-empty var set
+          spflag = true;
+        }
+      }
+    }
+    d_inter_cache[p] = rNode;
+  }
+  Trace("regexp-intersect") << "End of INTERSECT( " << mkString(r1) << ", " << mkString(r2) << " ) = " << mkString(rNode) << std::endl;
+  return rNode;
+}
 Node RegExpOpr::intersect(Node r1, Node r2, bool &spflag) {
-  std::map< unsigned, std::set< PairNodes > > cache;
+  //std::map< unsigned, std::set< PairNodes > > cache;
+  std::map< PairNodes, Node > cache;
   if(checkConstRegExp(r1) && checkConstRegExp(r2)) {
-    return intersectInternal(r1, r2, cache, spflag);
+    return intersectInternal2(r1, r2, cache, spflag, 1);
   } else {
     spflag = true;
     return Node::null();
@@ -1516,6 +1732,12 @@ std::string RegExpOpr::mkString( Node r ) {
         retStr += "]";
         break;
       }
+      case kind::REGEXP_RV: {
+        retStr += "<";
+        retStr += r[0].getConst<Rational>().getNumerator().toString();
+        retStr += ">";
+        break;
+      }
       default:
         Trace("strings-error") << "Unsupported term: " << r << " in RegExp." << std::endl;
         //Assert( false );
index e4ae1208d96fd8891fca515dc4546153d31a2c5c..2ae578cd61b2338672f5e6415385e36c317c80cd 100644 (file)
@@ -69,9 +69,14 @@ private:
   std::string niceChar( Node r );
   int gcd ( int a, int b );
   Node mkAllExceptOne( char c );
+  bool isPairNodesInSet(std::set< PairNodes > &s, Node n1, Node n2);
 
   void getCharSet( Node r, std::set<unsigned> &pcset, SetNodes &pvset );
   Node intersectInternal( Node r1, Node r2, std::map< unsigned, std::set< PairNodes > > cache, bool &spflag );
+  bool containC2(unsigned cnt, Node n);
+  Node convert1(unsigned cnt, Node n);
+  void convert2(unsigned cnt, Node n, Node &r1, Node &r2);
+  Node intersectInternal2( Node r1, Node r2, std::map< PairNodes, Node > cache, bool &spflag, unsigned cnt );
   void firstChars( Node r, std::set<unsigned> &pcset, SetNodes &pvset );
 
   //TODO: for intersection
index 2856ce1e09159bcce72992b9d7a477771454848c..ac1b1b1edd584f406d2a0335682e07d7f00458a1 100644 (file)
@@ -550,6 +550,10 @@ Node TheoryStrings::expandDefinition(LogicRequest &logicRequest, Node node) {
 
 
 void TheoryStrings::check(Effort e) {
+  if (done() && !fullEffort(e)) {
+    return;
+  }
+
   bool polarity;
   TNode atom;
 
@@ -2500,6 +2504,7 @@ bool TheoryStrings::checkMemberships() {
   std::vector< Node > processed;
   std::vector< Node > cprocessed;
 
+  Trace("regexp-debug") << "Checking Memberships ... " << std::endl;
   //if(options::stringEIT()) {
     //TODO: Opt for normal forms
     for(NodeListMap::const_iterator itr_xr = d_str_re_map.begin();
@@ -2507,6 +2512,7 @@ bool TheoryStrings::checkMemberships() {
       bool spflag = false;
       Node x = (*itr_xr).first;
       NodeList* lst = (*itr_xr).second;
+      Trace("regexp-debug") << "Checking Memberships for " << x << std::endl;
       if(d_inter_index.find(x) == d_inter_index.end()) {
         d_inter_index[x] = 0;
       }
@@ -2515,6 +2521,7 @@ bool TheoryStrings::checkMemberships() {
         if(lst->size() == 1) {
           d_inter_cache[x] = (*lst)[0];
           d_inter_index[x] = 1;
+          Trace("regexp-debug") << "... only one choice " << std::endl;
         } else if(lst->size() > 1) {
           Node r;
           if(d_inter_cache.find(x) != d_inter_cache.end()) {
@@ -2528,6 +2535,7 @@ bool TheoryStrings::checkMemberships() {
           for(int i=0; i<cur_inter_idx; i++) {
             ++itr_lst;
           }
+          Trace("regexp-debug") << "... staring from : " << cur_inter_idx << ", we have " << lst->size() << std::endl;
           for(;itr_lst != lst->end(); ++itr_lst) {
             Node r2 = *itr_lst;
             r = d_regexp_opr.intersect(r, r2, spflag);
@@ -2561,6 +2569,7 @@ bool TheoryStrings::checkMemberships() {
     }
   //}
 
+  Trace("regexp-debug") << "... No Intersec Conflict in Memberships " << std::endl;
   if(!addedLemma) {
     for( unsigned i=0; i<d_regexp_memberships.size(); i++ ) {
       //check regular expression membership
@@ -3325,4 +3334,4 @@ TheoryStrings::Statistics::~Statistics(){
 
 }/* CVC4::theory::strings namespace */
 }/* CVC4::theory namespace */
-}/* CVC4 namespace */
\ No newline at end of file
+}/* CVC4 namespace */
index 12ff92b5e3c1784296e8d7d719a8b9d83c9dc2aa..e37cabfb66953c27e4c5c7e1722be2b2973df57a 100644 (file)
@@ -164,8 +164,12 @@ Node TheoryStringsRewriter::prerewriteOrRegExp(TNode node) {
   for(unsigned i=0; i<node.getNumChildren(); ++i) {
     if(node[i].getKind() == kind::REGEXP_UNION) {
       Node tmpNode = prerewriteOrRegExp( node[i] );
-      for(unsigned int j=0; j<tmpNode.getNumChildren(); ++j) {
-        node_vec.push_back( tmpNode[j] );
+      if(tmpNode.getKind() == kind::REGEXP_UNION) {
+        for(unsigned int j=0; j<tmpNode.getNumChildren(); ++j) {
+          node_vec.push_back( tmpNode[j] );
+        }
+      } else {
+        node_vec.push_back( tmpNode );
       }
       flag = true;
     } else if(node[i].getKind() == kind::REGEXP_EMPTY) {
@@ -200,6 +204,7 @@ bool TheoryStringsRewriter::checkConstRegExp( TNode t ) {
 
 bool TheoryStringsRewriter::testConstStringInRegExp( CVC4::String &s, unsigned int index_start, TNode r ) {
   Assert( index_start <= s.size() );
+  Trace("regexp-debug") << "Checking " << s << " in " << r << ", starting at " << index_start << std::endl;
   int k = r.getKind();
   switch( k ) {
     case kind::STRING_TO_REGEXP: {
@@ -278,7 +283,7 @@ bool TheoryStringsRewriter::testConstStringInRegExp( CVC4::String &s, unsigned i
       return false;
     }
     case kind::REGEXP_SIGMA: {
-      if(s.size() == 1) {
+      if(s.size() == index_start + 1) {
         return true;
       } else {
         return false;
@@ -302,7 +307,7 @@ Node TheoryStringsRewriter::rewriteMembership(TNode node) {
 
   if(node[1].getKind() == kind::REGEXP_EMPTY) {
     retNode = NodeManager::currentNM()->mkConst( false );
-  } else if( x.getKind() == kind::CONST_STRING && checkConstRegExp(node[1]) ) {
+  } else if(x.getKind()==kind::CONST_STRING && checkConstRegExp(node[1])) {
     //test whether x in node[1]
     CVC4::String s = x.getConst<String>();
     retNode = NodeManager::currentNM()->mkConst( testConstStringInRegExp( s, 0, node[1] ) );
@@ -311,10 +316,12 @@ Node TheoryStringsRewriter::rewriteMembership(TNode node) {
     retNode = one.eqNode(NodeManager::currentNM()->mkNode(kind::STRING_LENGTH, x));
   } else if(node[1].getKind() == kind::REGEXP_STAR && node[1][0].getKind() == kind::REGEXP_SIGMA) {
     retNode = NodeManager::currentNM()->mkConst( true );
-  } else if( x != node[0] ) {
+  } else if(node[1].getKind() == kind::STRING_TO_REGEXP) {
+    retNode = x.eqNode(node[1][0]);
+  } else if(x != node[0]) {
     retNode = NodeManager::currentNM()->mkNode( kind::STRING_IN_REGEXP, x, node[1] );
   }
-    return retNode;
+  return retNode;
 }
 
 RewriteResponse TheoryStringsRewriter::postRewrite(TNode node) {
index 6d1bb1c98ddfcaaf2afa7000ac809f73621fe865..8a51ea36ca85c79c56a8769dff3a4a0c08539c55 100644 (file)
@@ -466,6 +466,21 @@ public:
   }
 };
 
+class RegExpRVTypeRule {
+public:
+  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+      throw (TypeCheckingExceptionPrivate, AssertionException) {
+    if( check ) {
+      TypeNode t = n[0].getType(check);
+      if (!t.isInteger()) {
+        throw TypeCheckingExceptionPrivate(n, "expecting an integer term in RV");
+      }
+    }
+    return nodeManager->regexpType();
+  }
+};
+
+
 }/* CVC4::theory::strings namespace */
 }/* CVC4::theory namespace */
 }/* CVC4 namespace */
index 7bfc7051f113f59d3acd6327cfc1d8ac70562727..867dd7c31a2ed0b854a4cb69526c6d3b0ef0ae16 100644 (file)
@@ -377,7 +377,7 @@ public:
   /**
    * Returns true if the assertFact queue is empty
    */
-  bool done() throw() {
+  bool done() const throw() {
     return d_factsHead == d_facts.size();
   }
 
@@ -678,7 +678,7 @@ public:
     * This function is called when an attribute is set by a user.  In SMT-LIBv2 this is done
     *  via the syntax (! n :attr)
     */
-  virtual void setUserAttribute(const std::string& attr, Node n) {
+  virtual void setUserAttribute(const std::string& attr, Node n, std::vector<Node> node_values, std::string str_value) {
     Unimplemented("Theory %s doesn't support Theory::setUserAttribute interface",
                   identify().c_str());
   }
index eb1da84b22a05ef36e1c837c6afd90022a2a7f73..ed56890ae540c784fa82d08ab59b444c95ba2f52 100644 (file)
@@ -34,6 +34,8 @@
 
 #include "smt/logic_exception.h"
 
+#include "proof/proof_manager.h"
+
 #include "util/node_visitor.h"
 #include "util/ite_removal.h"
 
@@ -63,6 +65,8 @@ using namespace CVC4;
 using namespace CVC4::theory;
 
 void TheoryEngine::finishInit() {
+  PROOF (ProofManager::initTheoryProof(); );
+
   // initialize the quantifiers engine
   d_quantEngine = new QuantifiersEngine(d_context, d_userContext, this);
 
@@ -153,7 +157,7 @@ TheoryEngine::TheoryEngine(context::Context* context,
   d_sharedTermsVisitor(d_sharedTerms),
   d_unconstrainedSimp(new UnconstrainedSimplifier(context, logicInfo)),
   d_bvToBoolPreprocessor(),
-  d_arithSubstitutionsAdded("zzz::arith::substitutions", 0)
+  d_arithSubstitutionsAdded("theory::arith::zzz::arith::substitutions", 0)
 {
   for(TheoryId theoryId = theory::THEORY_FIRST; theoryId != theory::THEORY_LAST; ++ theoryId) {
     d_theoryTable[theoryId] = NULL;
@@ -168,8 +172,6 @@ TheoryEngine::TheoryEngine(context::Context* context,
   d_true = NodeManager::currentNM()->mkConst<bool>(true);
   d_false = NodeManager::currentNM()->mkConst<bool>(false);
 
-  PROOF (ProofManager::currentPM()->initTheoryProof(); );
-
   d_iteUtilities = new ITEUtilities(d_iteRemover.getContainsVisitor());
 
   StatisticsRegistry::registerStat(&d_arithSubstitutionsAdded);
@@ -403,7 +405,7 @@ void TheoryEngine::check(Theory::Effort effort) {
       propagate(effort);
 
       // We do combination if all has been processed and we are in fullcheck
-      if (Theory::fullEffort(effort) && d_logicInfo.isSharingEnabled() && !d_factsAsserted && !d_lemmasAdded) {
+      if (Theory::fullEffort(effort) && d_logicInfo.isSharingEnabled() && !d_factsAsserted && !d_lemmasAdded && !d_inConflict) {
         // Do the combination
         Debug("theory") << "TheoryEngine::check(" << effort << "): running combination" << endl;
         combineTheories();
@@ -451,7 +453,7 @@ void TheoryEngine::check(Theory::Effort effort) {
 
 void TheoryEngine::combineTheories() {
 
-  Debug("sharing") << "TheoryEngine::combineTheories()" << endl;
+  Trace("combineTheories") << "TheoryEngine::combineTheories()" << endl;
 
   TimerStat::CodeTimer combineTheoriesTimer(d_combineTheoriesTime);
 
@@ -469,25 +471,48 @@ void TheoryEngine::combineTheories() {
   // Call on each parametric theory to give us its care graph
   CVC4_FOR_EACH_THEORY;
 
-  Debug("sharing") << "TheoryEngine::combineTheories(): care graph size = " << careGraph.size() << endl;
+  Trace("combineTheories") << "TheoryEngine::combineTheories(): care graph size = " << careGraph.size() << endl;
 
   // Now add splitters for the ones we are interested in
   CareGraph::const_iterator care_it = careGraph.begin();
   CareGraph::const_iterator care_it_end = careGraph.end();
+
   for (; care_it != care_it_end; ++ care_it) {
     const CarePair& carePair = *care_it;
 
-    Debug("sharing") << "TheoryEngine::combineTheories(): checking " << carePair.a << " = " << carePair.b << " from " << carePair.theory << endl;
+    Debug("combineTheories") << "TheoryEngine::combineTheories(): checking " << carePair.a << " = " << carePair.b << " from " << carePair.theory << endl;
 
     Assert(d_sharedTerms.isShared(carePair.a) || carePair.a.isConst());
     Assert(d_sharedTerms.isShared(carePair.b) || carePair.b.isConst());
 
     // The equality in question (order for no repetition)
     Node equality = carePair.a.eqNode(carePair.b);
+    EqualityStatus es = getEqualityStatus(carePair.a, carePair.b);
+    Debug("combineTheories") << "TheoryEngine::combineTheories(): " <<
+      (es == EQUALITY_TRUE_AND_PROPAGATED ? "EQUALITY_TRUE_AND_PROPAGATED" :
+      es == EQUALITY_FALSE_AND_PROPAGATED ? "EQUALITY_FALSE_AND_PROPAGATED" :
+      es == EQUALITY_TRUE ? "EQUALITY_TRUE" :
+      es == EQUALITY_FALSE ? "EQUALITY_FALSE" :
+      es == EQUALITY_TRUE_IN_MODEL ? "EQUALITY_TRUE_IN_MODEL" :
+      es == EQUALITY_FALSE_IN_MODEL ? "EQUALITY_FALSE_IN_MODEL" :
+      es == EQUALITY_UNKNOWN ? "EQUALITY_UNKNOWN" :
+       "Unexpected case") << endl;
 
     // We need to split on it
-    Debug("sharing") << "TheoryEngine::combineTheories(): requesting a split " << endl;
+    Debug("combineTheories") << "TheoryEngine::combineTheories(): requesting a split " << endl;
     lemma(equality.orNode(equality.notNode()), false, false, false, carePair.theory);
+    // This code is supposed to force preference to follow what the theory models already have
+    // but it doesn't seem to make a big difference - need to explore more -Clark
+    // if (true) {
+    //   if (es == EQUALITY_TRUE || es == EQUALITY_TRUE_IN_MODEL) {
+    //     Node e = ensureLiteral(equality);
+    //     d_propEngine->requirePhase(e, true);
+    //   }
+    //   else if (es == EQUALITY_FALSE_IN_MODEL) {
+    //     Node e = ensureLiteral(equality);
+    //     d_propEngine->requirePhase(e, false);
+    //   }
+    // }
   }
 }
 
@@ -1180,6 +1205,18 @@ Node TheoryEngine::getModelValue(TNode var) {
   return theoryOf(Theory::theoryOf(var.getType()))->getModelValue(var);
 }
 
+
+Node TheoryEngine::ensureLiteral(TNode n) {
+  Debug("ensureLiteral") << "rewriting: " << n << std::endl;
+  Node rewritten = Rewriter::rewrite(n);
+  Debug("ensureLiteral") << "      got: " << rewritten << std::endl;
+  Node preprocessed = preprocess(rewritten);
+  Debug("ensureLiteral") << "preprocessed: " << preprocessed << std::endl;
+  d_propEngine->ensureLiteral(preprocessed);
+  return preprocessed;
+}
+
+
 void TheoryEngine::printInstantiations( std::ostream& out ) {
   if( d_quantEngine ){
     d_quantEngine->printInstantiations( out );
@@ -1339,6 +1376,8 @@ void TheoryEngine::ensureLemmaAtoms(const std::vector<TNode>& atoms, theory::The
 }
 
 theory::LemmaStatus TheoryEngine::lemma(TNode node, bool negated, bool removable, bool preprocess, theory::TheoryId atomsTo) {
+  // For resource-limiting (also does a time check).
+  spendResource();
 
   // Do we need to check atoms
   if (atomsTo != theory::THEORY_LAST) {
@@ -1385,23 +1424,17 @@ theory::LemmaStatus TheoryEngine::lemma(TNode node, bool negated, bool removable
   }
 
   // assert to prop engine
-  d_propEngine->assertLemma(additionalLemmas[0], negated, removable);
+  d_propEngine->assertLemma(additionalLemmas[0], negated, removable, RULE_INVALID, node);
   for (unsigned i = 1; i < additionalLemmas.size(); ++ i) {
     additionalLemmas[i] = theory::Rewriter::rewrite(additionalLemmas[i]);
-    d_propEngine->assertLemma(additionalLemmas[i], false, removable);
+    d_propEngine->assertLemma(additionalLemmas[i], false, removable, RULE_INVALID, node);
   }
 
-  // WARNING: Below this point don't assume additionalLemmas[0] to be not negated.
   // WARNING: Below this point don't assume additionalLemmas[0] to be not negated.
   if(negated) {
-    // Can't we just get rid of passing around this 'negated' stuff?
-    // Is it that hard for the propEngine to figure that out itself?
-    // (I like the use of triple negation <evil laugh>.) --K
     additionalLemmas[0] = additionalLemmas[0].notNode();
     negated = false;
   }
-  // WARNING: Below this point don't assume additionalLemmas[0] to be not negated.
-  // WARNING: Below this point don't assume additionalLemmas[0] to be not negated.
 
   // assert to decision engine
   if(!removable) {
@@ -1668,11 +1701,11 @@ void TheoryEngine::ppUnconstrainedSimp(vector<Node>& assertions)
 }
 
 
-void TheoryEngine::setUserAttribute(const std::string& attr, Node n) {
+void TheoryEngine::setUserAttribute(const std::string& attr, Node n, std::vector<Node> node_values, std::string str_value) {
   Trace("te-attr") << "set user attribute " << attr << " " << n << endl;
   if( d_attr_handle.find( attr )!=d_attr_handle.end() ){
     for( size_t i=0; i<d_attr_handle[attr].size(); i++ ){
-      d_attr_handle[attr][i]->setUserAttribute(attr, n);
+      d_attr_handle[attr][i]->setUserAttribute(attr, n, node_values, str_value);
     }
   } else {
     //unhandled exception?
index e6684d56e6d490e4f185052fa0814c1543d37d7a..e589e8f8749d59c58dc325e843fab5ef922fce22 100644 (file)
@@ -758,6 +758,11 @@ public:
    */
   Node getModelValue(TNode var);
 
+  /**
+   * Takes a literal and returns an equivalent literal that is guaranteed to be a SAT literal
+   */
+  Node ensureLiteral(TNode n);
+
   /**
    * Print all instantiations made by the quantifiers module.
    */
@@ -820,7 +825,7 @@ public:
    * This function is called when an attribute is set by a user.  In SMT-LIBv2 this is done
    * via the syntax (! n :attr)
    */
-  void setUserAttribute(const std::string& attr, Node n);
+  void setUserAttribute(const std::string& attr, Node n, std::vector<Node> node_values, std::string str_value);
 
   /**
    * Handle user attribute.
index 26f87da79c06383ee63cfdc73916cc3255b4e326..d9e4c94770258e726747dedb8036d957e378d2ce 100644 (file)
@@ -29,8 +29,8 @@ option ufssSimpleCliques --uf-ss-simple-cliques bool :default true
  always use simple clique lemmas for uf strong solver
 option ufssDiseqPropagation --uf-ss-deq-prop bool :default false
  eagerly propagate disequalities for uf strong solver
-option ufssMinimalModel /--disable-uf-ss-min-model bool :default true
- disable finding a minimal model in uf strong solver
+option ufssMode --uf-ss=MODE CVC4::theory::uf::UfssMode :default CVC4::theory::uf::UF_SS_FULL :include "theory/uf/options_handlers.h" :handler CVC4::theory::uf::stringToUfssMode :handler-include "theory/uf/options_handlers.h"
+ mode of operation for uf strong solver.
 option ufssCliqueSplits --uf-ss-clique-splits bool :default false
  use cliques instead of splitting on demand to shrink model
 
index a885a10d203a4dc82de8d8403cea76486dfe087a..8c072e2321f05251f7d6ef0296c324208c68bf1b 100644 (file)
@@ -2,7 +2,7 @@
 /*! \file options_handlers.h
  ** \verbatim
  ** Original author: Morgan Deters
- ** Major contributors: none
+ ** Major contributors: Andrew Reynolds
  ** Minor contributors (to current version): none
  ** This file is part of the CVC4 project.
  ** Copyright (c) 2009-2014  New York University and The University of Iowa
 namespace CVC4 {
 namespace theory {
 namespace uf {
+  
+typedef enum {
+  /** default, use uf strong solver to find minimal models for uninterpreted sorts */
+  UF_SS_FULL,
+  /** use uf strong solver to shrink model sizes, but do no enforce minimality */
+  UF_SS_NO_MINIMAL,
+  /** do not use uf strong solver */
+  UF_SS_NONE,
+} UfssMode;
+  
+static const std::string ufssModeHelp = "\
+UF strong solver options currently supported by the --uf-ss option:\n\
+\n\
+full \n\
++ Default, use uf strong solver to find minimal models for uninterpreted sorts.\n\
+\n\
+no-minimal \n\
++ Use uf strong solver to shrink model sizes, but do no enforce minimality.\n\
+\n\
+none \n\
++ Do not use uf strong solver to shrink model sizes. \n\
+\n\
+";
+
+inline UfssMode stringToUfssMode(std::string option, std::string optarg, SmtEngine* smt) throw(OptionException) {
+  if(optarg ==  "default" || optarg == "full" ) {
+    return UF_SS_FULL;
+  } else if(optarg == "no-minimal") {
+    return UF_SS_NO_MINIMAL;
+  } else if(optarg == "none") {
+    return UF_SS_NONE;
+  } else if(optarg ==  "help") {
+    puts(ufssModeHelp.c_str());
+    exit(1);
+  } else {
+    throw OptionException(std::string("unknown option for --uf-ss: `") +
+                          optarg + "'.  Try --uf-ss help.");
+  }
+}
 
 }/* CVC4::theory::uf namespace */
 }/* CVC4::theory namespace */
index 0da8e8c32792f4f7cb42bbebdbe310a829d20b4e..2b9fc3daf8ce98f902914606ad25d36fdfc2d6d2 100644 (file)
@@ -61,7 +61,7 @@ void TheoryUF::setMasterEqualityEngine(eq::EqualityEngine* eq) {
 
 void TheoryUF::finishInit() {
   // initialize the strong solver
-  if (options::finiteModelFind()) {
+  if (options::finiteModelFind() && options::ufssMode()!=UF_SS_NONE) {
     d_thss = new StrongSolverTheoryUF(getSatContext(), getUserContext(), *d_out, this);
   }
 }
@@ -89,6 +89,10 @@ static Node mkAnd(const std::vector<TNode>& conjunctions) {
 }/* mkAnd() */
 
 void TheoryUF::check(Effort level) {
+  if (done() && !fullEffort(level)) {
+    return;
+  }
+
   while (!done() && !d_conflict)
   {
     // Get all the assertions
index 001b21d0afd35a0acb3be479374fb8188230a2f7..cddaace3edf51bc5a92e76d7aed24ec4155d7c0a 100644 (file)
@@ -339,16 +339,6 @@ bool StrongSolverTheoryUF::SortModel::Region::getCandidateClique( int cardinalit
   return false;
 }
 
-
-void StrongSolverTheoryUF::SortModel::Region::getRepresentatives( std::vector< Node >& reps ){
-  for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
-    RegionNodeInfo* rni = it->second;
-    if( rni->d_valid ){
-      reps.push_back( it->first );
-    }
-  }
-}
-
 void StrongSolverTheoryUF::SortModel::Region::getNumExternalDisequalities( std::map< Node, int >& num_ext_disequalities ){
   for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
     RegionNodeInfo* rni = it->second;
@@ -624,7 +614,7 @@ void StrongSolverTheoryUF::SortModel::check( Theory::Effort level, OutputChannel
           if( d_regions[i]->d_valid ){
             std::vector< Node > clique;
             if( d_regions[i]->check( level, d_cardinality, clique ) ){
-              if( options::ufssMinimalModel() ){
+              if( options::ufssMode()==UF_SS_FULL ){
                 //add clique lemma
                 addCliqueLemma( clique, out );
                 return;
@@ -695,7 +685,7 @@ void StrongSolverTheoryUF::SortModel::check( Theory::Effort level, OutputChannel
                 if( d_regions[i]->d_valid ){
                   int fcr = forceCombineRegion( i, false );
                   Trace("uf-ss-debug") << "Combined regions " << i << " " << fcr << std::endl;
-                  if( options::ufssMinimalModel() || fcr!=-1 ){
+                  if( options::ufssMode()==UF_SS_FULL || fcr!=-1 ){
                     recheck = true;
                     break;
                   }
@@ -921,7 +911,7 @@ void StrongSolverTheoryUF::SortModel::checkRegion( int ri, bool checkCombine ){
     //now check if region is in conflict
     std::vector< Node > clique;
     if( d_regions[ri]->check( Theory::EFFORT_STANDARD, d_cardinality, clique ) ){
-      if( options::ufssMinimalModel() ){
+      if( options::ufssMode()==UF_SS_FULL ){
         //explain clique
         addCliqueLemma( clique, &d_thss->getOutputChannel() );
       }
@@ -1085,7 +1075,7 @@ int StrongSolverTheoryUF::SortModel::addSplit( Region* r, OutputChannel* out ){
     }
     Assert( s!=Node::null() );
   }else{
-    if( !options::ufssMinimalModel() ){
+    if( options::ufssMode()!=UF_SS_FULL ){
       //since candidate clique is not reported, we may need to find splits manually
       for ( std::map< Node, Region::RegionNodeInfo* >::iterator it = r->d_nodes.begin(); it != r->d_nodes.end(); ++it ){
         if ( it->second->d_valid ){
@@ -1480,19 +1470,6 @@ int StrongSolverTheoryUF::SortModel::getNumRegions(){
   return count;
 }
 
-void StrongSolverTheoryUF::SortModel::getRepresentatives( std::vector< Node >& reps ){
-  for( int i=0; i<(int)d_regions_index; i++ ){
-    //should not have multiple regions at this point
-    //if( foundRegion ){
-    //  Assert( !d_regions[i]->d_valid );
-    //}
-    if( d_regions[i]->d_valid ){
-      //this is the only valid region
-      d_regions[i]->getRepresentatives( reps );
-    }
-  }
-}
-
 Node StrongSolverTheoryUF::SortModel::getCardinalityLiteral( int c ) {
   if( d_cardinality_literal.find( c )==d_cardinality_literal.end() ){
     d_cardinality_literal[c] = NodeManager::currentNM()->mkNode( CARDINALITY_CONSTRAINT, d_cardinality_term,
@@ -1661,7 +1638,7 @@ bool StrongSolverTheoryUF::areDisequal( Node a, Node b ) {
 void StrongSolverTheoryUF::check( Theory::Effort level ){
   if( !d_conflict ){
     Trace("uf-ss-solver") << "StrongSolverTheoryUF: check " << level << std::endl;
-    if( level==Theory::EFFORT_FULL ){
+    if( level==Theory::EFFORT_FULL && Debug.isOn( "uf-ss-debug" ) ){
       debugPrint( "uf-ss-debug" );
     }
     for( std::map< TypeNode, SortModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
@@ -1801,19 +1778,6 @@ int StrongSolverTheoryUF::getCardinality( TypeNode tn ) {
   return -1;
 }
 
-/*
-void StrongSolverTheoryUF::getRepresentatives( Node n, std::vector< Node >& reps ){
-  SortModel* c = getSortModel( n );
-  if( c ){
-    c->getRepresentatives( reps );
-    if( (int)reps.size()!=c->getCardinality() ){
-      Trace("uf-ss-warn") << "Sort " << n.getType() << " has cardinality " << c->getCardinality();
-      Trace("uf-ss-warn") << ", but provided " << reps.size() << " representatives!!!" << std::endl;
-    }
-  }
-}
-*/
-
 bool StrongSolverTheoryUF::minimize( TheoryModel* m ){
   for( std::map< TypeNode, SortModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
     if( !it->second->minimize( d_out, m ) ){
index 1e5a361a7f1e826ec87ca3ac578ea7eda8db9686..333f1717e5527e7bd77af4a79492b7874b91d53d 100644 (file)
@@ -146,8 +146,6 @@ public:
       bool getMustCombine( int cardinality );
       /** has splits */
       bool hasSplits() { return d_splitsSize>0; }
-      /** get representatives */
-      void getRepresentatives( std::vector< Node >& reps );
       /** get external disequalities */
       void getNumExternalDisequalities( std::map< Node, int >& num_ext_disequalities );
     public:
@@ -280,8 +278,6 @@ public:
     bool isConflict() { return d_conflict; }
     /** get cardinality */
     int getCardinality() { return d_cardinality; }
-    /** get representatives */
-    void getRepresentatives( std::vector< Node >& reps );
     /** has cardinality */
     bool hasCardinalityAsserted() { return d_hasCard; }
     /** get cardinality term */
@@ -381,8 +377,6 @@ public:
   int getCardinality( Node n );
   /** get cardinality for type */
   int getCardinality( TypeNode tn );
-  /** get representatives */
-  //void getRepresentatives( Node n, std::vector< Node >& reps );
   /** minimize */
   bool minimize( TheoryModel* m = NULL );
 
index 72d87878218d136831ac4da4b3c7012e1e0f804f..b2d7f4b2182ba572ae9536a0f4bd582008a80f17 100644 (file)
@@ -88,13 +88,7 @@ Node Valuation::getModelValue(TNode var) {
 }
 
 Node Valuation::ensureLiteral(TNode n) {
-  Debug("ensureLiteral") << "rewriting: " << n << std::endl;
-  Node rewritten = Rewriter::rewrite(n);
-  Debug("ensureLiteral") << "      got: " << rewritten << std::endl;
-  Node preprocessed = d_engine->preprocess(rewritten);
-  Debug("ensureLiteral") << "preproced: " << preprocessed << std::endl;
-  d_engine->getPropEngine()->ensureLiteral(preprocessed);
-  return preprocessed;
+  return d_engine->ensureLiteral(n);
 }
 
 bool Valuation::isDecision(Node lit) const {
index 5cf5da1e09ed4198e1cca4c1e6516f66dbdf0695..fc9192dd9024fbf93ac44593591d3d273a55a829 100644 (file)
@@ -97,7 +97,9 @@ libutil_la_SOURCES = \
        regexp.cpp \
        bin_heap.h \
        didyoumean.h \
-       didyoumean.cpp
+       didyoumean.cpp \
+       unsat_core.h \
+       unsat_core.cpp
 
 libstatistics_la_SOURCES = \
        statistics_registry.h \
@@ -156,7 +158,8 @@ EXTRA_DIST = \
        uninterpreted_constant.i \
        chain.i \
        regexp.i \
-       proof.i
+       proof.i \
+       unsat_core.i
 
 DISTCLEANFILES = \
        integer.h.tmp \
index 9e07c746a7c5585d6f5282c4eca3f5e8db19cef8..f0704520afeaa40789746c741cdf36c6bf2f1b7a 100644 (file)
@@ -299,8 +299,12 @@ Expr Datatype::mkGroundTerm( Type t ) const throw(IllegalArgumentException) {
     }
   }
   if( groundTerm.isNull() ){
-    // if we get all the way here, we aren't well-founded
-    CheckArgument(false, *this, "this datatype is not well-founded, cannot construct a ground term!");
+    if( !d_isCo ){
+      // if we get all the way here, we aren't well-founded
+      CheckArgument(false, *this, "this datatype is not well-founded, cannot construct a ground term!");
+    }else{
+      return groundTerm;
+    }
   }else{
     return groundTerm;
   }
index 68d7d9a34f11537b591e58a8791ea5989fbe5db2..97a6338ce7880f8fc7ff536f088e35f811399df2 100644 (file)
@@ -19,6 +19,7 @@
 #include "util/ite_removal.h"
 #include "expr/command.h"
 #include "theory/ite_utilities.h"
+#include "proof/proof_manager.h"
 
 using namespace CVC4;
 using namespace std;
@@ -47,13 +48,23 @@ size_t RemoveITE::collectedCacheSizes() const{
   return d_containsVisitor->cache_size() + d_iteCache.size();
 }
 
-void RemoveITE::run(std::vector<Node>& output, IteSkolemMap& iteSkolemMap)
+void RemoveITE::run(std::vector<Node>& output, IteSkolemMap& iteSkolemMap, bool reportDeps)
 {
+  size_t n = output.size();
   for (unsigned i = 0, i_end = output.size(); i < i_end; ++ i) {
     // Do this in two steps to avoid Node problems(?)
     // Appears related to bug 512, splitting this into two lines
     // fixes the bug on clang on Mac OS
     Node itesRemoved = run(output[i], output, iteSkolemMap, false);
+    // In some calling contexts, not necessary to report dependence information.
+    if(reportDeps && options::unsatCores()) {
+      // new assertions have a dependence on the node
+      PROOF( ProofManager::currentPM()->addDependence(itesRemoved, output[i]); )
+      while(n < output.size()) {
+        PROOF( ProofManager::currentPM()->addDependence(output[n], output[i]); )
+        ++n;
+      }
+    }
     output[i] = itesRemoved;
   }
 }
index 83c55dab7e893ce0386fc29cadfeae96051e2835..d71f9b13d414cddf24aab4477aaff253e28f7fd7 100644 (file)
@@ -50,8 +50,11 @@ public:
    * contains a map from introduced skolem variables to the index in
    * assertions containing the new Boolean ite created in conjunction
    * with that skolem variable.
+   *
+   * With reportDeps true, report reasoning dependences to the proof
+   * manager (for unsat cores).
    */
-  void run(std::vector<Node>& assertions, IteSkolemMap& iteSkolemMap);
+  void run(std::vector<Node>& assertions, IteSkolemMap& iteSkolemMap, bool reportDeps = false);
 
   /**
    * Removes the ITE from the node by introducing skolem
diff --git a/src/util/unsat_core.cpp b/src/util/unsat_core.cpp
new file mode 100644 (file)
index 0000000..929d5e9
--- /dev/null
@@ -0,0 +1,49 @@
+/*********************                                                        */
+/*! \file unsat_core.cpp
+ ** \verbatim
+ ** Original author: Morgan Deters
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014  New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Representation of unsat cores
+ **
+ ** Representation of unsat cores.
+ **/
+
+#include "util/unsat_core.h"
+#include "expr/command.h"
+#include "smt/smt_engine_scope.h"
+#include "printer/printer.h"
+
+namespace CVC4 {
+
+UnsatCore::const_iterator UnsatCore::begin() const {
+  return d_core.begin();
+}
+
+UnsatCore::const_iterator UnsatCore::end() const {
+  return d_core.end();
+}
+
+void UnsatCore::toStream(std::ostream& out) const {
+  smt::SmtScope smts(d_smt);
+  Expr::dag::Scope scope(out, false);
+  Printer::getPrinter(options::outputLanguage())->toStream(out, *this);
+}
+
+void UnsatCore::toStream(std::ostream& out, const std::map<Expr, std::string>& names) const {
+  smt::SmtScope smts(d_smt);
+  Expr::dag::Scope scope(out, false);
+  Printer::getPrinter(options::outputLanguage())->toStream(out, *this, names);
+}
+
+std::ostream& operator<<(std::ostream& out, const UnsatCore& core) {
+  core.toStream(out);
+  return out;
+}
+
+}/* CVC4 namespace */
diff --git a/src/util/unsat_core.h b/src/util/unsat_core.h
new file mode 100644 (file)
index 0000000..27cf864
--- /dev/null
@@ -0,0 +1,66 @@
+/*********************                                                        */
+/*! \file unsat_core.h
+ ** \verbatim
+ ** Original author: Morgan Deters
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014  New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief [[ Add one-line brief description here ]]
+ **
+ ** [[ Add lengthier description here ]]
+ ** \todo document this file
+ **/
+
+#include "cvc4_public.h"
+
+#ifndef __CVC4__UNSAT_CORE_H
+#define __CVC4__UNSAT_CORE_H
+
+#include <iostream>
+#include <vector>
+#include "expr/expr.h"
+
+namespace CVC4 {
+
+class SmtEngine;
+class UnsatCore;
+
+std::ostream& operator<<(std::ostream& out, const UnsatCore& core) CVC4_PUBLIC;
+
+class CVC4_PUBLIC UnsatCore {
+  friend std::ostream& operator<<(std::ostream&, const UnsatCore&);
+
+  /** The SmtEngine we're associated with */
+  SmtEngine* d_smt;
+
+  std::vector<Expr> d_core;
+
+public:
+  UnsatCore() : d_smt(NULL) {}
+
+  template <class T>
+  UnsatCore(SmtEngine* smt, T begin, T end) : d_smt(smt), d_core(begin, end) {}
+
+  ~UnsatCore() {}
+
+  /** get the smt engine that this unsat core is hooked up to */
+  SmtEngine* getSmtEngine() { return d_smt; }
+
+  typedef std::vector<Expr>::const_iterator iterator;
+  typedef std::vector<Expr>::const_iterator const_iterator;
+
+  const_iterator begin() const;
+  const_iterator end() const;
+
+  void toStream(std::ostream& out) const;
+  void toStream(std::ostream& out, const std::map<Expr, std::string>& names) const;
+
+};/* class UnsatCore */
+
+}/* CVC4 namespace */
+
+#endif /* __CVC4__UNSAT_CORE_H */
diff --git a/src/util/unsat_core.i b/src/util/unsat_core.i
new file mode 100644 (file)
index 0000000..9fc0dcd
--- /dev/null
@@ -0,0 +1,51 @@
+%{
+#include "util/unsat_core.h"
+%}
+
+#ifdef SWIGJAVA
+
+// Instead of UnsatCore::begin() and end(), create an
+// iterator() method on the Java side that returns a Java-style
+// Iterator.
+%ignore CVC4::UnsatCore::begin();
+%ignore CVC4::UnsatCore::end();
+%ignore CVC4::UnsatCore::begin() const;
+%ignore CVC4::UnsatCore::end() const;
+%extend CVC4::UnsatCore {
+  CVC4::JavaIteratorAdapter<CVC4::UnsatCore> iterator() {
+    return CVC4::JavaIteratorAdapter<CVC4::UnsatCore>(*$self);
+  }
+}
+
+// UnsatCore is "iterable" on the Java side
+%typemap(javainterfaces) CVC4::UnsatCore "java.lang.Iterable<edu.nyu.acsys.CVC4.Expr>";
+
+// the JavaIteratorAdapter should not be public, and implements Iterator
+%typemap(javaclassmodifiers) CVC4::JavaIteratorAdapter<CVC4::UnsatCore> "class";
+%typemap(javainterfaces) CVC4::JavaIteratorAdapter<CVC4::UnsatCore> "java.util.Iterator<edu.nyu.acsys.CVC4.Expr>";
+// add some functions to the Java side (do it here because there's no way to do these in C++)
+%typemap(javacode) CVC4::JavaIteratorAdapter<CVC4::UnsatCore> "
+  public void remove() {
+    throw new java.lang.UnsupportedOperationException();
+  }
+
+  public edu.nyu.acsys.CVC4.Expr next() {
+    if(hasNext()) {
+      return getNext();
+    } else {
+      throw new java.util.NoSuchElementException();
+    }
+  }
+"
+// getNext() just allows C++ iterator access from Java-side next(), make it private
+%javamethodmodifiers CVC4::JavaIteratorAdapter<CVC4::UnsatCore>::getNext() "private";
+
+// map the types appropriately
+%typemap(jni) CVC4::UnsatCore::const_iterator::value_type "jobject";
+%typemap(jtype) CVC4::UnsatCore::const_iterator::value_type "edu.nyu.acsys.CVC4.Expr";
+%typemap(jstype) CVC4::UnsatCore::const_iterator::value_type "edu.nyu.acsys.CVC4.Expr";
+%typemap(javaout) CVC4::UnsatCore::const_iterator::value_type { return $jnicall; }
+
+#endif /* SWIGJAVA */
+
+%include "util/unsat_core.h"
index c0ee0f2bb6d3e3d443a14a1d32a23dac0ff43db1..e7b8e3b737962988193d0f8c60bb667649ef0c91 100644 (file)
@@ -105,7 +105,6 @@ CVC_TESTS = \
        wiki.19.cvc \
        wiki.20.cvc \
        wiki.21.cvc \
-       simplification_bug3.cvc \
        queries0.cvc \
        print_lambda.cvc \
        trim.cvc
index c11d68780b9aefc8d03de5c7fc989d981bed47c2..804987da2ec4da1a18bc333c842ebee19ce75460 100644 (file)
@@ -40,11 +40,17 @@ TESTS =     \
        swap_t1_np_nf_ai_00005_007.cvc.smt \
        x2.smt \
        x3.smt \
-       parsing_ringer.cvc
-
-EXTRA_DIST = $(TESTS) \
+       parsing_ringer.cvc \
        bug272.smt \
-       bug272.minimized.smt
+       bug272.minimized.smt \
+       constarr.smt2 \
+       constarr2.smt2 \
+       constarr3.smt2 \
+       constarr.cvc \
+       constarr2.cvc \
+       constarr3.cvc
+
+EXTRA_DIST = $(TESTS)
 
 #if CVC4_BUILD_PROFILE_COMPETITION
 #else
diff --git a/test/regress/regress0/arrays/constarr.cvc b/test/regress/regress0/arrays/constarr.cvc
new file mode 100644 (file)
index 0000000..406a1ce
--- /dev/null
@@ -0,0 +1,7 @@
+% EXPECT: unsat
+all1 : ARRAY INT OF INT;
+a, i : INT;
+ASSERT all1 = ARRAY(INT OF INT) : 1;
+ASSERT a = all1[i];
+ASSERT a /= 1;
+CHECKSAT TRUE;
diff --git a/test/regress/regress0/arrays/constarr.smt2 b/test/regress/regress0/arrays/constarr.smt2
new file mode 100644 (file)
index 0000000..b1fb02b
--- /dev/null
@@ -0,0 +1,9 @@
+(set-logic QF_ALIA)
+(set-info :status unsat)
+(declare-const all1 (Array Int Int))
+(declare-const a Int)
+(declare-const i Int)
+(assert (= all1 ((as const (Array Int Int)) 1)))
+(assert (= a (select all1 i)))
+(assert (not (= a 1)))
+(check-sat)
diff --git a/test/regress/regress0/arrays/constarr2.cvc b/test/regress/regress0/arrays/constarr2.cvc
new file mode 100644 (file)
index 0000000..90ff114
--- /dev/null
@@ -0,0 +1,7 @@
+% EXPECT: unsat
+all1, all2 : ARRAY INT OF INT;
+a, i : INT;
+ASSERT all1 = ARRAY(INT OF INT) : 1;
+ASSERT all2 = ARRAY(INT OF INT) : 2;
+ASSERT all1 = all2;
+CHECKSAT;
diff --git a/test/regress/regress0/arrays/constarr2.smt2 b/test/regress/regress0/arrays/constarr2.smt2
new file mode 100644 (file)
index 0000000..c84e678
--- /dev/null
@@ -0,0 +1,10 @@
+(set-logic QF_ALIA)
+(set-info :status unsat)
+(declare-const all1 (Array Int Int))
+(declare-const all2 (Array Int Int))
+(declare-const a Int)
+(declare-const i Int)
+(assert (= all1 ((as const (Array Int Int)) 1)))
+(assert (= all2 ((as const (Array Int Int)) 2)))
+(assert (= all1 all2))
+(check-sat)
diff --git a/test/regress/regress0/arrays/constarr3.cvc b/test/regress/regress0/arrays/constarr3.cvc
new file mode 100644 (file)
index 0000000..bf5cf96
--- /dev/null
@@ -0,0 +1,12 @@
+% EXIT: 1
+% EXPECT: Array theory solver does not yet support write-chains connecting two different constant arrays
+% should be unsat
+all1, all2 : ARRAY INT OF INT;
+aa, bb : ARRAY INT OF INT;
+a, i : INT;
+ASSERT all1 = ARRAY(INT OF INT) : 1;
+ASSERT aa = all1 WITH [i] := 0;
+ASSERT all2 = ARRAY(INT OF INT) : 2;
+ASSERT bb = all2 WITH [i] := 0;
+ASSERT aa = bb;
+CHECKSAT;
diff --git a/test/regress/regress0/arrays/constarr3.smt2 b/test/regress/regress0/arrays/constarr3.smt2
new file mode 100644 (file)
index 0000000..d514fff
--- /dev/null
@@ -0,0 +1,16 @@
+; EXIT: 1
+; EXPECT: (error "Array theory solver does not yet support write-chains connecting two different constant arrays")
+(set-logic QF_ALIA)
+(set-info :status unsat)
+(declare-const all1 (Array Int Int))
+(declare-const all2 (Array Int Int))
+(declare-const aa (Array Int Int))
+(declare-const bb (Array Int Int))
+(declare-const a Int)
+(declare-const i Int)
+(assert (= all1 ((as const (Array Int Int)) 1)))
+(assert (= aa (store all1 i 0)))
+(assert (= all2 ((as const (Array Int Int)) 2)))
+(assert (= bb (store all2 i 0)))
+(assert (= aa bb))
+(check-sat)
index c9f8c9e2239f4b8e26f6163bb93aff68b08fa67f..2c2018ecd01cadc35a8e259994b69f0bea20a6d8 100644 (file)
@@ -9,6 +9,11 @@
 % EXPECT: sat
 % EXPECT: sat
 % EXPECT: sat
+% EXPECT: sat
+% EXPECT: sat
+% EXPECT: unsat
+% EXPECT: unsat
+% EXPECT: sat
 
 PUSH;
 
@@ -57,3 +62,33 @@ b : ARRAY INT OF INT;
 ASSERT a = a WITH [0]:=b WITH [1]:=1,[2]:=2;
 
 CHECKSAT;
+
+RESET;
+
+% more mixed stores, this time with constant arrays
+z : [# x:ARRAY INT OF [# x:INT #], y:[ARRAY INT OF INT, ARRAY INT OF INT] #];
+
+ASSERT z.y.1[1] /= 1;
+ASSERT (# x:=ARRAY(INT OF [# x:INT #]):(# x:=0 #), y:=(ARRAY(INT OF INT):1, ARRAY(INT OF INT):5) #) = z;
+
+CHECKSAT;
+
+ASSERT z.x[0].x /= z.y.0[5];
+
+CHECKSAT;
+
+ASSERT z.y.0[1] = z.x[5].x;
+
+CHECKSAT;
+
+ASSERT z.y.0[5] = z.x[-2].x;
+
+CHECKSAT;
+
+RESET;
+
+a : ARRAY INT OF INT;
+
+ASSERT a = a WITH [0]:=0, [1]:=1;
+
+CHECKSAT;
index 109940090e3e0c386b14cfd881e995275e7c359f..37403d8a30dc718f4a3b4884ff9ce188293f6a2d 100644 (file)
@@ -1,7 +1,7 @@
 (set-logic ALL_SUPPORTED)
 ; COMMAND-LINE: --incremental
 ; EXPECT: unknown
-; EXPECT: unknown
+; EXPECT: unsat
 ; EXPECT: unknown
 (declare-datatypes () ((OptInt0 (Some (value0 Int)) (None))))
 (declare-datatypes () ((List0 (Cons (head0 Int) (tail0 List0)) (Nil))))
index c02a708198b2a1412766112ca6dca0b0e00e38af..05eb710df8ac9f19f81c993645357c8afb36848b 100644 (file)
@@ -59,7 +59,8 @@ TESTS =       \
        bug286.cvc \
        bug438.cvc \
        bug438b.cvc \
-       wrong-sel-simp.cvc
+       wrong-sel-simp.cvc \
+       tenum-bug.smt2
 
 FAILING_TESTS = \
        datatype-dump.cvc
diff --git a/test/regress/regress0/datatypes/tenum-bug.smt2 b/test/regress/regress0/datatypes/tenum-bug.smt2
new file mode 100644 (file)
index 0000000..bf82c7b
--- /dev/null
@@ -0,0 +1,11 @@
+(set-logic QF_ALL_SUPPORTED)
+(set-info :status sat)
+
+(declare-datatypes () ((DNat (dnat (data Nat)))
+                       (Nat (succ (pred DNat)) (zero))))
+
+(declare-fun x () Nat)
+
+(assert (not (= x zero)))
+
+(check-sat)
\ No newline at end of file
index 7e8e1ea9921e31399c9f1d59344222c10c1c7b9e..41f66f92fc7e38bc3075741c8782fc753ec052c6 100644 (file)
@@ -43,7 +43,8 @@ TESTS =       \
        javafe.ast.StmtVec.009.smt2 \
        ARI176e1.smt2 \
         bi-artm-s.smt2 \
-       simp-typ-test.smt2
+       simp-typ-test.smt2 \
+       macros-int-real.smt2
 
 # regression can be solved with --finite-model-find --fmf-inst-engine
 # set3.smt2
diff --git a/test/regress/regress0/quantifiers/macros-int-real.smt2 b/test/regress/regress0/quantifiers/macros-int-real.smt2
new file mode 100644 (file)
index 0000000..d29ddfe
--- /dev/null
@@ -0,0 +1,9 @@
+; COMMAND-LINE: --macros-quant
+; EXPECT: unknown
+(set-logic AUFLIRA)
+
+(declare-fun round2 (Real) Int)
+(assert (forall ((i Int))  (= (round2 (to_real i)) i)))
+
+(assert (= (round2 1.5) 1))
+(check-sat)
\ No newline at end of file
diff --git a/test/regress/regress0/simplification_bug3.cvc b/test/regress/regress0/simplification_bug3.cvc
deleted file mode 100644 (file)
index 3f0ddc5..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-% COMMAND-LINE: --simplification=incremental
-x, y: BOOLEAN;
-ASSERT x OR y;
-ASSERT NOT x;
-ASSERT NOT y;
-% EXPECT: unsat
-CHECKSAT;
index ddc0eae7c10a29e805ff5c4a8ddf24fe3c36b920..233962d723bda682d501a51c256ab82ebac159e9 100644 (file)
@@ -30,7 +30,6 @@ TESTS =       \
   str005.smt2 \
   str006.smt2 \
   str007.smt2 \
-  fmf001.smt2 \
   fmf002.smt2 \
   type001.smt2 \
   type003.smt2 \
@@ -53,6 +52,7 @@ TESTS =       \
 FAILING_TESTS =
 
 EXTRA_DIST = $(TESTS) \
+  fmf001.smt2 \
   regexp002.smt2 \
   type002.smt2
 
index f0ffd765d61fe900d72758fc2aedb8332d421b4b..d234153a3504ed5be7ea0261c745fd158ccdc99b 100755 (executable)
@@ -41,6 +41,10 @@ while [ $# -gt 2 ]; do
   shift
 done
 
+[[ "$VALGRIND" = "1" ]] && {
+  wrapper="libtool --mode=execute valgrind $wrapper"
+}
+
 cvc4=$1
 benchmark_orig=$2
 benchmark="$benchmark_orig"
@@ -250,7 +254,15 @@ fi
 
 # we have to actual error file same treatment as other files. differences in
 # versions of echo/bash were causing failure on some platforms and not on others
+# (also grep out valgrind output, if 0 errors reported by valgrind)
 actual_error=$(cat $errfile)
+if [[ "$VALGRIND" = "1" ]]; then
+  #valgrind_output=$(cat $errfile|grep -E "^==[0-9]+== "|)
+  valgrind_num_errors=$(cat $errfile|grep -E "^==[0-9]+== "|tail -n1|awk '{print $4}')
+  echo "valgrind errors (not suppressed): $valgrind_num_errors" 1>&2
+
+  ((valgrind_num_errors == 0)) && actual_error=$(echo "$actual_error"|grep -vE "^==[0-9]+== ")
+fi
 if [ -z "$actual_error" ]; then
   # in case expected stderr output is empty, make sure we don't differ
   # by a newline, which we would if we echo "" >"$experrfile"
index 6651260599fa2c4c34ce6ec2e6deec11e261049e..db49e25217ef1f73e80a47014bf799b7f167c084 100644 (file)
@@ -67,7 +67,7 @@ public:
     return d_nextVar++;
   }
 
-  void addClause(SatClause& c, bool lemma) {
+  void addClause(SatClause& c, bool lemma, uint64_t) {
     d_addClauseCalled = true;
   }
 
@@ -93,6 +93,10 @@ public:
   void renewVar(SatLiteral lit, int level = -1) {
   }
 
+  bool spendResource() {
+    return false;
+  }
+
   void interrupt() {
   }
   
@@ -179,7 +183,7 @@ public:
     Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
     Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
     Node c = d_nodeManager->mkVar(d_nodeManager->booleanType());
-    d_cnfStream->convertAndAssert(d_nodeManager->mkNode(kind::AND, a, b, c), false, false);
+    d_cnfStream->convertAndAssert(d_nodeManager->mkNode(kind::AND, a, b, c), false, false, RULE_INVALID, Node::null());
     TS_ASSERT( d_satSolver->addClauseCalled() );
   }
 
@@ -196,19 +200,19 @@ public:
                                                         d_nodeManager->mkNode(kind::IFF,
                                                                               d_nodeManager->mkNode(kind::OR, c, d),
                                                                               d_nodeManager->mkNode(kind::NOT,
-                                                                                                    d_nodeManager->mkNode(kind::XOR, e, f)))), false, false );
+                                                                                                    d_nodeManager->mkNode(kind::XOR, e, f)))), false, false, RULE_INVALID, Node::null());
     TS_ASSERT( d_satSolver->addClauseCalled() );
   }
 
   void testTrue() {
     NodeManagerScope nms(d_nodeManager);
-    d_cnfStream->convertAndAssert( d_nodeManager->mkConst(true), false, false );
+    d_cnfStream->convertAndAssert( d_nodeManager->mkConst(true), false, false, RULE_INVALID, Node::null() );
     TS_ASSERT( d_satSolver->addClauseCalled() );
   }
 
   void testFalse() {
     NodeManagerScope nms(d_nodeManager);
-    d_cnfStream->convertAndAssert( d_nodeManager->mkConst(false), false, false );
+    d_cnfStream->convertAndAssert( d_nodeManager->mkConst(false), false, false, RULE_INVALID, Node::null() );
     TS_ASSERT( d_satSolver->addClauseCalled() );
   }
 
@@ -216,7 +220,7 @@ public:
     NodeManagerScope nms(d_nodeManager);
     Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
     Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
-    d_cnfStream->convertAndAssert( d_nodeManager->mkNode(kind::IFF, a, b), false, false );
+    d_cnfStream->convertAndAssert( d_nodeManager->mkNode(kind::IFF, a, b), false, false, RULE_INVALID, Node::null() );
     TS_ASSERT( d_satSolver->addClauseCalled() );
   }
 
@@ -224,7 +228,7 @@ public:
     NodeManagerScope nms(d_nodeManager);
     Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
     Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
-    d_cnfStream->convertAndAssert( d_nodeManager->mkNode(kind::IMPLIES, a, b), false, false );
+    d_cnfStream->convertAndAssert( d_nodeManager->mkNode(kind::IMPLIES, a, b), false, false, RULE_INVALID, Node::null() );
     TS_ASSERT( d_satSolver->addClauseCalled() );
   }
 
@@ -241,14 +245,14 @@ public:
   //              d_nodeManager->mkVar(d_nodeManager->integerType())
   //          ),
   //          d_nodeManager->mkVar(d_nodeManager->integerType())
-  //                            ), false, false);
+  //                            ), false, false, RULE_INVALID, Node::null());
   //
   //}
 
   void testNot() {
     NodeManagerScope nms(d_nodeManager);
     Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
-    d_cnfStream->convertAndAssert( d_nodeManager->mkNode(kind::NOT, a), false, false );
+    d_cnfStream->convertAndAssert( d_nodeManager->mkNode(kind::NOT, a), false, false, RULE_INVALID, Node::null() );
     TS_ASSERT( d_satSolver->addClauseCalled() );
   }
 
@@ -257,7 +261,7 @@ public:
     Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
     Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
     Node c = d_nodeManager->mkVar(d_nodeManager->booleanType());
-    d_cnfStream->convertAndAssert( d_nodeManager->mkNode(kind::OR, a, b, c), false, false );
+    d_cnfStream->convertAndAssert( d_nodeManager->mkNode(kind::OR, a, b, c), false, false, RULE_INVALID, Node::null() );
     TS_ASSERT( d_satSolver->addClauseCalled() );
   }
 
@@ -265,10 +269,10 @@ public:
     NodeManagerScope nms(d_nodeManager);
     Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
     Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
-    d_cnfStream->convertAndAssert(a, false, false);
+    d_cnfStream->convertAndAssert(a, false, false, RULE_INVALID, Node::null());
     TS_ASSERT( d_satSolver->addClauseCalled() );
     d_satSolver->reset();
-    d_cnfStream->convertAndAssert(b, false, false);
+    d_cnfStream->convertAndAssert(b, false, false, RULE_INVALID, Node::null());
     TS_ASSERT( d_satSolver->addClauseCalled() );
   }
 
@@ -276,7 +280,7 @@ public:
     NodeManagerScope nms(d_nodeManager);
     Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
     Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
-    d_cnfStream->convertAndAssert( d_nodeManager->mkNode(kind::XOR, a, b), false, false );
+    d_cnfStream->convertAndAssert( d_nodeManager->mkNode(kind::XOR, a, b), false, false, RULE_INVALID, Node::null() );
     TS_ASSERT( d_satSolver->addClauseCalled() );
   }
 
index 3dcb2db8503bbd2b7de45f2bd803348d15c10852..d9963f78cd756fe228311d94283abff0a6e852b7 100644 (file)
@@ -218,41 +218,27 @@ std::cout<<"here\n";
     Node cons = Node::fromExpr(DatatypeType(listColorsType.toType()).getDatatype().getConstructor("cons"));
     Node nil = d_nm->mkNode(APPLY_CONSTRUCTOR, DatatypeType(listColorsType.toType()).getDatatype().getConstructor("nil"));
     Node red = d_nm->mkNode(APPLY_CONSTRUCTOR, DatatypeType(colorsType.toType()).getDatatype().getConstructor("red"));
+    Node orange = d_nm->mkNode(APPLY_CONSTRUCTOR, DatatypeType(colorsType.toType()).getDatatype().getConstructor("orange"));
+    Node yellow = d_nm->mkNode(APPLY_CONSTRUCTOR, DatatypeType(colorsType.toType()).getDatatype().getConstructor("yellow"));
     TS_ASSERT_EQUALS(*te, nil);
     TS_ASSERT_EQUALS(*++te, d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red, nil));
     TS_ASSERT( ! te.isFinished() );
     TS_ASSERT_EQUALS(*++te, d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
                             d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red, nil)));
     TS_ASSERT( ! te.isFinished() );
-    TS_ASSERT_EQUALS(*++te, d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red, nil))));
+    TS_ASSERT_EQUALS(*++te, d_nm->mkNode(APPLY_CONSTRUCTOR, cons, orange, nil));
     TS_ASSERT( ! te.isFinished() );
     TS_ASSERT_EQUALS(*++te, d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
                             d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red, nil)))));
+                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red, nil))));
     TS_ASSERT( ! te.isFinished() );
-    TS_ASSERT_EQUALS(*++te, d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red, nil))))));
+    TS_ASSERT_EQUALS(*++te, d_nm->mkNode(APPLY_CONSTRUCTOR, cons, orange,
+                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red, nil)));
     TS_ASSERT( ! te.isFinished() );
-    TS_ASSERT_EQUALS(*++te, d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red, nil)))))));
+    TS_ASSERT_EQUALS(*++te, d_nm->mkNode(APPLY_CONSTRUCTOR, cons, yellow, nil));
     TS_ASSERT( ! te.isFinished() );
     TS_ASSERT_EQUALS(*++te, d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red,
-                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, red, nil))))))));
+                            d_nm->mkNode(APPLY_CONSTRUCTOR, cons, orange, nil)));
     TS_ASSERT( ! te.isFinished() );
   }