summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/ax_prog_doxygen.m4646
-rw-r--r--examples/api/java/Strings.java182
-rw-r--r--examples/api/strings.cpp202
-rw-r--r--proofs/lfsc_checker/libwriter.cpp476
-rw-r--r--proofs/lfsc_checker/libwriter.h56
-rw-r--r--proofs/lfsc_checker/print_smt2.cpp242
-rw-r--r--proofs/lfsc_checker/print_smt2.h34
-rw-r--r--proofs/lfsc_checker/sccwriter.cpp974
-rw-r--r--proofs/lfsc_checker/sccwriter.h172
-rwxr-xr-xproofs/signatures/ex_bv.plf112
-rwxr-xr-xproofs/signatures/th_bv.plf288
-rw-r--r--src/theory/quantifiers/conjecture_generator.cpp4360
-rw-r--r--src/theory/quantifiers/conjecture_generator.h874
-rw-r--r--src/theory/quantifiers/quant_conflict_find.cpp4454
-rw-r--r--src/theory/quantifiers/quant_conflict_find.h510
-rw-r--r--test/regress/regress0/fmf/fc-pigeonhole19.smt238
-rw-r--r--test/regress/regress0/fmf/fc-unsat-pent.smt238
-rw-r--r--test/regress/regress0/fmf/fc-unsat-tot-2.smt226
-rw-r--r--test/regress/regress0/quantifiers/simp-typ-test.smt212
-rw-r--r--test/regress/regress0/strings/at001.smt224
-rw-r--r--test/regress/regress0/strings/bug001.smt230
-rw-r--r--test/regress/regress0/strings/bug002.smt218
-rw-r--r--test/regress/regress0/strings/escchar.smt224
-rw-r--r--test/regress/regress0/strings/escchar_25.smt224
-rw-r--r--test/regress/regress0/strings/fmf001.smt240
-rw-r--r--test/regress/regress0/strings/fmf002.smt234
-rw-r--r--test/regress/regress0/strings/leadingzero001.smt222
-rw-r--r--test/regress/regress0/strings/loop008.smt220
-rw-r--r--test/regress/regress0/strings/loop009.smt220
-rw-r--r--test/regress/regress0/strings/regexp001.smt226
-rw-r--r--test/regress/regress0/strings/regexp002.smt248
-rw-r--r--test/regress/regress0/strings/regexp003.smt226
-rw-r--r--test/regress/regress0/strings/reloop.smt236
-rw-r--r--test/regress/regress0/strings/str006.smt228
-rw-r--r--test/regress/regress0/strings/str007.smt226
-rw-r--r--test/regress/regress0/strings/substr001.smt232
-rw-r--r--test/regress/regress0/strings/type001.smt240
-rw-r--r--test/regress/regress0/strings/type002.smt234
-rw-r--r--test/regress/regress0/strings/type003.smt224
39 files changed, 7136 insertions, 7136 deletions
diff --git a/config/ax_prog_doxygen.m4 b/config/ax_prog_doxygen.m4
index 2d50f4e6d..3a9744aa9 100644
--- a/config/ax_prog_doxygen.m4
+++ b/config/ax_prog_doxygen.m4
@@ -1,323 +1,323 @@
-# This file is part of Autoconf. -*- Autoconf -*-
-
-# Renamed doxygen.m4 from acinclude.m4 for inclusion in CVC4
-
-# Copyright (C) 2004 Oren Ben-Kiki
-# This file is distributed under the same terms as the Autoconf macro files.
-
-########## CHANGELOG ##################
-# 2009-01-14 Martin Mann
-# * DX_ARG_ABLE : new variable 'DX_FLAG_DX_CURRENT_FEATURE'
-# * DX_CLEAR_DEPEND : use of explicit variable 'DX_FLAG_DX_CURRENT_FEATURE'
-# in AC_SUBST instead of 'DX_FLAG[]DX_CURRENT_FEATURE' which is rejected by
-# newer autotools
-
-# Generate automatic documentation using Doxygen. Works in concert with the
-# aminclude.m4 file and a compatible doxygen configuration file. Defines the
-# following public macros:
-#
-# DX_???_FEATURE(ON|OFF) - control the default setting fo a Doxygen feature.
-# Supported features are 'DOXYGEN' itself, 'DOT' for generating graphics,
-# 'HTML' for plain HTML, 'CHM' for compressed HTML help (for MS users), 'CHI'
-# for generating a seperate .chi file by the .chm file, and 'MAN', 'RTF',
-# 'XML', 'PDF' and 'PS' for the appropriate output formats. The environment
-# variable DOXYGEN_PAPER_SIZE may be specified to override the default 'a4wide'
-# paper size.
-#
-# By default, HTML, PDF and PS documentation is generated as this seems to be
-# the most popular and portable combination. MAN pages created by Doxygen are
-# usually problematic, though by picking an appropriate subset and doing some
-# massaging they might be better than nothing. CHM and RTF are specific for MS
-# (note that you can't generate both HTML and CHM at the same time). The XML is
-# rather useless unless you apply specialized post-processing to it.
-#
-# The macro mainly controls the default state of the feature. The use can
-# override the default by specifying --enable or --disable. The macros ensure
-# that contradictory flags are not given (e.g., --enable-doxygen-html and
-# --enable-doxygen-chm, --enable-doxygen-anything with --disable-doxygen, etc.)
-# Finally, each feature will be automatically disabled (with a warning) if the
-# required programs are missing.
-#
-# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN with
-# the following parameters: a one-word name for the project for use as a
-# filename base etc., an optional configuration file name (the default is
-# 'Doxyfile', the same as Doxygen's default), and an optional output directory
-# name (the default is 'doxygen-doc').
-
-## ----------##
-## Defaults. ##
-## ----------##
-
-DX_ENV=""
-AC_DEFUN([DX_FEATURE_doc], ON)
-AC_DEFUN([DX_FEATURE_dot], ON)
-AC_DEFUN([DX_FEATURE_man], OFF)
-AC_DEFUN([DX_FEATURE_html], ON)
-AC_DEFUN([DX_FEATURE_chm], OFF)
-AC_DEFUN([DX_FEATURE_chi], OFF)
-AC_DEFUN([DX_FEATURE_rtf], OFF)
-AC_DEFUN([DX_FEATURE_xml], OFF)
-AC_DEFUN([DX_FEATURE_pdf], ON)
-AC_DEFUN([DX_FEATURE_ps], ON)
-
-## --------------- ##
-## Private macros. ##
-## --------------- ##
-
-# DX_ENV_APPEND(VARIABLE, VALUE)
-# ------------------------------
-# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen.
-AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])])
-
-# DX_DIRNAME_EXPR
-# ---------------
-# Expand into a shell expression prints the directory part of a path.
-AC_DEFUN([DX_DIRNAME_EXPR],
- [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
-
-# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
-# -------------------------------------
-# Expands according to the M4 (static) status of the feature.
-AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
-
-# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
-# ----------------------------------
-# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
-AC_DEFUN([DX_REQUIRE_PROG], [
-AC_PATH_TOOL([$1], [$2])
-if test "$DX_FLAG_DX_CURRENT_FEATURE$$1" = 1; then
- AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
- AC_SUBST([DX_FLAG_DX_CURRENT_FEATURE], 0)
-fi
-])
-
-# DX_TEST_FEATURE(FEATURE)
-# ------------------------
-# Expand to a shell expression testing whether the feature is active.
-AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
-
-# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
-# -------------------------------------------------
-# Verify that a required features has the right state before trying to turn on
-# the DX_CURRENT_FEATURE.
-AC_DEFUN([DX_CHECK_DEPEND], [
-test "$DX_FLAG_$1" = "$2" \
-|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
- requires, contradicts) doxygen-DX_CURRENT_FEATURE])
-])
-
-# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
-# ----------------------------------------------------------
-# Turn off the DX_CURRENT_FEATURE if the required feature is off.
-AC_DEFUN([DX_CLEAR_DEPEND], [
-test "$DX_FLAG_$1" = "$2" || AC_SUBST([DX_FLAG_DX_CURRENT_FEATURE], 0)
-])
-
-
-# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
-# CHECK_DEPEND, CLEAR_DEPEND,
-# REQUIRE, DO-IF-ON, DO-IF-OFF)
-# --------------------------------------------
-# Parse the command-line option controlling a feature. CHECK_DEPEND is called
-# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
-# otherwise CLEAR_DEPEND is called to turn off the default state if a required
-# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
-# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
-# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
-AC_DEFUN([DX_ARG_ABLE], [
- AC_DEFUN([DX_CURRENT_FEATURE], [$1])
- AC_DEFUN([DX_FLAG_DX_CURRENT_FEATURE], [DX_FLAG_$1])
- AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
- AC_ARG_ENABLE(doxygen-$1,
- [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
- [--enable-doxygen-$1]),
- DX_IF_FEATURE([$1], [don't $2], [$2]))],
- [
-case "$enableval" in
-#(
-y|Y|yes|Yes|YES)
- AC_SUBST([DX_FLAG_$1], 1)
- $3
-;; #(
-n|N|no|No|NO)
- AC_SUBST([DX_FLAG_$1], 0)
-;; #(
-*)
- AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
-;;
-esac
-], [
-AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
-$4
-])
-if DX_TEST_FEATURE([$1]); then
- $5
- :
-fi
-if DX_TEST_FEATURE([$1]); then
- AM_CONDITIONAL(DX_COND_$1, :)
- $6
- :
-else
- AM_CONDITIONAL(DX_COND_$1, false)
- $7
- :
-fi
-])
-
-## -------------- ##
-## Public macros. ##
-## -------------- ##
-
-# DX_XXX_FEATURE(DEFAULT_STATE)
-# -----------------------------
-AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])])
-AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])])
-AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])])
-AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])])
-AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])])
-AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])])
-AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
-AC_DEFUN([DX_DOT_FEATURE], [AC_DEFUN([DX_FEATURE_dot], [$1])])
-AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])])
-AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])])
-
-# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR])
-# ---------------------------------------------------------
-# PROJECT also serves as the base name for the documentation files.
-# The default CONFIG-FILE is "Doxyfile" and OUTPUT-DOC-DIR is "doxygen-doc".
-AC_DEFUN([DX_INIT_DOXYGEN], [
-
-# Files:
-AC_SUBST([DX_PROJECT], [$1])
-AC_SUBST([DX_CONFIG], [ifelse([$2], [], Doxyfile, [$2])])
-AC_SUBST([DX_DOCDIR], [ifelse([$3], [], doxygen-doc, [$3])])
-
-# Environment variables used inside doxygen.cfg:
-DX_ENV_APPEND(SRCDIR, $srcdir)
-DX_ENV_APPEND(PROJECT, $DX_PROJECT)
-DX_ENV_APPEND(DOCDIR, $DX_DOCDIR)
-DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
-
-# Doxygen itself:
-DX_ARG_ABLE(doc, [generate any doxygen documentation],
- [],
- [],
- [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
- DX_REQUIRE_PROG([DX_PERL], perl)],
- [DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
-
-# Dot for graphics:
-DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [DX_REQUIRE_PROG([DX_DOT], dot)],
- [DX_ENV_APPEND(HAVE_DOT, YES)
- DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
- [DX_ENV_APPEND(HAVE_DOT, NO)])
-
-# Man pages generation:
-DX_ARG_ABLE(man, [generate doxygen manual pages],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [],
- [DX_ENV_APPEND(GENERATE_MAN, YES)],
- [DX_ENV_APPEND(GENERATE_MAN, NO)])
-
-# RTF file generation:
-DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [],
- [DX_ENV_APPEND(GENERATE_RTF, YES)],
- [DX_ENV_APPEND(GENERATE_RTF, NO)])
-
-# XML file generation:
-DX_ARG_ABLE(xml, [generate doxygen XML documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [],
- [DX_ENV_APPEND(GENERATE_XML, YES)],
- [DX_ENV_APPEND(GENERATE_XML, NO)])
-
-# (Compressed) HTML help generation:
-DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [DX_REQUIRE_PROG([DX_HHC], hhc)],
- [DX_ENV_APPEND(HHC_PATH, $DX_HHC)
- DX_ENV_APPEND(GENERATE_HTML, YES)
- DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
- [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
-
-# Seperate CHI file generation.
-DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file],
- [DX_CHECK_DEPEND(chm, 1)],
- [DX_CLEAR_DEPEND(chm, 1)],
- [],
- [DX_ENV_APPEND(GENERATE_CHI, YES)],
- [DX_ENV_APPEND(GENERATE_CHI, NO)])
-
-# Plain HTML pages generation:
-DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
- [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
- [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
- [],
- [DX_ENV_APPEND(GENERATE_HTML, YES)],
- [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
-
-# PostScript file generation:
-DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [DX_REQUIRE_PROG([DX_LATEX], latex)
- DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
- DX_REQUIRE_PROG([DX_DVIPS], dvips)
- DX_REQUIRE_PROG([DX_EGREP], egrep)])
-
-# PDF file generation:
-DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
- DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
- DX_REQUIRE_PROG([DX_EGREP], egrep)])
-
-# LaTeX generation for PS and/or PDF:
-if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
- AM_CONDITIONAL(DX_COND_latex, :)
- DX_ENV_APPEND(GENERATE_LATEX, YES)
-else
- AM_CONDITIONAL(DX_COND_latex, false)
- DX_ENV_APPEND(GENERATE_LATEX, NO)
-fi
-
-# Paper size for PS and/or PDF:
-AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
- [a4wide (default), a4, letter, legal or executive])
-case "$DOXYGEN_PAPER_SIZE" in
-#(
-"")
- AC_SUBST(DOXYGEN_PAPER_SIZE, "")
-;; #(
-a4wide|a4|letter|legal|executive)
- DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
-;; #(
-*)
- AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
-;;
-esac
-
-#For debugging:
-#echo DX_FLAG_doc=$DX_FLAG_doc
-#echo DX_FLAG_dot=$DX_FLAG_dot
-#echo DX_FLAG_man=$DX_FLAG_man
-#echo DX_FLAG_html=$DX_FLAG_html
-#echo DX_FLAG_chm=$DX_FLAG_chm
-#echo DX_FLAG_chi=$DX_FLAG_chi
-#echo DX_FLAG_rtf=$DX_FLAG_rtf
-#echo DX_FLAG_xml=$DX_FLAG_xml
-#echo DX_FLAG_pdf=$DX_FLAG_pdf
-#echo DX_FLAG_ps=$DX_FLAG_ps
-#echo DX_ENV=$DX_ENV
-])
+# This file is part of Autoconf. -*- Autoconf -*-
+
+# Renamed doxygen.m4 from acinclude.m4 for inclusion in CVC4
+
+# Copyright (C) 2004 Oren Ben-Kiki
+# This file is distributed under the same terms as the Autoconf macro files.
+
+########## CHANGELOG ##################
+# 2009-01-14 Martin Mann
+# * DX_ARG_ABLE : new variable 'DX_FLAG_DX_CURRENT_FEATURE'
+# * DX_CLEAR_DEPEND : use of explicit variable 'DX_FLAG_DX_CURRENT_FEATURE'
+# in AC_SUBST instead of 'DX_FLAG[]DX_CURRENT_FEATURE' which is rejected by
+# newer autotools
+
+# Generate automatic documentation using Doxygen. Works in concert with the
+# aminclude.m4 file and a compatible doxygen configuration file. Defines the
+# following public macros:
+#
+# DX_???_FEATURE(ON|OFF) - control the default setting fo a Doxygen feature.
+# Supported features are 'DOXYGEN' itself, 'DOT' for generating graphics,
+# 'HTML' for plain HTML, 'CHM' for compressed HTML help (for MS users), 'CHI'
+# for generating a seperate .chi file by the .chm file, and 'MAN', 'RTF',
+# 'XML', 'PDF' and 'PS' for the appropriate output formats. The environment
+# variable DOXYGEN_PAPER_SIZE may be specified to override the default 'a4wide'
+# paper size.
+#
+# By default, HTML, PDF and PS documentation is generated as this seems to be
+# the most popular and portable combination. MAN pages created by Doxygen are
+# usually problematic, though by picking an appropriate subset and doing some
+# massaging they might be better than nothing. CHM and RTF are specific for MS
+# (note that you can't generate both HTML and CHM at the same time). The XML is
+# rather useless unless you apply specialized post-processing to it.
+#
+# The macro mainly controls the default state of the feature. The use can
+# override the default by specifying --enable or --disable. The macros ensure
+# that contradictory flags are not given (e.g., --enable-doxygen-html and
+# --enable-doxygen-chm, --enable-doxygen-anything with --disable-doxygen, etc.)
+# Finally, each feature will be automatically disabled (with a warning) if the
+# required programs are missing.
+#
+# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN with
+# the following parameters: a one-word name for the project for use as a
+# filename base etc., an optional configuration file name (the default is
+# 'Doxyfile', the same as Doxygen's default), and an optional output directory
+# name (the default is 'doxygen-doc').
+
+## ----------##
+## Defaults. ##
+## ----------##
+
+DX_ENV=""
+AC_DEFUN([DX_FEATURE_doc], ON)
+AC_DEFUN([DX_FEATURE_dot], ON)
+AC_DEFUN([DX_FEATURE_man], OFF)
+AC_DEFUN([DX_FEATURE_html], ON)
+AC_DEFUN([DX_FEATURE_chm], OFF)
+AC_DEFUN([DX_FEATURE_chi], OFF)
+AC_DEFUN([DX_FEATURE_rtf], OFF)
+AC_DEFUN([DX_FEATURE_xml], OFF)
+AC_DEFUN([DX_FEATURE_pdf], ON)
+AC_DEFUN([DX_FEATURE_ps], ON)
+
+## --------------- ##
+## Private macros. ##
+## --------------- ##
+
+# DX_ENV_APPEND(VARIABLE, VALUE)
+# ------------------------------
+# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen.
+AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])])
+
+# DX_DIRNAME_EXPR
+# ---------------
+# Expand into a shell expression prints the directory part of a path.
+AC_DEFUN([DX_DIRNAME_EXPR],
+ [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
+
+# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
+# -------------------------------------
+# Expands according to the M4 (static) status of the feature.
+AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
+
+# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
+# ----------------------------------
+# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
+AC_DEFUN([DX_REQUIRE_PROG], [
+AC_PATH_TOOL([$1], [$2])
+if test "$DX_FLAG_DX_CURRENT_FEATURE$$1" = 1; then
+ AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
+ AC_SUBST([DX_FLAG_DX_CURRENT_FEATURE], 0)
+fi
+])
+
+# DX_TEST_FEATURE(FEATURE)
+# ------------------------
+# Expand to a shell expression testing whether the feature is active.
+AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
+
+# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
+# -------------------------------------------------
+# Verify that a required features has the right state before trying to turn on
+# the DX_CURRENT_FEATURE.
+AC_DEFUN([DX_CHECK_DEPEND], [
+test "$DX_FLAG_$1" = "$2" \
+|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
+ requires, contradicts) doxygen-DX_CURRENT_FEATURE])
+])
+
+# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
+# ----------------------------------------------------------
+# Turn off the DX_CURRENT_FEATURE if the required feature is off.
+AC_DEFUN([DX_CLEAR_DEPEND], [
+test "$DX_FLAG_$1" = "$2" || AC_SUBST([DX_FLAG_DX_CURRENT_FEATURE], 0)
+])
+
+
+# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
+# CHECK_DEPEND, CLEAR_DEPEND,
+# REQUIRE, DO-IF-ON, DO-IF-OFF)
+# --------------------------------------------
+# Parse the command-line option controlling a feature. CHECK_DEPEND is called
+# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
+# otherwise CLEAR_DEPEND is called to turn off the default state if a required
+# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
+# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
+# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
+AC_DEFUN([DX_ARG_ABLE], [
+ AC_DEFUN([DX_CURRENT_FEATURE], [$1])
+ AC_DEFUN([DX_FLAG_DX_CURRENT_FEATURE], [DX_FLAG_$1])
+ AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
+ AC_ARG_ENABLE(doxygen-$1,
+ [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
+ [--enable-doxygen-$1]),
+ DX_IF_FEATURE([$1], [don't $2], [$2]))],
+ [
+case "$enableval" in
+#(
+y|Y|yes|Yes|YES)
+ AC_SUBST([DX_FLAG_$1], 1)
+ $3
+;; #(
+n|N|no|No|NO)
+ AC_SUBST([DX_FLAG_$1], 0)
+;; #(
+*)
+ AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
+;;
+esac
+], [
+AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
+$4
+])
+if DX_TEST_FEATURE([$1]); then
+ $5
+ :
+fi
+if DX_TEST_FEATURE([$1]); then
+ AM_CONDITIONAL(DX_COND_$1, :)
+ $6
+ :
+else
+ AM_CONDITIONAL(DX_COND_$1, false)
+ $7
+ :
+fi
+])
+
+## -------------- ##
+## Public macros. ##
+## -------------- ##
+
+# DX_XXX_FEATURE(DEFAULT_STATE)
+# -----------------------------
+AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])])
+AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])])
+AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])])
+AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])])
+AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])])
+AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])])
+AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
+AC_DEFUN([DX_DOT_FEATURE], [AC_DEFUN([DX_FEATURE_dot], [$1])])
+AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])])
+AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])])
+
+# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR])
+# ---------------------------------------------------------
+# PROJECT also serves as the base name for the documentation files.
+# The default CONFIG-FILE is "Doxyfile" and OUTPUT-DOC-DIR is "doxygen-doc".
+AC_DEFUN([DX_INIT_DOXYGEN], [
+
+# Files:
+AC_SUBST([DX_PROJECT], [$1])
+AC_SUBST([DX_CONFIG], [ifelse([$2], [], Doxyfile, [$2])])
+AC_SUBST([DX_DOCDIR], [ifelse([$3], [], doxygen-doc, [$3])])
+
+# Environment variables used inside doxygen.cfg:
+DX_ENV_APPEND(SRCDIR, $srcdir)
+DX_ENV_APPEND(PROJECT, $DX_PROJECT)
+DX_ENV_APPEND(DOCDIR, $DX_DOCDIR)
+DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
+
+# Doxygen itself:
+DX_ARG_ABLE(doc, [generate any doxygen documentation],
+ [],
+ [],
+ [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
+ DX_REQUIRE_PROG([DX_PERL], perl)],
+ [DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
+
+# Dot for graphics:
+DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_DOT], dot)],
+ [DX_ENV_APPEND(HAVE_DOT, YES)
+ DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
+ [DX_ENV_APPEND(HAVE_DOT, NO)])
+
+# Man pages generation:
+DX_ARG_ABLE(man, [generate doxygen manual pages],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_MAN, YES)],
+ [DX_ENV_APPEND(GENERATE_MAN, NO)])
+
+# RTF file generation:
+DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_RTF, YES)],
+ [DX_ENV_APPEND(GENERATE_RTF, NO)])
+
+# XML file generation:
+DX_ARG_ABLE(xml, [generate doxygen XML documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_XML, YES)],
+ [DX_ENV_APPEND(GENERATE_XML, NO)])
+
+# (Compressed) HTML help generation:
+DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_HHC], hhc)],
+ [DX_ENV_APPEND(HHC_PATH, $DX_HHC)
+ DX_ENV_APPEND(GENERATE_HTML, YES)
+ DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
+ [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
+
+# Seperate CHI file generation.
+DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file],
+ [DX_CHECK_DEPEND(chm, 1)],
+ [DX_CLEAR_DEPEND(chm, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_CHI, YES)],
+ [DX_ENV_APPEND(GENERATE_CHI, NO)])
+
+# Plain HTML pages generation:
+DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
+ [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
+ [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
+ [],
+ [DX_ENV_APPEND(GENERATE_HTML, YES)],
+ [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
+
+# PostScript file generation:
+DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_LATEX], latex)
+ DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
+ DX_REQUIRE_PROG([DX_DVIPS], dvips)
+ DX_REQUIRE_PROG([DX_EGREP], egrep)])
+
+# PDF file generation:
+DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
+ DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
+ DX_REQUIRE_PROG([DX_EGREP], egrep)])
+
+# LaTeX generation for PS and/or PDF:
+if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
+ AM_CONDITIONAL(DX_COND_latex, :)
+ DX_ENV_APPEND(GENERATE_LATEX, YES)
+else
+ AM_CONDITIONAL(DX_COND_latex, false)
+ DX_ENV_APPEND(GENERATE_LATEX, NO)
+fi
+
+# Paper size for PS and/or PDF:
+AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
+ [a4wide (default), a4, letter, legal or executive])
+case "$DOXYGEN_PAPER_SIZE" in
+#(
+"")
+ AC_SUBST(DOXYGEN_PAPER_SIZE, "")
+;; #(
+a4wide|a4|letter|legal|executive)
+ DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
+;; #(
+*)
+ AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
+;;
+esac
+
+#For debugging:
+#echo DX_FLAG_doc=$DX_FLAG_doc
+#echo DX_FLAG_dot=$DX_FLAG_dot
+#echo DX_FLAG_man=$DX_FLAG_man
+#echo DX_FLAG_html=$DX_FLAG_html
+#echo DX_FLAG_chm=$DX_FLAG_chm
+#echo DX_FLAG_chi=$DX_FLAG_chi
+#echo DX_FLAG_rtf=$DX_FLAG_rtf
+#echo DX_FLAG_xml=$DX_FLAG_xml
+#echo DX_FLAG_pdf=$DX_FLAG_pdf
+#echo DX_FLAG_ps=$DX_FLAG_ps
+#echo DX_ENV=$DX_ENV
+])
diff --git a/examples/api/java/Strings.java b/examples/api/java/Strings.java
index 9437115a9..bb9dcd822 100644
--- a/examples/api/java/Strings.java
+++ b/examples/api/java/Strings.java
@@ -1,91 +1,91 @@
-/********************* */
-/*! \file Strings.java
- ** \verbatim
- ** Original author: Tianyi Liang
- ** 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 Reasoning about strings with CVC4 via Java API.
- **
- ** A simple demonstration of reasoning about strings with CVC4 via Jave API.
- **/
-
-import edu.nyu.acsys.CVC4.*;
-
-public class Strings {
- public static void main(String[] args) {
- System.loadLibrary("cvc4jni");
-
- ExprManager em = new ExprManager();
- SmtEngine smt = new SmtEngine(em);
-
- // Set the logic
- smt.setLogic("S");
-
- // Produce models
- smt.setOption("produce-models", new SExpr(true));
- // The option strings-exp is needed
- smt.setOption("strings-exp", new SExpr(true));
- // output-language
- smt.setOption("output-language", new SExpr("smt2"));
-
- // String type
- Type string = em.stringType();
-
- // String constants
- Expr ab = em.mkConst(new CVC4String("ab"));
- Expr abc = em.mkConst(new CVC4String("abc"));
- // Variables
- Expr x = em.mkVar("x", string);
- Expr y = em.mkVar("y", string);
- Expr z = em.mkVar("z", string);
-
- // String concatenation: x.ab.y
- Expr lhs = em.mkExpr(Kind.STRING_CONCAT, x, ab, y);
- // String concatenation: abc.z
- Expr rhs = em.mkExpr(Kind.STRING_CONCAT, abc, z);;
- // x.ab.y = abc.z
- Expr formula1 = em.mkExpr(Kind.EQUAL, lhs, rhs);
-
- // Length of y: |y|
- Expr leny = em.mkExpr(Kind.STRING_LENGTH, y);
- // |y| >= 0
- Expr formula2 = em.mkExpr(Kind.GEQ, leny, em.mkConst(new Rational(0)));
-
- // Regular expression: (ab[c-e]*f)|g|h
- Expr r = em.mkExpr(Kind.REGEXP_UNION,
- em.mkExpr(Kind.REGEXP_CONCAT,
- em.mkExpr(Kind.STRING_TO_REGEXP, em.mkConst(new CVC4String("ab"))),
- em.mkExpr(Kind.REGEXP_STAR,
- em.mkExpr(Kind.REGEXP_RANGE, em.mkConst(new CVC4String("c")), em.mkConst(new CVC4String("e")))),
- em.mkExpr(Kind.STRING_TO_REGEXP, em.mkConst(new CVC4String("f")))),
- em.mkExpr(Kind.STRING_TO_REGEXP, em.mkConst(new CVC4String("g"))),
- em.mkExpr(Kind.STRING_TO_REGEXP, em.mkConst(new CVC4String("h"))));
-
- // String variables
- Expr s1 = em.mkVar("s1", string);
- Expr s2 = em.mkVar("s2", string);
- // String concatenation: s1.s2
- Expr s = em.mkExpr(Kind.STRING_CONCAT, s1, s2);
-
- // s1.s2 in (ab[c-e]*f)|g|h
- Expr formula3 = em.mkExpr(Kind.STRING_IN_REGEXP, s, r);
-
- // Make a query
- Expr q = em.mkExpr(Kind.AND,
- formula1,
- formula2,
- formula3);
-
- // check sat
- Result result = smt.checkSat(q);
- System.out.println("CVC4 reports: " + q + " is " + result + ".");
-
- System.out.println(" x = " + smt.getValue(x));
- System.out.println(" s1.s2 = " + smt.getValue(s));
- }
-}
+/********************* */
+/*! \file Strings.java
+ ** \verbatim
+ ** Original author: Tianyi Liang
+ ** 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 Reasoning about strings with CVC4 via Java API.
+ **
+ ** A simple demonstration of reasoning about strings with CVC4 via Jave API.
+ **/
+
+import edu.nyu.acsys.CVC4.*;
+
+public class Strings {
+ public static void main(String[] args) {
+ System.loadLibrary("cvc4jni");
+
+ ExprManager em = new ExprManager();
+ SmtEngine smt = new SmtEngine(em);
+
+ // Set the logic
+ smt.setLogic("S");
+
+ // Produce models
+ smt.setOption("produce-models", new SExpr(true));
+ // The option strings-exp is needed
+ smt.setOption("strings-exp", new SExpr(true));
+ // output-language
+ smt.setOption("output-language", new SExpr("smt2"));
+
+ // String type
+ Type string = em.stringType();
+
+ // String constants
+ Expr ab = em.mkConst(new CVC4String("ab"));
+ Expr abc = em.mkConst(new CVC4String("abc"));
+ // Variables
+ Expr x = em.mkVar("x", string);
+ Expr y = em.mkVar("y", string);
+ Expr z = em.mkVar("z", string);
+
+ // String concatenation: x.ab.y
+ Expr lhs = em.mkExpr(Kind.STRING_CONCAT, x, ab, y);
+ // String concatenation: abc.z
+ Expr rhs = em.mkExpr(Kind.STRING_CONCAT, abc, z);;
+ // x.ab.y = abc.z
+ Expr formula1 = em.mkExpr(Kind.EQUAL, lhs, rhs);
+
+ // Length of y: |y|
+ Expr leny = em.mkExpr(Kind.STRING_LENGTH, y);
+ // |y| >= 0
+ Expr formula2 = em.mkExpr(Kind.GEQ, leny, em.mkConst(new Rational(0)));
+
+ // Regular expression: (ab[c-e]*f)|g|h
+ Expr r = em.mkExpr(Kind.REGEXP_UNION,
+ em.mkExpr(Kind.REGEXP_CONCAT,
+ em.mkExpr(Kind.STRING_TO_REGEXP, em.mkConst(new CVC4String("ab"))),
+ em.mkExpr(Kind.REGEXP_STAR,
+ em.mkExpr(Kind.REGEXP_RANGE, em.mkConst(new CVC4String("c")), em.mkConst(new CVC4String("e")))),
+ em.mkExpr(Kind.STRING_TO_REGEXP, em.mkConst(new CVC4String("f")))),
+ em.mkExpr(Kind.STRING_TO_REGEXP, em.mkConst(new CVC4String("g"))),
+ em.mkExpr(Kind.STRING_TO_REGEXP, em.mkConst(new CVC4String("h"))));
+
+ // String variables
+ Expr s1 = em.mkVar("s1", string);
+ Expr s2 = em.mkVar("s2", string);
+ // String concatenation: s1.s2
+ Expr s = em.mkExpr(Kind.STRING_CONCAT, s1, s2);
+
+ // s1.s2 in (ab[c-e]*f)|g|h
+ Expr formula3 = em.mkExpr(Kind.STRING_IN_REGEXP, s, r);
+
+ // Make a query
+ Expr q = em.mkExpr(Kind.AND,
+ formula1,
+ formula2,
+ formula3);
+
+ // check sat
+ Result result = smt.checkSat(q);
+ System.out.println("CVC4 reports: " + q + " is " + result + ".");
+
+ System.out.println(" x = " + smt.getValue(x));
+ System.out.println(" s1.s2 = " + smt.getValue(s));
+ }
+}
diff --git a/examples/api/strings.cpp b/examples/api/strings.cpp
index a424c654a..14ab0e64d 100644
--- a/examples/api/strings.cpp
+++ b/examples/api/strings.cpp
@@ -1,101 +1,101 @@
-/********************* */
-/*! \file sets.cpp
- ** \verbatim
- ** Original author: Tianyi Liang
- ** 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 Reasoning about strings with CVC4 via C++ API.
- **
- ** A simple demonstration of reasoning about strings with CVC4 via C++ API.
- **/
-
-#include <iostream>
-
-//#include <cvc4/cvc4.h> // use this after CVC4 is properly installed
-#include "smt/smt_engine.h"
-
-using namespace CVC4;
-
-int main() {
- ExprManager em;
- SmtEngine smt(&em);
-
- // Set the logic
- smt.setLogic("S");
-
- // Produce models
- smt.setOption("produce-models", true);
-
- // The option strings-exp is needed
- smt.setOption("strings-exp", true);
-
- // Set output language to SMTLIB2
- std::cout << Expr::setlanguage(language::output::LANG_SMTLIB_V2);
-
- // String type
- Type string = em.stringType();
-
- // std::string
- std::string std_str_ab("ab");
- // CVC4::String
- CVC4::String cvc4_str_ab(std_str_ab);
- CVC4::String cvc4_str_abc("abc");
- // String constants
- Expr ab = em.mkConst(cvc4_str_ab);
- Expr abc = em.mkConst(CVC4::String("abc"));
- // String variables
- Expr x = em.mkVar("x", string);
- Expr y = em.mkVar("y", string);
- Expr z = em.mkVar("z", string);
-
- // String concatenation: x.ab.y
- Expr lhs = em.mkExpr(kind::STRING_CONCAT, x, ab, y);
- // String concatenation: abc.z
- Expr rhs = em.mkExpr(kind::STRING_CONCAT, abc, z);
- // x.ab.y = abc.z
- Expr formula1 = em.mkExpr(kind::EQUAL, lhs, rhs);
-
- // Length of y: |y|
- Expr leny = em.mkExpr(kind::STRING_LENGTH, y);
- // |y| >= 0
- Expr formula2 = em.mkExpr(kind::GEQ, leny, em.mkConst(Rational(0)));
-
- // Regular expression: (ab[c-e]*f)|g|h
- Expr r = em.mkExpr(kind::REGEXP_UNION,
- em.mkExpr(kind::REGEXP_CONCAT,
- em.mkExpr(kind::STRING_TO_REGEXP, em.mkConst(String("ab"))),
- em.mkExpr(kind::REGEXP_STAR,
- em.mkExpr(kind::REGEXP_RANGE, em.mkConst(String("c")), em.mkConst(String("e")))),
- em.mkExpr(kind::STRING_TO_REGEXP, em.mkConst(String("f")))),
- em.mkExpr(kind::STRING_TO_REGEXP, em.mkConst(String("g"))),
- em.mkExpr(kind::STRING_TO_REGEXP, em.mkConst(String("h"))));
-
- // String variables
- Expr s1 = em.mkVar("s1", string);
- Expr s2 = em.mkVar("s2", string);
- // String concatenation: s1.s2
- Expr s = em.mkExpr(kind::STRING_CONCAT, s1, s2);
-
- // s1.s2 in (ab[c-e]*f)|g|h
- Expr formula3 = em.mkExpr(kind::STRING_IN_REGEXP, s, r);
-
- // Make a query
- Expr q = em.mkExpr(kind::AND,
- formula1,
- formula2,
- formula3);
-
- // check sat
- Result result = smt.checkSat(q);
- std::cout << "CVC4 reports: " << q << " is " << result << "." << std::endl;
-
- if(result == Result::SAT) {
- std::cout << " x = " << smt.getValue(x) << std::endl;
- std::cout << " s1.s2 = " << smt.getValue(s) << std::endl;
- }
-}
+/********************* */
+/*! \file sets.cpp
+ ** \verbatim
+ ** Original author: Tianyi Liang
+ ** 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 Reasoning about strings with CVC4 via C++ API.
+ **
+ ** A simple demonstration of reasoning about strings with CVC4 via C++ API.
+ **/
+
+#include <iostream>
+
+//#include <cvc4/cvc4.h> // use this after CVC4 is properly installed
+#include "smt/smt_engine.h"
+
+using namespace CVC4;
+
+int main() {
+ ExprManager em;
+ SmtEngine smt(&em);
+
+ // Set the logic
+ smt.setLogic("S");
+
+ // Produce models
+ smt.setOption("produce-models", true);
+
+ // The option strings-exp is needed
+ smt.setOption("strings-exp", true);
+
+ // Set output language to SMTLIB2
+ std::cout << Expr::setlanguage(language::output::LANG_SMTLIB_V2);
+
+ // String type
+ Type string = em.stringType();
+
+ // std::string
+ std::string std_str_ab("ab");
+ // CVC4::String
+ CVC4::String cvc4_str_ab(std_str_ab);
+ CVC4::String cvc4_str_abc("abc");
+ // String constants
+ Expr ab = em.mkConst(cvc4_str_ab);
+ Expr abc = em.mkConst(CVC4::String("abc"));
+ // String variables
+ Expr x = em.mkVar("x", string);
+ Expr y = em.mkVar("y", string);
+ Expr z = em.mkVar("z", string);
+
+ // String concatenation: x.ab.y
+ Expr lhs = em.mkExpr(kind::STRING_CONCAT, x, ab, y);
+ // String concatenation: abc.z
+ Expr rhs = em.mkExpr(kind::STRING_CONCAT, abc, z);
+ // x.ab.y = abc.z
+ Expr formula1 = em.mkExpr(kind::EQUAL, lhs, rhs);
+
+ // Length of y: |y|
+ Expr leny = em.mkExpr(kind::STRING_LENGTH, y);
+ // |y| >= 0
+ Expr formula2 = em.mkExpr(kind::GEQ, leny, em.mkConst(Rational(0)));
+
+ // Regular expression: (ab[c-e]*f)|g|h
+ Expr r = em.mkExpr(kind::REGEXP_UNION,
+ em.mkExpr(kind::REGEXP_CONCAT,
+ em.mkExpr(kind::STRING_TO_REGEXP, em.mkConst(String("ab"))),
+ em.mkExpr(kind::REGEXP_STAR,
+ em.mkExpr(kind::REGEXP_RANGE, em.mkConst(String("c")), em.mkConst(String("e")))),
+ em.mkExpr(kind::STRING_TO_REGEXP, em.mkConst(String("f")))),
+ em.mkExpr(kind::STRING_TO_REGEXP, em.mkConst(String("g"))),
+ em.mkExpr(kind::STRING_TO_REGEXP, em.mkConst(String("h"))));
+
+ // String variables
+ Expr s1 = em.mkVar("s1", string);
+ Expr s2 = em.mkVar("s2", string);
+ // String concatenation: s1.s2
+ Expr s = em.mkExpr(kind::STRING_CONCAT, s1, s2);
+
+ // s1.s2 in (ab[c-e]*f)|g|h
+ Expr formula3 = em.mkExpr(kind::STRING_IN_REGEXP, s, r);
+
+ // Make a query
+ Expr q = em.mkExpr(kind::AND,
+ formula1,
+ formula2,
+ formula3);
+
+ // check sat
+ Result result = smt.checkSat(q);
+ std::cout << "CVC4 reports: " << q << " is " << result << "." << std::endl;
+
+ if(result == Result::SAT) {
+ std::cout << " x = " << smt.getValue(x) << std::endl;
+ std::cout << " s1.s2 = " << smt.getValue(s) << std::endl;
+ }
+}
diff --git a/proofs/lfsc_checker/libwriter.cpp b/proofs/lfsc_checker/libwriter.cpp
index 49e9bbaad..016016c9d 100644
--- a/proofs/lfsc_checker/libwriter.cpp
+++ b/proofs/lfsc_checker/libwriter.cpp
@@ -1,238 +1,238 @@
-#include "libwriter.h"
-#include <sstream>
-#include <algorithm>
-#include <fstream>
-
-void libwriter::get_var_name( const std::string& n, std::string& nn ) {
- nn = std::string( n.c_str() );
- for( int i = 0; i <(int)n.length(); i++ ){
- char c = n[i];
- if (c <= 47)
- c += 65;
- else if (c >= 58 && c <= 64)
- c += 97-58;
- if ((c >= 91 && c <= 94) || c == 96)
- c += 104-91;
- else if (c >= 123)
- c -= 4;
- nn[i] = c;
- }
-}
-
-void libwriter::write_file()
-{
- //std::cout << "write lib" << std::endl;
- std::ostringstream os_enum;
- std::ostringstream os_print;
- std::ostringstream os_constructor_h;
- std::ostringstream os_constructor_c;
-
- for ( int a=0; a<(int)syms.size(); a++ ) {
- //std::cout << "sym #" << (a+1) << ": ";
- //std::cout << ((SymSExpr*)syms[a])->s.c_str() << std::endl;
- //defs[a]->print( std::cout );
- //std::cout << std::endl;
-
- if( defs[a]->getclass()==CEXPR ){
- //calculate which arguments are required for input
- std::vector< Expr* > args;
- std::vector< bool > argsNeed;
- std::vector< Expr* > argTypes;
- CExpr* c = ((CExpr*)defs[a]);
- while( c->getop()==PI ){
- //std::cout << c->kids[0] << std::endl;
- if( ((CExpr*)c->kids[1])->getop()!=RUN ){
- args.push_back( c->kids[0] );
- argsNeed.push_back( true );
- argTypes.push_back( c->kids[1] );
- }
- for( int b=0; b<(int)args.size(); b++ ){
- if( argsNeed[b] ){
- if( ((CExpr*)c->kids[1])->getop()==RUN ){
- if( ((CExpr*)c->kids[1])->kids[1]->free_in( args[b] ) ){
- argsNeed[b] = false;
- }
- }else{
- if( c->kids[1]->free_in( args[b] ) ){
- argsNeed[b] = false;
- }
- }
- }
- }
- c = (CExpr*)(c->kids[2]);
- }
-
- //record if this declares a judgement
- if( ((CExpr*)defs[a])->getop()==PI && c->getop()==TYPE ){
- //std::cout << "This is a judgement" << std::endl;
- judgements.push_back( syms[a] );
- //record if this declares a proof rule
- }else if( c->getclass()==CEXPR && std::find( judgements.begin(), judgements.end(), c->kids[0] )!=judgements.end() ){
- std::cout << "Handle rule: " << ((SymSExpr*)syms[a])->s.c_str() << std::endl;
- //std::cout << "These are required to input:" << std::endl;
- //for( int b=0; b<(int)args.size(); b++ ){
- // if( argsNeed[b] ){
- // std::cout << ((SymSExpr*)args[b])->s.c_str() << std::endl;
- // }
- //}
- os_enum << " rule_" << ((SymSExpr*)syms[a])->s.c_str() << "," << std::endl;
-
- os_print << " case rule_" << ((SymSExpr*)syms[a])->s.c_str() << ": os << \"";
- os_print << ((SymSExpr*)syms[a])->s.c_str() << "\";break;" << std::endl;
-
- std::ostringstream os_args;
- os_args << "(";
- bool firstTime = true;
- for( int b=0; b<(int)args.size(); b++ ){
- if( argsNeed[b] ){
- if( !firstTime )
- os_args << ",";
- std::string str;
- get_var_name( ((SymSExpr*)args[b])->s, str );
- os_args << " LFSCProof* " << str.c_str();
- firstTime = false;
- }
- }
- if( !firstTime ){
- os_args << " ";
- }
- os_args << ")";
-
- os_constructor_h << " static LFSCProof* make_" << ((SymSExpr*)syms[a])->s.c_str();
- os_constructor_h << os_args.str().c_str() << ";" << std::endl;
-
- os_constructor_c << "LFSCProof* LFSCProof::make_" << ((SymSExpr*)syms[a])->s.c_str();
- os_constructor_c << os_args.str().c_str() << "{" << std::endl;
- os_constructor_c << " LFSCProof **kids = new LFSCProof *[" << (int)args.size()+1 << "];" << std::endl;
- for( int b=0; b<(int)args.size(); b++ ){
- os_constructor_c << " kids[" << b << "] = ";
- if( argsNeed[b] ){
- std::string str;
- get_var_name( ((SymSExpr*)args[b])->s, str );
- os_constructor_c << str.c_str();
- }else{
- os_constructor_c << "hole";
- }
- os_constructor_c << ";" << std::endl;
- }
- os_constructor_c << " kids[" << (int)args.size() << "] = 0;" << std::endl;
- os_constructor_c << " return new LFSCProofC( rule_" << ((SymSExpr*)syms[a])->s.c_str() << ", kids );" << std::endl;
- os_constructor_c << "}" << std::endl << std::endl;
- }
- }
-
- //write the header
- static std::string filename( "lfsc_proof" );
- std::fstream fsh;
- std::string fnameh( filename );
- fnameh.append(".h");
- fsh.open( fnameh.c_str(), std::ios::out );
-
- fsh << "#ifndef LFSC_PROOF_LIB_H" << std::endl;
- fsh << "#define LFSC_PROOF_LIB_H" << std::endl;
- fsh << std::endl;
- fsh << "#include <string>" << std::endl;
- fsh << std::endl;
- fsh << "class LFSCProof{" << std::endl;
- fsh << "protected:" << std::endl;
- fsh << " enum{" << std::endl;
- fsh << os_enum.str().c_str();
- fsh << " };" << std::endl;
- fsh << " static LFSCProof* hole;" << std::endl;
- fsh << " LFSCProof(){}" << std::endl;
- fsh << "public:" << std::endl;
- fsh << " virtual ~LFSCProof(){}" << std::endl;
- fsh << " static void init();" << std::endl;
- fsh << std::endl;
- fsh << " //functions to build LFSC proofs" << std::endl;
- fsh << os_constructor_h.str().c_str();
- fsh << std::endl;
- fsh << " virtual void set_child( int i, LFSCProof* e ) {}" << std::endl;
- fsh << " virtual void print( std::ostream& os ){}" << std::endl;
- fsh << "};" << std::endl;
- fsh << std::endl;
- fsh << "class LFSCProofC : public LFSCProof{" << std::endl;
- fsh << " short id;" << std::endl;
- fsh << " LFSCProof **kids;" << std::endl;
- fsh << "public:" << std::endl;
- fsh << " LFSCProofC( short d_id, LFSCProof **d_kids ) : id( d_id ), kids( d_kids ){}" << std::endl;
- fsh << " void set_child( int i, LFSCProof* e ) { kids[i] = e; }" << std::endl;
- fsh << " void print( std::ostream& os );" << std::endl;
- fsh << "};" << std::endl;
- fsh << std::endl;
- fsh << "class LFSCProofSym : public LFSCProof{" << std::endl;
- fsh << "private:" << std::endl;
- fsh << " std::string s;" << std::endl;
- fsh << " LFSCProofSym( std::string ss ) : s( ss ){}" << std::endl;
- fsh << "public:" << std::endl;
- fsh << " static LFSCProofSym* make( std::string ss ) { return new LFSCProofSym( ss ); }" << std::endl;
- fsh << " static LFSCProofSym* make( const char* ss ) { return new LFSCProofSym( std::string( ss ) ); }" << std::endl;
- fsh << " ~LFSCProofSym(){}" << std::endl;
- fsh << " void print( std::ostream& os ) { os << s.c_str(); }" << std::endl;
- fsh << "};" << std::endl;
- fsh << std::endl;
- fsh << "class LFSCProofLam : public LFSCProof{" << std::endl;
- fsh << " LFSCProofSym* var;" << std::endl;
- fsh << " LFSCProof* body;" << std::endl;
- fsh << " LFSCProof* typ;" << std::endl;
- fsh << " LFSCProofLam( LFSCProofSym* d_var, LFSCProof* d_body, LFSCProof* d_typ ) : var( d_var ), body( d_body ), typ( d_typ ){}" << std::endl;
- fsh << "public:" << std::endl;
- fsh << " static LFSCProof* make( LFSCProofSym* d_var, LFSCProof* d_body, LFSCProof* d_typ = NULL ) {" << std::endl;
- fsh << " return new LFSCProofLam( d_var, d_body, d_typ );" << std::endl;
- fsh << " }" << std::endl;
- fsh << " ~LFSCProofLam(){}" << std::endl;
- fsh << std::endl;
- fsh << " void print( std::ostream& os );" << std::endl;
- fsh << "};" << std::endl;
- fsh << std::endl;
- fsh << "#endif" << std::endl;
-
- //write the cpp
- std::fstream fsc;
- std::string fnamec( filename );
- fnamec.append(".cpp");
- fsc.open( fnamec.c_str(), std::ios::out );
-
- fsc << "#include \"lfsc_proof.h\"" << std::endl;
- fsc << std::endl;
- fsc << "LFSCProof* LFSCProof::hole = NULL;" << std::endl;
- fsc << std::endl;
- fsc << "void LFSCProof::init(){" << std::endl;
- fsc << " hole = LFSCProofSym::make( \"_\" );" << std::endl;
- fsc << "}" << std::endl;
- fsc << std::endl;
- fsc << "void LFSCProofC::print( std::ostream& os ){" << std::endl;
- fsc << " os << \"(\";" << std::endl;
- fsc << " switch( id ){" << std::endl;
- fsc << os_print.str().c_str();
- fsc << " }" << std::endl;
- fsc << " int counter = 0;" << std::endl;
- fsc << " while( kids[counter] ){" << std::endl;
- fsc << " os << \" \";" << std::endl;
- fsc << " kids[counter]->print( os );" << std::endl;
- fsc << " counter++;" << std::endl;
- fsc << " }" << std::endl;
- fsc << " os << \")\";" << std::endl;
- fsc << "}" << std::endl;
- fsc << std::endl;
- fsc << "void LFSCProofLam::print( std::ostream& os ){" << std::endl;
- fsc << " os << \"(\";" << std::endl;
- fsc << " if( typ ){" << std::endl;
- fsc << " os << \"% \";" << std::endl;
- fsc << " }else{" << std::endl;
- fsc << " os << \"\\\\ \";" << std::endl;
- fsc << " }" << std::endl;
- fsc << " var->print( os );" << std::endl;
- fsc << " if( typ ){" << std::endl;
- fsc << " os << \" \";" << std::endl;
- fsc << " typ->print( os );" << std::endl;
- fsc << " }" << std::endl;
- fsc << " os << std::endl;" << std::endl;
- fsc << " body->print( os );" << std::endl;
- fsc << " os << \")\";" << std::endl;
- fsc << "}" << std::endl;
- fsc << std::endl;
- fsc << os_constructor_c.str().c_str();
- fsc << std::endl;
- }
-}
+#include "libwriter.h"
+#include <sstream>
+#include <algorithm>
+#include <fstream>
+
+void libwriter::get_var_name( const std::string& n, std::string& nn ) {
+ nn = std::string( n.c_str() );
+ for( int i = 0; i <(int)n.length(); i++ ){
+ char c = n[i];
+ if (c <= 47)
+ c += 65;
+ else if (c >= 58 && c <= 64)
+ c += 97-58;
+ if ((c >= 91 && c <= 94) || c == 96)
+ c += 104-91;
+ else if (c >= 123)
+ c -= 4;
+ nn[i] = c;
+ }
+}
+
+void libwriter::write_file()
+{
+ //std::cout << "write lib" << std::endl;
+ std::ostringstream os_enum;
+ std::ostringstream os_print;
+ std::ostringstream os_constructor_h;
+ std::ostringstream os_constructor_c;
+
+ for ( int a=0; a<(int)syms.size(); a++ ) {
+ //std::cout << "sym #" << (a+1) << ": ";
+ //std::cout << ((SymSExpr*)syms[a])->s.c_str() << std::endl;
+ //defs[a]->print( std::cout );
+ //std::cout << std::endl;
+
+ if( defs[a]->getclass()==CEXPR ){
+ //calculate which arguments are required for input
+ std::vector< Expr* > args;
+ std::vector< bool > argsNeed;
+ std::vector< Expr* > argTypes;
+ CExpr* c = ((CExpr*)defs[a]);
+ while( c->getop()==PI ){
+ //std::cout << c->kids[0] << std::endl;
+ if( ((CExpr*)c->kids[1])->getop()!=RUN ){
+ args.push_back( c->kids[0] );
+ argsNeed.push_back( true );
+ argTypes.push_back( c->kids[1] );
+ }
+ for( int b=0; b<(int)args.size(); b++ ){
+ if( argsNeed[b] ){
+ if( ((CExpr*)c->kids[1])->getop()==RUN ){
+ if( ((CExpr*)c->kids[1])->kids[1]->free_in( args[b] ) ){
+ argsNeed[b] = false;
+ }
+ }else{
+ if( c->kids[1]->free_in( args[b] ) ){
+ argsNeed[b] = false;
+ }
+ }
+ }
+ }
+ c = (CExpr*)(c->kids[2]);
+ }
+
+ //record if this declares a judgement
+ if( ((CExpr*)defs[a])->getop()==PI && c->getop()==TYPE ){
+ //std::cout << "This is a judgement" << std::endl;
+ judgements.push_back( syms[a] );
+ //record if this declares a proof rule
+ }else if( c->getclass()==CEXPR && std::find( judgements.begin(), judgements.end(), c->kids[0] )!=judgements.end() ){
+ std::cout << "Handle rule: " << ((SymSExpr*)syms[a])->s.c_str() << std::endl;
+ //std::cout << "These are required to input:" << std::endl;
+ //for( int b=0; b<(int)args.size(); b++ ){
+ // if( argsNeed[b] ){
+ // std::cout << ((SymSExpr*)args[b])->s.c_str() << std::endl;
+ // }
+ //}
+ os_enum << " rule_" << ((SymSExpr*)syms[a])->s.c_str() << "," << std::endl;
+
+ os_print << " case rule_" << ((SymSExpr*)syms[a])->s.c_str() << ": os << \"";
+ os_print << ((SymSExpr*)syms[a])->s.c_str() << "\";break;" << std::endl;
+
+ std::ostringstream os_args;
+ os_args << "(";
+ bool firstTime = true;
+ for( int b=0; b<(int)args.size(); b++ ){
+ if( argsNeed[b] ){
+ if( !firstTime )
+ os_args << ",";
+ std::string str;
+ get_var_name( ((SymSExpr*)args[b])->s, str );
+ os_args << " LFSCProof* " << str.c_str();
+ firstTime = false;
+ }
+ }
+ if( !firstTime ){
+ os_args << " ";
+ }
+ os_args << ")";
+
+ os_constructor_h << " static LFSCProof* make_" << ((SymSExpr*)syms[a])->s.c_str();
+ os_constructor_h << os_args.str().c_str() << ";" << std::endl;
+
+ os_constructor_c << "LFSCProof* LFSCProof::make_" << ((SymSExpr*)syms[a])->s.c_str();
+ os_constructor_c << os_args.str().c_str() << "{" << std::endl;
+ os_constructor_c << " LFSCProof **kids = new LFSCProof *[" << (int)args.size()+1 << "];" << std::endl;
+ for( int b=0; b<(int)args.size(); b++ ){
+ os_constructor_c << " kids[" << b << "] = ";
+ if( argsNeed[b] ){
+ std::string str;
+ get_var_name( ((SymSExpr*)args[b])->s, str );
+ os_constructor_c << str.c_str();
+ }else{
+ os_constructor_c << "hole";
+ }
+ os_constructor_c << ";" << std::endl;
+ }
+ os_constructor_c << " kids[" << (int)args.size() << "] = 0;" << std::endl;
+ os_constructor_c << " return new LFSCProofC( rule_" << ((SymSExpr*)syms[a])->s.c_str() << ", kids );" << std::endl;
+ os_constructor_c << "}" << std::endl << std::endl;
+ }
+ }
+
+ //write the header
+ static std::string filename( "lfsc_proof" );
+ std::fstream fsh;
+ std::string fnameh( filename );
+ fnameh.append(".h");
+ fsh.open( fnameh.c_str(), std::ios::out );
+
+ fsh << "#ifndef LFSC_PROOF_LIB_H" << std::endl;
+ fsh << "#define LFSC_PROOF_LIB_H" << std::endl;
+ fsh << std::endl;
+ fsh << "#include <string>" << std::endl;
+ fsh << std::endl;
+ fsh << "class LFSCProof{" << std::endl;
+ fsh << "protected:" << std::endl;
+ fsh << " enum{" << std::endl;
+ fsh << os_enum.str().c_str();
+ fsh << " };" << std::endl;
+ fsh << " static LFSCProof* hole;" << std::endl;
+ fsh << " LFSCProof(){}" << std::endl;
+ fsh << "public:" << std::endl;
+ fsh << " virtual ~LFSCProof(){}" << std::endl;
+ fsh << " static void init();" << std::endl;
+ fsh << std::endl;
+ fsh << " //functions to build LFSC proofs" << std::endl;
+ fsh << os_constructor_h.str().c_str();
+ fsh << std::endl;
+ fsh << " virtual void set_child( int i, LFSCProof* e ) {}" << std::endl;
+ fsh << " virtual void print( std::ostream& os ){}" << std::endl;
+ fsh << "};" << std::endl;
+ fsh << std::endl;
+ fsh << "class LFSCProofC : public LFSCProof{" << std::endl;
+ fsh << " short id;" << std::endl;
+ fsh << " LFSCProof **kids;" << std::endl;
+ fsh << "public:" << std::endl;
+ fsh << " LFSCProofC( short d_id, LFSCProof **d_kids ) : id( d_id ), kids( d_kids ){}" << std::endl;
+ fsh << " void set_child( int i, LFSCProof* e ) { kids[i] = e; }" << std::endl;
+ fsh << " void print( std::ostream& os );" << std::endl;
+ fsh << "};" << std::endl;
+ fsh << std::endl;
+ fsh << "class LFSCProofSym : public LFSCProof{" << std::endl;
+ fsh << "private:" << std::endl;
+ fsh << " std::string s;" << std::endl;
+ fsh << " LFSCProofSym( std::string ss ) : s( ss ){}" << std::endl;
+ fsh << "public:" << std::endl;
+ fsh << " static LFSCProofSym* make( std::string ss ) { return new LFSCProofSym( ss ); }" << std::endl;
+ fsh << " static LFSCProofSym* make( const char* ss ) { return new LFSCProofSym( std::string( ss ) ); }" << std::endl;
+ fsh << " ~LFSCProofSym(){}" << std::endl;
+ fsh << " void print( std::ostream& os ) { os << s.c_str(); }" << std::endl;
+ fsh << "};" << std::endl;
+ fsh << std::endl;
+ fsh << "class LFSCProofLam : public LFSCProof{" << std::endl;
+ fsh << " LFSCProofSym* var;" << std::endl;
+ fsh << " LFSCProof* body;" << std::endl;
+ fsh << " LFSCProof* typ;" << std::endl;
+ fsh << " LFSCProofLam( LFSCProofSym* d_var, LFSCProof* d_body, LFSCProof* d_typ ) : var( d_var ), body( d_body ), typ( d_typ ){}" << std::endl;
+ fsh << "public:" << std::endl;
+ fsh << " static LFSCProof* make( LFSCProofSym* d_var, LFSCProof* d_body, LFSCProof* d_typ = NULL ) {" << std::endl;
+ fsh << " return new LFSCProofLam( d_var, d_body, d_typ );" << std::endl;
+ fsh << " }" << std::endl;
+ fsh << " ~LFSCProofLam(){}" << std::endl;
+ fsh << std::endl;
+ fsh << " void print( std::ostream& os );" << std::endl;
+ fsh << "};" << std::endl;
+ fsh << std::endl;
+ fsh << "#endif" << std::endl;
+
+ //write the cpp
+ std::fstream fsc;
+ std::string fnamec( filename );
+ fnamec.append(".cpp");
+ fsc.open( fnamec.c_str(), std::ios::out );
+
+ fsc << "#include \"lfsc_proof.h\"" << std::endl;
+ fsc << std::endl;
+ fsc << "LFSCProof* LFSCProof::hole = NULL;" << std::endl;
+ fsc << std::endl;
+ fsc << "void LFSCProof::init(){" << std::endl;
+ fsc << " hole = LFSCProofSym::make( \"_\" );" << std::endl;
+ fsc << "}" << std::endl;
+ fsc << std::endl;
+ fsc << "void LFSCProofC::print( std::ostream& os ){" << std::endl;
+ fsc << " os << \"(\";" << std::endl;
+ fsc << " switch( id ){" << std::endl;
+ fsc << os_print.str().c_str();
+ fsc << " }" << std::endl;
+ fsc << " int counter = 0;" << std::endl;
+ fsc << " while( kids[counter] ){" << std::endl;
+ fsc << " os << \" \";" << std::endl;
+ fsc << " kids[counter]->print( os );" << std::endl;
+ fsc << " counter++;" << std::endl;
+ fsc << " }" << std::endl;
+ fsc << " os << \")\";" << std::endl;
+ fsc << "}" << std::endl;
+ fsc << std::endl;
+ fsc << "void LFSCProofLam::print( std::ostream& os ){" << std::endl;
+ fsc << " os << \"(\";" << std::endl;
+ fsc << " if( typ ){" << std::endl;
+ fsc << " os << \"% \";" << std::endl;
+ fsc << " }else{" << std::endl;
+ fsc << " os << \"\\\\ \";" << std::endl;
+ fsc << " }" << std::endl;
+ fsc << " var->print( os );" << std::endl;
+ fsc << " if( typ ){" << std::endl;
+ fsc << " os << \" \";" << std::endl;
+ fsc << " typ->print( os );" << std::endl;
+ fsc << " }" << std::endl;
+ fsc << " os << std::endl;" << std::endl;
+ fsc << " body->print( os );" << std::endl;
+ fsc << " os << \")\";" << std::endl;
+ fsc << "}" << std::endl;
+ fsc << std::endl;
+ fsc << os_constructor_c.str().c_str();
+ fsc << std::endl;
+ }
+}
diff --git a/proofs/lfsc_checker/libwriter.h b/proofs/lfsc_checker/libwriter.h
index 093cf541b..91db5e911 100644
--- a/proofs/lfsc_checker/libwriter.h
+++ b/proofs/lfsc_checker/libwriter.h
@@ -1,28 +1,28 @@
-#ifndef LIB_WRITER_H
-#define LIB_WRITER_H
-
-#include "expr.h"
-#include <map>
-
-class libwriter
-{
-private:
- std::vector< Expr* > syms;
- std::vector< Expr* > defs;
-
- std::vector< Expr* > judgements;
- //get the variable name
- void get_var_name( const std::string& n, std::string& nn );
-public:
- libwriter(){}
- virtual ~libwriter(){}
-
- void add_symbol( Expr* s, Expr* t ) {
- syms.push_back( s );
- defs.push_back( t );
- }
-
- void write_file();
-};
-
-#endif
+#ifndef LIB_WRITER_H
+#define LIB_WRITER_H
+
+#include "expr.h"
+#include <map>
+
+class libwriter
+{
+private:
+ std::vector< Expr* > syms;
+ std::vector< Expr* > defs;
+
+ std::vector< Expr* > judgements;
+ //get the variable name
+ void get_var_name( const std::string& n, std::string& nn );
+public:
+ libwriter(){}
+ virtual ~libwriter(){}
+
+ void add_symbol( Expr* s, Expr* t ) {
+ syms.push_back( s );
+ defs.push_back( t );
+ }
+
+ void write_file();
+};
+
+#endif
diff --git a/proofs/lfsc_checker/print_smt2.cpp b/proofs/lfsc_checker/print_smt2.cpp
index 34cb00cc4..40d9d1206 100644
--- a/proofs/lfsc_checker/print_smt2.cpp
+++ b/proofs/lfsc_checker/print_smt2.cpp
@@ -1,122 +1,122 @@
-#include "print_smt2.h"
-
-#ifdef PRINT_SMT2
-
-void print_smt2( Expr* p, std::ostream& s, short mode )
-{
- switch( p->getclass() )
- {
- case CEXPR:
- {
- switch( p->getop() )
- {
- case APP:
- {
+#include "print_smt2.h"
+
+#ifdef PRINT_SMT2
+
+void print_smt2( Expr* p, std::ostream& s, short mode )
+{
+ switch( p->getclass() )
+ {
+ case CEXPR:
+ {
+ switch( p->getop() )
+ {
+ case APP:
+ {
std::vector<Expr *> args;
- Expr *head = p->collect_args(args, false);
- short newMode = get_mode( head );
- if( is_smt2_poly_formula( head ) )
- {
- s << "(";
- head->print( s );
- s << " ";
- print_smt2( args[1], s, newMode );
- s << " ";
- print_smt2( args[2], s, newMode );
- s << ")";
- }
- else if( ( mode==2 || mode==3 ) && mode==newMode )
- {
- print_smt2( args[0], s, newMode );
- s << " ";
- print_smt2( args[1], s, newMode );
- }
- else if( newMode==1 )
- {
- if( mode!=1 || newMode!=mode ){
- s << "(";
- }
- print_smt2( args[2], s, newMode );
- s << " ";
- print_smt2( args[3], s, 0 );
- if( mode!=1 || newMode!=mode ){
- s << ")";
- }
- }
- else
- {
- s << "(";
- switch( newMode )
- {
- case 4: s << "=>";break;
- default: head->print( s );break;
- }
- s << " ";
- for( int a=0; a<(int)args.size(); a++ ){
- print_smt2( args[a], s, newMode );
- if( a!=(int)args.size()-1 )
- s << " ";
- }
- s << ")";
- }
- }
- break;
- default:
- std::cout << "Unhandled op " << p->getop() << std::endl;
- break;
- }
- }
- break;
- case HOLE_EXPR:
- {
- HoleExpr *e = (HoleExpr *)p;
- if( e->val ){
- print_smt2( e->val, s, mode );
- }else{
- s << "_";
- }
- }
- break;
- case SYMS_EXPR:
- case SYM_EXPR:
- if( ((SymExpr*)p)->val )
- print_smt2( ((SymExpr*)p)->val, s, mode );
- else
- p->print( s );
- break;
- default:
- std::cout << "Unhandled class " << p->getclass() << std::endl;
- break;
- }
-}
-
-bool is_smt2_poly_formula( Expr* e )
-{
- if( e->getclass()==SYMS_EXPR )
- {
- SymSExpr* s = (SymSExpr*)e;
- static std::string eq("=");
- static std::string distinct("distinct");
- return s->s==eq || s->s==distinct;
- }else{
- return false;
- }
-}
-
-short get_mode( Expr* e )
-{
- if( e->getclass()==SYMS_EXPR ){
- SymSExpr* s = (SymSExpr*)e;
- static std::string applys("apply");
- if ( s->s==applys ) return 1;
- static std::string ands("and");
- if ( s->s==ands ) return 2;
- static std::string ors("or");
- if ( s->s==ors ) return 3;
- static std::string impls("impl");
- if ( s->s==impls ) return 4;
- }
- return 0;
-}
-
-#endif
+ Expr *head = p->collect_args(args, false);
+ short newMode = get_mode( head );
+ if( is_smt2_poly_formula( head ) )
+ {
+ s << "(";
+ head->print( s );
+ s << " ";
+ print_smt2( args[1], s, newMode );
+ s << " ";
+ print_smt2( args[2], s, newMode );
+ s << ")";
+ }
+ else if( ( mode==2 || mode==3 ) && mode==newMode )
+ {
+ print_smt2( args[0], s, newMode );
+ s << " ";
+ print_smt2( args[1], s, newMode );
+ }
+ else if( newMode==1 )
+ {
+ if( mode!=1 || newMode!=mode ){
+ s << "(";
+ }
+ print_smt2( args[2], s, newMode );
+ s << " ";
+ print_smt2( args[3], s, 0 );
+ if( mode!=1 || newMode!=mode ){
+ s << ")";
+ }
+ }
+ else
+ {
+ s << "(";
+ switch( newMode )
+ {
+ case 4: s << "=>";break;
+ default: head->print( s );break;
+ }
+ s << " ";
+ for( int a=0; a<(int)args.size(); a++ ){
+ print_smt2( args[a], s, newMode );
+ if( a!=(int)args.size()-1 )
+ s << " ";
+ }
+ s << ")";
+ }
+ }
+ break;
+ default:
+ std::cout << "Unhandled op " << p->getop() << std::endl;
+ break;
+ }
+ }
+ break;
+ case HOLE_EXPR:
+ {
+ HoleExpr *e = (HoleExpr *)p;
+ if( e->val ){
+ print_smt2( e->val, s, mode );
+ }else{
+ s << "_";
+ }
+ }
+ break;
+ case SYMS_EXPR:
+ case SYM_EXPR:
+ if( ((SymExpr*)p)->val )
+ print_smt2( ((SymExpr*)p)->val, s, mode );
+ else
+ p->print( s );
+ break;
+ default:
+ std::cout << "Unhandled class " << p->getclass() << std::endl;
+ break;
+ }
+}
+
+bool is_smt2_poly_formula( Expr* e )
+{
+ if( e->getclass()==SYMS_EXPR )
+ {
+ SymSExpr* s = (SymSExpr*)e;
+ static std::string eq("=");
+ static std::string distinct("distinct");
+ return s->s==eq || s->s==distinct;
+ }else{
+ return false;
+ }
+}
+
+short get_mode( Expr* e )
+{
+ if( e->getclass()==SYMS_EXPR ){
+ SymSExpr* s = (SymSExpr*)e;
+ static std::string applys("apply");
+ if ( s->s==applys ) return 1;
+ static std::string ands("and");
+ if ( s->s==ands ) return 2;
+ static std::string ors("or");
+ if ( s->s==ors ) return 3;
+ static std::string impls("impl");
+ if ( s->s==impls ) return 4;
+ }
+ return 0;
+}
+
+#endif
diff --git a/proofs/lfsc_checker/print_smt2.h b/proofs/lfsc_checker/print_smt2.h
index c70b1dfa4..9bee0e81c 100644
--- a/proofs/lfsc_checker/print_smt2.h
+++ b/proofs/lfsc_checker/print_smt2.h
@@ -1,17 +1,17 @@
-#ifndef PRINT_SMT2_H
-#define PRINT_SMT2_H
-
-#define PRINT_SMT2
-
-#include "expr.h"
-
-#ifdef PRINT_SMT2
-void print_smt2( Expr* p, std::ostream& s, short mode = 0 );
-
-bool is_smt2_poly_formula( Expr* p );
-short get_mode( Expr* p );
-
-#endif
-
-
-#endif
+#ifndef PRINT_SMT2_H
+#define PRINT_SMT2_H
+
+#define PRINT_SMT2
+
+#include "expr.h"
+
+#ifdef PRINT_SMT2
+void print_smt2( Expr* p, std::ostream& s, short mode = 0 );
+
+bool is_smt2_poly_formula( Expr* p );
+short get_mode( Expr* p );
+
+#endif
+
+
+#endif
diff --git a/proofs/lfsc_checker/sccwriter.cpp b/proofs/lfsc_checker/sccwriter.cpp
index d11a96b19..5c1da2a3f 100644
--- a/proofs/lfsc_checker/sccwriter.cpp
+++ b/proofs/lfsc_checker/sccwriter.cpp
@@ -1,335 +1,335 @@
-#include "sccwriter.h"
-
-#include <fstream>
-#include <sstream>
-
-int sccwriter::exprCount = 0;
-int sccwriter::strCount = 0;
-int sccwriter::argsCount = 0;
-int sccwriter::rnumCount = 0;
-
-int sccwriter::get_prog_index( const std::string& str )
-{
- for( int a=0; a<(int)progNames.size(); a++ ){
- if( progNames[a]==str ){
- return a;
- }
- }
- return -1;
-}
-
-int sccwriter::get_prog_index_by_expr( Expr* e )
-{
- for( int a=0; a<(int)progPtrs.size(); a++ ){
- if( progPtrs[a]==e ){
- return a;
- }
- }
- return -1;
-}
-
-bool sccwriter::is_var( const std::string& str )
-{
- for( int a=0; a<(int)vars.size(); a++ ){
- if( vars[a]==str ){
- return true;
- }
- }
- return false;
-}
-
-void sccwriter::add_global_sym( const std::string& str )
-{
- for( int a=0; a<(int)globalSyms.size(); a++ ){
- if( globalSyms[a]==str ){
- return;
- }
- }
- globalSyms.push_back( str );
-}
-
-void sccwriter::indent( std::ostream& os, int ind )
-{
- for( int a=0; a<ind; a++ )
- {
- os << " ";
- }
-}
-
-void sccwriter::write_function_header( std::ostream& os, int index, int opts )
-{
- //write the function header
- std::string fname;
- get_function_name( progNames[index], fname );
- os << "Expr* " << fname.c_str() << "( ";
- CExpr* progvars = (CExpr*)get_prog( index )->kids[1];
- int counter = 0;
- //write each argument
- while( progvars->kids[counter] )
- {
- if( counter!=0 )
- {
- os << ", ";
- }
- os << "Expr* ";
- write_variable( ((SymSExpr*)progvars->kids[counter])->s, os );
- //add to vars if options are set to do so
- if( opts&opt_write_add_args )
- {
- vars.push_back( ((SymSExpr*)progvars->kids[counter])->s );
- }
- counter++;
- }
- os << " )";
- if( opts&opt_write_call_debug )
- {
- os << "{" << std::endl;
- indent( os, 1 );
- os << "std::cout << \"Call function " << fname.c_str() << " with arguments \";" << std::endl;
- counter = 0;
- while( progvars->kids[counter] )
- {
- if( counter!=0 )
- {
- indent( os, 1 );
- os << "std::cout << \", \";" << std::endl;
- }
- indent( os, 1 );
- write_variable( ((SymSExpr*)progvars->kids[counter])->s, os );
- os << "->print( std::cout );" << std::endl;
- counter++;
- }
- indent( os, 1 );
- os << "std::cout << std::endl;" << std::endl;
- }
-}
-
-void sccwriter::get_function_name( const std::string& pname, std::string& fname )
-{
- fname = std::string( "f_" );
- fname.append( pname );
-}
-
-void sccwriter::write_variable( const std::string& n, std::ostream& os )
-{
- std::string nn;
- get_var_name( n, nn );
- os << nn.c_str();
-}
-
-void sccwriter::get_var_name( const std::string& n, std::string& nn ) {
- nn = std::string( n.c_str() );
- for( int i = 0; i <(int)n.length(); i++ ){
- char c = n[i];
- if (c <= 47)
- c += 65;
- else if (c >= 58 && c <= 64)
- c += 97-58;
- if ((c >= 91 && c <= 94) || c == 96)
- c += 104-91;
- else if (c >= 123)
- c -= 4;
- nn[i] = c;
- }
-}
-
-void sccwriter::write_file()
-{
- static std::string filename( "scccode" );
-
- //writer the h file
- std::fstream fsh;
- std::string fnameh( filename );
- fnameh.append(".h");
- fsh.open( fnameh.c_str(), std::ios::out );
- //write the header in h
- fsh << "#ifndef SCC_CODE_H" << std::endl;
- fsh << "#define SCC_CODE_H" << std::endl << std::endl;
- //include necessary files in h file
- fsh << "#include \"check.h\"" << std::endl << std::endl;
- //write the init function
- fsh << "void init_compiled_scc();" << std::endl << std::endl;
- //write the entry function
- fsh << "Expr* run_compiled_scc( Expr* p, std::vector< Expr* >& args );" << std::endl << std::endl;
- //write the side condition code functions
- for( int n=0; n<(int)progs.size(); n++ )
- {
- //write the header in the h file
- fsh << "inline ";
- write_function_header( fsh, n );
- fsh << ";" << std::endl << std::endl;
- }
- fsh << "#endif" << std::endl << std::endl;
- fsh.close();
-
-
- //writer the cpp code
- std::fstream fsc;
- std::string fnamec( filename );
- fnamec.append(".cpp");
- fsc.open( fnamec.c_str(), std::ios::out );
- //include the h file in the cpp
- fsc << "#include \"scccode.h\"" << std::endl << std::endl;
- std::ostringstream fsc_funcs;
- //write the side condition code functions
- for( currProgram=0; currProgram<(int)progs.size(); currProgram++ )
- {
- //reset naming counters
- vars.clear();
- exprCount = 0;
- strCount = 0;
- argsCount = 0;
- rnumCount = 0;
-
- //for debugging
- std::cout << "program #" << currProgram << " " << progNames[currProgram].c_str() << std::endl;
-
- //write the function header
- write_function_header( fsc_funcs, currProgram, opt_write_add_args|options );
- if( (options&opt_write_call_debug)==0 )
- {
- fsc_funcs << "{" << std::endl;
- }
- //write the code
- //std::vector< std::string > cleanVec;
- //write_code( get_prog( n )->kids[2], fsc, 1, "return ", cleanVec );
- //debug_write_code( progs[n].second->kids[2], fsc, 1 );
- std::string expr;
- write_expr( get_prog( currProgram )->kids[2], fsc_funcs, 1, expr );
- indent( fsc_funcs, 1 );
- fsc_funcs << "return " << expr.c_str() << ";" << std::endl;
- fsc_funcs << "}" << std::endl << std::endl;
- }
- //write the predefined symbols necessary - symbols and progs
- for( int a=0; a<(int)globalSyms.size(); a++ )
- {
- fsc << "Expr* e_" << globalSyms[a].c_str() << ";" << std::endl;
- }
- for( int a=0; a<(int)progs.size(); a++ )
- {
- fsc << "Expr* e_" << progNames[a].c_str() << ";" << std::endl;
- }
- fsc << std::endl;
- //write the init function - initialize symbols and progs
- fsc << "void init_compiled_scc(){" << std::endl;
- for( int a=0; a<(int)globalSyms.size(); a++ )
- {
- indent( fsc, 1 );
- fsc << "e_" << globalSyms[a].c_str() << " = symbols->get(\"" << globalSyms[a].c_str() << "\").first;" << std::endl;
- }
- for( int a=0; a<(int)progs.size(); a++ )
- {
- indent( fsc, 1 );
- fsc << "e_" << progNames[a].c_str() << " = progs[\"" << progNames[a].c_str() << "\"];" << std::endl;
- }
- fsc << "}" << std::endl << std::endl;
- fsc << "Expr* run_compiled_scc( Expr* p, std::vector< Expr* >& args ){" << std::endl;
- //for( int n=0; n<(int)progs.size(); n++ ){
- // indent( fsc, 1 );
- // fsc << "static std::string s_" << progNames[n].c_str() << " = std::string( \"" << progNames[n].c_str() << "\" );" << std::endl;
- //}
- for( int n=0; n<(int)progs.size(); n++ ){
- indent( fsc, 1 );
- if( n!=0 ){
- fsc << "}else ";
- }
- //for each function, test to see if the string matches the name of the function
- fsc << "if( p==e_" << progNames[n].c_str() << " ){" << std::endl;
- indent( fsc, 2 );
- std::string fname;
- get_function_name( progNames[n], fname );
- //map the function to the proper function
- fsc << "return " << fname.c_str() << "( ";
- //write the arguments to the function from args
- CExpr* progvars = (CExpr*)get_prog( n )->kids[1];
- int counter = 0;
- bool firstTime = true;
- while( progvars->kids[counter] )
- {
- if( !firstTime )
- {
- fsc << ", ";
- }
- fsc << "args[" << counter << "]";
- firstTime = false;
- counter++;
- }
- fsc << " );" << std::endl;
- }
- indent( fsc, 1 );
- fsc << "}else{" << std::endl;
- indent( fsc, 2 );
- //return null in the case the function could not be found
- fsc << "return NULL;" << std::endl;
- indent( fsc, 1 );
- fsc << "}" << std::endl;
- fsc << "}" << std::endl << std::endl;
- fsc << fsc_funcs.str().c_str();
-
- fsc.close();
-}
-
-void sccwriter::write_code( Expr* code, std::ostream& os, int ind, const char* retModStr, int opts )
-{
- std::string retModString;
- std::string incString;
- if ( retModStr )
- {
- retModString = std::string( retModStr );
- retModString.append( " = " );
- incString = std::string( retModStr );
- incString.append( "->inc();" );
- }
- switch( code->getclass() )
- {
- case INT_EXPR:
- {
- indent( os, ind );
- os << retModString.c_str();
- os << "new IntExpr( " << mpz_get_si( ((IntExpr*)code)->n ) << " );" << std::endl;
- indent( os, ind );
- os << incString.c_str() << std::endl;
- }
- break;
- case RAT_EXPR:
- {
- mpz_t num, den;
- mpz_init(num);
- mpz_init(den);
- mpq_get_num( num, ((RatExpr*)code)->n );
- mpq_get_den( den, ((RatExpr*)code)->n );
- indent( os, ind );
- os << retModString.c_str();
- os << "new RatExpr( " << mpz_get_si( num ) << ", " << mpz_get_si( den ) << " );" << std::endl;
- indent( os, ind );
- os << incString.c_str() << std::endl;
- }
- break;
- case SYMS_EXPR:
- {
- //if it is a variable, simply write it to buffer
- if( is_var( ((SymSExpr*)code)->s ) )
- {
- indent( os, ind );
- os << retModString.c_str();
- write_variable( ((SymSExpr*)code)->s.c_str(), os );
- os << ";" << std::endl;
- }
- else //else must look at symbol lookup table
- {
- std::string var;
- get_var_name( ((SymSExpr*)code)->s, var );
- indent( os, ind );
- os << retModString.c_str() << "e_" << var.c_str() << ";" << std::endl;
- add_global_sym( var );
- }
- indent( os, ind );
- os << incString.c_str() << std::endl;
- }
- break;
- default:
- switch( code->getop() )
- {
+#include "sccwriter.h"
+
+#include <fstream>
+#include <sstream>
+
+int sccwriter::exprCount = 0;
+int sccwriter::strCount = 0;
+int sccwriter::argsCount = 0;
+int sccwriter::rnumCount = 0;
+
+int sccwriter::get_prog_index( const std::string& str )
+{
+ for( int a=0; a<(int)progNames.size(); a++ ){
+ if( progNames[a]==str ){
+ return a;
+ }
+ }
+ return -1;
+}
+
+int sccwriter::get_prog_index_by_expr( Expr* e )
+{
+ for( int a=0; a<(int)progPtrs.size(); a++ ){
+ if( progPtrs[a]==e ){
+ return a;
+ }
+ }
+ return -1;
+}
+
+bool sccwriter::is_var( const std::string& str )
+{
+ for( int a=0; a<(int)vars.size(); a++ ){
+ if( vars[a]==str ){
+ return true;
+ }
+ }
+ return false;
+}
+
+void sccwriter::add_global_sym( const std::string& str )
+{
+ for( int a=0; a<(int)globalSyms.size(); a++ ){
+ if( globalSyms[a]==str ){
+ return;
+ }
+ }
+ globalSyms.push_back( str );
+}
+
+void sccwriter::indent( std::ostream& os, int ind )
+{
+ for( int a=0; a<ind; a++ )
+ {
+ os << " ";
+ }
+}
+
+void sccwriter::write_function_header( std::ostream& os, int index, int opts )
+{
+ //write the function header
+ std::string fname;
+ get_function_name( progNames[index], fname );
+ os << "Expr* " << fname.c_str() << "( ";
+ CExpr* progvars = (CExpr*)get_prog( index )->kids[1];
+ int counter = 0;
+ //write each argument
+ while( progvars->kids[counter] )
+ {
+ if( counter!=0 )
+ {
+ os << ", ";
+ }
+ os << "Expr* ";
+ write_variable( ((SymSExpr*)progvars->kids[counter])->s, os );
+ //add to vars if options are set to do so
+ if( opts&opt_write_add_args )
+ {
+ vars.push_back( ((SymSExpr*)progvars->kids[counter])->s );
+ }
+ counter++;
+ }
+ os << " )";
+ if( opts&opt_write_call_debug )
+ {
+ os << "{" << std::endl;
+ indent( os, 1 );
+ os << "std::cout << \"Call function " << fname.c_str() << " with arguments \";" << std::endl;
+ counter = 0;
+ while( progvars->kids[counter] )
+ {
+ if( counter!=0 )
+ {
+ indent( os, 1 );
+ os << "std::cout << \", \";" << std::endl;
+ }
+ indent( os, 1 );
+ write_variable( ((SymSExpr*)progvars->kids[counter])->s, os );
+ os << "->print( std::cout );" << std::endl;
+ counter++;
+ }
+ indent( os, 1 );
+ os << "std::cout << std::endl;" << std::endl;
+ }
+}
+
+void sccwriter::get_function_name( const std::string& pname, std::string& fname )
+{
+ fname = std::string( "f_" );
+ fname.append( pname );
+}
+
+void sccwriter::write_variable( const std::string& n, std::ostream& os )
+{
+ std::string nn;
+ get_var_name( n, nn );
+ os << nn.c_str();
+}
+
+void sccwriter::get_var_name( const std::string& n, std::string& nn ) {
+ nn = std::string( n.c_str() );
+ for( int i = 0; i <(int)n.length(); i++ ){
+ char c = n[i];
+ if (c <= 47)
+ c += 65;
+ else if (c >= 58 && c <= 64)
+ c += 97-58;
+ if ((c >= 91 && c <= 94) || c == 96)
+ c += 104-91;
+ else if (c >= 123)
+ c -= 4;
+ nn[i] = c;
+ }
+}
+
+void sccwriter::write_file()
+{
+ static std::string filename( "scccode" );
+
+ //writer the h file
+ std::fstream fsh;
+ std::string fnameh( filename );
+ fnameh.append(".h");
+ fsh.open( fnameh.c_str(), std::ios::out );
+ //write the header in h
+ fsh << "#ifndef SCC_CODE_H" << std::endl;
+ fsh << "#define SCC_CODE_H" << std::endl << std::endl;
+ //include necessary files in h file
+ fsh << "#include \"check.h\"" << std::endl << std::endl;
+ //write the init function
+ fsh << "void init_compiled_scc();" << std::endl << std::endl;
+ //write the entry function
+ fsh << "Expr* run_compiled_scc( Expr* p, std::vector< Expr* >& args );" << std::endl << std::endl;
+ //write the side condition code functions
+ for( int n=0; n<(int)progs.size(); n++ )
+ {
+ //write the header in the h file
+ fsh << "inline ";
+ write_function_header( fsh, n );
+ fsh << ";" << std::endl << std::endl;
+ }
+ fsh << "#endif" << std::endl << std::endl;
+ fsh.close();
+
+
+ //writer the cpp code
+ std::fstream fsc;
+ std::string fnamec( filename );
+ fnamec.append(".cpp");
+ fsc.open( fnamec.c_str(), std::ios::out );
+ //include the h file in the cpp
+ fsc << "#include \"scccode.h\"" << std::endl << std::endl;
+ std::ostringstream fsc_funcs;
+ //write the side condition code functions
+ for( currProgram=0; currProgram<(int)progs.size(); currProgram++ )
+ {
+ //reset naming counters
+ vars.clear();
+ exprCount = 0;
+ strCount = 0;
+ argsCount = 0;
+ rnumCount = 0;
+
+ //for debugging
+ std::cout << "program #" << currProgram << " " << progNames[currProgram].c_str() << std::endl;
+
+ //write the function header
+ write_function_header( fsc_funcs, currProgram, opt_write_add_args|options );
+ if( (options&opt_write_call_debug)==0 )
+ {
+ fsc_funcs << "{" << std::endl;
+ }
+ //write the code
+ //std::vector< std::string > cleanVec;
+ //write_code( get_prog( n )->kids[2], fsc, 1, "return ", cleanVec );
+ //debug_write_code( progs[n].second->kids[2], fsc, 1 );
+ std::string expr;
+ write_expr( get_prog( currProgram )->kids[2], fsc_funcs, 1, expr );
+ indent( fsc_funcs, 1 );
+ fsc_funcs << "return " << expr.c_str() << ";" << std::endl;
+ fsc_funcs << "}" << std::endl << std::endl;
+ }
+ //write the predefined symbols necessary - symbols and progs
+ for( int a=0; a<(int)globalSyms.size(); a++ )
+ {
+ fsc << "Expr* e_" << globalSyms[a].c_str() << ";" << std::endl;
+ }
+ for( int a=0; a<(int)progs.size(); a++ )
+ {
+ fsc << "Expr* e_" << progNames[a].c_str() << ";" << std::endl;
+ }
+ fsc << std::endl;
+ //write the init function - initialize symbols and progs
+ fsc << "void init_compiled_scc(){" << std::endl;
+ for( int a=0; a<(int)globalSyms.size(); a++ )
+ {
+ indent( fsc, 1 );
+ fsc << "e_" << globalSyms[a].c_str() << " = symbols->get(\"" << globalSyms[a].c_str() << "\").first;" << std::endl;
+ }
+ for( int a=0; a<(int)progs.size(); a++ )
+ {
+ indent( fsc, 1 );
+ fsc << "e_" << progNames[a].c_str() << " = progs[\"" << progNames[a].c_str() << "\"];" << std::endl;
+ }
+ fsc << "}" << std::endl << std::endl;
+ fsc << "Expr* run_compiled_scc( Expr* p, std::vector< Expr* >& args ){" << std::endl;
+ //for( int n=0; n<(int)progs.size(); n++ ){
+ // indent( fsc, 1 );
+ // fsc << "static std::string s_" << progNames[n].c_str() << " = std::string( \"" << progNames[n].c_str() << "\" );" << std::endl;
+ //}
+ for( int n=0; n<(int)progs.size(); n++ ){
+ indent( fsc, 1 );
+ if( n!=0 ){
+ fsc << "}else ";
+ }
+ //for each function, test to see if the string matches the name of the function
+ fsc << "if( p==e_" << progNames[n].c_str() << " ){" << std::endl;
+ indent( fsc, 2 );
+ std::string fname;
+ get_function_name( progNames[n], fname );
+ //map the function to the proper function
+ fsc << "return " << fname.c_str() << "( ";
+ //write the arguments to the function from args
+ CExpr* progvars = (CExpr*)get_prog( n )->kids[1];
+ int counter = 0;
+ bool firstTime = true;
+ while( progvars->kids[counter] )
+ {
+ if( !firstTime )
+ {
+ fsc << ", ";
+ }
+ fsc << "args[" << counter << "]";
+ firstTime = false;
+ counter++;
+ }
+ fsc << " );" << std::endl;
+ }
+ indent( fsc, 1 );
+ fsc << "}else{" << std::endl;
+ indent( fsc, 2 );
+ //return null in the case the function could not be found
+ fsc << "return NULL;" << std::endl;
+ indent( fsc, 1 );
+ fsc << "}" << std::endl;
+ fsc << "}" << std::endl << std::endl;
+ fsc << fsc_funcs.str().c_str();
+
+ fsc.close();
+}
+
+void sccwriter::write_code( Expr* code, std::ostream& os, int ind, const char* retModStr, int opts )
+{
+ std::string retModString;
+ std::string incString;
+ if ( retModStr )
+ {
+ retModString = std::string( retModStr );
+ retModString.append( " = " );
+ incString = std::string( retModStr );
+ incString.append( "->inc();" );
+ }
+ switch( code->getclass() )
+ {
+ case INT_EXPR:
+ {
+ indent( os, ind );
+ os << retModString.c_str();
+ os << "new IntExpr( " << mpz_get_si( ((IntExpr*)code)->n ) << " );" << std::endl;
+ indent( os, ind );
+ os << incString.c_str() << std::endl;
+ }
+ break;
+ case RAT_EXPR:
+ {
+ mpz_t num, den;
+ mpz_init(num);
+ mpz_init(den);
+ mpq_get_num( num, ((RatExpr*)code)->n );
+ mpq_get_den( den, ((RatExpr*)code)->n );
+ indent( os, ind );
+ os << retModString.c_str();
+ os << "new RatExpr( " << mpz_get_si( num ) << ", " << mpz_get_si( den ) << " );" << std::endl;
+ indent( os, ind );
+ os << incString.c_str() << std::endl;
+ }
+ break;
+ case SYMS_EXPR:
+ {
+ //if it is a variable, simply write it to buffer
+ if( is_var( ((SymSExpr*)code)->s ) )
+ {
+ indent( os, ind );
+ os << retModString.c_str();
+ write_variable( ((SymSExpr*)code)->s.c_str(), os );
+ os << ";" << std::endl;
+ }
+ else //else must look at symbol lookup table
+ {
+ std::string var;
+ get_var_name( ((SymSExpr*)code)->s, var );
+ indent( os, ind );
+ os << retModString.c_str() << "e_" << var.c_str() << ";" << std::endl;
+ add_global_sym( var );
+ }
+ indent( os, ind );
+ os << incString.c_str() << std::endl;
+ }
+ break;
+ default:
+ switch( code->getop() )
+ {
case APP:
{
//collect the arguments
@@ -403,7 +403,7 @@ void sccwriter::write_code( Expr* code, std::ostream& os, int ind, const char* r
//os << expr.c_str() << "->dec();" << std::endl;
}
}
- break;
+ break;
case MATCH:
{
//calculate the value for the expression
@@ -565,13 +565,13 @@ void sccwriter::write_code( Expr* code, std::ostream& os, int ind, const char* r
if( retModStr!=NULL ){
indent( os, ind );
os << retModString.c_str() << expr.c_str() << ";" << std::endl;
- indent( os, ind );
+ indent( os, ind );
os << incString.c_str() << std::endl;
}
write_dec( expr, os, ind );
}
break;
- case IFMARKED:
+ case IFMARKED:
{
//calculate the value for the expression
std::string expr;
@@ -585,10 +585,10 @@ void sccwriter::write_code( Expr* code, std::ostream& os, int ind, const char* r
os << "}else{" << std::endl;
write_code( ((CExpr*)code)->kids[2], os, ind+1, retModStr );
indent( os, ind );
- os << "}" << std::endl;
- //clean up memory
- write_dec( expr, os, ind );
- }
+ os << "}" << std::endl;
+ //clean up memory
+ write_dec( expr, os, ind );
+ }
break;
#else
case MARKVAR:
@@ -612,7 +612,7 @@ void sccwriter::write_code( Expr* code, std::ostream& os, int ind, const char* r
if( retModStr!=NULL ){
indent( os, ind );
os << retModString.c_str() << expr.c_str() << ";" << std::endl;
- indent( os, ind );
+ indent( os, ind );
os << incString.c_str() << std::endl;
}
write_dec( expr, os, ind );
@@ -631,12 +631,12 @@ void sccwriter::write_code( Expr* code, std::ostream& os, int ind, const char* r
write_code( ((CExpr*)code)->kids[3], os, ind+1, retModStr );
indent( os, ind );
os << "}" << std::endl;
- //clean up memory
+ //clean up memory
write_dec( expr1, os, ind );
write_dec( expr2, os, ind );
}
break;
- case IFMARKED:
+ case IFMARKED:
{
//calculate the value for the expression
std::string expr;
@@ -651,10 +651,10 @@ void sccwriter::write_code( Expr* code, std::ostream& os, int ind, const char* r
os << "}else{" << std::endl;
write_code( ((CExpr*)code)->kids[3], os, ind+1, retModStr );
indent( os, ind );
- os << "}" << std::endl;
- //clean up memory
- write_dec( expr, os, ind );
- }
+ os << "}" << std::endl;
+ //clean up memory
+ write_dec( expr, os, ind );
+ }
break;
#endif
case ADD:
@@ -709,8 +709,8 @@ void sccwriter::write_code( Expr* code, std::ostream& os, int ind, const char* r
write_dec( expr2, os, ind );
}
break;
- case NEG:
- {
+ case NEG:
+ {
//calculate the value for the first expression
std::string expr1;
write_expr( ((CExpr*)code)->kids[0], os, ind, expr1 );
@@ -726,9 +726,9 @@ void sccwriter::write_code( Expr* code, std::ostream& os, int ind, const char* r
indent( os, ind+1 );
os << "mpz_neg( " << ss.str().c_str() << ", ((IntExpr*)" << expr1.c_str() << "->followDefs())->n );" << std::endl;
indent( os, ind+1 );
- os << retModString.c_str() << "new IntExpr(" << ss.str().c_str() << ");" << std::endl;
+ os << retModString.c_str() << "new IntExpr(" << ss.str().c_str() << ");" << std::endl;
indent( os, ind );
- os << "}else if( " << expr1.c_str() << "->followDefs()->getclass()==RAT_EXPR ){" << std::endl;
+ os << "}else if( " << expr1.c_str() << "->followDefs()->getclass()==RAT_EXPR ){" << std::endl;
indent( os, ind+1 );
os << "mpq_t " << ss.str().c_str() << ";" << std::endl;
indent( os, ind+1 );
@@ -736,55 +736,55 @@ void sccwriter::write_code( Expr* code, std::ostream& os, int ind, const char* r
indent( os, ind+1 );
os << "mpq_neg( " << ss.str().c_str() << ", ((RatExpr*)" << expr1.c_str() << "->followDefs())->n );" << std::endl;
indent( os, ind+1 );
- os << retModString.c_str() << "new RatExpr(" << ss.str().c_str() << ");" << std::endl;
+ os << retModString.c_str() << "new RatExpr(" << ss.str().c_str() << ");" << std::endl;
indent( os, ind );
- os << "}" << std::endl;
- //clean up memory
- write_dec( expr1, os, ind );
- }
- break;
- case IFNEG:
- case IFZERO:
- {
+ os << "}" << std::endl;
+ //clean up memory
+ write_dec( expr1, os, ind );
+ }
+ break;
+ case IFNEG:
+ case IFZERO:
+ {
std::string expr1;
- write_expr( ((CExpr*)code)->kids[0], os, ind, expr1 );
+ write_expr( ((CExpr*)code)->kids[0], os, ind, expr1 );
indent( os, ind );
- os << "if( " << expr1.c_str() << "->followDefs()->getclass()==INT_EXPR ){" << std::endl;
- indent( os, ind+1 );
- os << "if( mpz_sgn( ((IntExpr *)" << expr1.c_str() << "->followDefs())->n ) ";
- if( code->getop()==IFNEG )
- os << "<";
- else
- os << "==";
- os << " 0 ){" << std::endl;
- write_code( ((CExpr*)code)->kids[1], os, ind+2, retModStr );
- indent( os, ind+1 );
- os << "}else{" << std::endl;
- write_code( ((CExpr*)code)->kids[2], os, ind+2, retModStr );
- indent( os, ind+1 );
- os << "}" << std::endl;
+ os << "if( " << expr1.c_str() << "->followDefs()->getclass()==INT_EXPR ){" << std::endl;
+ indent( os, ind+1 );
+ os << "if( mpz_sgn( ((IntExpr *)" << expr1.c_str() << "->followDefs())->n ) ";
+ if( code->getop()==IFNEG )
+ os << "<";
+ else
+ os << "==";
+ os << " 0 ){" << std::endl;
+ write_code( ((CExpr*)code)->kids[1], os, ind+2, retModStr );
+ indent( os, ind+1 );
+ os << "}else{" << std::endl;
+ write_code( ((CExpr*)code)->kids[2], os, ind+2, retModStr );
+ indent( os, ind+1 );
+ os << "}" << std::endl;
indent( os, ind );
- os << "}else if( " << expr1.c_str() << "->followDefs()->getclass()==RAT_EXPR ){" << std::endl;
- indent( os, ind+1 );
- os << "if( mpq_sgn( ((RatExpr *)" << expr1.c_str() << "->followDefs())->n ) ";
- if( code->getop()==IFNEG )
- os << "<";
- else
- os << "==";
- os << " 0 ){" << std::endl;
- write_code( ((CExpr*)code)->kids[1], os, ind+2, retModStr );
- indent( os, ind+1 );
- os << "}else{" << std::endl;
- write_code( ((CExpr*)code)->kids[2], os, ind+2, retModStr );
- indent( os, ind+1 );
- os << "}" << std::endl;
+ os << "}else if( " << expr1.c_str() << "->followDefs()->getclass()==RAT_EXPR ){" << std::endl;
+ indent( os, ind+1 );
+ os << "if( mpq_sgn( ((RatExpr *)" << expr1.c_str() << "->followDefs())->n ) ";
+ if( code->getop()==IFNEG )
+ os << "<";
+ else
+ os << "==";
+ os << " 0 ){" << std::endl;
+ write_code( ((CExpr*)code)->kids[1], os, ind+2, retModStr );
+ indent( os, ind+1 );
+ os << "}else{" << std::endl;
+ write_code( ((CExpr*)code)->kids[2], os, ind+2, retModStr );
+ indent( os, ind+1 );
+ os << "}" << std::endl;
indent( os, ind );
- os << "}" << std::endl;
- //clean up memory
- write_dec( expr1, os, ind );
- }
- break;
- case RUN:/*?*/break;
+ os << "}" << std::endl;
+ //clean up memory
+ write_dec( expr1, os, ind );
+ }
+ break;
+ case RUN:/*?*/break;
case PI:/*?*/break;
case LAM:/*?*/break;
case TYPE:/*?*/break;
@@ -793,16 +793,16 @@ void sccwriter::write_code( Expr* code, std::ostream& os, int ind, const char* r
case MPZ:/*?*/break;
case PROG:/*?*/break;
case PROGVARS:/*?*/break;
- case PAT:/*?*/break;
- }
- break;
- }
-}
-
-void sccwriter::write_args( CExpr* code, std::ostream& os, int ind, int childCounter,
- std::vector< std::string >& args, int opts )
-{
- bool encounterCase = false;
+ case PAT:/*?*/break;
+ }
+ break;
+ }
+}
+
+void sccwriter::write_args( CExpr* code, std::ostream& os, int ind, int childCounter,
+ std::vector< std::string >& args, int opts )
+{
+ bool encounterCase = false;
while( code->kids[childCounter] &&
(!encounterCase || code->kids[childCounter]->getop()==CASE ) )
{
@@ -819,68 +819,68 @@ void sccwriter::write_args( CExpr* code, std::ostream& os, int ind, int childCou
args.push_back( expr );
}
childCounter++;
- }
-}
-
-void sccwriter::write_expr( Expr* code, std::ostream& os, int ind, std::string& expr, int opts )
-{
- if( code->getclass()==SYMS_EXPR && is_var( ((SymSExpr*)code)->s ) )
- {
- get_var_name( ((SymSExpr*)code)->s, expr );
- indent( os, ind );
- os << expr.c_str() << "->inc();" << std::endl;
- }
- else
- {
+ }
+}
+
+void sccwriter::write_expr( Expr* code, std::ostream& os, int ind, std::string& expr, int opts )
+{
+ if( code->getclass()==SYMS_EXPR && is_var( ((SymSExpr*)code)->s ) )
+ {
+ get_var_name( ((SymSExpr*)code)->s, expr );
+ indent( os, ind );
+ os << expr.c_str() << "->inc();" << std::endl;
+ }
+ else
+ {
std::ostringstream ss;
ss << "e" << exprCount;
- exprCount++;
- //declare the expression
- indent( os, ind );
- if( code->getclass()==SYMS_EXPR && !is_var( ((SymSExpr*)code)->s ) )
- {
- os << "static ";
- }
- os << "Expr* " << ss.str().c_str() << ";" << std::endl;
- //write the expression
+ exprCount++;
+ //declare the expression
+ indent( os, ind );
+ if( code->getclass()==SYMS_EXPR && !is_var( ((SymSExpr*)code)->s ) )
+ {
+ os << "static ";
+ }
+ os << "Expr* " << ss.str().c_str() << ";" << std::endl;
+ //write the expression
std::ostringstream ss2;
ss2 << ss.str().c_str();
- write_code( code, os, ind, ss2.str().c_str(), opts );
-
- //if is not a sym expression, then decrement the expression and return null
- if( opts&opt_write_check_sym_expr )
+ write_code( code, os, ind, ss2.str().c_str(), opts );
+
+ //if is not a sym expression, then decrement the expression and return null
+ if( opts&opt_write_check_sym_expr )
{
indent( os, ind );
os << "if (" << expr.c_str() << "->getclass() != SYM_EXPR) {" << std::endl;
indent( os, ind+1 );
os << "exit( 1 );" << std::endl;
indent( os, ind );
- os << "}" << std::endl;
- }
-
- expr = std::string( ss.str().c_str() );
- vars.push_back( expr );
- }
- //increment the counter for memory management
- //indent( os, ind );
- //os << expr.c_str() << "->inc();" << std::endl;
-}
-
-void sccwriter::write_dec( const std::string& expr, std::ostream& os, int ind )
-{
- bool wd = true;
- if( wd )
- {
- indent( os, ind );
- os << expr.c_str() << "->dec();" << std::endl;
- }
-}
-
-void sccwriter::debug_write_code( Expr* code, std::ostream& os, int ind )
-{
- indent( os, ind );
- switch( code->getclass() )
- {
+ os << "}" << std::endl;
+ }
+
+ expr = std::string( ss.str().c_str() );
+ vars.push_back( expr );
+ }
+ //increment the counter for memory management
+ //indent( os, ind );
+ //os << expr.c_str() << "->inc();" << std::endl;
+}
+
+void sccwriter::write_dec( const std::string& expr, std::ostream& os, int ind )
+{
+ bool wd = true;
+ if( wd )
+ {
+ indent( os, ind );
+ os << expr.c_str() << "->dec();" << std::endl;
+ }
+}
+
+void sccwriter::debug_write_code( Expr* code, std::ostream& os, int ind )
+{
+ indent( os, ind );
+ switch( code->getclass() )
+ {
case INT_EXPR:
os << "int_expr";
break;
@@ -890,12 +890,12 @@ void sccwriter::debug_write_code( Expr* code, std::ostream& os, int ind )
case SYM_EXPR:
os << "sym_expr";
break;
- case SYMS_EXPR:
- os << "syms_expr: " << ((SymSExpr*)code)->s.c_str();
- break;
- default:
- switch( code->getop() )
- {
+ case SYMS_EXPR:
+ os << "syms_expr: " << ((SymSExpr*)code)->s.c_str();
+ break;
+ default:
+ switch( code->getop() )
+ {
case APP:
os << "app";
break;
@@ -920,9 +920,9 @@ void sccwriter::debug_write_code( Expr* code, std::ostream& os, int ind )
case PROG:
os << "prog";
break;
- case PROGVARS:
- os << "progvars";
- break;
+ case PROGVARS:
+ os << "progvars";
+ break;
case MATCH:
os << "match";
break;
@@ -953,25 +953,25 @@ void sccwriter::debug_write_code( Expr* code, std::ostream& os, int ind )
case MARKVAR:
os << "markvar";
break;
- case IFMARKED:
- os << "ifmarked";
- break;
- case COMPARE:
- os << "compare";
- break;
- default:
- os << "???";
- break;
- }
- }
- os << std::endl;
- if( code->getop()!=0 )
- {
- CExpr* ce = (CExpr*)code;
- int counter = 0;
- while( ce->kids[counter] ){
- debug_write_code( ce->kids[counter], os, ind+1 );
- counter++;
- }
- }
-}
+ case IFMARKED:
+ os << "ifmarked";
+ break;
+ case COMPARE:
+ os << "compare";
+ break;
+ default:
+ os << "???";
+ break;
+ }
+ }
+ os << std::endl;
+ if( code->getop()!=0 )
+ {
+ CExpr* ce = (CExpr*)code;
+ int counter = 0;
+ while( ce->kids[counter] ){
+ debug_write_code( ce->kids[counter], os, ind+1 );
+ counter++;
+ }
+ }
+}
diff --git a/proofs/lfsc_checker/sccwriter.h b/proofs/lfsc_checker/sccwriter.h
index f8922934f..bd9732579 100644
--- a/proofs/lfsc_checker/sccwriter.h
+++ b/proofs/lfsc_checker/sccwriter.h
@@ -1,86 +1,86 @@
-#ifndef SCC_WRITER_H
-#define SCC_WRITER_H
-
-#include "expr.h"
-#include <vector>
-#include "check.h"
-
-enum
-{
- opt_write_case_body = 0x00000001,
- opt_write_check_sym_expr = 0x00000002,
- opt_write_add_args = 0x000000004,
- opt_write_no_inc = 0x00000008,
-
- opt_write_call_debug = 0x00000010,
- opt_write_nested_app = 0x00000020,
-};
-
-class sccwriter
-{
-private:
- //options
- int options;
- //programs to write to file
- symmap progs;
- //list of indicies in progs
- std::vector< Expr* > progPtrs;
- std::vector< std::string > progNames;
- int currProgram;
- //current variables in the scope
- std::vector< std::string > vars;
- //global variables stored for lookups
- std::vector< std::string > globalSyms;
- //symbols that must be dec'ed
- std::vector< std::string > decSyms;
- //get program
- CExpr* get_prog( int n ) { return (CExpr*)progs[ progNames[n] ]; }
- //get index for string
- int get_prog_index_by_expr( Expr* e );
- int get_prog_index( const std::string& str );
- //is variable in current scope
- bool is_var( const std::string& str );
- //add global sym
- void add_global_sym( const std::string& str );
- //expression count
- static int exprCount;
- //string count
- static int strCount;
- //args count
- static int argsCount;
- //num count
- static int rnumCount;
- //indent
- static void indent( std::ostream& os, int ind );
- //write function header
- void write_function_header( std::ostream& os, int index, int opts = 0 );
- void write_code( Expr* code, std::ostream& os, int ind, const char* retModStr, int opts = 0 );
- //write all children starting at child counter to stream, store in Expr* e_...e_;
- void write_args( CExpr* code, std::ostream& os, int ind, int childCounter, std::vector< std::string >& args, int opts = 0 );
- //write expression - store result of code into e_ for some Expr* e_;
- void write_expr( Expr* code, std::ostream& os, int ind, std::string& expr, int opts = 0 );
- //write variable
- void write_variable( const std::string& n, std::ostream& os );
- //get function name
- void get_function_name( const std::string& pname, std::string& fname );
- //get the variable name
- void get_var_name( const std::string& n, std::string& nn );
- //write dec
- void write_dec( const std::string& expr, std::ostream& os, int ind );
-public:
- sccwriter( int opts = 0 ) : options( opts ){}
- virtual ~sccwriter(){}
-
- void add_scc( const std::string& pname, Expr* exp ) {
- //progs.push_back( std::pair< std::string, CExpr* >( pname, exp ) );
- progs[pname] = exp;
- progPtrs.push_back( exp );
- progNames.push_back( pname );
- }
-
- void write_file();
- //write code
- static void debug_write_code( Expr* code, std::ostream& os, int ind );
-};
-
-#endif
+#ifndef SCC_WRITER_H
+#define SCC_WRITER_H
+
+#include "expr.h"
+#include <vector>
+#include "check.h"
+
+enum
+{
+ opt_write_case_body = 0x00000001,
+ opt_write_check_sym_expr = 0x00000002,
+ opt_write_add_args = 0x000000004,
+ opt_write_no_inc = 0x00000008,
+
+ opt_write_call_debug = 0x00000010,
+ opt_write_nested_app = 0x00000020,
+};
+
+class sccwriter
+{
+private:
+ //options
+ int options;
+ //programs to write to file
+ symmap progs;
+ //list of indicies in progs
+ std::vector< Expr* > progPtrs;
+ std::vector< std::string > progNames;
+ int currProgram;
+ //current variables in the scope
+ std::vector< std::string > vars;
+ //global variables stored for lookups
+ std::vector< std::string > globalSyms;
+ //symbols that must be dec'ed
+ std::vector< std::string > decSyms;
+ //get program
+ CExpr* get_prog( int n ) { return (CExpr*)progs[ progNames[n] ]; }
+ //get index for string
+ int get_prog_index_by_expr( Expr* e );
+ int get_prog_index( const std::string& str );
+ //is variable in current scope
+ bool is_var( const std::string& str );
+ //add global sym
+ void add_global_sym( const std::string& str );
+ //expression count
+ static int exprCount;
+ //string count
+ static int strCount;
+ //args count
+ static int argsCount;
+ //num count
+ static int rnumCount;
+ //indent
+ static void indent( std::ostream& os, int ind );
+ //write function header
+ void write_function_header( std::ostream& os, int index, int opts = 0 );
+ void write_code( Expr* code, std::ostream& os, int ind, const char* retModStr, int opts = 0 );
+ //write all children starting at child counter to stream, store in Expr* e_...e_;
+ void write_args( CExpr* code, std::ostream& os, int ind, int childCounter, std::vector< std::string >& args, int opts = 0 );
+ //write expression - store result of code into e_ for some Expr* e_;
+ void write_expr( Expr* code, std::ostream& os, int ind, std::string& expr, int opts = 0 );
+ //write variable
+ void write_variable( const std::string& n, std::ostream& os );
+ //get function name
+ void get_function_name( const std::string& pname, std::string& fname );
+ //get the variable name
+ void get_var_name( const std::string& n, std::string& nn );
+ //write dec
+ void write_dec( const std::string& expr, std::ostream& os, int ind );
+public:
+ sccwriter( int opts = 0 ) : options( opts ){}
+ virtual ~sccwriter(){}
+
+ void add_scc( const std::string& pname, Expr* exp ) {
+ //progs.push_back( std::pair< std::string, CExpr* >( pname, exp ) );
+ progs[pname] = exp;
+ progPtrs.push_back( exp );
+ progNames.push_back( pname );
+ }
+
+ void write_file();
+ //write code
+ static void debug_write_code( Expr* code, std::ostream& os, int ind );
+};
+
+#endif
diff --git a/proofs/signatures/ex_bv.plf b/proofs/signatures/ex_bv.plf
index 02cadaeab..ae585e455 100755
--- a/proofs/signatures/ex_bv.plf
+++ b/proofs/signatures/ex_bv.plf
@@ -1,57 +1,57 @@
-; a = b ^ a = 00000 ^ b = 11111 is UNSAT
-
-(check
-(% a var_bv
-(% b var_bv
-(% f1 (th_holds (= BitVec (a_var_bv a) (a_var_bv b)))
-(% f2 (th_holds (= BitVec (a_var_bv a) (a_bv (bvc b0 (bvc b0 (bvc b0 (bvc b0 (bvc b0 bvn))))))))
-(% f3 (th_holds (= BitVec (a_var_bv b) (a_bv (bvc b1 (bvc b1 (bvc b1 (bvc b1 (bvc b1 bvn))))))))
-(: (holds cln)
-
-(decl_bv_atom_var 5 a (\ ba1
-(decl_bv_atom_var 5 b (\ ba2
-(decl_bv_atom_const _ (bvc b0 (bvc b0 (bvc b0 (bvc b0 (bvc b0 bvn))))) (\ c (\ ba3
-(decl_bv_atom_const _ (bvc b1 (bvc b1 (bvc b1 (bvc b1 (bvc b1 bvn))))) (\ d (\ ba4
-
-(decl_atom (bblast a 4) (\ v1 (\ a1
-(decl_atom (bblast b 4) (\ v2 (\ a2
-
-; bitblasting terms
-(th_let_pf _ (bv_bbl_var _ _ _ ba1) (\ bt1
-(th_let_pf _ (bv_bbl_var _ _ _ ba2) (\ bt2
-(th_let_pf _ (bv_bbl_const _ _ _ _ ba3) (\ bt3
-(th_let_pf _ (bv_bbl_const _ _ _ _ ba4) (\ bt4
-
-; bitblasting formulas
-(th_let_pf _ (bv_bbl_eq _ _ _ _ _ bt1 bt2) (\ bf1
-(th_let_pf _ (bv_bbl_eq _ _ _ _ _ bt1 bt3) (\ bf2
-(th_let_pf _ (bv_bbl_eq _ _ _ _ _ bt2 bt4) (\ bf3
-
-; CNFication
-; a.4 V ~b.4
-(satlem _ _
-(asf _ _ _ a1 (\ l1
-(ast _ _ _ a2 (\ l2
-(clausify_false
- (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
-))))) (\ C2
-
-; ~a.4
-(satlem _ _
-(ast _ _ _ a1 (\ l1
-(clausify_false
- (impl_elim _ _ l1 (iff_elim_1 _ _ (and_elim_1 _ _ (impl_elim _ _ f2 bf2))))
-))) (\ C3
-
-; b.4
-(satlem _ _
-(asf _ _ _ a2 (\ l2
-(clausify_false
- (contra _ (impl_elim _ _ truth (iff_elim_2 _ _ (and_elim_1 _ _ (impl_elim _ _ f3 bf3)))) l2)
-))) (\ C6
-
-
-(satlem_simplify _ _ _
-(R _ _ (R _ _ C6 C2 v2) C3 v1) (\ x x))
-
+; a = b ^ a = 00000 ^ b = 11111 is UNSAT
+
+(check
+(% a var_bv
+(% b var_bv
+(% f1 (th_holds (= BitVec (a_var_bv a) (a_var_bv b)))
+(% f2 (th_holds (= BitVec (a_var_bv a) (a_bv (bvc b0 (bvc b0 (bvc b0 (bvc b0 (bvc b0 bvn))))))))
+(% f3 (th_holds (= BitVec (a_var_bv b) (a_bv (bvc b1 (bvc b1 (bvc b1 (bvc b1 (bvc b1 bvn))))))))
+(: (holds cln)
+
+(decl_bv_atom_var 5 a (\ ba1
+(decl_bv_atom_var 5 b (\ ba2
+(decl_bv_atom_const _ (bvc b0 (bvc b0 (bvc b0 (bvc b0 (bvc b0 bvn))))) (\ c (\ ba3
+(decl_bv_atom_const _ (bvc b1 (bvc b1 (bvc b1 (bvc b1 (bvc b1 bvn))))) (\ d (\ ba4
+
+(decl_atom (bblast a 4) (\ v1 (\ a1
+(decl_atom (bblast b 4) (\ v2 (\ a2
+
+; bitblasting terms
+(th_let_pf _ (bv_bbl_var _ _ _ ba1) (\ bt1
+(th_let_pf _ (bv_bbl_var _ _ _ ba2) (\ bt2
+(th_let_pf _ (bv_bbl_const _ _ _ _ ba3) (\ bt3
+(th_let_pf _ (bv_bbl_const _ _ _ _ ba4) (\ bt4
+
+; bitblasting formulas
+(th_let_pf _ (bv_bbl_eq _ _ _ _ _ bt1 bt2) (\ bf1
+(th_let_pf _ (bv_bbl_eq _ _ _ _ _ bt1 bt3) (\ bf2
+(th_let_pf _ (bv_bbl_eq _ _ _ _ _ bt2 bt4) (\ bf3
+
+; CNFication
+; a.4 V ~b.4
+(satlem _ _
+(asf _ _ _ a1 (\ l1
+(ast _ _ _ a2 (\ l2
+(clausify_false
+ (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
+))))) (\ C2
+
+; ~a.4
+(satlem _ _
+(ast _ _ _ a1 (\ l1
+(clausify_false
+ (impl_elim _ _ l1 (iff_elim_1 _ _ (and_elim_1 _ _ (impl_elim _ _ f2 bf2))))
+))) (\ C3
+
+; b.4
+(satlem _ _
+(asf _ _ _ a2 (\ l2
+(clausify_false
+ (contra _ (impl_elim _ _ truth (iff_elim_2 _ _ (and_elim_1 _ _ (impl_elim _ _ f3 bf3)))) l2)
+))) (\ C6
+
+
+(satlem_simplify _ _ _
+(R _ _ (R _ _ C6 C2 v2) C3 v1) (\ x x))
+
))))))))))))))))))))))))))))))))))))))))))) \ No newline at end of file
diff --git a/proofs/signatures/th_bv.plf b/proofs/signatures/th_bv.plf
index 3fb9d1356..0fb50f8cf 100755
--- a/proofs/signatures/th_bv.plf
+++ b/proofs/signatures/th_bv.plf
@@ -1,145 +1,145 @@
-; "bitvec" is a term of type "sort"
-(declare BitVec sort)
-
-; bit type
-(declare bit type)
-(declare b0 bit)
-(declare b1 bit)
-
-; bit vector type
-(declare bv type)
-(declare bvn bv)
-(declare bvc (! b bit (! v bv bv)))
-; a bv constant term
-(declare a_bv (! v bv (term BitVec)))
-
-; calculate the length of a bitvector
-(program bv_len ((v bv)) mpz
- (match v
- (bvn 0)
- ((bvc b v') (mp_add (bv_len v') 1))))
-
-; a bv variable
-(declare var_bv type)
-; a bv variable term
-(declare a_var_bv (! v var_bv (term BitVec)))
-
-
-; bit vector operators
-(define bvoper (! x (term BitVec)
- (! y (term BitVec)
- (term BitVec))))
-(declare bvand bvoper)
-(declare bvadd bvoper)
-;....
-
-; all bit-vector terms are mapped with "bv_atom" to:
-; - a simply-typed term of type "var_bv", which is necessary for bit-blasting
-; - a integer size
-(declare bv_atom (! x (term BitVec) (! y var_bv (! n mpz type))))
-
-(declare decl_bv_atom_var (! n mpz ; must be specified
- (! x var_bv
- (! p (! u (bv_atom (a_var_bv x) x n)
- (holds cln))
- (holds cln)))))
-
-(declare decl_bv_atom_const (! n mpz
- (! v bv
- (! s (^ (bv_len v) n)
- (! p (! w var_bv
- (! u (bv_atom (a_bv v) w n)
- (holds cln)))
- (holds cln))))))
-
-
-; other terms here?
-
-
-; bit blasted terms
-(declare bblt type)
-(declare bbltn bblt)
-(declare bbltc (! f formula (! v bblt bblt)))
-
-; (bblast_term x y) means term x corresponds to bit level interpretation y
-(declare bblast_term (! x (term BitVec) (! y bblt formula)))
-
-; a predicate to represent the n^th bit of a bitvector term
-(declare bblast (! x var_bv (! n mpz formula)))
-
-
-; bit blast constant
-(program bblast_const ((v bv) (n mpz)) bblt
- (mp_ifneg n (match v (bvn bbltn)
- (default (fail bblt)))
- (match v ((bvc b v') (bbltc (match b (b0 false) (b1 true)) (bblast_const v' (mp_add n (~ 1)))))
- (default (fail bblt)))))
-
-(declare bv_bbl_const (! n mpz
- (! v bv
- (! x var_bv
- (! f bblt
- (! u (bv_atom (a_bv v) x n)
- (! c (^ (bblast_const v (mp_add n (~ 1))) f)
- (th_holds (bblast_term (a_bv v) f)))))))))
-
-; bit blast variable
-(program bblast_var ((x var_bv) (n mpz)) bblt
- (mp_ifneg n bbltn
- (bbltc (bblast x n) (bblast_var x (mp_add n (~ 1))))))
-
-(declare bv_bbl_var (! n mpz
- (! x var_bv
- (! f bblt
- (! u (bv_atom (a_var_bv x) x n)
- (! c (^ (bblast_var x (mp_add n (~ 1))) f)
- (th_holds (bblast_term (a_var_bv x) f))))))))
-
-; bit blast x = y
-; for x,y of size n, it will return a conjuction (x.{n-1} = y.{n-1} ^ ( ... ^ (x.0 = y.0 ^ true)))
-(program bblast_eq ((x bblt) (y bblt)) formula
- (match x
- (bbltn (match y (bbltn true) (default (fail formula))))
- ((bbltc fx x') (match y
- (bbltn (fail formula))
- ((bbltc fy y') (and (iff fx fy) (bblast_eq x' y')))))))
-
-(declare bv_bbl_eq (! x (term BitVec)
- (! y (term BitVec)
- (! fx bblt
- (! fy bblt
- (! f formula
- (! ux (th_holds (bblast_term x fx))
- (! uy (th_holds (bblast_term y fy))
- (! c (^ (bblast_eq fx fy) f)
- (th_holds (impl (= BitVec x y) f)))))))))))
-
-
-; rewrite rule :
-; x + y = y + x
-(declare bvadd_symm (! x (term BitVec)
- (! y (term BitVec)
- (! x' var_bv
- (! y' var_bv
- (! n mpz
- (! ux (bv_atom x x' n)
- (! uy (bv_atom y y' n)
- (th_holds (= BitVec (bvadd x y) (bvadd y x)))))))))))
-
-
-
-; necessary?
-(program calc_bvand ((a bv) (b bv)) bv
- (match a
- (bvn (match b (bvn bvn) (default (fail bv))))
- ((bvc ba a') (match b
- ((bvc bb b') (bvc (match ba (b0 b0) (b1 bb)) (calc_bvand a' b')))
- (default (fail bv))))))
-
-; rewrite rule (w constants) :
-; a & b = c
-(declare bvand_const (! c bv
- (! a bv
- (! b bv
- (! u (^ (calc_bvand a b) c)
+; "bitvec" is a term of type "sort"
+(declare BitVec sort)
+
+; bit type
+(declare bit type)
+(declare b0 bit)
+(declare b1 bit)
+
+; bit vector type
+(declare bv type)
+(declare bvn bv)
+(declare bvc (! b bit (! v bv bv)))
+; a bv constant term
+(declare a_bv (! v bv (term BitVec)))
+
+; calculate the length of a bitvector
+(program bv_len ((v bv)) mpz
+ (match v
+ (bvn 0)
+ ((bvc b v') (mp_add (bv_len v') 1))))
+
+; a bv variable
+(declare var_bv type)
+; a bv variable term
+(declare a_var_bv (! v var_bv (term BitVec)))
+
+
+; bit vector operators
+(define bvoper (! x (term BitVec)
+ (! y (term BitVec)
+ (term BitVec))))
+(declare bvand bvoper)
+(declare bvadd bvoper)
+;....
+
+; all bit-vector terms are mapped with "bv_atom" to:
+; - a simply-typed term of type "var_bv", which is necessary for bit-blasting
+; - a integer size
+(declare bv_atom (! x (term BitVec) (! y var_bv (! n mpz type))))
+
+(declare decl_bv_atom_var (! n mpz ; must be specified
+ (! x var_bv
+ (! p (! u (bv_atom (a_var_bv x) x n)
+ (holds cln))
+ (holds cln)))))
+
+(declare decl_bv_atom_const (! n mpz
+ (! v bv
+ (! s (^ (bv_len v) n)
+ (! p (! w var_bv
+ (! u (bv_atom (a_bv v) w n)
+ (holds cln)))
+ (holds cln))))))
+
+
+; other terms here?
+
+
+; bit blasted terms
+(declare bblt type)
+(declare bbltn bblt)
+(declare bbltc (! f formula (! v bblt bblt)))
+
+; (bblast_term x y) means term x corresponds to bit level interpretation y
+(declare bblast_term (! x (term BitVec) (! y bblt formula)))
+
+; a predicate to represent the n^th bit of a bitvector term
+(declare bblast (! x var_bv (! n mpz formula)))
+
+
+; bit blast constant
+(program bblast_const ((v bv) (n mpz)) bblt
+ (mp_ifneg n (match v (bvn bbltn)
+ (default (fail bblt)))
+ (match v ((bvc b v') (bbltc (match b (b0 false) (b1 true)) (bblast_const v' (mp_add n (~ 1)))))
+ (default (fail bblt)))))
+
+(declare bv_bbl_const (! n mpz
+ (! v bv
+ (! x var_bv
+ (! f bblt
+ (! u (bv_atom (a_bv v) x n)
+ (! c (^ (bblast_const v (mp_add n (~ 1))) f)
+ (th_holds (bblast_term (a_bv v) f)))))))))
+
+; bit blast variable
+(program bblast_var ((x var_bv) (n mpz)) bblt
+ (mp_ifneg n bbltn
+ (bbltc (bblast x n) (bblast_var x (mp_add n (~ 1))))))
+
+(declare bv_bbl_var (! n mpz
+ (! x var_bv
+ (! f bblt
+ (! u (bv_atom (a_var_bv x) x n)
+ (! c (^ (bblast_var x (mp_add n (~ 1))) f)
+ (th_holds (bblast_term (a_var_bv x) f))))))))
+
+; bit blast x = y
+; for x,y of size n, it will return a conjuction (x.{n-1} = y.{n-1} ^ ( ... ^ (x.0 = y.0 ^ true)))
+(program bblast_eq ((x bblt) (y bblt)) formula
+ (match x
+ (bbltn (match y (bbltn true) (default (fail formula))))
+ ((bbltc fx x') (match y
+ (bbltn (fail formula))
+ ((bbltc fy y') (and (iff fx fy) (bblast_eq x' y')))))))
+
+(declare bv_bbl_eq (! x (term BitVec)
+ (! y (term BitVec)
+ (! fx bblt
+ (! fy bblt
+ (! f formula
+ (! ux (th_holds (bblast_term x fx))
+ (! uy (th_holds (bblast_term y fy))
+ (! c (^ (bblast_eq fx fy) f)
+ (th_holds (impl (= BitVec x y) f)))))))))))
+
+
+; rewrite rule :
+; x + y = y + x
+(declare bvadd_symm (! x (term BitVec)
+ (! y (term BitVec)
+ (! x' var_bv
+ (! y' var_bv
+ (! n mpz
+ (! ux (bv_atom x x' n)
+ (! uy (bv_atom y y' n)
+ (th_holds (= BitVec (bvadd x y) (bvadd y x)))))))))))
+
+
+
+; necessary?
+(program calc_bvand ((a bv) (b bv)) bv
+ (match a
+ (bvn (match b (bvn bvn) (default (fail bv))))
+ ((bvc ba a') (match b
+ ((bvc bb b') (bvc (match ba (b0 b0) (b1 bb)) (calc_bvand a' b')))
+ (default (fail bv))))))
+
+; rewrite rule (w constants) :
+; a & b = c
+(declare bvand_const (! c bv
+ (! a bv
+ (! b bv
+ (! u (^ (calc_bvand a b) c)
(th_holds (= BitVec (bvand (a_bv a) (a_bv b)) (a_bv c)))))))) \ No newline at end of file
diff --git a/src/theory/quantifiers/conjecture_generator.cpp b/src/theory/quantifiers/conjecture_generator.cpp
index 116debb7c..4167c3ad9 100644
--- a/src/theory/quantifiers/conjecture_generator.cpp
+++ b/src/theory/quantifiers/conjecture_generator.cpp
@@ -1,2180 +1,2180 @@
-/********************* */
-/*! \file conjecture_generator.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 conjecture generator class
- **
- **/
-
-#include "theory/quantifiers/conjecture_generator.h"
-#include "theory/theory_engine.h"
-#include "theory/quantifiers/options.h"
-#include "theory/quantifiers/term_database.h"
-#include "theory/quantifiers/trigger.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 {
-
-struct sortConjectureScore {
- std::vector< int > d_scores;
- bool operator() (unsigned i, unsigned j) { return d_scores[i]>d_scores[j]; }
-};
-
-
-void OpArgIndex::addTerm( ConjectureGenerator * s, TNode n, unsigned index ){
- if( index==n.getNumChildren() ){
- Assert( n.hasOperator() );
- if( std::find( d_ops.begin(), d_ops.end(), n.getOperator() )==d_ops.end() ){
- d_ops.push_back( n.getOperator() );
- d_op_terms.push_back( n );
- }
- }else{
- d_child[s->getTermDatabase()->d_arg_reps[n][index]].addTerm( s, n, index+1 );
- }
-}
-
-Node OpArgIndex::getGroundTerm( ConjectureGenerator * s, std::vector< TNode >& args ) {
- if( d_ops.empty() ){
- for( std::map< TNode, OpArgIndex >::iterator it = d_child.begin(); it != d_child.end(); ++it ){
- std::map< TNode, Node >::iterator itf = s->d_ground_eqc_map.find( it->first );
- if( itf!=s->d_ground_eqc_map.end() ){
- args.push_back( itf->second );
- Node n = it->second.getGroundTerm( s, args );
- args.pop_back();
- if( !n.isNull() ){
- return n;
- }
- }
- }
- return Node::null();
- }else{
- std::vector< TNode > args2;
- args2.push_back( d_ops[0] );
- args2.insert( args2.end(), args.begin(), args.end() );
- return NodeManager::currentNM()->mkNode( d_op_terms[0].getKind(), args2 );
- }
-}
-
-void OpArgIndex::getGroundTerms( ConjectureGenerator * s, std::vector< TNode >& terms ) {
- terms.insert( terms.end(), d_op_terms.begin(), d_op_terms.end() );
- for( std::map< TNode, OpArgIndex >::iterator it = d_child.begin(); it != d_child.end(); ++it ){
- if( s->isGroundEqc( it->first ) ){
- it->second.getGroundTerms( s, terms );
- }
- }
-}
-
-
-
-ConjectureGenerator::ConjectureGenerator( QuantifiersEngine * qe, context::Context* c ) : QuantifiersModule( qe ),
-d_notify( *this ),
-d_uequalityEngine(d_notify, c, "ConjectureGenerator::ee", false),
-d_ee_conjectures( c ){
- d_fullEffortCount = 0;
- d_uequalityEngine.addFunctionKind( kind::APPLY_UF );
- d_uequalityEngine.addFunctionKind( kind::APPLY_CONSTRUCTOR );
-
-}
-
-void ConjectureGenerator::eqNotifyNewClass( TNode t ){
- Trace("thm-ee-debug") << "UEE : new equivalence class " << t << std::endl;
- d_upendingAdds.push_back( t );
-}
-
-void ConjectureGenerator::eqNotifyPreMerge(TNode t1, TNode t2) {
- //get maintained representatives
- TNode rt1 = t1;
- TNode rt2 = t2;
- std::map< Node, EqcInfo* >::iterator it1 = d_eqc_info.find( t1 );
- if( it1!=d_eqc_info.end() && !it1->second->d_rep.get().isNull() ){
- rt1 = it1->second->d_rep.get();
- }
- std::map< Node, EqcInfo* >::iterator it2 = d_eqc_info.find( t2 );
- if( it2!=d_eqc_info.end() && !it2->second->d_rep.get().isNull() ){
- rt2 = it2->second->d_rep.get();
- }
- Trace("thm-ee-debug") << "UEE : equality holds : " << t1 << " == " << t2 << std::endl;
- Trace("thm-ee-debug") << " ureps : " << rt1 << " == " << rt2 << std::endl;
- Trace("thm-ee-debug") << " relevant : " << d_pattern_is_relevant[rt1] << " " << d_pattern_is_relevant[rt2] << std::endl;
- Trace("thm-ee-debug") << " normal : " << d_pattern_is_normal[rt1] << " " << d_pattern_is_normal[rt2] << std::endl;
- Trace("thm-ee-debug") << " size : " << d_pattern_fun_sum[rt1] << " " << d_pattern_fun_sum[rt2] << std::endl;
-
- if( isUniversalLessThan( rt2, rt1 ) ){
- EqcInfo * ei;
- if( it1==d_eqc_info.end() ){
- ei = getOrMakeEqcInfo( t1, true );
- }else{
- ei = it1->second;
- }
- ei->d_rep = t2;
- }
-}
-
-void ConjectureGenerator::eqNotifyPostMerge(TNode t1, TNode t2) {
-
-}
-
-void ConjectureGenerator::eqNotifyDisequal(TNode t1, TNode t2, TNode reason) {
- Trace("thm-ee-debug") << "UEE : disequality holds : " << t1 << " != " << t2 << std::endl;
-
-}
-
-
-ConjectureGenerator::EqcInfo::EqcInfo( context::Context* c ) : d_rep( c, Node::null() ){
-
-}
-
-ConjectureGenerator::EqcInfo* ConjectureGenerator::getOrMakeEqcInfo( TNode n, bool doMake ) {
- //Assert( getUniversalRepresentative( n )==n );
- std::map< Node, EqcInfo* >::iterator eqc_i = d_eqc_info.find( n );
- if( eqc_i!=d_eqc_info.end() ){
- return eqc_i->second;
- }else if( doMake ){
- EqcInfo* ei = new EqcInfo( d_quantEngine->getSatContext() );
- d_eqc_info[n] = ei;
- return ei;
- }else{
- return NULL;
- }
-}
-
-void ConjectureGenerator::setUniversalRelevant( TNode n ) {
- //add pattern information
- registerPattern( n, n.getType() );
- d_urelevant_terms[n] = true;
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- setUniversalRelevant( n[i] );
- }
-}
-
-bool ConjectureGenerator::isUniversalLessThan( TNode rt1, TNode rt2 ) {
- //prefer the one that is (normal, smaller) lexographically
- Assert( d_pattern_is_relevant.find( rt1 )!=d_pattern_is_relevant.end() );
- Assert( d_pattern_is_relevant.find( rt2 )!=d_pattern_is_relevant.end() );
- Assert( d_pattern_is_normal.find( rt1 )!=d_pattern_is_normal.end() );
- Assert( d_pattern_is_normal.find( rt2 )!=d_pattern_is_normal.end() );
- Assert( d_pattern_fun_sum.find( rt1 )!=d_pattern_fun_sum.end() );
- Assert( d_pattern_fun_sum.find( rt2 )!=d_pattern_fun_sum.end() );
-
- if( d_pattern_is_relevant[rt1] && !d_pattern_is_relevant[rt2] ){
- Trace("thm-ee-debug") << "UEE : LT due to relevant." << std::endl;
- return true;
- }else if( d_pattern_is_relevant[rt1]==d_pattern_is_relevant[rt2] ){
- if( d_pattern_is_normal[rt1] && !d_pattern_is_normal[rt2] ){
- Trace("thm-ee-debug") << "UEE : LT due to normal." << std::endl;
- return true;
- }else if( d_pattern_is_normal[rt1]==d_pattern_is_normal[rt2] ){
- if( d_pattern_fun_sum[rt1]<d_pattern_fun_sum[rt2] ){
- Trace("thm-ee-debug") << "UEE : LT due to size." << std::endl;
- //decide which representative to use : based on size of the term
- return true;
- }else if( d_pattern_fun_sum[rt1]==d_pattern_fun_sum[rt2] ){
- //same size : tie goes to term that has already been reported
- return isReportedCanon( rt1 ) && !isReportedCanon( rt2 );
- }
- }
- }
- return false;
-}
-
-
-bool ConjectureGenerator::isReportedCanon( TNode n ) {
- return std::find( d_ue_canon.begin(), d_ue_canon.end(), n )==d_ue_canon.end();
-}
-
-void ConjectureGenerator::markReportedCanon( TNode n ) {
- if( !isReportedCanon( n ) ){
- d_ue_canon.push_back( n );
- }
-}
-
-bool ConjectureGenerator::areUniversalEqual( TNode n1, TNode n2 ) {
- return n1==n2 || ( d_uequalityEngine.hasTerm( n1 ) && d_uequalityEngine.hasTerm( n2 ) && d_uequalityEngine.areEqual( n1, n2 ) );
-}
-
-bool ConjectureGenerator::areUniversalDisequal( TNode n1, TNode n2 ) {
- return n1!=n2 && d_uequalityEngine.hasTerm( n1 ) && d_uequalityEngine.hasTerm( n2 ) && d_uequalityEngine.areDisequal( n1, n2, false );
-}
-
-TNode ConjectureGenerator::getUniversalRepresentative( TNode n, bool add ) {
- if( add ){
- if( d_urelevant_terms.find( n )==d_urelevant_terms.end() ){
- setUniversalRelevant( n );
- //add term to universal equality engine
- d_uequalityEngine.addTerm( n );
- // addding this term to equality engine will lead to a set of new terms (the new subterms of n)
- // now, do instantiation-based merging for each of these terms
- Trace("thm-ee-debug") << "Merge equivalence classes based on instantiations of terms..." << std::endl;
- //merge all pending equalities
- while( !d_upendingAdds.empty() ){
- Trace("sg-pending") << "Add " << d_upendingAdds.size() << " pending terms..." << std::endl;
- std::vector< Node > pending;
- pending.insert( pending.end(), d_upendingAdds.begin(), d_upendingAdds.end() );
- d_upendingAdds.clear();
- for( unsigned i=0; i<pending.size(); i++ ){
- Node t = pending[i];
- TypeNode tn = t.getType();
- Trace("thm-ee-add") << "UEE : Add universal term " << t << std::endl;
- std::vector< Node > eq_terms;
- //if occurs modulo equality at ground level, it is equivalent to representative of ground equality engine
- TNode gt = getTermDatabase()->evaluateTerm( t );
- if( !gt.isNull() && gt!=t ){
- eq_terms.push_back( gt );
- }
- //get all equivalent terms based on theorem database
- d_thm_index.getEquivalentTerms( t, eq_terms );
- if( !eq_terms.empty() ){
- Trace("thm-ee-add") << "UEE : Based on ground EE/theorem DB, it is equivalent to " << eq_terms.size() << " terms : " << std::endl;
- //add equivalent terms as equalities to universal engine
- for( unsigned i=0; i<eq_terms.size(); i++ ){
- Trace("thm-ee-add") << " " << eq_terms[i] << std::endl;
- bool assertEq = false;
- if( d_urelevant_terms.find( eq_terms[i] )!=d_urelevant_terms.end() ){
- assertEq = true;
- }else{
- Assert( eq_terms[i].getType()==tn );
- registerPattern( eq_terms[i], tn );
- if( isUniversalLessThan( eq_terms[i], t ) || ( options::conjectureUeeIntro() && d_pattern_fun_sum[t]>=d_pattern_fun_sum[eq_terms[i]] ) ){
- setUniversalRelevant( eq_terms[i] );
- assertEq = true;
- }
- }
- if( assertEq ){
- Node exp;
- d_uequalityEngine.assertEquality( t.eqNode( eq_terms[i] ), true, exp );
- }else{
- Trace("thm-ee-no-add") << "Do not add : " << t << " == " << eq_terms[i] << std::endl;
- }
- }
- }else{
- Trace("thm-ee-add") << "UEE : No equivalent terms." << std::endl;
- }
- }
- }
- }
- }
-
- if( d_uequalityEngine.hasTerm( n ) ){
- Node r = d_uequalityEngine.getRepresentative( n );
- EqcInfo * ei = getOrMakeEqcInfo( r );
- if( ei && !ei->d_rep.get().isNull() ){
- return ei->d_rep.get();
- }else{
- return r;
- }
- }else{
- return n;
- }
-}
-
-Node ConjectureGenerator::getFreeVar( TypeNode tn, unsigned i ) {
- Assert( !tn.isNull() );
- while( d_free_var[tn].size()<=i ){
- std::stringstream oss;
- oss << tn;
- std::string typ_name = oss.str();
- while( typ_name[0]=='(' ){
- typ_name.erase( typ_name.begin() );
- }
- std::stringstream os;
- os << typ_name[0] << i;
- Node x = NodeManager::currentNM()->mkBoundVar( os.str().c_str(), tn );
- d_free_var_num[x] = d_free_var[tn].size();
- d_free_var[tn].push_back( x );
- }
- return d_free_var[tn][i];
-}
-
-
-
-Node ConjectureGenerator::getCanonicalTerm( TNode n, std::map< TypeNode, unsigned >& var_count, std::map< TNode, TNode >& subs ) {
- if( n.getKind()==BOUND_VARIABLE ){
- std::map< TNode, TNode >::iterator it = subs.find( n );
- if( it==subs.end() ){
- TypeNode tn = n.getType();
- //allocate variable
- unsigned vn = var_count[tn];
- var_count[tn]++;
- subs[n] = getFreeVar( tn, vn );
- return subs[n];
- }else{
- return it->second;
- }
- }else{
- std::vector< Node > children;
- if( n.getKind()!=EQUAL ){
- if( n.hasOperator() ){
- TNode op = n.getOperator();
- if( !d_tge.isRelevantFunc( op ) ){
- return Node::null();
- }
- children.push_back( op );
- }else{
- return Node::null();
- }
- }
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- Node cn = getCanonicalTerm( n[i], var_count, subs );
- if( cn.isNull() ){
- return Node::null();
- }else{
- children.push_back( cn );
- }
- }
- return NodeManager::currentNM()->mkNode( n.getKind(), children );
- }
-}
-
-bool ConjectureGenerator::isHandledTerm( TNode n ){
- return !n.getAttribute(NoMatchAttribute()) && inst::Trigger::isAtomicTrigger( n ) && ( n.getKind()!=APPLY_UF || n.getOperator().getKind()!=SKOLEM );
-}
-
-Node ConjectureGenerator::getGroundEqc( TNode r ) {
- std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r );
- return it!=d_ground_eqc_map.end() ? it->second : Node::null();
-}
-
-bool ConjectureGenerator::isGroundEqc( TNode r ) {
- return d_ground_eqc_map.find( r )!=d_ground_eqc_map.end();
-}
-
-bool ConjectureGenerator::isGroundTerm( TNode n ) {
- return std::find( d_ground_terms.begin(), d_ground_terms.end(), n )!=d_ground_terms.end();
-}
-
-bool ConjectureGenerator::needsCheck( Theory::Effort e ) {
- // synchonized with instantiation engine
- return d_quantEngine->getInstWhenNeedsCheck( e );
-}
-
-bool ConjectureGenerator::hasEnumeratedUf( Node n ) {
- if( options::conjectureGenGtEnum()>0 ){
- std::map< Node, bool >::iterator it = d_uf_enum.find( n.getOperator() );
- if( it==d_uf_enum.end() ){
- d_uf_enum[n.getOperator()] = true;
- std::vector< Node > lem;
- getEnumeratePredUfTerm( n, options::conjectureGenGtEnum(), lem );
- if( !lem.empty() ){
- for( unsigned j=0; j<lem.size(); j++ ){
- d_quantEngine->addLemma( lem[j], false );
- d_hasAddedLemma = true;
- }
- return false;
- }
- }
- }
- return true;
-}
-
-void ConjectureGenerator::reset_round( Theory::Effort e ) {
-
-}
-
-void ConjectureGenerator::check( Theory::Effort e, unsigned quant_e ) {
- if( quant_e==QuantifiersEngine::QEFFORT_STANDARD ){
- d_fullEffortCount++;
- if( d_fullEffortCount%optFullCheckFrequency()==0 ){
- d_hasAddedLemma = false;
- d_tge.d_cg = this;
- double clSet = 0;
- if( Trace.isOn("sg-engine") ){
- clSet = double(clock())/double(CLOCKS_PER_SEC);
- Trace("sg-engine") << "---Conjecture Engine Round, effort = " << e << "---" << std::endl;
- }
- eq::EqualityEngine * ee = getEqualityEngine();
- d_conj_count = 0;
-
- Trace("sg-proc") << "Get eq classes..." << std::endl;
- d_op_arg_index.clear();
- d_ground_eqc_map.clear();
- d_bool_eqc[0] = Node::null();
- d_bool_eqc[1] = Node::null();
- std::vector< TNode > eqcs;
- d_em.clear();
- eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );
- while( !eqcs_i.isFinished() ){
- TNode r = (*eqcs_i);
- eqcs.push_back( r );
- if( r.getType().isBoolean() ){
- if( areEqual( r, getTermDatabase()->d_true ) ){
- d_ground_eqc_map[r] = getTermDatabase()->d_true;
- d_bool_eqc[0] = r;
- }else if( areEqual( r, getTermDatabase()->d_false ) ){
- d_ground_eqc_map[r] = getTermDatabase()->d_false;
- d_bool_eqc[1] = r;
- }
- }
- d_em[r] = eqcs.size();
- eq::EqClassIterator ieqc_i = eq::EqClassIterator( r, ee );
- while( !ieqc_i.isFinished() ){
- TNode n = (*ieqc_i);
- if( getTermDatabase()->hasTermCurrent( n ) ){
- if( isHandledTerm( n ) ){
- d_op_arg_index[r].addTerm( this, n );
- }
- }
- ++ieqc_i;
- }
- ++eqcs_i;
- }
- Assert( !d_bool_eqc[0].isNull() );
- Assert( !d_bool_eqc[1].isNull() );
- d_urelevant_terms.clear();
- Trace("sg-proc") << "...done get eq classes" << std::endl;
-
- Trace("sg-proc") << "Determine ground EQC..." << std::endl;
- bool success;
- do{
- success = false;
- for( unsigned i=0; i<eqcs.size(); i++ ){
- TNode r = eqcs[i];
- if( d_ground_eqc_map.find( r )==d_ground_eqc_map.end() ){
- std::vector< TNode > args;
- Trace("sg-pat-debug") << "******* Get ground term for " << r << std::endl;
- Node n;
- if( getTermDatabase()->isInductionTerm( r ) ){
- n = d_op_arg_index[r].getGroundTerm( this, args );
- }else{
- n = r;
- }
- if( !n.isNull() ){
- Trace("sg-pat") << "Ground term for eqc " << r << " : " << std::endl;
- Trace("sg-pat") << " " << n << std::endl;
- d_ground_eqc_map[r] = n;
- success = true;
- }else{
- Trace("sg-pat-debug") << "...could not find ground term." << std::endl;
- }
- }
- }
- }while( success );
- //also get ground terms
- d_ground_terms.clear();
- for( unsigned i=0; i<eqcs.size(); i++ ){
- TNode r = eqcs[i];
- d_op_arg_index[r].getGroundTerms( this, d_ground_terms );
- }
- Trace("sg-proc") << "...done determine ground EQC" << std::endl;
-
- //debug printing
- if( Trace.isOn("sg-gen-eqc") ){
- for( unsigned i=0; i<eqcs.size(); i++ ){
- TNode r = eqcs[i];
- //print out members
- bool firstTime = true;
- bool isFalse = areEqual( r, getTermDatabase()->d_false );
- eq::EqClassIterator eqc_i = eq::EqClassIterator( r, ee );
- while( !eqc_i.isFinished() ){
- TNode n = (*eqc_i);
- if( getTermDatabase()->hasTermCurrent( n ) && !n.getAttribute(NoMatchAttribute()) && ( n.getKind()!=EQUAL || isFalse ) ){
- if( firstTime ){
- Trace("sg-gen-eqc") << "e" << d_em[r] << " : { " << std::endl;
- firstTime = false;
- }
- if( n.hasOperator() ){
- Trace("sg-gen-eqc") << " (" << n.getOperator();
- getTermDatabase()->computeArgReps( n );
- for( unsigned i=0; i<getTermDatabase()->d_arg_reps[n].size(); i++ ){
- Trace("sg-gen-eqc") << " e" << d_em[getTermDatabase()->d_arg_reps[n][i]];
- }
- Trace("sg-gen-eqc") << ") :: " << n << std::endl;
- }else{
- Trace("sg-gen-eqc") << " " << n << std::endl;
- }
- }
- ++eqc_i;
- }
- if( !firstTime ){
- Trace("sg-gen-eqc") << "}" << std::endl;
- //print out ground term
- std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r );
- if( it!=d_ground_eqc_map.end() ){
- Trace("sg-gen-eqc") << "- Ground term : " << it->second << std::endl;
- }
- }
- }
- }
-
- Trace("sg-proc") << "Compute relevant eqc..." << std::endl;
- d_tge.d_relevant_eqc[0].clear();
- d_tge.d_relevant_eqc[1].clear();
- for( unsigned i=0; i<eqcs.size(); i++ ){
- TNode r = eqcs[i];
- std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r );
- unsigned index = 1;
- if( it==d_ground_eqc_map.end() ){
- index = 0;
- }
- //based on unproven conjectures? TODO
- d_tge.d_relevant_eqc[index].push_back( r );
- }
- Trace("sg-gen-tg-debug") << "Initial relevant eqc : ";
- for( unsigned i=0; i<d_tge.d_relevant_eqc[0].size(); i++ ){
- Trace("sg-gen-tg-debug") << "e" << d_em[d_tge.d_relevant_eqc[0][i]] << " ";
- }
- Trace("sg-gen-tg-debug") << std::endl;
- Trace("sg-proc") << "...done compute relevant eqc" << std::endl;
-
-
- Trace("sg-proc") << "Collect signature information..." << std::endl;
- d_tge.collectSignatureInformation();
- if( d_hasAddedLemma ){
- Trace("sg-proc") << "...added enumeration lemmas." << std::endl;
- }
- Trace("sg-proc") << "...done collect signature information" << std::endl;
-
-
-
- Trace("sg-proc") << "Build theorem index..." << std::endl;
- d_ue_canon.clear();
- d_thm_index.clear();
- std::vector< Node > provenConj;
- quantifiers::FirstOrderModel* m = d_quantEngine->getModel();
- for( int i=0; i<m->getNumAssertedQuantifiers(); i++ ){
- Node q = m->getAssertedQuantifier( i );
- Trace("thm-db-debug") << "Is " << q << " a relevant theorem?" << std::endl;
- Node conjEq;
- if( q[1].getKind()==EQUAL ){
- bool isSubsume = false;
- bool inEe = false;
- for( unsigned r=0; r<2; r++ ){
- TNode nl = q[1][r==0 ? 0 : 1];
- TNode nr = q[1][r==0 ? 1 : 0];
- Node eq = nl.eqNode( nr );
- if( r==1 || std::find( d_conjectures.begin(), d_conjectures.end(), q )==d_conjectures.end() ){
- //must make it canonical
- std::map< TypeNode, unsigned > var_count;
- std::map< TNode, TNode > subs;
- Trace("sg-proc-debug") << "get canonical " << eq << std::endl;
- eq = getCanonicalTerm( eq, var_count, subs );
- }
- if( !eq.isNull() ){
- if( r==0 ){
- inEe = d_ee_conjectures.find( q[1] )!=d_ee_conjectures.end();
- if( !inEe ){
- //add to universal equality engine
- Node nl = getUniversalRepresentative( eq[0], true );
- Node nr = getUniversalRepresentative( eq[1], true );
- if( areUniversalEqual( nl, nr ) ){
- isSubsume = true;
- //set inactive (will be ignored by other modules)
- d_quantEngine->getModel()->setQuantifierActive( q, false );
- }else{
- Node exp;
- d_ee_conjectures[q[1]] = true;
- d_uequalityEngine.assertEquality( nl.eqNode( nr ), true, exp );
- }
- }
- Trace("sg-conjecture") << "*** CONJECTURE : currently proven" << (isSubsume ? " and subsumed" : "");
- Trace("sg-conjecture") << " : " << q[1] << std::endl;
- provenConj.push_back( q );
- }
- if( !isSubsume ){
- Trace("thm-db-debug") << "Adding theorem to database " << eq[0] << " == " << eq[1] << std::endl;
- d_thm_index.addTheorem( eq[0], eq[1] );
- }else{
- break;
- }
- }else{
- break;
- }
- }
- }
- }
- //examine status of other conjectures
- for( unsigned i=0; i<d_conjectures.size(); i++ ){
- Node q = d_conjectures[i];
- if( std::find( provenConj.begin(), provenConj.end(), q )==provenConj.end() ){
- //check each skolem variable
- bool disproven = true;
- //std::vector< Node > sk;
- //getTermDatabase()->getSkolemConstants( q, sk, true );
- Trace("sg-conjecture") << " CONJECTURE : ";
- std::vector< Node > ce;
- for( unsigned j=0; j<getTermDatabase()->d_skolem_constants[q].size(); j++ ){
- TNode k = getTermDatabase()->d_skolem_constants[q][j];
- TNode rk = getRepresentative( k );
- std::map< TNode, Node >::iterator git = d_ground_eqc_map.find( rk );
- //check if it is a ground term
- if( git==d_ground_eqc_map.end() ){
- Trace("sg-conjecture") << "ACTIVE : " << q;
- if( Trace.isOn("sg-gen-eqc") ){
- Trace("sg-conjecture") << " { ";
- for( unsigned k=0; k<getTermDatabase()->d_skolem_constants[q].size(); k++ ){ Trace("sg-conjecture") << getTermDatabase()->d_skolem_constants[q][k] << ( j==k ? "*" : "" ) << " "; }
- Trace("sg-conjecture") << "}";
- }
- Trace("sg-conjecture") << std::endl;
- disproven = false;
- break;
- }else{
- ce.push_back( git->second );
- }
- }
- if( disproven ){
- Trace("sg-conjecture") << "disproven : " << q << " : ";
- for( unsigned i=0; i<ce.size(); i++ ){
- Trace("sg-conjecture") << q[0][i] << " -> " << ce[i] << " ";
- }
- Trace("sg-conjecture") << std::endl;
- }
- }
- }
- Trace("thm-db") << "Theorem database is : " << std::endl;
- d_thm_index.debugPrint( "thm-db" );
- Trace("thm-db") << std::endl;
- Trace("sg-proc") << "...done build theorem index" << std::endl;
-
-
- //clear patterns
- d_patterns.clear();
- d_pattern_var_id.clear();
- d_pattern_var_duplicate.clear();
- d_pattern_is_normal.clear();
- d_pattern_is_relevant.clear();
- d_pattern_fun_id.clear();
- d_pattern_fun_sum.clear();
- d_rel_patterns.clear();
- d_rel_pattern_var_sum.clear();
- d_rel_pattern_typ_index.clear();
- d_rel_pattern_subs_index.clear();
-
- unsigned rel_term_count = 0;
- std::map< TypeNode, unsigned > rt_var_max;
- std::vector< TypeNode > rt_types;
- std::map< TypeNode, std::map< int, std::vector< Node > > > conj_lhs;
- unsigned addedLemmas = 0;
- for( unsigned depth=1; depth<=3; depth++ ){
- Trace("sg-proc") << "Generate relevant LHS at depth " << depth << "..." << std::endl;
- Trace("sg-rel-term") << "Relevant terms of depth " << depth << " : " << std::endl;
- //set up environment
- d_tge.d_var_id.clear();
- d_tge.d_var_limit.clear();
- d_tge.reset( depth, true, TypeNode::null() );
- while( d_tge.getNextTerm() ){
- //construct term
- Node nn = d_tge.getTerm();
- if( !options::conjectureFilterCanonical() || considerTermCanon( nn, true ) ){
- rel_term_count++;
- Trace("sg-rel-term") << "*** Relevant term : ";
- d_tge.debugPrint( "sg-rel-term", "sg-rel-term-debug2" );
- Trace("sg-rel-term") << std::endl;
-
- for( unsigned r=0; r<2; r++ ){
- Trace("sg-rel-term-debug") << "...from equivalence classes (" << r << ") : ";
- int index = d_tge.d_ccand_eqc[r].size()-1;
- for( unsigned j=0; j<d_tge.d_ccand_eqc[r][index].size(); j++ ){
- Trace("sg-rel-term-debug") << "e" << d_em[d_tge.d_ccand_eqc[r][index][j]] << " ";
- }
- Trace("sg-rel-term-debug") << std::endl;
- }
- TypeNode tnn = nn.getType();
- Trace("sg-gen-tg-debug") << "...term is " << nn << std::endl;
- conj_lhs[tnn][depth].push_back( nn );
-
- //add information about pattern
- Trace("sg-gen-tg-debug") << "Collect pattern information..." << std::endl;
- Assert( std::find( d_rel_patterns[tnn].begin(), d_rel_patterns[tnn].end(), nn )==d_rel_patterns[tnn].end() );
- d_rel_patterns[tnn].push_back( nn );
- //build information concerning the variables in this pattern
- unsigned sum = 0;
- std::map< TypeNode, unsigned > typ_to_subs_index;
- std::vector< TNode > gsubs_vars;
- for( std::map< TypeNode, unsigned >::iterator it = d_tge.d_var_id.begin(); it != d_tge.d_var_id.end(); ++it ){
- if( it->second>0 ){
- typ_to_subs_index[it->first] = sum;
- sum += it->second;
- for( unsigned i=0; i<it->second; i++ ){
- gsubs_vars.push_back( getFreeVar( it->first, i ) );
- }
- }
- }
- d_rel_pattern_var_sum[nn] = sum;
- //register the pattern
- registerPattern( nn, tnn );
- Assert( d_pattern_is_normal[nn] );
- Trace("sg-gen-tg-debug") << "...done collect pattern information" << std::endl;
-
- //record information about types
- Trace("sg-gen-tg-debug") << "Collect type information..." << std::endl;
- PatternTypIndex * pti = &d_rel_pattern_typ_index;
- for( std::map< TypeNode, unsigned >::iterator it = d_tge.d_var_id.begin(); it != d_tge.d_var_id.end(); ++it ){
- pti = &pti->d_children[it->first][it->second];
- //record maximum
- if( rt_var_max.find( it->first )==rt_var_max.end() || it->second>rt_var_max[it->first] ){
- rt_var_max[it->first] = it->second;
- }
- }
- if( std::find( rt_types.begin(), rt_types.end(), tnn )==rt_types.end() ){
- rt_types.push_back( tnn );
- }
- pti->d_terms.push_back( nn );
- Trace("sg-gen-tg-debug") << "...done collect type information" << std::endl;
-
- Trace("sg-gen-tg-debug") << "Build substitutions for ground EQC..." << std::endl;
- std::vector< TNode > gsubs_terms;
- gsubs_terms.resize( gsubs_vars.size() );
- int index = d_tge.d_ccand_eqc[1].size()-1;
- for( unsigned j=0; j<d_tge.d_ccand_eqc[1][index].size(); j++ ){
- TNode r = d_tge.d_ccand_eqc[1][index][j];
- Trace("sg-rel-term-debug") << " Matches for e" << d_em[r] << ", which is ground term " << d_ground_eqc_map[r] << ":" << std::endl;
- std::map< TypeNode, std::map< unsigned, TNode > > subs;
- std::map< TNode, bool > rev_subs;
- //only get ground terms
- unsigned mode = 2;
- d_tge.resetMatching( r, mode );
- while( d_tge.getNextMatch( r, subs, rev_subs ) ){
- //we will be building substitutions
- bool firstTime = true;
- for( std::map< TypeNode, std::map< unsigned, TNode > >::iterator it = subs.begin(); it != subs.end(); ++it ){
- unsigned tindex = typ_to_subs_index[it->first];
- for( std::map< unsigned, TNode >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
- if( !firstTime ){
- Trace("sg-rel-term-debug") << ", ";
- }else{
- firstTime = false;
- Trace("sg-rel-term-debug") << " ";
- }
- Trace("sg-rel-term-debug") << it->first << ":x" << it2->first << " -> " << it2->second;
- Assert( tindex+it2->first<gsubs_terms.size() );
- gsubs_terms[tindex+it2->first] = it2->second;
- }
- }
- Trace("sg-rel-term-debug") << std::endl;
- d_rel_pattern_subs_index[nn].addSubstitution( r, gsubs_vars, gsubs_terms );
- }
- }
- Trace("sg-gen-tg-debug") << "...done build substitutions for ground EQC" << std::endl;
- }else{
- Trace("sg-gen-tg-debug") << "> not canonical : " << nn << std::endl;
- }
- }
- Trace("sg-proc") << "...done generate terms at depth " << depth << std::endl;
- Trace("sg-stats") << "--------> Total LHS of depth " << depth << " : " << rel_term_count << std::endl;
- //Trace("conjecture-count") << "Total LHS of depth " << depth << " : " << conj_lhs[depth].size() << std::endl;
-
- /* test...
- for( unsigned i=0; i<rt_types.size(); i++ ){
- Trace("sg-term-enum") << "Term enumeration for " << rt_types[i] << " : " << std::endl;
- Trace("sg-term-enum") << "Ground term : " << rt_types[i].mkGroundTerm() << std::endl;
- for( unsigned j=0; j<150; j++ ){
- Trace("sg-term-enum") << " " << getEnumerateTerm( rt_types[i], j ) << std::endl;
- }
- }
- */
-
- //consider types from relevant terms
- for( unsigned rdepth=0; rdepth<=depth; rdepth++ ){
- //set up environment
- d_tge.d_var_id.clear();
- d_tge.d_var_limit.clear();
- for( std::map< TypeNode, unsigned >::iterator it = rt_var_max.begin(); it != rt_var_max.end(); ++it ){
- d_tge.d_var_id[ it->first ] = it->second;
- d_tge.d_var_limit[ it->first ] = it->second;
- }
- std::random_shuffle( rt_types.begin(), rt_types.end() );
- std::map< TypeNode, std::vector< Node > > conj_rhs;
- for( unsigned i=0; i<rt_types.size(); i++ ){
-
- Trace("sg-proc") << "Generate relevant RHS terms of type " << rt_types[i] << " at depth " << rdepth << "..." << std::endl;
- d_tge.reset( rdepth, false, rt_types[i] );
-
- while( d_tge.getNextTerm() ){
- Node rhs = d_tge.getTerm();
- if( considerTermCanon( rhs, false ) ){
- Trace("sg-rel-prop") << "Relevant RHS : " << rhs << std::endl;
- //register pattern
- Assert( rhs.getType()==rt_types[i] );
- registerPattern( rhs, rt_types[i] );
- if( rdepth<depth ){
- //consider against all LHS at depth
- for( unsigned j=0; j<conj_lhs[rt_types[i]][depth].size(); j++ ){
- processCandidateConjecture( conj_lhs[rt_types[i]][depth][j], rhs, depth, rdepth );
- }
- }else{
- conj_rhs[rt_types[i]].push_back( rhs );
- }
- }
- }
- }
- flushWaitingConjectures( addedLemmas, depth, rdepth );
- //consider against all LHS up to depth
- if( rdepth==depth ){
- for( unsigned lhs_depth = 1; lhs_depth<=depth; lhs_depth++ ){
- if( (int)addedLemmas<options::conjectureGenPerRound() ){
- Trace("sg-proc") << "Consider conjectures at depth (" << lhs_depth << ", " << rdepth << ")..." << std::endl;
- for( std::map< TypeNode, std::vector< Node > >::iterator it = conj_rhs.begin(); it != conj_rhs.end(); ++it ){
- for( unsigned j=0; j<it->second.size(); j++ ){
- for( unsigned k=0; k<conj_lhs[it->first][lhs_depth].size(); k++ ){
- processCandidateConjecture( conj_lhs[it->first][lhs_depth][k], it->second[j], lhs_depth, rdepth );
- }
- }
- }
- flushWaitingConjectures( addedLemmas, lhs_depth, depth );
- }
- }
- }
- if( (int)addedLemmas>=options::conjectureGenPerRound() ){
- break;
- }
- }
- if( (int)addedLemmas>=options::conjectureGenPerRound() ){
- break;
- }
- }
- Trace("sg-stats") << "Total conjectures considered : " << d_conj_count << std::endl;
- if( Trace.isOn("thm-ee") ){
- Trace("thm-ee") << "Universal equality engine is : " << std::endl;
- eq::EqClassesIterator ueqcs_i = eq::EqClassesIterator( &d_uequalityEngine );
- while( !ueqcs_i.isFinished() ){
- TNode r = (*ueqcs_i);
- bool firstTime = true;
- TNode rr = getUniversalRepresentative( r );
- Trace("thm-ee") << " " << rr;
- Trace("thm-ee") << " : { ";
- eq::EqClassIterator ueqc_i = eq::EqClassIterator( r, &d_uequalityEngine );
- while( !ueqc_i.isFinished() ){
- TNode n = (*ueqc_i);
- if( rr!=n ){
- if( firstTime ){
- Trace("thm-ee") << std::endl;
- firstTime = false;
- }
- Trace("thm-ee") << " " << n << std::endl;
- }
- ++ueqc_i;
- }
- if( !firstTime ){ Trace("thm-ee") << " "; }
- Trace("thm-ee") << "}" << std::endl;
- ++ueqcs_i;
- }
- Trace("thm-ee") << std::endl;
- }
- if( Trace.isOn("sg-engine") ){
- double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
- Trace("sg-engine") << "Finished conjecture generator, time = " << (clSet2-clSet) << std::endl;
- }
- }
- }
-}
-
-unsigned ConjectureGenerator::flushWaitingConjectures( unsigned& addedLemmas, int ldepth, int rdepth ) {
- if( !d_waiting_conjectures_lhs.empty() ){
- Trace("sg-proc") << "Generated " << d_waiting_conjectures_lhs.size() << " conjectures at depth " << ldepth << "/" << rdepth << "." << std::endl;
- if( (int)addedLemmas<options::conjectureGenPerRound() ){
- /*
- std::vector< unsigned > indices;
- for( unsigned i=0; i<d_waiting_conjectures_lhs.size(); i++ ){
- indices.push_back( i );
- }
- bool doSort = false;
- if( doSort ){
- //sort them based on score
- sortConjectureScore scs;
- scs.d_scores.insert( scs.d_scores.begin(), d_waiting_conjectures_score.begin(), d_waiting_conjectures_score.end() );
- std::sort( indices.begin(), indices.end(), scs );
- }
- //if( doSort && d_waiting_conjectures_score[indices[0]]<optFilterScoreThreshold() ){
- */
- unsigned prevCount = d_conj_count;
- for( unsigned i=0; i<d_waiting_conjectures_lhs.size(); i++ ){
- if( d_waiting_conjectures_score[i]>=optFilterScoreThreshold() ){
- //we have determined a relevant subgoal
- Node lhs = d_waiting_conjectures_lhs[i];
- Node rhs = d_waiting_conjectures_rhs[i];
- if( options::conjectureFilterCanonical() && ( getUniversalRepresentative( lhs )!=lhs || getUniversalRepresentative( rhs )!=rhs ) ){
- //skip
- }else{
- Trace("sg-engine") << "*** Consider conjecture : " << lhs << " == " << rhs << std::endl;
- Trace("sg-engine-debug") << " score : " << d_waiting_conjectures_score[i] << std::endl;
- if( optStatsOnly() ){
- d_conj_count++;
- }else{
- std::vector< Node > bvs;
- for( std::map< TypeNode, unsigned >::iterator it = d_pattern_var_id[lhs].begin(); it != d_pattern_var_id[lhs].end(); ++it ){
- for( unsigned i=0; i<=it->second; i++ ){
- bvs.push_back( getFreeVar( it->first, i ) );
- }
- }
- Node rsg;
- if( !bvs.empty() ){
- Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, bvs );
- rsg = NodeManager::currentNM()->mkNode( FORALL, bvl, lhs.eqNode( rhs ) );
- }else{
- rsg = lhs.eqNode( rhs );
- }
- rsg = Rewriter::rewrite( rsg );
- d_conjectures.push_back( rsg );
- d_eq_conjectures[lhs].push_back( rhs );
- d_eq_conjectures[rhs].push_back( lhs );
-
- Node lem = NodeManager::currentNM()->mkNode( OR, rsg.negate(), rsg );
- d_quantEngine->addLemma( lem, false );
- d_quantEngine->addRequirePhase( rsg, false );
- addedLemmas++;
- if( (int)addedLemmas>=options::conjectureGenPerRound() ){
- break;
- }
- }
- }
- }
- }
- Trace("sg-proc") << "...have now added " << addedLemmas << " conjecture lemmas." << std::endl;
- if( optStatsOnly() ){
- Trace("sg-stats") << "Generated " << (d_conj_count-prevCount) << " conjectures at depth " << ldepth << "/" << rdepth << "." << std::endl;
- }
- }
- d_waiting_conjectures_lhs.clear();
- d_waiting_conjectures_rhs.clear();
- d_waiting_conjectures_score.clear();
- d_waiting_conjectures.clear();
- }
- return addedLemmas;
-}
-
-void ConjectureGenerator::registerQuantifier( Node q ) {
-
-}
-
-void ConjectureGenerator::assertNode( Node n ) {
-
-}
-
-bool ConjectureGenerator::considerTermCanon( Node ln, bool genRelevant ){
- if( !ln.isNull() ){
- //do not consider if it is non-canonical, and either:
- // (1) we are not generating relevant terms, or
- // (2) its canonical form is a generalization.
- TNode lnr = getUniversalRepresentative( ln, true );
- if( lnr==ln ){
- markReportedCanon( ln );
- }else if( !genRelevant || isGeneralization( lnr, ln ) ){
- Trace("sg-gen-consider-term") << "Do not consider term, " << ln << " is not canonical representation (which is " << lnr << ")." << std::endl;
- return false;
- }
- }
- Trace("sg-gen-tg-debug") << "Will consider term canon " << ln << std::endl;
- Trace("sg-gen-consider-term-debug") << std::endl;
- return true;
-}
-
-unsigned ConjectureGenerator::collectFunctions( TNode opat, TNode pat, std::map< TNode, unsigned >& funcs,
- std::map< TypeNode, unsigned >& mnvn, std::map< TypeNode, unsigned >& mxvn ){
- if( pat.hasOperator() ){
- funcs[pat.getOperator()]++;
- if( !d_tge.isRelevantFunc( pat.getOperator() ) ){
- d_pattern_is_relevant[opat] = false;
- }
- unsigned sum = 1;
- for( unsigned i=0; i<pat.getNumChildren(); i++ ){
- sum += collectFunctions( opat, pat[i], funcs, mnvn, mxvn );
- }
- return sum;
- }else{
- Assert( pat.getNumChildren()==0 );
- funcs[pat]++;
- //for variables
- if( pat.getKind()==BOUND_VARIABLE ){
- if( funcs[pat]>1 ){
- //duplicate variable
- d_pattern_var_duplicate[opat]++;
- }else{
- //check for max/min
- TypeNode tn = pat.getType();
- unsigned vn = d_free_var_num[pat];
- std::map< TypeNode, unsigned >::iterator it = mnvn.find( tn );
- if( it!=mnvn.end() ){
- if( vn<it->second ){
- d_pattern_is_normal[opat] = false;
- mnvn[tn] = vn;
- }else if( vn>mxvn[tn] ){
- if( vn!=mxvn[tn]+1 ){
- d_pattern_is_normal[opat] = false;
- }
- mxvn[tn] = vn;
- }
- }else{
- //first variable of this type
- mnvn[tn] = vn;
- mxvn[tn] = vn;
- }
- }
- }else{
- d_pattern_is_relevant[opat] = false;
- }
- return 1;
- }
-}
-
-void ConjectureGenerator::registerPattern( Node pat, TypeNode tpat ) {
- if( std::find( d_patterns[tpat].begin(), d_patterns[tpat].end(), pat )==d_patterns[tpat].end() ){
- d_patterns[TypeNode::null()].push_back( pat );
- d_patterns[tpat].push_back( pat );
-
- Assert( d_pattern_fun_id.find( pat )==d_pattern_fun_id.end() );
- Assert( d_pattern_var_id.find( pat )==d_pattern_var_id.end() );
-
- //collect functions
- std::map< TypeNode, unsigned > mnvn;
- d_pattern_fun_sum[pat] = collectFunctions( pat, pat, d_pattern_fun_id[pat], mnvn, d_pattern_var_id[pat] );
- if( d_pattern_is_normal.find( pat )==d_pattern_is_normal.end() ){
- d_pattern_is_normal[pat] = true;
- }
- if( d_pattern_is_relevant.find( pat )==d_pattern_is_relevant.end() ){
- d_pattern_is_relevant[pat] = true;
- }
- }
-}
-
-bool ConjectureGenerator::isGeneralization( TNode patg, TNode pat, std::map< TNode, TNode >& subs ) {
- if( patg.getKind()==BOUND_VARIABLE ){
- std::map< TNode, TNode >::iterator it = subs.find( patg );
- if( it!=subs.end() ){
- return it->second==pat;
- }else{
- subs[patg] = pat;
- return true;
- }
- }else{
- Assert( patg.hasOperator() );
- if( !pat.hasOperator() || patg.getOperator()!=pat.getOperator() ){
- return false;
- }else{
- Assert( patg.getNumChildren()==pat.getNumChildren() );
- for( unsigned i=0; i<patg.getNumChildren(); i++ ){
- if( !isGeneralization( patg[i], pat[i], subs ) ){
- return false;
- }
- }
- return true;
- }
- }
-}
-
-int ConjectureGenerator::calculateGeneralizationDepth( TNode n, std::vector< TNode >& fv ) {
- if( n.getKind()==BOUND_VARIABLE ){
- if( std::find( fv.begin(), fv.end(), n )==fv.end() ){
- fv.push_back( n );
- return 0;
- }else{
- return 1;
- }
- }else{
- int depth = 1;
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- depth += calculateGeneralizationDepth( n[i], fv );
- }
- return depth;
- }
-}
-
-Node ConjectureGenerator::getPredicateForType( TypeNode tn ) {
- std::map< TypeNode, Node >::iterator it = d_typ_pred.find( tn );
- if( it==d_typ_pred.end() ){
- TypeNode op_tn = NodeManager::currentNM()->mkFunctionType( tn, NodeManager::currentNM()->booleanType() );
- Node op = NodeManager::currentNM()->mkSkolem( "PE", op_tn, "was created by conjecture ground term enumerator." );
- d_typ_pred[tn] = op;
- return op;
- }else{
- return it->second;
- }
-}
-
-void ConjectureGenerator::getEnumerateUfTerm( Node n, unsigned num, std::vector< Node >& terms ) {
- if( n.getNumChildren()>0 ){
- std::vector< int > vec;
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- vec.push_back( 0 );
- }
- vec.pop_back();
- int size_limit = 0;
- int vec_sum = -1;
- unsigned index = 0;
- unsigned last_size = terms.size();
- while( terms.size()<num ){
- bool success = true;
- if( vec_sum==-1 ){
- vec_sum = 0;
- vec.push_back( size_limit );
- }else{
- //see if we can iterate current
- if( vec_sum<size_limit && !getTermDatabase()->getEnumerateTerm( n[index].getType(), vec[index]+1 ).isNull() ){
- vec[index]++;
- vec_sum++;
- vec.push_back( size_limit - vec_sum );
- }else{
- vec_sum -= vec[index];
- vec[index] = 0;
- index++;
- if( index==n.getNumChildren() ){
- success = false;
- }
- }
- }
- if( success ){
- if( vec.size()==n.getNumChildren() ){
- Node lc = getTermDatabase()->getEnumerateTerm( n[vec.size()-1].getType(), vec[vec.size()-1] );
- if( !lc.isNull() ){
- for( unsigned i=0; i<vec.size(); i++ ){
- Trace("sg-gt-enum-debug") << vec[i] << " ";
- }
- Trace("sg-gt-enum-debug") << " / " << size_limit << std::endl;
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- Trace("sg-gt-enum-debug") << n[i].getType() << " ";
- }
- Trace("sg-gt-enum-debug") << std::endl;
- std::vector< Node > children;
- children.push_back( n.getOperator() );
- for( unsigned i=0; i<(vec.size()-1); i++ ){
- Node nn = getTermDatabase()->getEnumerateTerm( n[i].getType(), vec[i] );
- Assert( !nn.isNull() );
- Assert( nn.getType()==n[i].getType() );
- children.push_back( nn );
- }
- children.push_back( lc );
- Node n = NodeManager::currentNM()->mkNode( APPLY_UF, children );
- Trace("sg-gt-enum") << "Ground term enumerate : " << n << std::endl;
- terms.push_back( n );
- }
- vec.pop_back();
- index = 0;
- }
- }else{
- if( terms.size()>last_size ){
- last_size = terms.size();
- size_limit++;
- for( unsigned i=0; i<vec.size(); i++ ){
- vec[i] = 0;
- }
- vec_sum = -1;
- }else{
- return;
- }
- }
- }
- }else{
- terms.push_back( n );
- }
-}
-
-void ConjectureGenerator::getEnumeratePredUfTerm( Node n, unsigned num, std::vector< Node >& terms ) {
- std::vector< Node > uf_terms;
- getEnumerateUfTerm( n, num, uf_terms );
- Node p = getPredicateForType( n.getType() );
- for( unsigned i=0; i<uf_terms.size(); i++ ){
- terms.push_back( NodeManager::currentNM()->mkNode( APPLY_UF, p, uf_terms[i] ) );
- }
-}
-
-void ConjectureGenerator::processCandidateConjecture( TNode lhs, TNode rhs, unsigned lhs_depth, unsigned rhs_depth ) {
- int score = considerCandidateConjecture( lhs, rhs );
- if( score>0 ){
- Trace("sg-conjecture") << "* Candidate conjecture : " << lhs << " == " << rhs << std::endl;
- Trace("sg-conjecture-debug") << " LHS, RHS generalization depth : " << lhs_depth << ", " << rhs_depth << std::endl;
- Trace("sg-conjecture-debug") << " confirmed = " << d_subs_confirmCount << ", #witnesses range = " << d_subs_confirmWitnessRange.size() << "." << std::endl;
- Trace("sg-conjecture-debug") << " #witnesses for ";
- bool firstTime = true;
- for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){
- if( !firstTime ){
- Trace("sg-conjecture-debug") << ", ";
- }
- Trace("sg-conjecture-debug") << it->first << " : " << it->second.size();
- //if( it->second.size()==1 ){
- // Trace("sg-conjecture-debug") << " (" << it->second[0] << ")";
- //}
- Trace("sg-conjecture-debug2") << " (";
- for( unsigned j=0; j<it->second.size(); j++ ){
- if( j>0 ){ Trace("sg-conjecture-debug2") << " "; }
- Trace("sg-conjecture-debug2") << d_ground_eqc_map[it->second[j]];
- }
- Trace("sg-conjecture-debug2") << ")";
- firstTime = false;
- }
- Trace("sg-conjecture-debug") << std::endl;
- Trace("sg-conjecture-debug") << " unknown = " << d_subs_unkCount << std::endl;
- //Assert( getUniversalRepresentative( rhs )==rhs );
- //Assert( getUniversalRepresentative( lhs )==lhs );
- d_waiting_conjectures_lhs.push_back( lhs );
- d_waiting_conjectures_rhs.push_back( rhs );
- d_waiting_conjectures_score.push_back( score );
- d_waiting_conjectures[lhs].push_back( rhs );
- d_waiting_conjectures[rhs].push_back( lhs );
- }
-}
-
-int ConjectureGenerator::considerCandidateConjecture( TNode lhs, TNode rhs ) {
- Assert( lhs.getType()==rhs.getType() );
-
- Trace("sg-cconj-debug") << "Consider candidate conjecture : " << lhs << " == " << rhs << "?" << std::endl;
- if( lhs==rhs ){
- Trace("sg-cconj-debug") << " -> trivial." << std::endl;
- return -1;
- }else{
- if( lhs.getKind()==APPLY_CONSTRUCTOR && rhs.getKind()==APPLY_CONSTRUCTOR ){
- Trace("sg-cconj-debug") << " -> irrelevant by syntactic analysis." << std::endl;
- return -1;
- }
- //variables of LHS must subsume variables of RHS
- for( std::map< TypeNode, unsigned >::iterator it = d_pattern_var_id[rhs].begin(); it != d_pattern_var_id[rhs].end(); ++it ){
- std::map< TypeNode, unsigned >::iterator itl = d_pattern_var_id[lhs].find( it->first );
- if( itl!=d_pattern_var_id[lhs].end() ){
- if( itl->second<it->second ){
- Trace("sg-cconj-debug") << " -> variables of sort " << it->first << " are not subsumed." << std::endl;
- return -1;
- }else{
- Trace("sg-cconj-debug2") << " variables of sort " << it->first << " are : " << itl->second << " vs " << it->second << std::endl;
- }
- }else{
- Trace("sg-cconj-debug") << " -> has no variables of sort " << it->first << "." << std::endl;
- return -1;
- }
- }
-
- //currently active conjecture?
- std::map< Node, std::vector< Node > >::iterator iteq = d_eq_conjectures.find( lhs );
- if( iteq!=d_eq_conjectures.end() ){
- if( std::find( iteq->second.begin(), iteq->second.end(), rhs )!=iteq->second.end() ){
- Trace("sg-cconj-debug") << " -> this conjecture is already active." << std::endl;
- return -1;
- }
- }
- //current a waiting conjecture?
- std::map< Node, std::vector< Node > >::iterator itw = d_waiting_conjectures.find( lhs );
- if( itw!=d_waiting_conjectures.end() ){
- if( std::find( itw->second.begin(), itw->second.end(), rhs )!=itw->second.end() ){
- Trace("sg-cconj-debug") << " -> already are considering this conjecture." << std::endl;
- return -1;
- }
- }
- //check if canonical representation (should be, but for efficiency this is not guarenteed)
- //if( options::conjectureFilterCanonical() && ( getUniversalRepresentative( lhs )!=lhs || getUniversalRepresentative( rhs )!=rhs ) ){
- // Trace("sg-cconj") << " -> after processing, not canonical." << std::endl;
- // return -1;
- //}
-
- int score;
- bool scoreSet = false;
-
- Trace("sg-cconj") << "Consider possible candidate conjecture : " << lhs << " == " << rhs << "?" << std::endl;
- //find witness for counterexample, if possible
- if( options::conjectureFilterModel() ){
- Assert( d_rel_pattern_var_sum.find( lhs )!=d_rel_pattern_var_sum.end() );
- Trace("sg-cconj-debug") << "Notify substitutions over " << d_rel_pattern_var_sum[lhs] << " variables." << std::endl;
- std::map< TNode, TNode > subs;
- d_subs_confirmCount = 0;
- d_subs_confirmWitnessRange.clear();
- d_subs_confirmWitnessDomain.clear();
- d_subs_unkCount = 0;
- if( !d_rel_pattern_subs_index[lhs].notifySubstitutions( this, subs, rhs, d_rel_pattern_var_sum[lhs] ) ){
- Trace("sg-cconj") << " -> found witness that falsifies the conjecture." << std::endl;
- return -1;
- }
- //score is the minimum number of distinct substitutions for a variable
- for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){
- int num = (int)it->second.size();
- if( !scoreSet || num<score ){
- score = num;
- scoreSet = true;
- }
- }
- if( !scoreSet ){
- score = 0;
- }
- Trace("sg-cconj") << " confirmed = " << d_subs_confirmCount << ", #witnesses range = " << d_subs_confirmWitnessRange.size() << "." << std::endl;
- for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){
- Trace("sg-cconj") << " #witnesses for " << it->first << " : " << it->second.size() << std::endl;
- }
- }else{
- score = 1;
- }
-
- Trace("sg-cconj") << " -> SUCCESS." << std::endl;
- Trace("sg-cconj") << " score : " << score << std::endl;
-
- return score;
- }
-}
-
-bool ConjectureGenerator::notifySubstitution( TNode glhs, std::map< TNode, TNode >& subs, TNode rhs ) {
- if( Trace.isOn("sg-cconj-debug") ){
- Trace("sg-cconj-debug") << "Ground eqc for LHS : " << glhs << ", based on substituion: " << std::endl;
- for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){
- Assert( getRepresentative( it->second )==it->second );
- Trace("sg-cconj-debug") << " " << it->first << " -> " << it->second << std::endl;
- }
- }
- Trace("sg-cconj-debug") << "Evaluate RHS : : " << rhs << std::endl;
- //get the representative of rhs with substitution subs
- TNode grhs = getTermDatabase()->evaluateTerm( rhs, subs, true );
- Trace("sg-cconj-debug") << "...done evaluating term, got : " << grhs << std::endl;
- if( !grhs.isNull() ){
- if( glhs!=grhs ){
- Trace("sg-cconj-debug") << "Ground eqc for RHS : " << grhs << std::endl;
- //check based on ground terms
- std::map< TNode, Node >::iterator itl = d_ground_eqc_map.find( glhs );
- if( itl!=d_ground_eqc_map.end() ){
- std::map< TNode, Node >::iterator itr = d_ground_eqc_map.find( grhs );
- if( itr!=d_ground_eqc_map.end() ){
- Trace("sg-cconj-debug") << "We have ground terms " << itl->second << " and " << itr->second << "." << std::endl;
- if( itl->second.isConst() && itr->second.isConst() ){
- Trace("sg-cconj-debug") << "...disequal constants." << std::endl;
- Trace("sg-cconj-witness") << " Witness of falsification : " << itl->second << " != " << itr->second << ", substutition is : " << std::endl;
- for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){
- Trace("sg-cconj-witness") << " " << it->first << " -> " << it->second << std::endl;
- }
- return false;
- }
- }
- }
- }
- Trace("sg-cconj-debug") << "RHS is identical." << std::endl;
- bool isGroundSubs = true;
- for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){
- std::map< TNode, Node >::iterator git = d_ground_eqc_map.find( it->second );
- if( git==d_ground_eqc_map.end() ){
- isGroundSubs = false;
- break;
- }
- }
- if( isGroundSubs ){
- if( glhs==grhs ){
- Trace("sg-cconj-witness") << " Witnessed " << glhs << " == " << grhs << ", substutition is : " << std::endl;
- for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){
- Trace("sg-cconj-witness") << " " << it->first << " -> " << it->second << std::endl;
- if( std::find( d_subs_confirmWitnessDomain[it->first].begin(), d_subs_confirmWitnessDomain[it->first].end(), it->second )==d_subs_confirmWitnessDomain[it->first].end() ){
- d_subs_confirmWitnessDomain[it->first].push_back( it->second );
- }
- }
- d_subs_confirmCount++;
- if( std::find( d_subs_confirmWitnessRange.begin(), d_subs_confirmWitnessRange.end(), glhs )==d_subs_confirmWitnessRange.end() ){
- d_subs_confirmWitnessRange.push_back( glhs );
- }
- }else{
- if( optFilterUnknown() ){
- Trace("sg-cconj-debug") << "...ground substitution giving terms that are neither equal nor disequal." << std::endl;
- return false;
- }
- }
- }
- }else{
- Trace("sg-cconj-debug") << "(could not ground eqc for RHS)." << std::endl;
- }
- return true;
-}
-
-
-
-
-
-
-void TermGenerator::reset( TermGenEnv * s, TypeNode tn ) {
- Assert( d_children.empty() );
- d_typ = tn;
- d_status = 0;
- d_status_num = 0;
- d_children.clear();
- Trace("sg-gen-tg-debug2") << "...add to context " << this << std::endl;
- d_id = s->d_tg_id;
- s->changeContext( true );
-}
-
-bool TermGenerator::getNextTerm( TermGenEnv * s, unsigned depth ) {
- if( Trace.isOn("sg-gen-tg-debug2") ){
- Trace("sg-gen-tg-debug2") << this << " getNextTerm depth " << depth << " : status = " << d_status << ", num = " << d_status_num;
- if( d_status==5 ){
- TNode f = s->getTgFunc( d_typ, d_status_num );
- Trace("sg-gen-tg-debug2") << ", f = " << f;
- Trace("sg-gen-tg-debug2") << ", #args = " << s->d_func_args[f].size();
- Trace("sg-gen-tg-debug2") << ", childNum = " << d_status_child_num;
- Trace("sg-gen-tg-debug2") << ", #children = " << d_children.size();
- }
- Trace("sg-gen-tg-debug2") << std::endl;
- }
-
- if( d_status==0 ){
- d_status++;
- if( !d_typ.isNull() ){
- if( s->allowVar( d_typ ) ){
- //allocate variable
- d_status_num = s->d_var_id[d_typ];
- s->addVar( d_typ );
- Trace("sg-gen-tg-debug2") << this << " ...return unique var #" << d_status_num << std::endl;
- return s->considerCurrentTerm() ? true : getNextTerm( s, depth );
- }else{
- //check allocating new variable
- d_status++;
- d_status_num = -1;
- if( s->d_gen_relevant_terms ){
- s->d_tg_gdepth++;
- }
- return getNextTerm( s, depth );
- }
- }else{
- d_status = 4;
- d_status_num = -1;
- return getNextTerm( s, depth );
- }
- }else if( d_status==2 ){
- //cleanup previous information
- //if( d_status_num>=0 ){
- // s->d_var_eq_tg[d_status_num].pop_back();
- //}
- //check if there is another variable
- if( (d_status_num+1)<(int)s->getNumTgVars( d_typ ) ){
- d_status_num++;
- //we have equated two variables
- //s->d_var_eq_tg[d_status_num].push_back( d_id );
- Trace("sg-gen-tg-debug2") << this << "...consider other var #" << d_status_num << std::endl;
- return s->considerCurrentTerm() ? true : getNextTerm( s, depth );
- }else{
- if( s->d_gen_relevant_terms ){
- s->d_tg_gdepth--;
- }
- d_status++;
- return getNextTerm( s, depth );
- }
- }else if( d_status==4 ){
- d_status++;
- if( depth>0 && (d_status_num+1)<(int)s->getNumTgFuncs( d_typ ) ){
- d_status_num++;
- d_status_child_num = 0;
- Trace("sg-gen-tg-debug2") << this << "...consider function " << s->getTgFunc( d_typ, d_status_num ) << std::endl;
- s->d_tg_gdepth++;
- if( !s->considerCurrentTerm() ){
- s->d_tg_gdepth--;
- //don't consider this function
- d_status--;
- }else{
- //we have decided on a function application
- }
- return getNextTerm( s, depth );
- }else{
- //do not choose function applications at depth 0
- d_status++;
- return getNextTerm( s, depth );
- }
- }else if( d_status==5 ){
- //iterating over arguments
- TNode f = s->getTgFunc( d_typ, d_status_num );
- if( d_status_child_num<0 ){
- //no more arguments
- s->d_tg_gdepth--;
- d_status--;
- return getNextTerm( s, depth );
- }else if( d_status_child_num==(int)s->d_func_args[f].size() ){
- d_status_child_num--;
- return s->considerCurrentTermCanon( d_id ) ? true : getNextTerm( s, depth );
- //return true;
- }else{
- Assert( d_status_child_num<(int)s->d_func_args[f].size() );
- if( d_status_child_num==(int)d_children.size() ){
- d_children.push_back( s->d_tg_id );
- Assert( s->d_tg_alloc.find( s->d_tg_id )==s->d_tg_alloc.end() );
- s->d_tg_alloc[d_children[d_status_child_num]].reset( s, s->d_func_args[f][d_status_child_num] );
- return getNextTerm( s, depth );
- }else{
- Assert( d_status_child_num+1==(int)d_children.size() );
- if( s->d_tg_alloc[d_children[d_status_child_num]].getNextTerm( s, depth-1 ) ){
- d_status_child_num++;
- return getNextTerm( s, depth );
- }else{
- d_children.pop_back();
- d_status_child_num--;
- return getNextTerm( s, depth );
- }
- }
- }
- }else if( d_status==1 || d_status==3 ){
- if( d_status==1 ){
- s->removeVar( d_typ );
- Assert( d_status_num==(int)s->d_var_id[d_typ] );
- //check if there is only one feasible equivalence class. if so, don't make pattern any more specific.
- //unsigned i = s->d_ccand_eqc[0].size()-1;
- //if( s->d_ccand_eqc[0][i].size()==1 && s->d_ccand_eqc[1][i].empty() ){
- // d_status = 6;
- // return getNextTerm( s, depth );
- //}
- s->d_tg_gdepth++;
- }
- d_status++;
- d_status_num = -1;
- return getNextTerm( s, depth );
- }else{
- //clean up
- Assert( d_children.empty() );
- Trace("sg-gen-tg-debug2") << "...remove from context " << this << std::endl;
- s->changeContext( false );
- Assert( d_id==s->d_tg_id );
- return false;
- }
-}
-
-void TermGenerator::resetMatching( TermGenEnv * s, TNode eqc, unsigned mode ) {
- d_match_status = 0;
- d_match_status_child_num = 0;
- d_match_children.clear();
- d_match_children_end.clear();
- d_match_mode = mode;
- //if this term generalizes, it must generalize a non-ground term
- //if( (d_match_mode & ( 1 << 2 ))!=0 && s->isGroundEqc( eqc ) && d_status==5 ){
- // d_match_status = -1;
- //}
-}
-
-bool TermGenerator::getNextMatch( TermGenEnv * s, TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs ) {
- if( d_match_status<0 ){
- return false;
- }
- if( Trace.isOn("sg-gen-tg-match") ){
- Trace("sg-gen-tg-match") << "Matching ";
- debugPrint( s, "sg-gen-tg-match", "sg-gen-tg-match" );
- Trace("sg-gen-tg-match") << " with eqc e" << s->d_cg->d_em[eqc] << "..." << std::endl;
- Trace("sg-gen-tg-match") << " mstatus = " << d_match_status;
- if( d_status==5 ){
- TNode f = s->getTgFunc( d_typ, d_status_num );
- Trace("sg-gen-tg-debug2") << ", f = " << f;
- Trace("sg-gen-tg-debug2") << ", #args = " << s->d_func_args[f].size();
- Trace("sg-gen-tg-debug2") << ", mchildNum = " << d_match_status_child_num;
- Trace("sg-gen-tg-debug2") << ", #mchildren = " << d_match_children.size();
- }
- Trace("sg-gen-tg-debug2") << ", current substitution : {";
- for( std::map< TypeNode, std::map< unsigned, TNode > >::iterator itt = subs.begin(); itt != subs.end(); ++itt ){
- for( std::map< unsigned, TNode >::iterator it = itt->second.begin(); it != itt->second.end(); ++it ){
- Trace("sg-gen-tg-debug2") << " " << it->first << " -> e" << s->d_cg->d_em[it->second];
- }
- }
- Trace("sg-gen-tg-debug2") << " } " << std::endl;
- }
- if( d_status==1 ){
- //a variable
- if( d_match_status==0 ){
- d_match_status++;
- if( (d_match_mode & ( 1 << 1 ))!=0 ){
- //only ground terms
- if( !s->isGroundEqc( eqc ) ){
- return false;
- }
- }else if( (d_match_mode & ( 1 << 2 ))!=0 ){
- //only non-ground terms
- //if( s->isGroundEqc( eqc ) ){
- // return false;
- //}
- }
- //store the match : restricted if match_mode.0 = 1
- if( (d_match_mode & ( 1 << 0 ))!=0 ){
- std::map< TNode, bool >::iterator it = rev_subs.find( eqc );
- if( it==rev_subs.end() ){
- rev_subs[eqc] = true;
- }else{
- return false;
- }
- }
- Assert( subs[d_typ].find( d_status_num )==subs[d_typ].end() );
- subs[d_typ][d_status_num] = eqc;
- return true;
- }else{
- //clean up
- subs[d_typ].erase( d_status_num );
- if( (d_match_mode & ( 1 << 0 ))!=0 ){
- rev_subs.erase( eqc );
- }
- return false;
- }
- }else if( d_status==2 ){
- if( d_match_status==0 ){
- d_match_status++;
- Assert( d_status_num<(int)s->getNumTgVars( d_typ ) );
- std::map< unsigned, TNode >::iterator it = subs[d_typ].find( d_status_num );
- Assert( it!=subs[d_typ].end() );
- return it->second==eqc;
- }else{
- return false;
- }
- }else if( d_status==5 ){
- //Assert( d_match_children.size()<=d_children.size() );
- //enumerating over f-applications in eqc
- if( d_match_status_child_num<0 ){
- return false;
- }else if( d_match_status==0 ){
- //set up next binding
- if( d_match_status_child_num==(int)d_match_children.size() ){
- if( d_match_status_child_num==0 ){
- //initial binding
- TNode f = s->getTgFunc( d_typ, d_status_num );
- std::map< TNode, TermArgTrie >::iterator it = s->getTermDatabase()->d_func_map_eqc_trie[f].d_data.find( eqc );
- if( it!=s->getTermDatabase()->d_func_map_eqc_trie[f].d_data.end() ){
- d_match_children.push_back( it->second.d_data.begin() );
- d_match_children_end.push_back( it->second.d_data.end() );
- }else{
- d_match_status++;
- d_match_status_child_num--;
- return getNextMatch( s, eqc, subs, rev_subs );
- }
- }else{
- d_match_children.push_back( d_match_children[d_match_status_child_num-1]->second.d_data.begin() );
- d_match_children_end.push_back( d_match_children[d_match_status_child_num-1]->second.d_data.end() );
- }
- }
- d_match_status++;
- Assert( d_match_status_child_num+1==(int)d_match_children.size() );
- if( d_match_children[d_match_status_child_num]==d_match_children_end[d_match_status_child_num] ){
- //no more arguments to bind
- d_match_children.pop_back();
- d_match_children_end.pop_back();
- d_match_status_child_num--;
- return getNextMatch( s, eqc, subs, rev_subs );
- }else{
- if( d_match_status_child_num==(int)d_children.size() ){
- //successfully matched all children
- d_match_children.pop_back();
- d_match_children_end.pop_back();
- d_match_status_child_num--;
- return true;//return d_match_children[d_match_status]!=d_match_children_end[d_match_status];
- }else{
- //do next binding
- 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 );
- return getNextMatch( s, eqc, subs, rev_subs );
- }
- }
- }else{
- Assert( d_match_status==1 );
- Assert( d_match_status_child_num+1==(int)d_match_children.size() );
- Assert( d_match_children[d_match_status_child_num]!=d_match_children_end[d_match_status_child_num] );
- d_match_status--;
- 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 ) ){
- d_match_status_child_num++;
- return getNextMatch( s, eqc, subs, rev_subs );
- }else{
- //iterate
- d_match_children[d_match_status_child_num]++;
- return getNextMatch( s, eqc, subs, rev_subs );
- }
- }
- }
- Assert( false );
- return false;
-}
-
-unsigned TermGenerator::getDepth( TermGenEnv * s ) {
- if( d_status==5 ){
- unsigned maxd = 0;
- for( unsigned i=0; i<d_children.size(); i++ ){
- unsigned d = s->d_tg_alloc[d_children[i]].getDepth( s );
- if( d>maxd ){
- maxd = d;
- }
- }
- return 1+maxd;
- }else{
- return 0;
- }
-}
-
-unsigned TermGenerator::calculateGeneralizationDepth( TermGenEnv * s, std::map< TypeNode, std::vector< int > >& fvs ) {
- if( d_status==5 ){
- unsigned sum = 1;
- for( unsigned i=0; i<d_children.size(); i++ ){
- sum += s->d_tg_alloc[d_children[i]].calculateGeneralizationDepth( s, fvs );
- }
- return sum;
- }else{
- Assert( d_status==2 || d_status==1 );
- std::map< TypeNode, std::vector< int > >::iterator it = fvs.find( d_typ );
- if( it!=fvs.end() ){
- if( std::find( it->second.begin(), it->second.end(), d_status_num )!=it->second.end() ){
- return 1;
- }
- }
- fvs[d_typ].push_back( d_status_num );
- return 0;
- }
-}
-
-unsigned TermGenerator::getGeneralizationDepth( TermGenEnv * s ) {
- //if( s->d_gen_relevant_terms ){
- // return s->d_tg_gdepth;
- //}else{
- std::map< TypeNode, std::vector< int > > fvs;
- return calculateGeneralizationDepth( s, fvs );
- //}
-}
-
-Node TermGenerator::getTerm( TermGenEnv * s ) {
- if( d_status==1 || d_status==2 ){
- Assert( !d_typ.isNull() );
- return s->getFreeVar( d_typ, d_status_num );
- }else if( d_status==5 ){
- Node f = s->getTgFunc( d_typ, d_status_num );
- if( d_children.size()==s->d_func_args[f].size() ){
- std::vector< Node > children;
- if( s->d_tg_func_param[f] ){
- children.push_back( f );
- }
- for( unsigned i=0; i<d_children.size(); i++ ){
- Node nc = s->d_tg_alloc[d_children[i]].getTerm( s );
- if( nc.isNull() ){
- return Node::null();
- }else{
- //Assert( nc.getType()==s->d_func_args[f][i] );
- children.push_back( nc );
- }
- }
- return NodeManager::currentNM()->mkNode( s->d_func_kind[f], children );
- }
- }else{
- Assert( false );
- }
- return Node::null();
-}
-
-void TermGenerator::debugPrint( TermGenEnv * s, const char * c, const char * cd ) {
- Trace(cd) << "[*" << d_id << "," << d_status << "]:";
- if( d_status==1 || d_status==2 ){
- Trace(c) << s->getFreeVar( d_typ, d_status_num );
- }else if( d_status==5 ){
- TNode f = s->getTgFunc( d_typ, d_status_num );
- Trace(c) << "(" << f;
- for( unsigned i=0; i<d_children.size(); i++ ){
- Trace(c) << " ";
- s->d_tg_alloc[d_children[i]].debugPrint( s, c, cd );
- }
- if( d_children.size()<s->d_func_args[f].size() ){
- Trace(c) << " ...";
- }
- Trace(c) << ")";
- }else{
- Trace(c) << "???";
- }
-}
-
-void TermGenEnv::collectSignatureInformation() {
- d_typ_tg_funcs.clear();
- d_funcs.clear();
- d_func_kind.clear();
- d_func_args.clear();
- TypeNode tnull;
- for( std::map< Node, TermArgTrie >::iterator it = getTermDatabase()->d_func_map_trie.begin(); it != getTermDatabase()->d_func_map_trie.end(); ++it ){
- if( !getTermDatabase()->d_op_map[it->first].empty() ){
- Node nn = getTermDatabase()->d_op_map[it->first][0];
- if( d_cg->isHandledTerm( nn ) && nn.getKind()!=APPLY_SELECTOR_TOTAL && !nn.getType().isBoolean() ){
- bool do_enum = true;
- //check if we have enumerated ground terms
- if( nn.getKind()==APPLY_UF ){
- if( !d_cg->hasEnumeratedUf( nn ) ){
- do_enum = false;
- }
- }
- if( do_enum ){
- d_funcs.push_back( it->first );
- for( unsigned i=0; i<nn.getNumChildren(); i++ ){
- d_func_args[it->first].push_back( nn[i].getType() );
- }
- d_func_kind[it->first] = nn.getKind();
- d_typ_tg_funcs[tnull].push_back( it->first );
- d_typ_tg_funcs[nn.getType()].push_back( it->first );
- d_tg_func_param[it->first] = ( nn.getMetaKind() == kind::metakind::PARAMETERIZED );
- Trace("sg-rel-sig") << "Will enumerate function applications of : " << it->first << ", #args = " << d_func_args[it->first].size() << ", kind = " << nn.getKind() << std::endl;
- getTermDatabase()->computeUfEqcTerms( it->first );
- }
- }
- }
- }
- //shuffle functions
- for( std::map< TypeNode, std::vector< TNode > >::iterator it = d_typ_tg_funcs.begin(); it != d_typ_tg_funcs.end(); ++it ){
- std::random_shuffle( it->second.begin(), it->second.end() );
- if( it->first.isNull() ){
- Trace("sg-gen-tg-debug") << "In this order : ";
- for( unsigned i=0; i<it->second.size(); i++ ){
- Trace("sg-gen-tg-debug") << it->second[i] << " ";
- }
- Trace("sg-gen-tg-debug") << std::endl;
- }
- }
-}
-
-void TermGenEnv::reset( unsigned depth, bool genRelevant, TypeNode tn ) {
- Assert( d_tg_alloc.empty() );
- d_tg_alloc.clear();
-
- if( genRelevant ){
- for( unsigned i=0; i<2; i++ ){
- d_ccand_eqc[i].clear();
- d_ccand_eqc[i].push_back( d_relevant_eqc[i] );
- }
- }
-
- d_tg_id = 0;
- d_tg_gdepth = 0;
- d_tg_gdepth_limit = depth;
- d_gen_relevant_terms = genRelevant;
- d_tg_alloc[0].reset( this, tn );
-}
-
-bool TermGenEnv::getNextTerm() {
- if( d_tg_alloc[0].getNextTerm( this, d_tg_gdepth_limit ) ){
- Assert( (int)d_tg_alloc[0].getGeneralizationDepth( this )<=d_tg_gdepth_limit );
- if( (int)d_tg_alloc[0].getGeneralizationDepth( this )!=d_tg_gdepth_limit ){
- return getNextTerm();
- }else{
- return true;
- }
- }else{
- return false;
- }
-}
-
-//reset matching
-void TermGenEnv::resetMatching( TNode eqc, unsigned mode ) {
- d_tg_alloc[0].resetMatching( this, eqc, mode );
-}
-
-//get next match
-bool TermGenEnv::getNextMatch( TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs ) {
- return d_tg_alloc[0].getNextMatch( this, eqc, subs, rev_subs );
-}
-
-//get term
-Node TermGenEnv::getTerm() {
- return d_tg_alloc[0].getTerm( this );
-}
-
-void TermGenEnv::debugPrint( const char * c, const char * cd ) {
- d_tg_alloc[0].debugPrint( this, c, cd );
-}
-
-unsigned TermGenEnv::getNumTgVars( TypeNode tn ) {
- return d_var_id[tn];
-}
-
-bool TermGenEnv::allowVar( TypeNode tn ) {
- std::map< TypeNode, unsigned >::iterator it = d_var_limit.find( tn );
- if( it==d_var_limit.end() ){
- return true;
- }else{
- return d_var_id[tn]<it->second;
- }
-}
-
-void TermGenEnv::addVar( TypeNode tn ) {
- d_var_id[tn]++;
-}
-
-void TermGenEnv::removeVar( TypeNode tn ) {
- d_var_id[tn]--;
- //d_var_eq_tg.pop_back();
- //d_var_tg.pop_back();
-}
-
-unsigned TermGenEnv::getNumTgFuncs( TypeNode tn ) {
- return d_typ_tg_funcs[tn].size();
-}
-
-TNode TermGenEnv::getTgFunc( TypeNode tn, unsigned i ) {
- return d_typ_tg_funcs[tn][i];
-}
-
-Node TermGenEnv::getFreeVar( TypeNode tn, unsigned i ) {
- return d_cg->getFreeVar( tn, i );
-}
-
-bool TermGenEnv::considerCurrentTerm() {
- Assert( !d_tg_alloc.empty() );
-
- //if generalization depth is too large, don't consider it
- unsigned i = d_tg_alloc.size();
- Trace("sg-gen-tg-debug") << "Consider term ";
- d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" );
- Trace("sg-gen-tg-debug") << "? curr term size = " << d_tg_alloc.size() << ", last status = " << d_tg_alloc[i-1].d_status;
- Trace("sg-gen-tg-debug") << std::endl;
-
- if( d_tg_gdepth_limit>=0 && d_tg_alloc[0].getGeneralizationDepth( this )>(unsigned)d_tg_gdepth_limit ){
- Trace("sg-gen-consider-term") << "-> generalization depth of ";
- d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-tg-debug" );
- Trace("sg-gen-consider-term") << " is too high " << d_tg_gdepth << " " << d_tg_alloc[0].getGeneralizationDepth( this ) << ", do not consider." << std::endl;
- return false;
- }
-
- //----optimizations
- /*
- if( d_tg_alloc[i-1].d_status==1 ){
- }else if( d_tg_alloc[i-1].d_status==2 ){
- }else if( d_tg_alloc[i-1].d_status==5 ){
- }else{
- Trace("sg-gen-tg-debug") << "Bad tg: " << &d_tg_alloc[i-1] << std::endl;
- Assert( false );
- }
- */
- //if equated two variables, first check if context-independent TODO
- //----end optimizations
-
-
- //check based on which candidate equivalence classes match
- if( d_gen_relevant_terms ){
- Trace("sg-gen-tg-debug") << "Filter based on relevant ground EQC";
- Trace("sg-gen-tg-debug") << ", #eqc to try = " << d_ccand_eqc[0][i-1].size() << "/" << d_ccand_eqc[1][i-1].size() << std::endl;
-
- Assert( d_ccand_eqc[0].size()>=2 );
- Assert( d_ccand_eqc[0].size()==d_ccand_eqc[1].size() );
- Assert( d_ccand_eqc[0].size()==d_tg_id+1 );
- Assert( d_tg_id==d_tg_alloc.size() );
- for( unsigned r=0; r<2; r++ ){
- d_ccand_eqc[r][i].clear();
- }
-
- //re-check feasibility of EQC
- for( unsigned r=0; r<2; r++ ){
- for( unsigned j=0; j<d_ccand_eqc[r][i-1].size(); j++ ){
- std::map< TypeNode, std::map< unsigned, TNode > > subs;
- std::map< TNode, bool > rev_subs;
- unsigned mode;
- if( r==0 ){
- mode = d_cg->optReqDistinctVarPatterns() ? ( 1 << 0 ) : 0;
- mode = mode | (1 << 2 );
- }else{
- mode = 1 << 1;
- }
- d_tg_alloc[0].resetMatching( this, d_ccand_eqc[r][i-1][j], mode );
- if( d_tg_alloc[0].getNextMatch( this, d_ccand_eqc[r][i-1][j], subs, rev_subs ) ){
- d_ccand_eqc[r][i].push_back( d_ccand_eqc[r][i-1][j] );
- }
- }
- }
- for( unsigned r=0; r<2; r++ ){
- Trace("sg-gen-tg-debug") << "Current eqc of type " << r << " : ";
- for( unsigned j=0; j<d_ccand_eqc[r][i].size(); j++ ){
- Trace("sg-gen-tg-debug") << "e" << d_cg->d_em[d_ccand_eqc[r][i][j]] << " ";
- }
- Trace("sg-gen-tg-debug") << std::endl;
- }
- if( options::conjectureFilterActiveTerms() && d_ccand_eqc[0][i].empty() ){
- Trace("sg-gen-consider-term") << "Do not consider term of form ";
- d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-consider-term-debug" );
- Trace("sg-gen-consider-term") << " since no relevant EQC matches it." << std::endl;
- return false;
- }
- if( options::conjectureFilterModel() && d_ccand_eqc[1][i].empty() ){
- Trace("sg-gen-consider-term") << "Do not consider term of form ";
- d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-consider-term-debug" );
- Trace("sg-gen-consider-term") << " since no ground EQC matches it." << std::endl;
- return false;
- }
- }
- Trace("sg-gen-tg-debug") << "Will consider term ";
- d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" );
- Trace("sg-gen-tg-debug") << std::endl;
- Trace("sg-gen-consider-term-debug") << std::endl;
- return true;
-}
-
-void TermGenEnv::changeContext( bool add ) {
- if( add ){
- for( unsigned r=0; r<2; r++ ){
- d_ccand_eqc[r].push_back( std::vector< TNode >() );
- }
- d_tg_id++;
- }else{
- for( unsigned r=0; r<2; r++ ){
- d_ccand_eqc[r].pop_back();
- }
- d_tg_id--;
- Assert( d_tg_alloc.find( d_tg_id )!=d_tg_alloc.end() );
- d_tg_alloc.erase( d_tg_id );
- }
-}
-
-bool TermGenEnv::considerCurrentTermCanon( unsigned tg_id ){
- Assert( tg_id<d_tg_alloc.size() );
- if( options::conjectureFilterCanonical() ){
- //check based on a canonicity of the term (if there is one)
- Trace("sg-gen-tg-debug") << "Consider term canon ";
- d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" );
- Trace("sg-gen-tg-debug") << ", tg is [" << tg_id << "]..." << std::endl;
-
- Node ln = d_tg_alloc[tg_id].getTerm( this );
- Trace("sg-gen-tg-debug") << "Term is " << ln << std::endl;
- return d_cg->considerTermCanon( ln, d_gen_relevant_terms );
- }
- return true;
-}
-
-bool TermGenEnv::isRelevantFunc( Node f ) {
- return std::find( d_funcs.begin(), d_funcs.end(), f )!=d_funcs.end();
-}
-TermDb * TermGenEnv::getTermDatabase() {
- return d_cg->getTermDatabase();
-}
-Node TermGenEnv::getGroundEqc( TNode r ) {
- return d_cg->getGroundEqc( r );
-}
-bool TermGenEnv::isGroundEqc( TNode r ){
- return d_cg->isGroundEqc( r );
-}
-bool TermGenEnv::isGroundTerm( TNode n ){
- return d_cg->isGroundTerm( n );
-}
-
-
-void SubstitutionIndex::addSubstitution( TNode eqc, std::vector< TNode >& vars, std::vector< TNode >& terms, unsigned i ) {
- if( i==vars.size() ){
- d_var = eqc;
- }else{
- Assert( d_var.isNull() || d_var==vars[i] );
- d_var = vars[i];
- d_children[terms[i]].addSubstitution( eqc, vars, terms, i+1 );
- }
-}
-
-bool SubstitutionIndex::notifySubstitutions( ConjectureGenerator * s, std::map< TNode, TNode >& subs, TNode rhs, unsigned numVars, unsigned i ) {
- if( i==numVars ){
- Assert( d_children.empty() );
- return s->notifySubstitution( d_var, subs, rhs );
- }else{
- Assert( i==0 || !d_children.empty() );
- for( std::map< TNode, SubstitutionIndex >::iterator it = d_children.begin(); it != d_children.end(); ++it ){
- Trace("sg-cconj-debug2") << "Try " << d_var << " -> " << it->first << " (" << i << "/" << numVars << ")" << std::endl;
- subs[d_var] = it->first;
- if( !it->second.notifySubstitutions( s, subs, rhs, numVars, i+1 ) ){
- return false;
- }
- }
- return true;
- }
-}
-
-
-void TheoremIndex::addTheorem( std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs ){
- if( lhs_v.empty() ){
- if( std::find( d_terms.begin(), d_terms.end(), rhs )==d_terms.end() ){
- d_terms.push_back( rhs );
- }
- }else{
- unsigned index = lhs_v.size()-1;
- if( lhs_arg[index]==lhs_v[index].getNumChildren() ){
- lhs_v.pop_back();
- lhs_arg.pop_back();
- addTheorem( lhs_v, lhs_arg, rhs );
- }else{
- lhs_arg[index]++;
- addTheoremNode( lhs_v[index][lhs_arg[index]-1], lhs_v, lhs_arg, rhs );
- }
- }
-}
-
-void TheoremIndex::addTheoremNode( TNode curr, std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs ){
- Trace("thm-db-debug") << "Adding conjecture for subterm " << curr << "..." << std::endl;
- if( curr.hasOperator() ){
- lhs_v.push_back( curr );
- lhs_arg.push_back( 0 );
- d_children[curr.getOperator()].addTheorem( lhs_v, lhs_arg, rhs );
- }else{
- Assert( curr.getKind()==kind::BOUND_VARIABLE );
- TypeNode tn = curr.getType();
- Assert( d_var[tn].isNull() || d_var[tn]==curr );
- d_var[tn] = curr;
- d_children[curr].addTheorem( lhs_v, lhs_arg, rhs );
- }
-}
-
-void TheoremIndex::getEquivalentTerms( std::vector< TNode >& n_v, std::vector< unsigned >& n_arg,
- std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs,
- std::vector< Node >& terms ) {
- Trace("thm-db-debug") << "Get equivalent terms " << n_v.size() << " " << n_arg.size() << std::endl;
- if( n_v.empty() ){
- Trace("thm-db-debug") << "Number of terms : " << d_terms.size() << std::endl;
- //apply substutitions to RHS's
- for( unsigned i=0; i<d_terms.size(); i++ ){
- Node n = d_terms[i].substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
- terms.push_back( n );
- }
- }else{
- unsigned index = n_v.size()-1;
- if( n_arg[index]==n_v[index].getNumChildren() ){
- n_v.pop_back();
- n_arg.pop_back();
- getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms );
- }else{
- n_arg[index]++;
- getEquivalentTermsNode( n_v[index][n_arg[index]-1], n_v, n_arg, smap, vars, subs, terms );
- }
- }
-}
-
-void TheoremIndex::getEquivalentTermsNode( Node curr, std::vector< TNode >& n_v, std::vector< unsigned >& n_arg,
- std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs,
- std::vector< Node >& terms ) {
- Trace("thm-db-debug") << "Get equivalent based on subterm " << curr << "..." << std::endl;
- if( curr.hasOperator() ){
- Trace("thm-db-debug") << "Check based on operator..." << std::endl;
- std::map< TNode, TheoremIndex >::iterator it = d_children.find( curr.getOperator() );
- if( it!=d_children.end() ){
- n_v.push_back( curr );
- n_arg.push_back( 0 );
- it->second.getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms );
- }
- Trace("thm-db-debug") << "...done check based on operator" << std::endl;
- }
- TypeNode tn = curr.getType();
- std::map< TypeNode, TNode >::iterator itt = d_var.find( tn );
- if( itt!=d_var.end() ){
- Trace("thm-db-debug") << "Check for substitution with " << itt->second << "..." << std::endl;
- Assert( curr.getType()==itt->second.getType() );
- //add to substitution if possible
- bool success = false;
- std::map< TNode, TNode >::iterator it = smap.find( itt->second );
- if( it==smap.end() ){
- smap[itt->second] = curr;
- vars.push_back( itt->second );
- subs.push_back( curr );
- success = true;
- }else if( it->second==curr ){
- success = true;
- }else{
- //also check modulo equality (in universal equality engine)
- }
- Trace("thm-db-debug") << "...check for substitution with " << itt->second << ", success = " << success << "." << std::endl;
- if( success ){
- d_children[itt->second].getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms );
- }
- }
-}
-
-void TheoremIndex::debugPrint( const char * c, unsigned ind ) {
- for( std::map< TNode, TheoremIndex >::iterator it = d_children.begin(); it != d_children.end(); ++it ){
- for( unsigned i=0; i<ind; i++ ){ Trace(c) << " "; }
- Trace(c) << it->first << std::endl;
- it->second.debugPrint( c, ind+1 );
- }
- if( !d_terms.empty() ){
- for( unsigned i=0; i<ind; i++ ){ Trace(c) << " "; }
- Trace(c) << "{";
- for( unsigned i=0; i<d_terms.size(); i++ ){
- Trace(c) << " " << d_terms[i];
- }
- Trace(c) << " }" << std::endl;
- }
- //if( !d_var.isNull() ){
- // for( unsigned i=0; i<ind; i++ ){ Trace(c) << " "; }
- // Trace(c) << "var:" << d_var << std::endl;
- //}
-}
-
-bool ConjectureGenerator::optReqDistinctVarPatterns() { return false; }
-bool ConjectureGenerator::optFilterUnknown() { return true; } //may change
-int ConjectureGenerator::optFilterScoreThreshold() { return 1; }
-unsigned ConjectureGenerator::optFullCheckFrequency() { return 1; }
-
-bool ConjectureGenerator::optStatsOnly() { return false; }
-
-}
+/********************* */
+/*! \file conjecture_generator.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 conjecture generator class
+ **
+ **/
+
+#include "theory/quantifiers/conjecture_generator.h"
+#include "theory/theory_engine.h"
+#include "theory/quantifiers/options.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/trigger.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 {
+
+struct sortConjectureScore {
+ std::vector< int > d_scores;
+ bool operator() (unsigned i, unsigned j) { return d_scores[i]>d_scores[j]; }
+};
+
+
+void OpArgIndex::addTerm( ConjectureGenerator * s, TNode n, unsigned index ){
+ if( index==n.getNumChildren() ){
+ Assert( n.hasOperator() );
+ if( std::find( d_ops.begin(), d_ops.end(), n.getOperator() )==d_ops.end() ){
+ d_ops.push_back( n.getOperator() );
+ d_op_terms.push_back( n );
+ }
+ }else{
+ d_child[s->getTermDatabase()->d_arg_reps[n][index]].addTerm( s, n, index+1 );
+ }
+}
+
+Node OpArgIndex::getGroundTerm( ConjectureGenerator * s, std::vector< TNode >& args ) {
+ if( d_ops.empty() ){
+ for( std::map< TNode, OpArgIndex >::iterator it = d_child.begin(); it != d_child.end(); ++it ){
+ std::map< TNode, Node >::iterator itf = s->d_ground_eqc_map.find( it->first );
+ if( itf!=s->d_ground_eqc_map.end() ){
+ args.push_back( itf->second );
+ Node n = it->second.getGroundTerm( s, args );
+ args.pop_back();
+ if( !n.isNull() ){
+ return n;
+ }
+ }
+ }
+ return Node::null();
+ }else{
+ std::vector< TNode > args2;
+ args2.push_back( d_ops[0] );
+ args2.insert( args2.end(), args.begin(), args.end() );
+ return NodeManager::currentNM()->mkNode( d_op_terms[0].getKind(), args2 );
+ }
+}
+
+void OpArgIndex::getGroundTerms( ConjectureGenerator * s, std::vector< TNode >& terms ) {
+ terms.insert( terms.end(), d_op_terms.begin(), d_op_terms.end() );
+ for( std::map< TNode, OpArgIndex >::iterator it = d_child.begin(); it != d_child.end(); ++it ){
+ if( s->isGroundEqc( it->first ) ){
+ it->second.getGroundTerms( s, terms );
+ }
+ }
+}
+
+
+
+ConjectureGenerator::ConjectureGenerator( QuantifiersEngine * qe, context::Context* c ) : QuantifiersModule( qe ),
+d_notify( *this ),
+d_uequalityEngine(d_notify, c, "ConjectureGenerator::ee", false),
+d_ee_conjectures( c ){
+ d_fullEffortCount = 0;
+ d_uequalityEngine.addFunctionKind( kind::APPLY_UF );
+ d_uequalityEngine.addFunctionKind( kind::APPLY_CONSTRUCTOR );
+
+}
+
+void ConjectureGenerator::eqNotifyNewClass( TNode t ){
+ Trace("thm-ee-debug") << "UEE : new equivalence class " << t << std::endl;
+ d_upendingAdds.push_back( t );
+}
+
+void ConjectureGenerator::eqNotifyPreMerge(TNode t1, TNode t2) {
+ //get maintained representatives
+ TNode rt1 = t1;
+ TNode rt2 = t2;
+ std::map< Node, EqcInfo* >::iterator it1 = d_eqc_info.find( t1 );
+ if( it1!=d_eqc_info.end() && !it1->second->d_rep.get().isNull() ){
+ rt1 = it1->second->d_rep.get();
+ }
+ std::map< Node, EqcInfo* >::iterator it2 = d_eqc_info.find( t2 );
+ if( it2!=d_eqc_info.end() && !it2->second->d_rep.get().isNull() ){
+ rt2 = it2->second->d_rep.get();
+ }
+ Trace("thm-ee-debug") << "UEE : equality holds : " << t1 << " == " << t2 << std::endl;
+ Trace("thm-ee-debug") << " ureps : " << rt1 << " == " << rt2 << std::endl;
+ Trace("thm-ee-debug") << " relevant : " << d_pattern_is_relevant[rt1] << " " << d_pattern_is_relevant[rt2] << std::endl;
+ Trace("thm-ee-debug") << " normal : " << d_pattern_is_normal[rt1] << " " << d_pattern_is_normal[rt2] << std::endl;
+ Trace("thm-ee-debug") << " size : " << d_pattern_fun_sum[rt1] << " " << d_pattern_fun_sum[rt2] << std::endl;
+
+ if( isUniversalLessThan( rt2, rt1 ) ){
+ EqcInfo * ei;
+ if( it1==d_eqc_info.end() ){
+ ei = getOrMakeEqcInfo( t1, true );
+ }else{
+ ei = it1->second;
+ }
+ ei->d_rep = t2;
+ }
+}
+
+void ConjectureGenerator::eqNotifyPostMerge(TNode t1, TNode t2) {
+
+}
+
+void ConjectureGenerator::eqNotifyDisequal(TNode t1, TNode t2, TNode reason) {
+ Trace("thm-ee-debug") << "UEE : disequality holds : " << t1 << " != " << t2 << std::endl;
+
+}
+
+
+ConjectureGenerator::EqcInfo::EqcInfo( context::Context* c ) : d_rep( c, Node::null() ){
+
+}
+
+ConjectureGenerator::EqcInfo* ConjectureGenerator::getOrMakeEqcInfo( TNode n, bool doMake ) {
+ //Assert( getUniversalRepresentative( n )==n );
+ std::map< Node, EqcInfo* >::iterator eqc_i = d_eqc_info.find( n );
+ if( eqc_i!=d_eqc_info.end() ){
+ return eqc_i->second;
+ }else if( doMake ){
+ EqcInfo* ei = new EqcInfo( d_quantEngine->getSatContext() );
+ d_eqc_info[n] = ei;
+ return ei;
+ }else{
+ return NULL;
+ }
+}
+
+void ConjectureGenerator::setUniversalRelevant( TNode n ) {
+ //add pattern information
+ registerPattern( n, n.getType() );
+ d_urelevant_terms[n] = true;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ setUniversalRelevant( n[i] );
+ }
+}
+
+bool ConjectureGenerator::isUniversalLessThan( TNode rt1, TNode rt2 ) {
+ //prefer the one that is (normal, smaller) lexographically
+ Assert( d_pattern_is_relevant.find( rt1 )!=d_pattern_is_relevant.end() );
+ Assert( d_pattern_is_relevant.find( rt2 )!=d_pattern_is_relevant.end() );
+ Assert( d_pattern_is_normal.find( rt1 )!=d_pattern_is_normal.end() );
+ Assert( d_pattern_is_normal.find( rt2 )!=d_pattern_is_normal.end() );
+ Assert( d_pattern_fun_sum.find( rt1 )!=d_pattern_fun_sum.end() );
+ Assert( d_pattern_fun_sum.find( rt2 )!=d_pattern_fun_sum.end() );
+
+ if( d_pattern_is_relevant[rt1] && !d_pattern_is_relevant[rt2] ){
+ Trace("thm-ee-debug") << "UEE : LT due to relevant." << std::endl;
+ return true;
+ }else if( d_pattern_is_relevant[rt1]==d_pattern_is_relevant[rt2] ){
+ if( d_pattern_is_normal[rt1] && !d_pattern_is_normal[rt2] ){
+ Trace("thm-ee-debug") << "UEE : LT due to normal." << std::endl;
+ return true;
+ }else if( d_pattern_is_normal[rt1]==d_pattern_is_normal[rt2] ){
+ if( d_pattern_fun_sum[rt1]<d_pattern_fun_sum[rt2] ){
+ Trace("thm-ee-debug") << "UEE : LT due to size." << std::endl;
+ //decide which representative to use : based on size of the term
+ return true;
+ }else if( d_pattern_fun_sum[rt1]==d_pattern_fun_sum[rt2] ){
+ //same size : tie goes to term that has already been reported
+ return isReportedCanon( rt1 ) && !isReportedCanon( rt2 );
+ }
+ }
+ }
+ return false;
+}
+
+
+bool ConjectureGenerator::isReportedCanon( TNode n ) {
+ return std::find( d_ue_canon.begin(), d_ue_canon.end(), n )==d_ue_canon.end();
+}
+
+void ConjectureGenerator::markReportedCanon( TNode n ) {
+ if( !isReportedCanon( n ) ){
+ d_ue_canon.push_back( n );
+ }
+}
+
+bool ConjectureGenerator::areUniversalEqual( TNode n1, TNode n2 ) {
+ return n1==n2 || ( d_uequalityEngine.hasTerm( n1 ) && d_uequalityEngine.hasTerm( n2 ) && d_uequalityEngine.areEqual( n1, n2 ) );
+}
+
+bool ConjectureGenerator::areUniversalDisequal( TNode n1, TNode n2 ) {
+ return n1!=n2 && d_uequalityEngine.hasTerm( n1 ) && d_uequalityEngine.hasTerm( n2 ) && d_uequalityEngine.areDisequal( n1, n2, false );
+}
+
+TNode ConjectureGenerator::getUniversalRepresentative( TNode n, bool add ) {
+ if( add ){
+ if( d_urelevant_terms.find( n )==d_urelevant_terms.end() ){
+ setUniversalRelevant( n );
+ //add term to universal equality engine
+ d_uequalityEngine.addTerm( n );
+ // addding this term to equality engine will lead to a set of new terms (the new subterms of n)
+ // now, do instantiation-based merging for each of these terms
+ Trace("thm-ee-debug") << "Merge equivalence classes based on instantiations of terms..." << std::endl;
+ //merge all pending equalities
+ while( !d_upendingAdds.empty() ){
+ Trace("sg-pending") << "Add " << d_upendingAdds.size() << " pending terms..." << std::endl;
+ std::vector< Node > pending;
+ pending.insert( pending.end(), d_upendingAdds.begin(), d_upendingAdds.end() );
+ d_upendingAdds.clear();
+ for( unsigned i=0; i<pending.size(); i++ ){
+ Node t = pending[i];
+ TypeNode tn = t.getType();
+ Trace("thm-ee-add") << "UEE : Add universal term " << t << std::endl;
+ std::vector< Node > eq_terms;
+ //if occurs modulo equality at ground level, it is equivalent to representative of ground equality engine
+ TNode gt = getTermDatabase()->evaluateTerm( t );
+ if( !gt.isNull() && gt!=t ){
+ eq_terms.push_back( gt );
+ }
+ //get all equivalent terms based on theorem database
+ d_thm_index.getEquivalentTerms( t, eq_terms );
+ if( !eq_terms.empty() ){
+ Trace("thm-ee-add") << "UEE : Based on ground EE/theorem DB, it is equivalent to " << eq_terms.size() << " terms : " << std::endl;
+ //add equivalent terms as equalities to universal engine
+ for( unsigned i=0; i<eq_terms.size(); i++ ){
+ Trace("thm-ee-add") << " " << eq_terms[i] << std::endl;
+ bool assertEq = false;
+ if( d_urelevant_terms.find( eq_terms[i] )!=d_urelevant_terms.end() ){
+ assertEq = true;
+ }else{
+ Assert( eq_terms[i].getType()==tn );
+ registerPattern( eq_terms[i], tn );
+ if( isUniversalLessThan( eq_terms[i], t ) || ( options::conjectureUeeIntro() && d_pattern_fun_sum[t]>=d_pattern_fun_sum[eq_terms[i]] ) ){
+ setUniversalRelevant( eq_terms[i] );
+ assertEq = true;
+ }
+ }
+ if( assertEq ){
+ Node exp;
+ d_uequalityEngine.assertEquality( t.eqNode( eq_terms[i] ), true, exp );
+ }else{
+ Trace("thm-ee-no-add") << "Do not add : " << t << " == " << eq_terms[i] << std::endl;
+ }
+ }
+ }else{
+ Trace("thm-ee-add") << "UEE : No equivalent terms." << std::endl;
+ }
+ }
+ }
+ }
+ }
+
+ if( d_uequalityEngine.hasTerm( n ) ){
+ Node r = d_uequalityEngine.getRepresentative( n );
+ EqcInfo * ei = getOrMakeEqcInfo( r );
+ if( ei && !ei->d_rep.get().isNull() ){
+ return ei->d_rep.get();
+ }else{
+ return r;
+ }
+ }else{
+ return n;
+ }
+}
+
+Node ConjectureGenerator::getFreeVar( TypeNode tn, unsigned i ) {
+ Assert( !tn.isNull() );
+ while( d_free_var[tn].size()<=i ){
+ std::stringstream oss;
+ oss << tn;
+ std::string typ_name = oss.str();
+ while( typ_name[0]=='(' ){
+ typ_name.erase( typ_name.begin() );
+ }
+ std::stringstream os;
+ os << typ_name[0] << i;
+ Node x = NodeManager::currentNM()->mkBoundVar( os.str().c_str(), tn );
+ d_free_var_num[x] = d_free_var[tn].size();
+ d_free_var[tn].push_back( x );
+ }
+ return d_free_var[tn][i];
+}
+
+
+
+Node ConjectureGenerator::getCanonicalTerm( TNode n, std::map< TypeNode, unsigned >& var_count, std::map< TNode, TNode >& subs ) {
+ if( n.getKind()==BOUND_VARIABLE ){
+ std::map< TNode, TNode >::iterator it = subs.find( n );
+ if( it==subs.end() ){
+ TypeNode tn = n.getType();
+ //allocate variable
+ unsigned vn = var_count[tn];
+ var_count[tn]++;
+ subs[n] = getFreeVar( tn, vn );
+ return subs[n];
+ }else{
+ return it->second;
+ }
+ }else{
+ std::vector< Node > children;
+ if( n.getKind()!=EQUAL ){
+ if( n.hasOperator() ){
+ TNode op = n.getOperator();
+ if( !d_tge.isRelevantFunc( op ) ){
+ return Node::null();
+ }
+ children.push_back( op );
+ }else{
+ return Node::null();
+ }
+ }
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ Node cn = getCanonicalTerm( n[i], var_count, subs );
+ if( cn.isNull() ){
+ return Node::null();
+ }else{
+ children.push_back( cn );
+ }
+ }
+ return NodeManager::currentNM()->mkNode( n.getKind(), children );
+ }
+}
+
+bool ConjectureGenerator::isHandledTerm( TNode n ){
+ return !n.getAttribute(NoMatchAttribute()) && inst::Trigger::isAtomicTrigger( n ) && ( n.getKind()!=APPLY_UF || n.getOperator().getKind()!=SKOLEM );
+}
+
+Node ConjectureGenerator::getGroundEqc( TNode r ) {
+ std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r );
+ return it!=d_ground_eqc_map.end() ? it->second : Node::null();
+}
+
+bool ConjectureGenerator::isGroundEqc( TNode r ) {
+ return d_ground_eqc_map.find( r )!=d_ground_eqc_map.end();
+}
+
+bool ConjectureGenerator::isGroundTerm( TNode n ) {
+ return std::find( d_ground_terms.begin(), d_ground_terms.end(), n )!=d_ground_terms.end();
+}
+
+bool ConjectureGenerator::needsCheck( Theory::Effort e ) {
+ // synchonized with instantiation engine
+ return d_quantEngine->getInstWhenNeedsCheck( e );
+}
+
+bool ConjectureGenerator::hasEnumeratedUf( Node n ) {
+ if( options::conjectureGenGtEnum()>0 ){
+ std::map< Node, bool >::iterator it = d_uf_enum.find( n.getOperator() );
+ if( it==d_uf_enum.end() ){
+ d_uf_enum[n.getOperator()] = true;
+ std::vector< Node > lem;
+ getEnumeratePredUfTerm( n, options::conjectureGenGtEnum(), lem );
+ if( !lem.empty() ){
+ for( unsigned j=0; j<lem.size(); j++ ){
+ d_quantEngine->addLemma( lem[j], false );
+ d_hasAddedLemma = true;
+ }
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+void ConjectureGenerator::reset_round( Theory::Effort e ) {
+
+}
+
+void ConjectureGenerator::check( Theory::Effort e, unsigned quant_e ) {
+ if( quant_e==QuantifiersEngine::QEFFORT_STANDARD ){
+ d_fullEffortCount++;
+ if( d_fullEffortCount%optFullCheckFrequency()==0 ){
+ d_hasAddedLemma = false;
+ d_tge.d_cg = this;
+ double clSet = 0;
+ if( Trace.isOn("sg-engine") ){
+ clSet = double(clock())/double(CLOCKS_PER_SEC);
+ Trace("sg-engine") << "---Conjecture Engine Round, effort = " << e << "---" << std::endl;
+ }
+ eq::EqualityEngine * ee = getEqualityEngine();
+ d_conj_count = 0;
+
+ Trace("sg-proc") << "Get eq classes..." << std::endl;
+ d_op_arg_index.clear();
+ d_ground_eqc_map.clear();
+ d_bool_eqc[0] = Node::null();
+ d_bool_eqc[1] = Node::null();
+ std::vector< TNode > eqcs;
+ d_em.clear();
+ eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );
+ while( !eqcs_i.isFinished() ){
+ TNode r = (*eqcs_i);
+ eqcs.push_back( r );
+ if( r.getType().isBoolean() ){
+ if( areEqual( r, getTermDatabase()->d_true ) ){
+ d_ground_eqc_map[r] = getTermDatabase()->d_true;
+ d_bool_eqc[0] = r;
+ }else if( areEqual( r, getTermDatabase()->d_false ) ){
+ d_ground_eqc_map[r] = getTermDatabase()->d_false;
+ d_bool_eqc[1] = r;
+ }
+ }
+ d_em[r] = eqcs.size();
+ eq::EqClassIterator ieqc_i = eq::EqClassIterator( r, ee );
+ while( !ieqc_i.isFinished() ){
+ TNode n = (*ieqc_i);
+ if( getTermDatabase()->hasTermCurrent( n ) ){
+ if( isHandledTerm( n ) ){
+ d_op_arg_index[r].addTerm( this, n );
+ }
+ }
+ ++ieqc_i;
+ }
+ ++eqcs_i;
+ }
+ Assert( !d_bool_eqc[0].isNull() );
+ Assert( !d_bool_eqc[1].isNull() );
+ d_urelevant_terms.clear();
+ Trace("sg-proc") << "...done get eq classes" << std::endl;
+
+ Trace("sg-proc") << "Determine ground EQC..." << std::endl;
+ bool success;
+ do{
+ success = false;
+ for( unsigned i=0; i<eqcs.size(); i++ ){
+ TNode r = eqcs[i];
+ if( d_ground_eqc_map.find( r )==d_ground_eqc_map.end() ){
+ std::vector< TNode > args;
+ Trace("sg-pat-debug") << "******* Get ground term for " << r << std::endl;
+ Node n;
+ if( getTermDatabase()->isInductionTerm( r ) ){
+ n = d_op_arg_index[r].getGroundTerm( this, args );
+ }else{
+ n = r;
+ }
+ if( !n.isNull() ){
+ Trace("sg-pat") << "Ground term for eqc " << r << " : " << std::endl;
+ Trace("sg-pat") << " " << n << std::endl;
+ d_ground_eqc_map[r] = n;
+ success = true;
+ }else{
+ Trace("sg-pat-debug") << "...could not find ground term." << std::endl;
+ }
+ }
+ }
+ }while( success );
+ //also get ground terms
+ d_ground_terms.clear();
+ for( unsigned i=0; i<eqcs.size(); i++ ){
+ TNode r = eqcs[i];
+ d_op_arg_index[r].getGroundTerms( this, d_ground_terms );
+ }
+ Trace("sg-proc") << "...done determine ground EQC" << std::endl;
+
+ //debug printing
+ if( Trace.isOn("sg-gen-eqc") ){
+ for( unsigned i=0; i<eqcs.size(); i++ ){
+ TNode r = eqcs[i];
+ //print out members
+ bool firstTime = true;
+ bool isFalse = areEqual( r, getTermDatabase()->d_false );
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( r, ee );
+ while( !eqc_i.isFinished() ){
+ TNode n = (*eqc_i);
+ if( getTermDatabase()->hasTermCurrent( n ) && !n.getAttribute(NoMatchAttribute()) && ( n.getKind()!=EQUAL || isFalse ) ){
+ if( firstTime ){
+ Trace("sg-gen-eqc") << "e" << d_em[r] << " : { " << std::endl;
+ firstTime = false;
+ }
+ if( n.hasOperator() ){
+ Trace("sg-gen-eqc") << " (" << n.getOperator();
+ getTermDatabase()->computeArgReps( n );
+ for( unsigned i=0; i<getTermDatabase()->d_arg_reps[n].size(); i++ ){
+ Trace("sg-gen-eqc") << " e" << d_em[getTermDatabase()->d_arg_reps[n][i]];
+ }
+ Trace("sg-gen-eqc") << ") :: " << n << std::endl;
+ }else{
+ Trace("sg-gen-eqc") << " " << n << std::endl;
+ }
+ }
+ ++eqc_i;
+ }
+ if( !firstTime ){
+ Trace("sg-gen-eqc") << "}" << std::endl;
+ //print out ground term
+ std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r );
+ if( it!=d_ground_eqc_map.end() ){
+ Trace("sg-gen-eqc") << "- Ground term : " << it->second << std::endl;
+ }
+ }
+ }
+ }
+
+ Trace("sg-proc") << "Compute relevant eqc..." << std::endl;
+ d_tge.d_relevant_eqc[0].clear();
+ d_tge.d_relevant_eqc[1].clear();
+ for( unsigned i=0; i<eqcs.size(); i++ ){
+ TNode r = eqcs[i];
+ std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r );
+ unsigned index = 1;
+ if( it==d_ground_eqc_map.end() ){
+ index = 0;
+ }
+ //based on unproven conjectures? TODO
+ d_tge.d_relevant_eqc[index].push_back( r );
+ }
+ Trace("sg-gen-tg-debug") << "Initial relevant eqc : ";
+ for( unsigned i=0; i<d_tge.d_relevant_eqc[0].size(); i++ ){
+ Trace("sg-gen-tg-debug") << "e" << d_em[d_tge.d_relevant_eqc[0][i]] << " ";
+ }
+ Trace("sg-gen-tg-debug") << std::endl;
+ Trace("sg-proc") << "...done compute relevant eqc" << std::endl;
+
+
+ Trace("sg-proc") << "Collect signature information..." << std::endl;
+ d_tge.collectSignatureInformation();
+ if( d_hasAddedLemma ){
+ Trace("sg-proc") << "...added enumeration lemmas." << std::endl;
+ }
+ Trace("sg-proc") << "...done collect signature information" << std::endl;
+
+
+
+ Trace("sg-proc") << "Build theorem index..." << std::endl;
+ d_ue_canon.clear();
+ d_thm_index.clear();
+ std::vector< Node > provenConj;
+ quantifiers::FirstOrderModel* m = d_quantEngine->getModel();
+ for( int i=0; i<m->getNumAssertedQuantifiers(); i++ ){
+ Node q = m->getAssertedQuantifier( i );
+ Trace("thm-db-debug") << "Is " << q << " a relevant theorem?" << std::endl;
+ Node conjEq;
+ if( q[1].getKind()==EQUAL ){
+ bool isSubsume = false;
+ bool inEe = false;
+ for( unsigned r=0; r<2; r++ ){
+ TNode nl = q[1][r==0 ? 0 : 1];
+ TNode nr = q[1][r==0 ? 1 : 0];
+ Node eq = nl.eqNode( nr );
+ if( r==1 || std::find( d_conjectures.begin(), d_conjectures.end(), q )==d_conjectures.end() ){
+ //must make it canonical
+ std::map< TypeNode, unsigned > var_count;
+ std::map< TNode, TNode > subs;
+ Trace("sg-proc-debug") << "get canonical " << eq << std::endl;
+ eq = getCanonicalTerm( eq, var_count, subs );
+ }
+ if( !eq.isNull() ){
+ if( r==0 ){
+ inEe = d_ee_conjectures.find( q[1] )!=d_ee_conjectures.end();
+ if( !inEe ){
+ //add to universal equality engine
+ Node nl = getUniversalRepresentative( eq[0], true );
+ Node nr = getUniversalRepresentative( eq[1], true );
+ if( areUniversalEqual( nl, nr ) ){
+ isSubsume = true;
+ //set inactive (will be ignored by other modules)
+ d_quantEngine->getModel()->setQuantifierActive( q, false );
+ }else{
+ Node exp;
+ d_ee_conjectures[q[1]] = true;
+ d_uequalityEngine.assertEquality( nl.eqNode( nr ), true, exp );
+ }
+ }
+ Trace("sg-conjecture") << "*** CONJECTURE : currently proven" << (isSubsume ? " and subsumed" : "");
+ Trace("sg-conjecture") << " : " << q[1] << std::endl;
+ provenConj.push_back( q );
+ }
+ if( !isSubsume ){
+ Trace("thm-db-debug") << "Adding theorem to database " << eq[0] << " == " << eq[1] << std::endl;
+ d_thm_index.addTheorem( eq[0], eq[1] );
+ }else{
+ break;
+ }
+ }else{
+ break;
+ }
+ }
+ }
+ }
+ //examine status of other conjectures
+ for( unsigned i=0; i<d_conjectures.size(); i++ ){
+ Node q = d_conjectures[i];
+ if( std::find( provenConj.begin(), provenConj.end(), q )==provenConj.end() ){
+ //check each skolem variable
+ bool disproven = true;
+ //std::vector< Node > sk;
+ //getTermDatabase()->getSkolemConstants( q, sk, true );
+ Trace("sg-conjecture") << " CONJECTURE : ";
+ std::vector< Node > ce;
+ for( unsigned j=0; j<getTermDatabase()->d_skolem_constants[q].size(); j++ ){
+ TNode k = getTermDatabase()->d_skolem_constants[q][j];
+ TNode rk = getRepresentative( k );
+ std::map< TNode, Node >::iterator git = d_ground_eqc_map.find( rk );
+ //check if it is a ground term
+ if( git==d_ground_eqc_map.end() ){
+ Trace("sg-conjecture") << "ACTIVE : " << q;
+ if( Trace.isOn("sg-gen-eqc") ){
+ Trace("sg-conjecture") << " { ";
+ for( unsigned k=0; k<getTermDatabase()->d_skolem_constants[q].size(); k++ ){ Trace("sg-conjecture") << getTermDatabase()->d_skolem_constants[q][k] << ( j==k ? "*" : "" ) << " "; }
+ Trace("sg-conjecture") << "}";
+ }
+ Trace("sg-conjecture") << std::endl;
+ disproven = false;
+ break;
+ }else{
+ ce.push_back( git->second );
+ }
+ }
+ if( disproven ){
+ Trace("sg-conjecture") << "disproven : " << q << " : ";
+ for( unsigned i=0; i<ce.size(); i++ ){
+ Trace("sg-conjecture") << q[0][i] << " -> " << ce[i] << " ";
+ }
+ Trace("sg-conjecture") << std::endl;
+ }
+ }
+ }
+ Trace("thm-db") << "Theorem database is : " << std::endl;
+ d_thm_index.debugPrint( "thm-db" );
+ Trace("thm-db") << std::endl;
+ Trace("sg-proc") << "...done build theorem index" << std::endl;
+
+
+ //clear patterns
+ d_patterns.clear();
+ d_pattern_var_id.clear();
+ d_pattern_var_duplicate.clear();
+ d_pattern_is_normal.clear();
+ d_pattern_is_relevant.clear();
+ d_pattern_fun_id.clear();
+ d_pattern_fun_sum.clear();
+ d_rel_patterns.clear();
+ d_rel_pattern_var_sum.clear();
+ d_rel_pattern_typ_index.clear();
+ d_rel_pattern_subs_index.clear();
+
+ unsigned rel_term_count = 0;
+ std::map< TypeNode, unsigned > rt_var_max;
+ std::vector< TypeNode > rt_types;
+ std::map< TypeNode, std::map< int, std::vector< Node > > > conj_lhs;
+ unsigned addedLemmas = 0;
+ for( unsigned depth=1; depth<=3; depth++ ){
+ Trace("sg-proc") << "Generate relevant LHS at depth " << depth << "..." << std::endl;
+ Trace("sg-rel-term") << "Relevant terms of depth " << depth << " : " << std::endl;
+ //set up environment
+ d_tge.d_var_id.clear();
+ d_tge.d_var_limit.clear();
+ d_tge.reset( depth, true, TypeNode::null() );
+ while( d_tge.getNextTerm() ){
+ //construct term
+ Node nn = d_tge.getTerm();
+ if( !options::conjectureFilterCanonical() || considerTermCanon( nn, true ) ){
+ rel_term_count++;
+ Trace("sg-rel-term") << "*** Relevant term : ";
+ d_tge.debugPrint( "sg-rel-term", "sg-rel-term-debug2" );
+ Trace("sg-rel-term") << std::endl;
+
+ for( unsigned r=0; r<2; r++ ){
+ Trace("sg-rel-term-debug") << "...from equivalence classes (" << r << ") : ";
+ int index = d_tge.d_ccand_eqc[r].size()-1;
+ for( unsigned j=0; j<d_tge.d_ccand_eqc[r][index].size(); j++ ){
+ Trace("sg-rel-term-debug") << "e" << d_em[d_tge.d_ccand_eqc[r][index][j]] << " ";
+ }
+ Trace("sg-rel-term-debug") << std::endl;
+ }
+ TypeNode tnn = nn.getType();
+ Trace("sg-gen-tg-debug") << "...term is " << nn << std::endl;
+ conj_lhs[tnn][depth].push_back( nn );
+
+ //add information about pattern
+ Trace("sg-gen-tg-debug") << "Collect pattern information..." << std::endl;
+ Assert( std::find( d_rel_patterns[tnn].begin(), d_rel_patterns[tnn].end(), nn )==d_rel_patterns[tnn].end() );
+ d_rel_patterns[tnn].push_back( nn );
+ //build information concerning the variables in this pattern
+ unsigned sum = 0;
+ std::map< TypeNode, unsigned > typ_to_subs_index;
+ std::vector< TNode > gsubs_vars;
+ for( std::map< TypeNode, unsigned >::iterator it = d_tge.d_var_id.begin(); it != d_tge.d_var_id.end(); ++it ){
+ if( it->second>0 ){
+ typ_to_subs_index[it->first] = sum;
+ sum += it->second;
+ for( unsigned i=0; i<it->second; i++ ){
+ gsubs_vars.push_back( getFreeVar( it->first, i ) );
+ }
+ }
+ }
+ d_rel_pattern_var_sum[nn] = sum;
+ //register the pattern
+ registerPattern( nn, tnn );
+ Assert( d_pattern_is_normal[nn] );
+ Trace("sg-gen-tg-debug") << "...done collect pattern information" << std::endl;
+
+ //record information about types
+ Trace("sg-gen-tg-debug") << "Collect type information..." << std::endl;
+ PatternTypIndex * pti = &d_rel_pattern_typ_index;
+ for( std::map< TypeNode, unsigned >::iterator it = d_tge.d_var_id.begin(); it != d_tge.d_var_id.end(); ++it ){
+ pti = &pti->d_children[it->first][it->second];
+ //record maximum
+ if( rt_var_max.find( it->first )==rt_var_max.end() || it->second>rt_var_max[it->first] ){
+ rt_var_max[it->first] = it->second;
+ }
+ }
+ if( std::find( rt_types.begin(), rt_types.end(), tnn )==rt_types.end() ){
+ rt_types.push_back( tnn );
+ }
+ pti->d_terms.push_back( nn );
+ Trace("sg-gen-tg-debug") << "...done collect type information" << std::endl;
+
+ Trace("sg-gen-tg-debug") << "Build substitutions for ground EQC..." << std::endl;
+ std::vector< TNode > gsubs_terms;
+ gsubs_terms.resize( gsubs_vars.size() );
+ int index = d_tge.d_ccand_eqc[1].size()-1;
+ for( unsigned j=0; j<d_tge.d_ccand_eqc[1][index].size(); j++ ){
+ TNode r = d_tge.d_ccand_eqc[1][index][j];
+ Trace("sg-rel-term-debug") << " Matches for e" << d_em[r] << ", which is ground term " << d_ground_eqc_map[r] << ":" << std::endl;
+ std::map< TypeNode, std::map< unsigned, TNode > > subs;
+ std::map< TNode, bool > rev_subs;
+ //only get ground terms
+ unsigned mode = 2;
+ d_tge.resetMatching( r, mode );
+ while( d_tge.getNextMatch( r, subs, rev_subs ) ){
+ //we will be building substitutions
+ bool firstTime = true;
+ for( std::map< TypeNode, std::map< unsigned, TNode > >::iterator it = subs.begin(); it != subs.end(); ++it ){
+ unsigned tindex = typ_to_subs_index[it->first];
+ for( std::map< unsigned, TNode >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
+ if( !firstTime ){
+ Trace("sg-rel-term-debug") << ", ";
+ }else{
+ firstTime = false;
+ Trace("sg-rel-term-debug") << " ";
+ }
+ Trace("sg-rel-term-debug") << it->first << ":x" << it2->first << " -> " << it2->second;
+ Assert( tindex+it2->first<gsubs_terms.size() );
+ gsubs_terms[tindex+it2->first] = it2->second;
+ }
+ }
+ Trace("sg-rel-term-debug") << std::endl;
+ d_rel_pattern_subs_index[nn].addSubstitution( r, gsubs_vars, gsubs_terms );
+ }
+ }
+ Trace("sg-gen-tg-debug") << "...done build substitutions for ground EQC" << std::endl;
+ }else{
+ Trace("sg-gen-tg-debug") << "> not canonical : " << nn << std::endl;
+ }
+ }
+ Trace("sg-proc") << "...done generate terms at depth " << depth << std::endl;
+ Trace("sg-stats") << "--------> Total LHS of depth " << depth << " : " << rel_term_count << std::endl;
+ //Trace("conjecture-count") << "Total LHS of depth " << depth << " : " << conj_lhs[depth].size() << std::endl;
+
+ /* test...
+ for( unsigned i=0; i<rt_types.size(); i++ ){
+ Trace("sg-term-enum") << "Term enumeration for " << rt_types[i] << " : " << std::endl;
+ Trace("sg-term-enum") << "Ground term : " << rt_types[i].mkGroundTerm() << std::endl;
+ for( unsigned j=0; j<150; j++ ){
+ Trace("sg-term-enum") << " " << getEnumerateTerm( rt_types[i], j ) << std::endl;
+ }
+ }
+ */
+
+ //consider types from relevant terms
+ for( unsigned rdepth=0; rdepth<=depth; rdepth++ ){
+ //set up environment
+ d_tge.d_var_id.clear();
+ d_tge.d_var_limit.clear();
+ for( std::map< TypeNode, unsigned >::iterator it = rt_var_max.begin(); it != rt_var_max.end(); ++it ){
+ d_tge.d_var_id[ it->first ] = it->second;
+ d_tge.d_var_limit[ it->first ] = it->second;
+ }
+ std::random_shuffle( rt_types.begin(), rt_types.end() );
+ std::map< TypeNode, std::vector< Node > > conj_rhs;
+ for( unsigned i=0; i<rt_types.size(); i++ ){
+
+ Trace("sg-proc") << "Generate relevant RHS terms of type " << rt_types[i] << " at depth " << rdepth << "..." << std::endl;
+ d_tge.reset( rdepth, false, rt_types[i] );
+
+ while( d_tge.getNextTerm() ){
+ Node rhs = d_tge.getTerm();
+ if( considerTermCanon( rhs, false ) ){
+ Trace("sg-rel-prop") << "Relevant RHS : " << rhs << std::endl;
+ //register pattern
+ Assert( rhs.getType()==rt_types[i] );
+ registerPattern( rhs, rt_types[i] );
+ if( rdepth<depth ){
+ //consider against all LHS at depth
+ for( unsigned j=0; j<conj_lhs[rt_types[i]][depth].size(); j++ ){
+ processCandidateConjecture( conj_lhs[rt_types[i]][depth][j], rhs, depth, rdepth );
+ }
+ }else{
+ conj_rhs[rt_types[i]].push_back( rhs );
+ }
+ }
+ }
+ }
+ flushWaitingConjectures( addedLemmas, depth, rdepth );
+ //consider against all LHS up to depth
+ if( rdepth==depth ){
+ for( unsigned lhs_depth = 1; lhs_depth<=depth; lhs_depth++ ){
+ if( (int)addedLemmas<options::conjectureGenPerRound() ){
+ Trace("sg-proc") << "Consider conjectures at depth (" << lhs_depth << ", " << rdepth << ")..." << std::endl;
+ for( std::map< TypeNode, std::vector< Node > >::iterator it = conj_rhs.begin(); it != conj_rhs.end(); ++it ){
+ for( unsigned j=0; j<it->second.size(); j++ ){
+ for( unsigned k=0; k<conj_lhs[it->first][lhs_depth].size(); k++ ){
+ processCandidateConjecture( conj_lhs[it->first][lhs_depth][k], it->second[j], lhs_depth, rdepth );
+ }
+ }
+ }
+ flushWaitingConjectures( addedLemmas, lhs_depth, depth );
+ }
+ }
+ }
+ if( (int)addedLemmas>=options::conjectureGenPerRound() ){
+ break;
+ }
+ }
+ if( (int)addedLemmas>=options::conjectureGenPerRound() ){
+ break;
+ }
+ }
+ Trace("sg-stats") << "Total conjectures considered : " << d_conj_count << std::endl;
+ if( Trace.isOn("thm-ee") ){
+ Trace("thm-ee") << "Universal equality engine is : " << std::endl;
+ eq::EqClassesIterator ueqcs_i = eq::EqClassesIterator( &d_uequalityEngine );
+ while( !ueqcs_i.isFinished() ){
+ TNode r = (*ueqcs_i);
+ bool firstTime = true;
+ TNode rr = getUniversalRepresentative( r );
+ Trace("thm-ee") << " " << rr;
+ Trace("thm-ee") << " : { ";
+ eq::EqClassIterator ueqc_i = eq::EqClassIterator( r, &d_uequalityEngine );
+ while( !ueqc_i.isFinished() ){
+ TNode n = (*ueqc_i);
+ if( rr!=n ){
+ if( firstTime ){
+ Trace("thm-ee") << std::endl;
+ firstTime = false;
+ }
+ Trace("thm-ee") << " " << n << std::endl;
+ }
+ ++ueqc_i;
+ }
+ if( !firstTime ){ Trace("thm-ee") << " "; }
+ Trace("thm-ee") << "}" << std::endl;
+ ++ueqcs_i;
+ }
+ Trace("thm-ee") << std::endl;
+ }
+ if( Trace.isOn("sg-engine") ){
+ double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
+ Trace("sg-engine") << "Finished conjecture generator, time = " << (clSet2-clSet) << std::endl;
+ }
+ }
+ }
+}
+
+unsigned ConjectureGenerator::flushWaitingConjectures( unsigned& addedLemmas, int ldepth, int rdepth ) {
+ if( !d_waiting_conjectures_lhs.empty() ){
+ Trace("sg-proc") << "Generated " << d_waiting_conjectures_lhs.size() << " conjectures at depth " << ldepth << "/" << rdepth << "." << std::endl;
+ if( (int)addedLemmas<options::conjectureGenPerRound() ){
+ /*
+ std::vector< unsigned > indices;
+ for( unsigned i=0; i<d_waiting_conjectures_lhs.size(); i++ ){
+ indices.push_back( i );
+ }
+ bool doSort = false;
+ if( doSort ){
+ //sort them based on score
+ sortConjectureScore scs;
+ scs.d_scores.insert( scs.d_scores.begin(), d_waiting_conjectures_score.begin(), d_waiting_conjectures_score.end() );
+ std::sort( indices.begin(), indices.end(), scs );
+ }
+ //if( doSort && d_waiting_conjectures_score[indices[0]]<optFilterScoreThreshold() ){
+ */
+ unsigned prevCount = d_conj_count;
+ for( unsigned i=0; i<d_waiting_conjectures_lhs.size(); i++ ){
+ if( d_waiting_conjectures_score[i]>=optFilterScoreThreshold() ){
+ //we have determined a relevant subgoal
+ Node lhs = d_waiting_conjectures_lhs[i];
+ Node rhs = d_waiting_conjectures_rhs[i];
+ if( options::conjectureFilterCanonical() && ( getUniversalRepresentative( lhs )!=lhs || getUniversalRepresentative( rhs )!=rhs ) ){
+ //skip
+ }else{
+ Trace("sg-engine") << "*** Consider conjecture : " << lhs << " == " << rhs << std::endl;
+ Trace("sg-engine-debug") << " score : " << d_waiting_conjectures_score[i] << std::endl;
+ if( optStatsOnly() ){
+ d_conj_count++;
+ }else{
+ std::vector< Node > bvs;
+ for( std::map< TypeNode, unsigned >::iterator it = d_pattern_var_id[lhs].begin(); it != d_pattern_var_id[lhs].end(); ++it ){
+ for( unsigned i=0; i<=it->second; i++ ){
+ bvs.push_back( getFreeVar( it->first, i ) );
+ }
+ }
+ Node rsg;
+ if( !bvs.empty() ){
+ Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, bvs );
+ rsg = NodeManager::currentNM()->mkNode( FORALL, bvl, lhs.eqNode( rhs ) );
+ }else{
+ rsg = lhs.eqNode( rhs );
+ }
+ rsg = Rewriter::rewrite( rsg );
+ d_conjectures.push_back( rsg );
+ d_eq_conjectures[lhs].push_back( rhs );
+ d_eq_conjectures[rhs].push_back( lhs );
+
+ Node lem = NodeManager::currentNM()->mkNode( OR, rsg.negate(), rsg );
+ d_quantEngine->addLemma( lem, false );
+ d_quantEngine->addRequirePhase( rsg, false );
+ addedLemmas++;
+ if( (int)addedLemmas>=options::conjectureGenPerRound() ){
+ break;
+ }
+ }
+ }
+ }
+ }
+ Trace("sg-proc") << "...have now added " << addedLemmas << " conjecture lemmas." << std::endl;
+ if( optStatsOnly() ){
+ Trace("sg-stats") << "Generated " << (d_conj_count-prevCount) << " conjectures at depth " << ldepth << "/" << rdepth << "." << std::endl;
+ }
+ }
+ d_waiting_conjectures_lhs.clear();
+ d_waiting_conjectures_rhs.clear();
+ d_waiting_conjectures_score.clear();
+ d_waiting_conjectures.clear();
+ }
+ return addedLemmas;
+}
+
+void ConjectureGenerator::registerQuantifier( Node q ) {
+
+}
+
+void ConjectureGenerator::assertNode( Node n ) {
+
+}
+
+bool ConjectureGenerator::considerTermCanon( Node ln, bool genRelevant ){
+ if( !ln.isNull() ){
+ //do not consider if it is non-canonical, and either:
+ // (1) we are not generating relevant terms, or
+ // (2) its canonical form is a generalization.
+ TNode lnr = getUniversalRepresentative( ln, true );
+ if( lnr==ln ){
+ markReportedCanon( ln );
+ }else if( !genRelevant || isGeneralization( lnr, ln ) ){
+ Trace("sg-gen-consider-term") << "Do not consider term, " << ln << " is not canonical representation (which is " << lnr << ")." << std::endl;
+ return false;
+ }
+ }
+ Trace("sg-gen-tg-debug") << "Will consider term canon " << ln << std::endl;
+ Trace("sg-gen-consider-term-debug") << std::endl;
+ return true;
+}
+
+unsigned ConjectureGenerator::collectFunctions( TNode opat, TNode pat, std::map< TNode, unsigned >& funcs,
+ std::map< TypeNode, unsigned >& mnvn, std::map< TypeNode, unsigned >& mxvn ){
+ if( pat.hasOperator() ){
+ funcs[pat.getOperator()]++;
+ if( !d_tge.isRelevantFunc( pat.getOperator() ) ){
+ d_pattern_is_relevant[opat] = false;
+ }
+ unsigned sum = 1;
+ for( unsigned i=0; i<pat.getNumChildren(); i++ ){
+ sum += collectFunctions( opat, pat[i], funcs, mnvn, mxvn );
+ }
+ return sum;
+ }else{
+ Assert( pat.getNumChildren()==0 );
+ funcs[pat]++;
+ //for variables
+ if( pat.getKind()==BOUND_VARIABLE ){
+ if( funcs[pat]>1 ){
+ //duplicate variable
+ d_pattern_var_duplicate[opat]++;
+ }else{
+ //check for max/min
+ TypeNode tn = pat.getType();
+ unsigned vn = d_free_var_num[pat];
+ std::map< TypeNode, unsigned >::iterator it = mnvn.find( tn );
+ if( it!=mnvn.end() ){
+ if( vn<it->second ){
+ d_pattern_is_normal[opat] = false;
+ mnvn[tn] = vn;
+ }else if( vn>mxvn[tn] ){
+ if( vn!=mxvn[tn]+1 ){
+ d_pattern_is_normal[opat] = false;
+ }
+ mxvn[tn] = vn;
+ }
+ }else{
+ //first variable of this type
+ mnvn[tn] = vn;
+ mxvn[tn] = vn;
+ }
+ }
+ }else{
+ d_pattern_is_relevant[opat] = false;
+ }
+ return 1;
+ }
+}
+
+void ConjectureGenerator::registerPattern( Node pat, TypeNode tpat ) {
+ if( std::find( d_patterns[tpat].begin(), d_patterns[tpat].end(), pat )==d_patterns[tpat].end() ){
+ d_patterns[TypeNode::null()].push_back( pat );
+ d_patterns[tpat].push_back( pat );
+
+ Assert( d_pattern_fun_id.find( pat )==d_pattern_fun_id.end() );
+ Assert( d_pattern_var_id.find( pat )==d_pattern_var_id.end() );
+
+ //collect functions
+ std::map< TypeNode, unsigned > mnvn;
+ d_pattern_fun_sum[pat] = collectFunctions( pat, pat, d_pattern_fun_id[pat], mnvn, d_pattern_var_id[pat] );
+ if( d_pattern_is_normal.find( pat )==d_pattern_is_normal.end() ){
+ d_pattern_is_normal[pat] = true;
+ }
+ if( d_pattern_is_relevant.find( pat )==d_pattern_is_relevant.end() ){
+ d_pattern_is_relevant[pat] = true;
+ }
+ }
+}
+
+bool ConjectureGenerator::isGeneralization( TNode patg, TNode pat, std::map< TNode, TNode >& subs ) {
+ if( patg.getKind()==BOUND_VARIABLE ){
+ std::map< TNode, TNode >::iterator it = subs.find( patg );
+ if( it!=subs.end() ){
+ return it->second==pat;
+ }else{
+ subs[patg] = pat;
+ return true;
+ }
+ }else{
+ Assert( patg.hasOperator() );
+ if( !pat.hasOperator() || patg.getOperator()!=pat.getOperator() ){
+ return false;
+ }else{
+ Assert( patg.getNumChildren()==pat.getNumChildren() );
+ for( unsigned i=0; i<patg.getNumChildren(); i++ ){
+ if( !isGeneralization( patg[i], pat[i], subs ) ){
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+}
+
+int ConjectureGenerator::calculateGeneralizationDepth( TNode n, std::vector< TNode >& fv ) {
+ if( n.getKind()==BOUND_VARIABLE ){
+ if( std::find( fv.begin(), fv.end(), n )==fv.end() ){
+ fv.push_back( n );
+ return 0;
+ }else{
+ return 1;
+ }
+ }else{
+ int depth = 1;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ depth += calculateGeneralizationDepth( n[i], fv );
+ }
+ return depth;
+ }
+}
+
+Node ConjectureGenerator::getPredicateForType( TypeNode tn ) {
+ std::map< TypeNode, Node >::iterator it = d_typ_pred.find( tn );
+ if( it==d_typ_pred.end() ){
+ TypeNode op_tn = NodeManager::currentNM()->mkFunctionType( tn, NodeManager::currentNM()->booleanType() );
+ Node op = NodeManager::currentNM()->mkSkolem( "PE", op_tn, "was created by conjecture ground term enumerator." );
+ d_typ_pred[tn] = op;
+ return op;
+ }else{
+ return it->second;
+ }
+}
+
+void ConjectureGenerator::getEnumerateUfTerm( Node n, unsigned num, std::vector< Node >& terms ) {
+ if( n.getNumChildren()>0 ){
+ std::vector< int > vec;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ vec.push_back( 0 );
+ }
+ vec.pop_back();
+ int size_limit = 0;
+ int vec_sum = -1;
+ unsigned index = 0;
+ unsigned last_size = terms.size();
+ while( terms.size()<num ){
+ bool success = true;
+ if( vec_sum==-1 ){
+ vec_sum = 0;
+ vec.push_back( size_limit );
+ }else{
+ //see if we can iterate current
+ if( vec_sum<size_limit && !getTermDatabase()->getEnumerateTerm( n[index].getType(), vec[index]+1 ).isNull() ){
+ vec[index]++;
+ vec_sum++;
+ vec.push_back( size_limit - vec_sum );
+ }else{
+ vec_sum -= vec[index];
+ vec[index] = 0;
+ index++;
+ if( index==n.getNumChildren() ){
+ success = false;
+ }
+ }
+ }
+ if( success ){
+ if( vec.size()==n.getNumChildren() ){
+ Node lc = getTermDatabase()->getEnumerateTerm( n[vec.size()-1].getType(), vec[vec.size()-1] );
+ if( !lc.isNull() ){
+ for( unsigned i=0; i<vec.size(); i++ ){
+ Trace("sg-gt-enum-debug") << vec[i] << " ";
+ }
+ Trace("sg-gt-enum-debug") << " / " << size_limit << std::endl;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ Trace("sg-gt-enum-debug") << n[i].getType() << " ";
+ }
+ Trace("sg-gt-enum-debug") << std::endl;
+ std::vector< Node > children;
+ children.push_back( n.getOperator() );
+ for( unsigned i=0; i<(vec.size()-1); i++ ){
+ Node nn = getTermDatabase()->getEnumerateTerm( n[i].getType(), vec[i] );
+ Assert( !nn.isNull() );
+ Assert( nn.getType()==n[i].getType() );
+ children.push_back( nn );
+ }
+ children.push_back( lc );
+ Node n = NodeManager::currentNM()->mkNode( APPLY_UF, children );
+ Trace("sg-gt-enum") << "Ground term enumerate : " << n << std::endl;
+ terms.push_back( n );
+ }
+ vec.pop_back();
+ index = 0;
+ }
+ }else{
+ if( terms.size()>last_size ){
+ last_size = terms.size();
+ size_limit++;
+ for( unsigned i=0; i<vec.size(); i++ ){
+ vec[i] = 0;
+ }
+ vec_sum = -1;
+ }else{
+ return;
+ }
+ }
+ }
+ }else{
+ terms.push_back( n );
+ }
+}
+
+void ConjectureGenerator::getEnumeratePredUfTerm( Node n, unsigned num, std::vector< Node >& terms ) {
+ std::vector< Node > uf_terms;
+ getEnumerateUfTerm( n, num, uf_terms );
+ Node p = getPredicateForType( n.getType() );
+ for( unsigned i=0; i<uf_terms.size(); i++ ){
+ terms.push_back( NodeManager::currentNM()->mkNode( APPLY_UF, p, uf_terms[i] ) );
+ }
+}
+
+void ConjectureGenerator::processCandidateConjecture( TNode lhs, TNode rhs, unsigned lhs_depth, unsigned rhs_depth ) {
+ int score = considerCandidateConjecture( lhs, rhs );
+ if( score>0 ){
+ Trace("sg-conjecture") << "* Candidate conjecture : " << lhs << " == " << rhs << std::endl;
+ Trace("sg-conjecture-debug") << " LHS, RHS generalization depth : " << lhs_depth << ", " << rhs_depth << std::endl;
+ Trace("sg-conjecture-debug") << " confirmed = " << d_subs_confirmCount << ", #witnesses range = " << d_subs_confirmWitnessRange.size() << "." << std::endl;
+ Trace("sg-conjecture-debug") << " #witnesses for ";
+ bool firstTime = true;
+ for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){
+ if( !firstTime ){
+ Trace("sg-conjecture-debug") << ", ";
+ }
+ Trace("sg-conjecture-debug") << it->first << " : " << it->second.size();
+ //if( it->second.size()==1 ){
+ // Trace("sg-conjecture-debug") << " (" << it->second[0] << ")";
+ //}
+ Trace("sg-conjecture-debug2") << " (";
+ for( unsigned j=0; j<it->second.size(); j++ ){
+ if( j>0 ){ Trace("sg-conjecture-debug2") << " "; }
+ Trace("sg-conjecture-debug2") << d_ground_eqc_map[it->second[j]];
+ }
+ Trace("sg-conjecture-debug2") << ")";
+ firstTime = false;
+ }
+ Trace("sg-conjecture-debug") << std::endl;
+ Trace("sg-conjecture-debug") << " unknown = " << d_subs_unkCount << std::endl;
+ //Assert( getUniversalRepresentative( rhs )==rhs );
+ //Assert( getUniversalRepresentative( lhs )==lhs );
+ d_waiting_conjectures_lhs.push_back( lhs );
+ d_waiting_conjectures_rhs.push_back( rhs );
+ d_waiting_conjectures_score.push_back( score );
+ d_waiting_conjectures[lhs].push_back( rhs );
+ d_waiting_conjectures[rhs].push_back( lhs );
+ }
+}
+
+int ConjectureGenerator::considerCandidateConjecture( TNode lhs, TNode rhs ) {
+ Assert( lhs.getType()==rhs.getType() );
+
+ Trace("sg-cconj-debug") << "Consider candidate conjecture : " << lhs << " == " << rhs << "?" << std::endl;
+ if( lhs==rhs ){
+ Trace("sg-cconj-debug") << " -> trivial." << std::endl;
+ return -1;
+ }else{
+ if( lhs.getKind()==APPLY_CONSTRUCTOR && rhs.getKind()==APPLY_CONSTRUCTOR ){
+ Trace("sg-cconj-debug") << " -> irrelevant by syntactic analysis." << std::endl;
+ return -1;
+ }
+ //variables of LHS must subsume variables of RHS
+ for( std::map< TypeNode, unsigned >::iterator it = d_pattern_var_id[rhs].begin(); it != d_pattern_var_id[rhs].end(); ++it ){
+ std::map< TypeNode, unsigned >::iterator itl = d_pattern_var_id[lhs].find( it->first );
+ if( itl!=d_pattern_var_id[lhs].end() ){
+ if( itl->second<it->second ){
+ Trace("sg-cconj-debug") << " -> variables of sort " << it->first << " are not subsumed." << std::endl;
+ return -1;
+ }else{
+ Trace("sg-cconj-debug2") << " variables of sort " << it->first << " are : " << itl->second << " vs " << it->second << std::endl;
+ }
+ }else{
+ Trace("sg-cconj-debug") << " -> has no variables of sort " << it->first << "." << std::endl;
+ return -1;
+ }
+ }
+
+ //currently active conjecture?
+ std::map< Node, std::vector< Node > >::iterator iteq = d_eq_conjectures.find( lhs );
+ if( iteq!=d_eq_conjectures.end() ){
+ if( std::find( iteq->second.begin(), iteq->second.end(), rhs )!=iteq->second.end() ){
+ Trace("sg-cconj-debug") << " -> this conjecture is already active." << std::endl;
+ return -1;
+ }
+ }
+ //current a waiting conjecture?
+ std::map< Node, std::vector< Node > >::iterator itw = d_waiting_conjectures.find( lhs );
+ if( itw!=d_waiting_conjectures.end() ){
+ if( std::find( itw->second.begin(), itw->second.end(), rhs )!=itw->second.end() ){
+ Trace("sg-cconj-debug") << " -> already are considering this conjecture." << std::endl;
+ return -1;
+ }
+ }
+ //check if canonical representation (should be, but for efficiency this is not guarenteed)
+ //if( options::conjectureFilterCanonical() && ( getUniversalRepresentative( lhs )!=lhs || getUniversalRepresentative( rhs )!=rhs ) ){
+ // Trace("sg-cconj") << " -> after processing, not canonical." << std::endl;
+ // return -1;
+ //}
+
+ int score;
+ bool scoreSet = false;
+
+ Trace("sg-cconj") << "Consider possible candidate conjecture : " << lhs << " == " << rhs << "?" << std::endl;
+ //find witness for counterexample, if possible
+ if( options::conjectureFilterModel() ){
+ Assert( d_rel_pattern_var_sum.find( lhs )!=d_rel_pattern_var_sum.end() );
+ Trace("sg-cconj-debug") << "Notify substitutions over " << d_rel_pattern_var_sum[lhs] << " variables." << std::endl;
+ std::map< TNode, TNode > subs;
+ d_subs_confirmCount = 0;
+ d_subs_confirmWitnessRange.clear();
+ d_subs_confirmWitnessDomain.clear();
+ d_subs_unkCount = 0;
+ if( !d_rel_pattern_subs_index[lhs].notifySubstitutions( this, subs, rhs, d_rel_pattern_var_sum[lhs] ) ){
+ Trace("sg-cconj") << " -> found witness that falsifies the conjecture." << std::endl;
+ return -1;
+ }
+ //score is the minimum number of distinct substitutions for a variable
+ for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){
+ int num = (int)it->second.size();
+ if( !scoreSet || num<score ){
+ score = num;
+ scoreSet = true;
+ }
+ }
+ if( !scoreSet ){
+ score = 0;
+ }
+ Trace("sg-cconj") << " confirmed = " << d_subs_confirmCount << ", #witnesses range = " << d_subs_confirmWitnessRange.size() << "." << std::endl;
+ for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){
+ Trace("sg-cconj") << " #witnesses for " << it->first << " : " << it->second.size() << std::endl;
+ }
+ }else{
+ score = 1;
+ }
+
+ Trace("sg-cconj") << " -> SUCCESS." << std::endl;
+ Trace("sg-cconj") << " score : " << score << std::endl;
+
+ return score;
+ }
+}
+
+bool ConjectureGenerator::notifySubstitution( TNode glhs, std::map< TNode, TNode >& subs, TNode rhs ) {
+ if( Trace.isOn("sg-cconj-debug") ){
+ Trace("sg-cconj-debug") << "Ground eqc for LHS : " << glhs << ", based on substituion: " << std::endl;
+ for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){
+ Assert( getRepresentative( it->second )==it->second );
+ Trace("sg-cconj-debug") << " " << it->first << " -> " << it->second << std::endl;
+ }
+ }
+ Trace("sg-cconj-debug") << "Evaluate RHS : : " << rhs << std::endl;
+ //get the representative of rhs with substitution subs
+ TNode grhs = getTermDatabase()->evaluateTerm( rhs, subs, true );
+ Trace("sg-cconj-debug") << "...done evaluating term, got : " << grhs << std::endl;
+ if( !grhs.isNull() ){
+ if( glhs!=grhs ){
+ Trace("sg-cconj-debug") << "Ground eqc for RHS : " << grhs << std::endl;
+ //check based on ground terms
+ std::map< TNode, Node >::iterator itl = d_ground_eqc_map.find( glhs );
+ if( itl!=d_ground_eqc_map.end() ){
+ std::map< TNode, Node >::iterator itr = d_ground_eqc_map.find( grhs );
+ if( itr!=d_ground_eqc_map.end() ){
+ Trace("sg-cconj-debug") << "We have ground terms " << itl->second << " and " << itr->second << "." << std::endl;
+ if( itl->second.isConst() && itr->second.isConst() ){
+ Trace("sg-cconj-debug") << "...disequal constants." << std::endl;
+ Trace("sg-cconj-witness") << " Witness of falsification : " << itl->second << " != " << itr->second << ", substutition is : " << std::endl;
+ for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){
+ Trace("sg-cconj-witness") << " " << it->first << " -> " << it->second << std::endl;
+ }
+ return false;
+ }
+ }
+ }
+ }
+ Trace("sg-cconj-debug") << "RHS is identical." << std::endl;
+ bool isGroundSubs = true;
+ for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){
+ std::map< TNode, Node >::iterator git = d_ground_eqc_map.find( it->second );
+ if( git==d_ground_eqc_map.end() ){
+ isGroundSubs = false;
+ break;
+ }
+ }
+ if( isGroundSubs ){
+ if( glhs==grhs ){
+ Trace("sg-cconj-witness") << " Witnessed " << glhs << " == " << grhs << ", substutition is : " << std::endl;
+ for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){
+ Trace("sg-cconj-witness") << " " << it->first << " -> " << it->second << std::endl;
+ if( std::find( d_subs_confirmWitnessDomain[it->first].begin(), d_subs_confirmWitnessDomain[it->first].end(), it->second )==d_subs_confirmWitnessDomain[it->first].end() ){
+ d_subs_confirmWitnessDomain[it->first].push_back( it->second );
+ }
+ }
+ d_subs_confirmCount++;
+ if( std::find( d_subs_confirmWitnessRange.begin(), d_subs_confirmWitnessRange.end(), glhs )==d_subs_confirmWitnessRange.end() ){
+ d_subs_confirmWitnessRange.push_back( glhs );
+ }
+ }else{
+ if( optFilterUnknown() ){
+ Trace("sg-cconj-debug") << "...ground substitution giving terms that are neither equal nor disequal." << std::endl;
+ return false;
+ }
+ }
+ }
+ }else{
+ Trace("sg-cconj-debug") << "(could not ground eqc for RHS)." << std::endl;
+ }
+ return true;
+}
+
+
+
+
+
+
+void TermGenerator::reset( TermGenEnv * s, TypeNode tn ) {
+ Assert( d_children.empty() );
+ d_typ = tn;
+ d_status = 0;
+ d_status_num = 0;
+ d_children.clear();
+ Trace("sg-gen-tg-debug2") << "...add to context " << this << std::endl;
+ d_id = s->d_tg_id;
+ s->changeContext( true );
+}
+
+bool TermGenerator::getNextTerm( TermGenEnv * s, unsigned depth ) {
+ if( Trace.isOn("sg-gen-tg-debug2") ){
+ Trace("sg-gen-tg-debug2") << this << " getNextTerm depth " << depth << " : status = " << d_status << ", num = " << d_status_num;
+ if( d_status==5 ){
+ TNode f = s->getTgFunc( d_typ, d_status_num );
+ Trace("sg-gen-tg-debug2") << ", f = " << f;
+ Trace("sg-gen-tg-debug2") << ", #args = " << s->d_func_args[f].size();
+ Trace("sg-gen-tg-debug2") << ", childNum = " << d_status_child_num;
+ Trace("sg-gen-tg-debug2") << ", #children = " << d_children.size();
+ }
+ Trace("sg-gen-tg-debug2") << std::endl;
+ }
+
+ if( d_status==0 ){
+ d_status++;
+ if( !d_typ.isNull() ){
+ if( s->allowVar( d_typ ) ){
+ //allocate variable
+ d_status_num = s->d_var_id[d_typ];
+ s->addVar( d_typ );
+ Trace("sg-gen-tg-debug2") << this << " ...return unique var #" << d_status_num << std::endl;
+ return s->considerCurrentTerm() ? true : getNextTerm( s, depth );
+ }else{
+ //check allocating new variable
+ d_status++;
+ d_status_num = -1;
+ if( s->d_gen_relevant_terms ){
+ s->d_tg_gdepth++;
+ }
+ return getNextTerm( s, depth );
+ }
+ }else{
+ d_status = 4;
+ d_status_num = -1;
+ return getNextTerm( s, depth );
+ }
+ }else if( d_status==2 ){
+ //cleanup previous information
+ //if( d_status_num>=0 ){
+ // s->d_var_eq_tg[d_status_num].pop_back();
+ //}
+ //check if there is another variable
+ if( (d_status_num+1)<(int)s->getNumTgVars( d_typ ) ){
+ d_status_num++;
+ //we have equated two variables
+ //s->d_var_eq_tg[d_status_num].push_back( d_id );
+ Trace("sg-gen-tg-debug2") << this << "...consider other var #" << d_status_num << std::endl;
+ return s->considerCurrentTerm() ? true : getNextTerm( s, depth );
+ }else{
+ if( s->d_gen_relevant_terms ){
+ s->d_tg_gdepth--;
+ }
+ d_status++;
+ return getNextTerm( s, depth );
+ }
+ }else if( d_status==4 ){
+ d_status++;
+ if( depth>0 && (d_status_num+1)<(int)s->getNumTgFuncs( d_typ ) ){
+ d_status_num++;
+ d_status_child_num = 0;
+ Trace("sg-gen-tg-debug2") << this << "...consider function " << s->getTgFunc( d_typ, d_status_num ) << std::endl;
+ s->d_tg_gdepth++;
+ if( !s->considerCurrentTerm() ){
+ s->d_tg_gdepth--;
+ //don't consider this function
+ d_status--;
+ }else{
+ //we have decided on a function application
+ }
+ return getNextTerm( s, depth );
+ }else{
+ //do not choose function applications at depth 0
+ d_status++;
+ return getNextTerm( s, depth );
+ }
+ }else if( d_status==5 ){
+ //iterating over arguments
+ TNode f = s->getTgFunc( d_typ, d_status_num );
+ if( d_status_child_num<0 ){
+ //no more arguments
+ s->d_tg_gdepth--;
+ d_status--;
+ return getNextTerm( s, depth );
+ }else if( d_status_child_num==(int)s->d_func_args[f].size() ){
+ d_status_child_num--;
+ return s->considerCurrentTermCanon( d_id ) ? true : getNextTerm( s, depth );
+ //return true;
+ }else{
+ Assert( d_status_child_num<(int)s->d_func_args[f].size() );
+ if( d_status_child_num==(int)d_children.size() ){
+ d_children.push_back( s->d_tg_id );
+ Assert( s->d_tg_alloc.find( s->d_tg_id )==s->d_tg_alloc.end() );
+ s->d_tg_alloc[d_children[d_status_child_num]].reset( s, s->d_func_args[f][d_status_child_num] );
+ return getNextTerm( s, depth );
+ }else{
+ Assert( d_status_child_num+1==(int)d_children.size() );
+ if( s->d_tg_alloc[d_children[d_status_child_num]].getNextTerm( s, depth-1 ) ){
+ d_status_child_num++;
+ return getNextTerm( s, depth );
+ }else{
+ d_children.pop_back();
+ d_status_child_num--;
+ return getNextTerm( s, depth );
+ }
+ }
+ }
+ }else if( d_status==1 || d_status==3 ){
+ if( d_status==1 ){
+ s->removeVar( d_typ );
+ Assert( d_status_num==(int)s->d_var_id[d_typ] );
+ //check if there is only one feasible equivalence class. if so, don't make pattern any more specific.
+ //unsigned i = s->d_ccand_eqc[0].size()-1;
+ //if( s->d_ccand_eqc[0][i].size()==1 && s->d_ccand_eqc[1][i].empty() ){
+ // d_status = 6;
+ // return getNextTerm( s, depth );
+ //}
+ s->d_tg_gdepth++;
+ }
+ d_status++;
+ d_status_num = -1;
+ return getNextTerm( s, depth );
+ }else{
+ //clean up
+ Assert( d_children.empty() );
+ Trace("sg-gen-tg-debug2") << "...remove from context " << this << std::endl;
+ s->changeContext( false );
+ Assert( d_id==s->d_tg_id );
+ return false;
+ }
+}
+
+void TermGenerator::resetMatching( TermGenEnv * s, TNode eqc, unsigned mode ) {
+ d_match_status = 0;
+ d_match_status_child_num = 0;
+ d_match_children.clear();
+ d_match_children_end.clear();
+ d_match_mode = mode;
+ //if this term generalizes, it must generalize a non-ground term
+ //if( (d_match_mode & ( 1 << 2 ))!=0 && s->isGroundEqc( eqc ) && d_status==5 ){
+ // d_match_status = -1;
+ //}
+}
+
+bool TermGenerator::getNextMatch( TermGenEnv * s, TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs ) {
+ if( d_match_status<0 ){
+ return false;
+ }
+ if( Trace.isOn("sg-gen-tg-match") ){
+ Trace("sg-gen-tg-match") << "Matching ";
+ debugPrint( s, "sg-gen-tg-match", "sg-gen-tg-match" );
+ Trace("sg-gen-tg-match") << " with eqc e" << s->d_cg->d_em[eqc] << "..." << std::endl;
+ Trace("sg-gen-tg-match") << " mstatus = " << d_match_status;
+ if( d_status==5 ){
+ TNode f = s->getTgFunc( d_typ, d_status_num );
+ Trace("sg-gen-tg-debug2") << ", f = " << f;
+ Trace("sg-gen-tg-debug2") << ", #args = " << s->d_func_args[f].size();
+ Trace("sg-gen-tg-debug2") << ", mchildNum = " << d_match_status_child_num;
+ Trace("sg-gen-tg-debug2") << ", #mchildren = " << d_match_children.size();
+ }
+ Trace("sg-gen-tg-debug2") << ", current substitution : {";
+ for( std::map< TypeNode, std::map< unsigned, TNode > >::iterator itt = subs.begin(); itt != subs.end(); ++itt ){
+ for( std::map< unsigned, TNode >::iterator it = itt->second.begin(); it != itt->second.end(); ++it ){
+ Trace("sg-gen-tg-debug2") << " " << it->first << " -> e" << s->d_cg->d_em[it->second];
+ }
+ }
+ Trace("sg-gen-tg-debug2") << " } " << std::endl;
+ }
+ if( d_status==1 ){
+ //a variable
+ if( d_match_status==0 ){
+ d_match_status++;
+ if( (d_match_mode & ( 1 << 1 ))!=0 ){
+ //only ground terms
+ if( !s->isGroundEqc( eqc ) ){
+ return false;
+ }
+ }else if( (d_match_mode & ( 1 << 2 ))!=0 ){
+ //only non-ground terms
+ //if( s->isGroundEqc( eqc ) ){
+ // return false;
+ //}
+ }
+ //store the match : restricted if match_mode.0 = 1
+ if( (d_match_mode & ( 1 << 0 ))!=0 ){
+ std::map< TNode, bool >::iterator it = rev_subs.find( eqc );
+ if( it==rev_subs.end() ){
+ rev_subs[eqc] = true;
+ }else{
+ return false;
+ }
+ }
+ Assert( subs[d_typ].find( d_status_num )==subs[d_typ].end() );
+ subs[d_typ][d_status_num] = eqc;
+ return true;
+ }else{
+ //clean up
+ subs[d_typ].erase( d_status_num );
+ if( (d_match_mode & ( 1 << 0 ))!=0 ){
+ rev_subs.erase( eqc );
+ }
+ return false;
+ }
+ }else if( d_status==2 ){
+ if( d_match_status==0 ){
+ d_match_status++;
+ Assert( d_status_num<(int)s->getNumTgVars( d_typ ) );
+ std::map< unsigned, TNode >::iterator it = subs[d_typ].find( d_status_num );
+ Assert( it!=subs[d_typ].end() );
+ return it->second==eqc;
+ }else{
+ return false;
+ }
+ }else if( d_status==5 ){
+ //Assert( d_match_children.size()<=d_children.size() );
+ //enumerating over f-applications in eqc
+ if( d_match_status_child_num<0 ){
+ return false;
+ }else if( d_match_status==0 ){
+ //set up next binding
+ if( d_match_status_child_num==(int)d_match_children.size() ){
+ if( d_match_status_child_num==0 ){
+ //initial binding
+ TNode f = s->getTgFunc( d_typ, d_status_num );
+ std::map< TNode, TermArgTrie >::iterator it = s->getTermDatabase()->d_func_map_eqc_trie[f].d_data.find( eqc );
+ if( it!=s->getTermDatabase()->d_func_map_eqc_trie[f].d_data.end() ){
+ d_match_children.push_back( it->second.d_data.begin() );
+ d_match_children_end.push_back( it->second.d_data.end() );
+ }else{
+ d_match_status++;
+ d_match_status_child_num--;
+ return getNextMatch( s, eqc, subs, rev_subs );
+ }
+ }else{
+ d_match_children.push_back( d_match_children[d_match_status_child_num-1]->second.d_data.begin() );
+ d_match_children_end.push_back( d_match_children[d_match_status_child_num-1]->second.d_data.end() );
+ }
+ }
+ d_match_status++;
+ Assert( d_match_status_child_num+1==(int)d_match_children.size() );
+ if( d_match_children[d_match_status_child_num]==d_match_children_end[d_match_status_child_num] ){
+ //no more arguments to bind
+ d_match_children.pop_back();
+ d_match_children_end.pop_back();
+ d_match_status_child_num--;
+ return getNextMatch( s, eqc, subs, rev_subs );
+ }else{
+ if( d_match_status_child_num==(int)d_children.size() ){
+ //successfully matched all children
+ d_match_children.pop_back();
+ d_match_children_end.pop_back();
+ d_match_status_child_num--;
+ return true;//return d_match_children[d_match_status]!=d_match_children_end[d_match_status];
+ }else{
+ //do next binding
+ 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 );
+ return getNextMatch( s, eqc, subs, rev_subs );
+ }
+ }
+ }else{
+ Assert( d_match_status==1 );
+ Assert( d_match_status_child_num+1==(int)d_match_children.size() );
+ Assert( d_match_children[d_match_status_child_num]!=d_match_children_end[d_match_status_child_num] );
+ d_match_status--;
+ 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 ) ){
+ d_match_status_child_num++;
+ return getNextMatch( s, eqc, subs, rev_subs );
+ }else{
+ //iterate
+ d_match_children[d_match_status_child_num]++;
+ return getNextMatch( s, eqc, subs, rev_subs );
+ }
+ }
+ }
+ Assert( false );
+ return false;
+}
+
+unsigned TermGenerator::getDepth( TermGenEnv * s ) {
+ if( d_status==5 ){
+ unsigned maxd = 0;
+ for( unsigned i=0; i<d_children.size(); i++ ){
+ unsigned d = s->d_tg_alloc[d_children[i]].getDepth( s );
+ if( d>maxd ){
+ maxd = d;
+ }
+ }
+ return 1+maxd;
+ }else{
+ return 0;
+ }
+}
+
+unsigned TermGenerator::calculateGeneralizationDepth( TermGenEnv * s, std::map< TypeNode, std::vector< int > >& fvs ) {
+ if( d_status==5 ){
+ unsigned sum = 1;
+ for( unsigned i=0; i<d_children.size(); i++ ){
+ sum += s->d_tg_alloc[d_children[i]].calculateGeneralizationDepth( s, fvs );
+ }
+ return sum;
+ }else{
+ Assert( d_status==2 || d_status==1 );
+ std::map< TypeNode, std::vector< int > >::iterator it = fvs.find( d_typ );
+ if( it!=fvs.end() ){
+ if( std::find( it->second.begin(), it->second.end(), d_status_num )!=it->second.end() ){
+ return 1;
+ }
+ }
+ fvs[d_typ].push_back( d_status_num );
+ return 0;
+ }
+}
+
+unsigned TermGenerator::getGeneralizationDepth( TermGenEnv * s ) {
+ //if( s->d_gen_relevant_terms ){
+ // return s->d_tg_gdepth;
+ //}else{
+ std::map< TypeNode, std::vector< int > > fvs;
+ return calculateGeneralizationDepth( s, fvs );
+ //}
+}
+
+Node TermGenerator::getTerm( TermGenEnv * s ) {
+ if( d_status==1 || d_status==2 ){
+ Assert( !d_typ.isNull() );
+ return s->getFreeVar( d_typ, d_status_num );
+ }else if( d_status==5 ){
+ Node f = s->getTgFunc( d_typ, d_status_num );
+ if( d_children.size()==s->d_func_args[f].size() ){
+ std::vector< Node > children;
+ if( s->d_tg_func_param[f] ){
+ children.push_back( f );
+ }
+ for( unsigned i=0; i<d_children.size(); i++ ){
+ Node nc = s->d_tg_alloc[d_children[i]].getTerm( s );
+ if( nc.isNull() ){
+ return Node::null();
+ }else{
+ //Assert( nc.getType()==s->d_func_args[f][i] );
+ children.push_back( nc );
+ }
+ }
+ return NodeManager::currentNM()->mkNode( s->d_func_kind[f], children );
+ }
+ }else{
+ Assert( false );
+ }
+ return Node::null();
+}
+
+void TermGenerator::debugPrint( TermGenEnv * s, const char * c, const char * cd ) {
+ Trace(cd) << "[*" << d_id << "," << d_status << "]:";
+ if( d_status==1 || d_status==2 ){
+ Trace(c) << s->getFreeVar( d_typ, d_status_num );
+ }else if( d_status==5 ){
+ TNode f = s->getTgFunc( d_typ, d_status_num );
+ Trace(c) << "(" << f;
+ for( unsigned i=0; i<d_children.size(); i++ ){
+ Trace(c) << " ";
+ s->d_tg_alloc[d_children[i]].debugPrint( s, c, cd );
+ }
+ if( d_children.size()<s->d_func_args[f].size() ){
+ Trace(c) << " ...";
+ }
+ Trace(c) << ")";
+ }else{
+ Trace(c) << "???";
+ }
+}
+
+void TermGenEnv::collectSignatureInformation() {
+ d_typ_tg_funcs.clear();
+ d_funcs.clear();
+ d_func_kind.clear();
+ d_func_args.clear();
+ TypeNode tnull;
+ for( std::map< Node, TermArgTrie >::iterator it = getTermDatabase()->d_func_map_trie.begin(); it != getTermDatabase()->d_func_map_trie.end(); ++it ){
+ if( !getTermDatabase()->d_op_map[it->first].empty() ){
+ Node nn = getTermDatabase()->d_op_map[it->first][0];
+ if( d_cg->isHandledTerm( nn ) && nn.getKind()!=APPLY_SELECTOR_TOTAL && !nn.getType().isBoolean() ){
+ bool do_enum = true;
+ //check if we have enumerated ground terms
+ if( nn.getKind()==APPLY_UF ){
+ if( !d_cg->hasEnumeratedUf( nn ) ){
+ do_enum = false;
+ }
+ }
+ if( do_enum ){
+ d_funcs.push_back( it->first );
+ for( unsigned i=0; i<nn.getNumChildren(); i++ ){
+ d_func_args[it->first].push_back( nn[i].getType() );
+ }
+ d_func_kind[it->first] = nn.getKind();
+ d_typ_tg_funcs[tnull].push_back( it->first );
+ d_typ_tg_funcs[nn.getType()].push_back( it->first );
+ d_tg_func_param[it->first] = ( nn.getMetaKind() == kind::metakind::PARAMETERIZED );
+ Trace("sg-rel-sig") << "Will enumerate function applications of : " << it->first << ", #args = " << d_func_args[it->first].size() << ", kind = " << nn.getKind() << std::endl;
+ getTermDatabase()->computeUfEqcTerms( it->first );
+ }
+ }
+ }
+ }
+ //shuffle functions
+ for( std::map< TypeNode, std::vector< TNode > >::iterator it = d_typ_tg_funcs.begin(); it != d_typ_tg_funcs.end(); ++it ){
+ std::random_shuffle( it->second.begin(), it->second.end() );
+ if( it->first.isNull() ){
+ Trace("sg-gen-tg-debug") << "In this order : ";
+ for( unsigned i=0; i<it->second.size(); i++ ){
+ Trace("sg-gen-tg-debug") << it->second[i] << " ";
+ }
+ Trace("sg-gen-tg-debug") << std::endl;
+ }
+ }
+}
+
+void TermGenEnv::reset( unsigned depth, bool genRelevant, TypeNode tn ) {
+ Assert( d_tg_alloc.empty() );
+ d_tg_alloc.clear();
+
+ if( genRelevant ){
+ for( unsigned i=0; i<2; i++ ){
+ d_ccand_eqc[i].clear();
+ d_ccand_eqc[i].push_back( d_relevant_eqc[i] );
+ }
+ }
+
+ d_tg_id = 0;
+ d_tg_gdepth = 0;
+ d_tg_gdepth_limit = depth;
+ d_gen_relevant_terms = genRelevant;
+ d_tg_alloc[0].reset( this, tn );
+}
+
+bool TermGenEnv::getNextTerm() {
+ if( d_tg_alloc[0].getNextTerm( this, d_tg_gdepth_limit ) ){
+ Assert( (int)d_tg_alloc[0].getGeneralizationDepth( this )<=d_tg_gdepth_limit );
+ if( (int)d_tg_alloc[0].getGeneralizationDepth( this )!=d_tg_gdepth_limit ){
+ return getNextTerm();
+ }else{
+ return true;
+ }
+ }else{
+ return false;
+ }
+}
+
+//reset matching
+void TermGenEnv::resetMatching( TNode eqc, unsigned mode ) {
+ d_tg_alloc[0].resetMatching( this, eqc, mode );
+}
+
+//get next match
+bool TermGenEnv::getNextMatch( TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs ) {
+ return d_tg_alloc[0].getNextMatch( this, eqc, subs, rev_subs );
+}
+
+//get term
+Node TermGenEnv::getTerm() {
+ return d_tg_alloc[0].getTerm( this );
+}
+
+void TermGenEnv::debugPrint( const char * c, const char * cd ) {
+ d_tg_alloc[0].debugPrint( this, c, cd );
+}
+
+unsigned TermGenEnv::getNumTgVars( TypeNode tn ) {
+ return d_var_id[tn];
+}
+
+bool TermGenEnv::allowVar( TypeNode tn ) {
+ std::map< TypeNode, unsigned >::iterator it = d_var_limit.find( tn );
+ if( it==d_var_limit.end() ){
+ return true;
+ }else{
+ return d_var_id[tn]<it->second;
+ }
+}
+
+void TermGenEnv::addVar( TypeNode tn ) {
+ d_var_id[tn]++;
+}
+
+void TermGenEnv::removeVar( TypeNode tn ) {
+ d_var_id[tn]--;
+ //d_var_eq_tg.pop_back();
+ //d_var_tg.pop_back();
+}
+
+unsigned TermGenEnv::getNumTgFuncs( TypeNode tn ) {
+ return d_typ_tg_funcs[tn].size();
+}
+
+TNode TermGenEnv::getTgFunc( TypeNode tn, unsigned i ) {
+ return d_typ_tg_funcs[tn][i];
+}
+
+Node TermGenEnv::getFreeVar( TypeNode tn, unsigned i ) {
+ return d_cg->getFreeVar( tn, i );
+}
+
+bool TermGenEnv::considerCurrentTerm() {
+ Assert( !d_tg_alloc.empty() );
+
+ //if generalization depth is too large, don't consider it
+ unsigned i = d_tg_alloc.size();
+ Trace("sg-gen-tg-debug") << "Consider term ";
+ d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" );
+ Trace("sg-gen-tg-debug") << "? curr term size = " << d_tg_alloc.size() << ", last status = " << d_tg_alloc[i-1].d_status;
+ Trace("sg-gen-tg-debug") << std::endl;
+
+ if( d_tg_gdepth_limit>=0 && d_tg_alloc[0].getGeneralizationDepth( this )>(unsigned)d_tg_gdepth_limit ){
+ Trace("sg-gen-consider-term") << "-> generalization depth of ";
+ d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-tg-debug" );
+ Trace("sg-gen-consider-term") << " is too high " << d_tg_gdepth << " " << d_tg_alloc[0].getGeneralizationDepth( this ) << ", do not consider." << std::endl;
+ return false;
+ }
+
+ //----optimizations
+ /*
+ if( d_tg_alloc[i-1].d_status==1 ){
+ }else if( d_tg_alloc[i-1].d_status==2 ){
+ }else if( d_tg_alloc[i-1].d_status==5 ){
+ }else{
+ Trace("sg-gen-tg-debug") << "Bad tg: " << &d_tg_alloc[i-1] << std::endl;
+ Assert( false );
+ }
+ */
+ //if equated two variables, first check if context-independent TODO
+ //----end optimizations
+
+
+ //check based on which candidate equivalence classes match
+ if( d_gen_relevant_terms ){
+ Trace("sg-gen-tg-debug") << "Filter based on relevant ground EQC";
+ Trace("sg-gen-tg-debug") << ", #eqc to try = " << d_ccand_eqc[0][i-1].size() << "/" << d_ccand_eqc[1][i-1].size() << std::endl;
+
+ Assert( d_ccand_eqc[0].size()>=2 );
+ Assert( d_ccand_eqc[0].size()==d_ccand_eqc[1].size() );
+ Assert( d_ccand_eqc[0].size()==d_tg_id+1 );
+ Assert( d_tg_id==d_tg_alloc.size() );
+ for( unsigned r=0; r<2; r++ ){
+ d_ccand_eqc[r][i].clear();
+ }
+
+ //re-check feasibility of EQC
+ for( unsigned r=0; r<2; r++ ){
+ for( unsigned j=0; j<d_ccand_eqc[r][i-1].size(); j++ ){
+ std::map< TypeNode, std::map< unsigned, TNode > > subs;
+ std::map< TNode, bool > rev_subs;
+ unsigned mode;
+ if( r==0 ){
+ mode = d_cg->optReqDistinctVarPatterns() ? ( 1 << 0 ) : 0;
+ mode = mode | (1 << 2 );
+ }else{
+ mode = 1 << 1;
+ }
+ d_tg_alloc[0].resetMatching( this, d_ccand_eqc[r][i-1][j], mode );
+ if( d_tg_alloc[0].getNextMatch( this, d_ccand_eqc[r][i-1][j], subs, rev_subs ) ){
+ d_ccand_eqc[r][i].push_back( d_ccand_eqc[r][i-1][j] );
+ }
+ }
+ }
+ for( unsigned r=0; r<2; r++ ){
+ Trace("sg-gen-tg-debug") << "Current eqc of type " << r << " : ";
+ for( unsigned j=0; j<d_ccand_eqc[r][i].size(); j++ ){
+ Trace("sg-gen-tg-debug") << "e" << d_cg->d_em[d_ccand_eqc[r][i][j]] << " ";
+ }
+ Trace("sg-gen-tg-debug") << std::endl;
+ }
+ if( options::conjectureFilterActiveTerms() && d_ccand_eqc[0][i].empty() ){
+ Trace("sg-gen-consider-term") << "Do not consider term of form ";
+ d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-consider-term-debug" );
+ Trace("sg-gen-consider-term") << " since no relevant EQC matches it." << std::endl;
+ return false;
+ }
+ if( options::conjectureFilterModel() && d_ccand_eqc[1][i].empty() ){
+ Trace("sg-gen-consider-term") << "Do not consider term of form ";
+ d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-consider-term-debug" );
+ Trace("sg-gen-consider-term") << " since no ground EQC matches it." << std::endl;
+ return false;
+ }
+ }
+ Trace("sg-gen-tg-debug") << "Will consider term ";
+ d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" );
+ Trace("sg-gen-tg-debug") << std::endl;
+ Trace("sg-gen-consider-term-debug") << std::endl;
+ return true;
+}
+
+void TermGenEnv::changeContext( bool add ) {
+ if( add ){
+ for( unsigned r=0; r<2; r++ ){
+ d_ccand_eqc[r].push_back( std::vector< TNode >() );
+ }
+ d_tg_id++;
+ }else{
+ for( unsigned r=0; r<2; r++ ){
+ d_ccand_eqc[r].pop_back();
+ }
+ d_tg_id--;
+ Assert( d_tg_alloc.find( d_tg_id )!=d_tg_alloc.end() );
+ d_tg_alloc.erase( d_tg_id );
+ }
+}
+
+bool TermGenEnv::considerCurrentTermCanon( unsigned tg_id ){
+ Assert( tg_id<d_tg_alloc.size() );
+ if( options::conjectureFilterCanonical() ){
+ //check based on a canonicity of the term (if there is one)
+ Trace("sg-gen-tg-debug") << "Consider term canon ";
+ d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" );
+ Trace("sg-gen-tg-debug") << ", tg is [" << tg_id << "]..." << std::endl;
+
+ Node ln = d_tg_alloc[tg_id].getTerm( this );
+ Trace("sg-gen-tg-debug") << "Term is " << ln << std::endl;
+ return d_cg->considerTermCanon( ln, d_gen_relevant_terms );
+ }
+ return true;
+}
+
+bool TermGenEnv::isRelevantFunc( Node f ) {
+ return std::find( d_funcs.begin(), d_funcs.end(), f )!=d_funcs.end();
+}
+TermDb * TermGenEnv::getTermDatabase() {
+ return d_cg->getTermDatabase();
+}
+Node TermGenEnv::getGroundEqc( TNode r ) {
+ return d_cg->getGroundEqc( r );
+}
+bool TermGenEnv::isGroundEqc( TNode r ){
+ return d_cg->isGroundEqc( r );
+}
+bool TermGenEnv::isGroundTerm( TNode n ){
+ return d_cg->isGroundTerm( n );
+}
+
+
+void SubstitutionIndex::addSubstitution( TNode eqc, std::vector< TNode >& vars, std::vector< TNode >& terms, unsigned i ) {
+ if( i==vars.size() ){
+ d_var = eqc;
+ }else{
+ Assert( d_var.isNull() || d_var==vars[i] );
+ d_var = vars[i];
+ d_children[terms[i]].addSubstitution( eqc, vars, terms, i+1 );
+ }
+}
+
+bool SubstitutionIndex::notifySubstitutions( ConjectureGenerator * s, std::map< TNode, TNode >& subs, TNode rhs, unsigned numVars, unsigned i ) {
+ if( i==numVars ){
+ Assert( d_children.empty() );
+ return s->notifySubstitution( d_var, subs, rhs );
+ }else{
+ Assert( i==0 || !d_children.empty() );
+ for( std::map< TNode, SubstitutionIndex >::iterator it = d_children.begin(); it != d_children.end(); ++it ){
+ Trace("sg-cconj-debug2") << "Try " << d_var << " -> " << it->first << " (" << i << "/" << numVars << ")" << std::endl;
+ subs[d_var] = it->first;
+ if( !it->second.notifySubstitutions( s, subs, rhs, numVars, i+1 ) ){
+ return false;
+ }
+ }
+ return true;
+ }
+}
+
+
+void TheoremIndex::addTheorem( std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs ){
+ if( lhs_v.empty() ){
+ if( std::find( d_terms.begin(), d_terms.end(), rhs )==d_terms.end() ){
+ d_terms.push_back( rhs );
+ }
+ }else{
+ unsigned index = lhs_v.size()-1;
+ if( lhs_arg[index]==lhs_v[index].getNumChildren() ){
+ lhs_v.pop_back();
+ lhs_arg.pop_back();
+ addTheorem( lhs_v, lhs_arg, rhs );
+ }else{
+ lhs_arg[index]++;
+ addTheoremNode( lhs_v[index][lhs_arg[index]-1], lhs_v, lhs_arg, rhs );
+ }
+ }
+}
+
+void TheoremIndex::addTheoremNode( TNode curr, std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs ){
+ Trace("thm-db-debug") << "Adding conjecture for subterm " << curr << "..." << std::endl;
+ if( curr.hasOperator() ){
+ lhs_v.push_back( curr );
+ lhs_arg.push_back( 0 );
+ d_children[curr.getOperator()].addTheorem( lhs_v, lhs_arg, rhs );
+ }else{
+ Assert( curr.getKind()==kind::BOUND_VARIABLE );
+ TypeNode tn = curr.getType();
+ Assert( d_var[tn].isNull() || d_var[tn]==curr );
+ d_var[tn] = curr;
+ d_children[curr].addTheorem( lhs_v, lhs_arg, rhs );
+ }
+}
+
+void TheoremIndex::getEquivalentTerms( std::vector< TNode >& n_v, std::vector< unsigned >& n_arg,
+ std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs,
+ std::vector< Node >& terms ) {
+ Trace("thm-db-debug") << "Get equivalent terms " << n_v.size() << " " << n_arg.size() << std::endl;
+ if( n_v.empty() ){
+ Trace("thm-db-debug") << "Number of terms : " << d_terms.size() << std::endl;
+ //apply substutitions to RHS's
+ for( unsigned i=0; i<d_terms.size(); i++ ){
+ Node n = d_terms[i].substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ terms.push_back( n );
+ }
+ }else{
+ unsigned index = n_v.size()-1;
+ if( n_arg[index]==n_v[index].getNumChildren() ){
+ n_v.pop_back();
+ n_arg.pop_back();
+ getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms );
+ }else{
+ n_arg[index]++;
+ getEquivalentTermsNode( n_v[index][n_arg[index]-1], n_v, n_arg, smap, vars, subs, terms );
+ }
+ }
+}
+
+void TheoremIndex::getEquivalentTermsNode( Node curr, std::vector< TNode >& n_v, std::vector< unsigned >& n_arg,
+ std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs,
+ std::vector< Node >& terms ) {
+ Trace("thm-db-debug") << "Get equivalent based on subterm " << curr << "..." << std::endl;
+ if( curr.hasOperator() ){
+ Trace("thm-db-debug") << "Check based on operator..." << std::endl;
+ std::map< TNode, TheoremIndex >::iterator it = d_children.find( curr.getOperator() );
+ if( it!=d_children.end() ){
+ n_v.push_back( curr );
+ n_arg.push_back( 0 );
+ it->second.getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms );
+ }
+ Trace("thm-db-debug") << "...done check based on operator" << std::endl;
+ }
+ TypeNode tn = curr.getType();
+ std::map< TypeNode, TNode >::iterator itt = d_var.find( tn );
+ if( itt!=d_var.end() ){
+ Trace("thm-db-debug") << "Check for substitution with " << itt->second << "..." << std::endl;
+ Assert( curr.getType()==itt->second.getType() );
+ //add to substitution if possible
+ bool success = false;
+ std::map< TNode, TNode >::iterator it = smap.find( itt->second );
+ if( it==smap.end() ){
+ smap[itt->second] = curr;
+ vars.push_back( itt->second );
+ subs.push_back( curr );
+ success = true;
+ }else if( it->second==curr ){
+ success = true;
+ }else{
+ //also check modulo equality (in universal equality engine)
+ }
+ Trace("thm-db-debug") << "...check for substitution with " << itt->second << ", success = " << success << "." << std::endl;
+ if( success ){
+ d_children[itt->second].getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms );
+ }
+ }
+}
+
+void TheoremIndex::debugPrint( const char * c, unsigned ind ) {
+ for( std::map< TNode, TheoremIndex >::iterator it = d_children.begin(); it != d_children.end(); ++it ){
+ for( unsigned i=0; i<ind; i++ ){ Trace(c) << " "; }
+ Trace(c) << it->first << std::endl;
+ it->second.debugPrint( c, ind+1 );
+ }
+ if( !d_terms.empty() ){
+ for( unsigned i=0; i<ind; i++ ){ Trace(c) << " "; }
+ Trace(c) << "{";
+ for( unsigned i=0; i<d_terms.size(); i++ ){
+ Trace(c) << " " << d_terms[i];
+ }
+ Trace(c) << " }" << std::endl;
+ }
+ //if( !d_var.isNull() ){
+ // for( unsigned i=0; i<ind; i++ ){ Trace(c) << " "; }
+ // Trace(c) << "var:" << d_var << std::endl;
+ //}
+}
+
+bool ConjectureGenerator::optReqDistinctVarPatterns() { return false; }
+bool ConjectureGenerator::optFilterUnknown() { return true; } //may change
+int ConjectureGenerator::optFilterScoreThreshold() { return 1; }
+unsigned ConjectureGenerator::optFullCheckFrequency() { return 1; }
+
+bool ConjectureGenerator::optStatsOnly() { return false; }
+
+}
diff --git a/src/theory/quantifiers/conjecture_generator.h b/src/theory/quantifiers/conjecture_generator.h
index 48694c99a..6f99777f4 100644
--- a/src/theory/quantifiers/conjecture_generator.h
+++ b/src/theory/quantifiers/conjecture_generator.h
@@ -1,437 +1,437 @@
-/********************* */
-/*! \file conjecture_generator.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 conjecture generator class
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CONJECTURE_GENERATOR_H
-#define CONJECTURE_GENERATOR_H
-
-#include "context/cdhashmap.h"
-#include "context/cdchunk_list.h"
-#include "theory/quantifiers_engine.h"
-#include "theory/type_enumerator.h"
-
-namespace CVC4 {
-namespace theory {
-namespace quantifiers {
-
-class TermArgTrie;
-
-//algorithm for computing candidate subgoals
-
-class ConjectureGenerator;
-
-// operator independent index of arguments for an EQC
-class OpArgIndex
-{
-public:
- std::map< TNode, OpArgIndex > d_child;
- std::vector< TNode > d_ops;
- std::vector< TNode > d_op_terms;
- void addTerm( ConjectureGenerator * s, TNode n, unsigned index = 0 );
- Node getGroundTerm( ConjectureGenerator * s, std::vector< TNode >& args );
- void getGroundTerms( ConjectureGenerator * s, std::vector< TNode >& terms );
-};
-
-class PatternTypIndex
-{
-public:
- std::vector< TNode > d_terms;
- std::map< TypeNode, std::map< unsigned, PatternTypIndex > > d_children;
- void clear() {
- d_terms.clear();
- d_children.clear();
- }
-};
-
-class SubstitutionIndex
-{
-public:
- //current variable, or ground EQC if d_children.empty()
- TNode d_var;
- std::map< TNode, SubstitutionIndex > d_children;
- //add substitution
- void addSubstitution( TNode eqc, std::vector< TNode >& vars, std::vector< TNode >& terms, unsigned i = 0 );
- //notify substitutions
- bool notifySubstitutions( ConjectureGenerator * s, std::map< TNode, TNode >& subs, TNode rhs, unsigned numVars, unsigned i = 0 );
-};
-
-class TermGenEnv;
-
-class TermGenerator
-{
-private:
- unsigned calculateGeneralizationDepth( TermGenEnv * s, std::map< TypeNode, std::vector< int > >& fvs );
-public:
- TermGenerator(){}
- TypeNode d_typ;
- unsigned d_id;
- //1 : consider as unique variable
- //2 : consider equal to another variable
- //5 : consider a function application
- unsigned d_status;
- int d_status_num;
- //for function applications: the number of children you have built
- int d_status_child_num;
- //children (pointers to TermGenerators)
- std::vector< unsigned > d_children;
-
- //match status
- int d_match_status;
- int d_match_status_child_num;
- //match mode bits
- //0 : different variables must have different matches
- //1 : variables must map to ground terms
- //2 : variables must map to non-ground terms
- unsigned d_match_mode;
- //children
- std::vector< std::map< TNode, TermArgTrie >::iterator > d_match_children;
- std::vector< std::map< TNode, TermArgTrie >::iterator > d_match_children_end;
-
- void reset( TermGenEnv * s, TypeNode tn );
- bool getNextTerm( TermGenEnv * s, unsigned depth );
- void resetMatching( TermGenEnv * s, TNode eqc, unsigned mode );
- bool getNextMatch( TermGenEnv * s, TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs );
-
- unsigned getDepth( TermGenEnv * s );
- unsigned getGeneralizationDepth( TermGenEnv * s );
- Node getTerm( TermGenEnv * s );
-
- void debugPrint( TermGenEnv * s, const char * c, const char * cd );
-};
-
-
-class TermGenEnv
-{
-public:
- //collect signature information
- void collectSignatureInformation();
- //reset function
- void reset( unsigned gdepth, bool genRelevant, TypeNode tgen );
- //get next term
- bool getNextTerm();
- //reset matching
- void resetMatching( TNode eqc, unsigned mode );
- //get next match
- bool getNextMatch( TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs );
- //get term
- Node getTerm();
- //debug print
- void debugPrint( const char * c, const char * cd );
-
- //conjecture generation
- ConjectureGenerator * d_cg;
- //the current number of enumerated variables per type
- std::map< TypeNode, unsigned > d_var_id;
- //the limit of number of variables per type to enumerate
- std::map< TypeNode, unsigned > d_var_limit;
- //the functions we can currently generate
- std::map< TypeNode, std::vector< TNode > > d_typ_tg_funcs;
- // whether functions must add operators
- std::map< TNode, bool > d_tg_func_param;
- //the equivalence classes (if applicable) that match the currently generated term
- bool d_gen_relevant_terms;
- //relevant equivalence classes
- std::vector< TNode > d_relevant_eqc[2];
- //candidate equivalence classes
- std::vector< std::vector< TNode > > d_ccand_eqc[2];
- //the term generation objects
- unsigned d_tg_id;
- std::map< unsigned, TermGenerator > d_tg_alloc;
- unsigned d_tg_gdepth;
- int d_tg_gdepth_limit;
-
- //all functions
- std::vector< TNode > d_funcs;
- //function to kind map
- std::map< TNode, Kind > d_func_kind;
- //type of each argument of the function
- std::map< TNode, std::vector< TypeNode > > d_func_args;
-
- //access functions
- unsigned getNumTgVars( TypeNode tn );
- bool allowVar( TypeNode tn );
- void addVar( TypeNode tn );
- void removeVar( TypeNode tn );
- unsigned getNumTgFuncs( TypeNode tn );
- TNode getTgFunc( TypeNode tn, unsigned i );
- Node getFreeVar( TypeNode tn, unsigned i );
- bool considerCurrentTerm();
- bool considerCurrentTermCanon( unsigned tg_id );
- void changeContext( bool add );
- bool isRelevantFunc( Node f );
- //carry
- TermDb * getTermDatabase();
- Node getGroundEqc( TNode r );
- bool isGroundEqc( TNode r );
- bool isGroundTerm( TNode n );
-};
-
-
-
-class TheoremIndex
-{
-private:
- void addTheorem( std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs );
- void addTheoremNode( TNode curr, std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs );
- void getEquivalentTerms( std::vector< TNode >& n_v, std::vector< unsigned >& n_arg,
- std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs,
- std::vector< Node >& terms );
- void getEquivalentTermsNode( Node curr, std::vector< TNode >& n_v, std::vector< unsigned >& n_arg,
- std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs,
- std::vector< Node >& terms );
-public:
- std::map< TypeNode, TNode > d_var;
- std::map< TNode, TheoremIndex > d_children;
- std::vector< Node > d_terms;
-
- void addTheorem( TNode lhs, TNode rhs ) {
- std::vector< TNode > v;
- std::vector< unsigned > a;
- addTheoremNode( lhs, v, a, rhs );
- }
- void getEquivalentTerms( TNode n, std::vector< Node >& terms ) {
- std::vector< TNode > nv;
- std::vector< unsigned > na;
- std::map< TNode, TNode > smap;
- std::vector< TNode > vars;
- std::vector< TNode > subs;
- getEquivalentTermsNode( n, nv, na, smap, vars, subs, terms );
- }
- void clear(){
- d_var.clear();
- d_children.clear();
- d_terms.clear();
- }
- void debugPrint( const char * c, unsigned ind = 0 );
-};
-
-
-
-class ConjectureGenerator : public QuantifiersModule
-{
- friend class OpArgIndex;
- friend class PatGen;
- friend class PatternGenEqc;
- friend class PatternGen;
- friend class SubsEqcIndex;
- friend class TermGenerator;
- friend class TermGenEnv;
- typedef context::CDChunkList<Node> NodeList;
- typedef context::CDHashMap< Node, Node, NodeHashFunction > NodeMap;
- typedef context::CDHashMap< Node, bool, NodeHashFunction > BoolMap;
-//this class maintains a congruence closure for *universal* facts
-private:
- //notification class for equality engine
- class NotifyClass : public eq::EqualityEngineNotify {
- ConjectureGenerator& d_sg;
- public:
- NotifyClass(ConjectureGenerator& sg): d_sg(sg) {}
- bool eqNotifyTriggerEquality(TNode equality, bool value) { return true; }
- bool eqNotifyTriggerPredicate(TNode predicate, bool value) { return true; }
- bool eqNotifyTriggerTermEquality(TheoryId tag, TNode t1, TNode t2, bool value) { return true; }
- void eqNotifyConstantTermMerge(TNode t1, TNode t2) { }
- void eqNotifyNewClass(TNode t) { d_sg.eqNotifyNewClass(t); }
- void eqNotifyPreMerge(TNode t1, TNode t2) { d_sg.eqNotifyPreMerge(t1, t2); }
- void eqNotifyPostMerge(TNode t1, TNode t2) { d_sg.eqNotifyPostMerge(t1, t2); }
- void eqNotifyDisequal(TNode t1, TNode t2, TNode reason) {d_sg.eqNotifyDisequal(t1, t2, reason); }
- };/* class ConjectureGenerator::NotifyClass */
- /** The notify class */
- NotifyClass d_notify;
- class EqcInfo{
- public:
- EqcInfo( context::Context* c );
- //representative
- context::CDO< Node > d_rep;
- };
- /** get or make eqc info */
- EqcInfo* getOrMakeEqcInfo( TNode n, bool doMake = false );
- /** (universal) equaltity engine */
- eq::EqualityEngine d_uequalityEngine;
- /** pending adds */
- std::vector< Node > d_upendingAdds;
- /** relevant terms */
- std::map< Node, bool > d_urelevant_terms;
- /** information necessary for equivalence classes */
- std::map< Node, EqcInfo* > d_eqc_info;
- /** called when a new equivalance class is created */
- void eqNotifyNewClass(TNode t);
- /** called when two equivalance classes will merge */
- void eqNotifyPreMerge(TNode t1, TNode t2);
- /** called when two equivalance classes have merged */
- void eqNotifyPostMerge(TNode t1, TNode t2);
- /** called when two equivalence classes are made disequal */
- void eqNotifyDisequal(TNode t1, TNode t2, TNode reason);
- /** are universal equal */
- bool areUniversalEqual( TNode n1, TNode n2 );
- /** are universal disequal */
- bool areUniversalDisequal( TNode n1, TNode n2 );
- /** get universal representative */
- TNode getUniversalRepresentative( TNode n, bool add = false );
- /** set relevant */
- void setUniversalRelevant( TNode n );
- /** ordering for universal terms */
- bool isUniversalLessThan( TNode rt1, TNode rt2 );
-
- /** the nodes we have reported as canonical representative */
- std::vector< TNode > d_ue_canon;
- /** is reported canon */
- bool isReportedCanon( TNode n );
- /** mark that term has been reported as canonical rep */
- void markReportedCanon( TNode n );
-
-private: //information regarding the conjectures
- /** list of all conjectures */
- std::vector< Node > d_conjectures;
- /** list of all waiting conjectures */
- std::vector< Node > d_waiting_conjectures_lhs;
- std::vector< Node > d_waiting_conjectures_rhs;
- std::vector< int > d_waiting_conjectures_score;
- /** map of currently considered equality conjectures */
- std::map< Node, std::vector< Node > > d_waiting_conjectures;
- /** map of equality conjectures */
- std::map< Node, std::vector< Node > > d_eq_conjectures;
- /** currently existing conjectures in equality engine */
- BoolMap d_ee_conjectures;
- /** conjecture index */
- TheoremIndex d_thm_index;
-private: //free variable list
- //free variables
- std::map< TypeNode, std::vector< Node > > d_free_var;
- //map from free variable to FV#
- std::map< TNode, unsigned > d_free_var_num;
- // get canonical free variable #i of type tn
- Node getFreeVar( TypeNode tn, unsigned i );
- // get canonical term, return null if it contains a term apart from handled signature
- Node getCanonicalTerm( TNode n, std::map< TypeNode, unsigned >& var_count, std::map< TNode, TNode >& subs );
-private: //information regarding the terms
- //relevant patterns (the LHS's)
- std::map< TypeNode, std::vector< Node > > d_rel_patterns;
- //total number of unique variables
- std::map< TNode, unsigned > d_rel_pattern_var_sum;
- //by types
- PatternTypIndex d_rel_pattern_typ_index;
- // substitution to ground EQC index
- std::map< TNode, SubstitutionIndex > d_rel_pattern_subs_index;
- //patterns (the RHS's)
- std::map< TypeNode, std::vector< Node > > d_patterns;
- //patterns to # variables per type
- std::map< TNode, std::map< TypeNode, unsigned > > d_pattern_var_id;
- // # duplicated variables
- std::map< TNode, unsigned > d_pattern_var_duplicate;
- // is normal pattern? (variables allocated in canonical way left to right)
- std::map< TNode, int > d_pattern_is_normal;
- std::map< TNode, int > d_pattern_is_relevant;
- // patterns to a count of # operators (variables and functions)
- std::map< TNode, std::map< TNode, unsigned > > d_pattern_fun_id;
- // term size
- std::map< TNode, unsigned > d_pattern_fun_sum;
- // collect functions
- unsigned collectFunctions( TNode opat, TNode pat, std::map< TNode, unsigned >& funcs,
- std::map< TypeNode, unsigned >& mnvn, std::map< TypeNode, unsigned >& mxvn );
- // add pattern
- void registerPattern( Node pat, TypeNode tpat );
-private: //for debugging
- std::map< TNode, unsigned > d_em;
- unsigned d_conj_count;
-public:
- //term generation environment
- TermGenEnv d_tge;
- //consider term canon
- bool considerTermCanon( Node ln, bool genRelevant );
-public: //for generalization
- //generalizations
- bool isGeneralization( TNode patg, TNode pat ) {
- std::map< TNode, TNode > subs;
- return isGeneralization( patg, pat, subs );
- }
- bool isGeneralization( TNode patg, TNode pat, std::map< TNode, TNode >& subs );
- // get generalization depth
- int calculateGeneralizationDepth( TNode n, std::vector< TNode >& fv );
-private:
- //predicate for type
- std::map< TypeNode, Node > d_typ_pred;
- //get predicate for type
- Node getPredicateForType( TypeNode tn );
- //
- void getEnumerateUfTerm( Node n, unsigned num, std::vector< Node >& terms );
- //
- void getEnumeratePredUfTerm( Node n, unsigned num, std::vector< Node >& terms );
- // uf operators enumerated
- std::map< Node, bool > d_uf_enum;
-public: //for property enumeration
- //process this candidate conjecture
- void processCandidateConjecture( TNode lhs, TNode rhs, unsigned lhs_depth, unsigned rhs_depth );
- //whether it should be considered, negative : no, positive returns score
- int considerCandidateConjecture( TNode lhs, TNode rhs );
- //notified of a substitution
- bool notifySubstitution( TNode glhs, std::map< TNode, TNode >& subs, TNode rhs );
- //confirmation count
- unsigned d_subs_confirmCount;
- //individual witnesses (for range)
- std::vector< TNode > d_subs_confirmWitnessRange;
- //individual witnesses (for domain)
- std::map< TNode, std::vector< TNode > > d_subs_confirmWitnessDomain;
- //number of ground substitutions whose equality is unknown
- unsigned d_subs_unkCount;
-private: //information about ground equivalence classes
- TNode d_bool_eqc[2];
- std::map< TNode, Node > d_ground_eqc_map;
- std::vector< TNode > d_ground_terms;
- //operator independent term index
- std::map< TNode, OpArgIndex > d_op_arg_index;
- //is handled term
- bool isHandledTerm( TNode n );
- Node getGroundEqc( TNode r );
- bool isGroundEqc( TNode r );
- bool isGroundTerm( TNode n );
- //has enumerated UF
- bool hasEnumeratedUf( Node n );
- // count of full effort checks
- unsigned d_fullEffortCount;
- // has added lemma
- bool d_hasAddedLemma;
- //flush the waiting conjectures
- unsigned flushWaitingConjectures( unsigned& addedLemmas, int ldepth, int rdepth );
-public:
- ConjectureGenerator( QuantifiersEngine * qe, context::Context* c );
- ~ConjectureGenerator() throw() {}
- /* needs check */
- bool needsCheck( Theory::Effort e );
- /* reset at a round */
- void reset_round( 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 );
- /** Identify this module (for debugging, dynamic configuration, etc..) */
- std::string identify() const { return "ConjectureGenerator"; }
-//options
-private:
- bool optReqDistinctVarPatterns();
- bool optFilterUnknown();
- int optFilterScoreThreshold();
- unsigned optFullCheckFrequency();
- unsigned optFullCheckConjectures();
-
- bool optStatsOnly();
-};
-
-
-}
-}
-}
-
-#endif
+/********************* */
+/*! \file conjecture_generator.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 conjecture generator class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef CONJECTURE_GENERATOR_H
+#define CONJECTURE_GENERATOR_H
+
+#include "context/cdhashmap.h"
+#include "context/cdchunk_list.h"
+#include "theory/quantifiers_engine.h"
+#include "theory/type_enumerator.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+class TermArgTrie;
+
+//algorithm for computing candidate subgoals
+
+class ConjectureGenerator;
+
+// operator independent index of arguments for an EQC
+class OpArgIndex
+{
+public:
+ std::map< TNode, OpArgIndex > d_child;
+ std::vector< TNode > d_ops;
+ std::vector< TNode > d_op_terms;
+ void addTerm( ConjectureGenerator * s, TNode n, unsigned index = 0 );
+ Node getGroundTerm( ConjectureGenerator * s, std::vector< TNode >& args );
+ void getGroundTerms( ConjectureGenerator * s, std::vector< TNode >& terms );
+};
+
+class PatternTypIndex
+{
+public:
+ std::vector< TNode > d_terms;
+ std::map< TypeNode, std::map< unsigned, PatternTypIndex > > d_children;
+ void clear() {
+ d_terms.clear();
+ d_children.clear();
+ }
+};
+
+class SubstitutionIndex
+{
+public:
+ //current variable, or ground EQC if d_children.empty()
+ TNode d_var;
+ std::map< TNode, SubstitutionIndex > d_children;
+ //add substitution
+ void addSubstitution( TNode eqc, std::vector< TNode >& vars, std::vector< TNode >& terms, unsigned i = 0 );
+ //notify substitutions
+ bool notifySubstitutions( ConjectureGenerator * s, std::map< TNode, TNode >& subs, TNode rhs, unsigned numVars, unsigned i = 0 );
+};
+
+class TermGenEnv;
+
+class TermGenerator
+{
+private:
+ unsigned calculateGeneralizationDepth( TermGenEnv * s, std::map< TypeNode, std::vector< int > >& fvs );
+public:
+ TermGenerator(){}
+ TypeNode d_typ;
+ unsigned d_id;
+ //1 : consider as unique variable
+ //2 : consider equal to another variable
+ //5 : consider a function application
+ unsigned d_status;
+ int d_status_num;
+ //for function applications: the number of children you have built
+ int d_status_child_num;
+ //children (pointers to TermGenerators)
+ std::vector< unsigned > d_children;
+
+ //match status
+ int d_match_status;
+ int d_match_status_child_num;
+ //match mode bits
+ //0 : different variables must have different matches
+ //1 : variables must map to ground terms
+ //2 : variables must map to non-ground terms
+ unsigned d_match_mode;
+ //children
+ std::vector< std::map< TNode, TermArgTrie >::iterator > d_match_children;
+ std::vector< std::map< TNode, TermArgTrie >::iterator > d_match_children_end;
+
+ void reset( TermGenEnv * s, TypeNode tn );
+ bool getNextTerm( TermGenEnv * s, unsigned depth );
+ void resetMatching( TermGenEnv * s, TNode eqc, unsigned mode );
+ bool getNextMatch( TermGenEnv * s, TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs );
+
+ unsigned getDepth( TermGenEnv * s );
+ unsigned getGeneralizationDepth( TermGenEnv * s );
+ Node getTerm( TermGenEnv * s );
+
+ void debugPrint( TermGenEnv * s, const char * c, const char * cd );
+};
+
+
+class TermGenEnv
+{
+public:
+ //collect signature information
+ void collectSignatureInformation();
+ //reset function
+ void reset( unsigned gdepth, bool genRelevant, TypeNode tgen );
+ //get next term
+ bool getNextTerm();
+ //reset matching
+ void resetMatching( TNode eqc, unsigned mode );
+ //get next match
+ bool getNextMatch( TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs );
+ //get term
+ Node getTerm();
+ //debug print
+ void debugPrint( const char * c, const char * cd );
+
+ //conjecture generation
+ ConjectureGenerator * d_cg;
+ //the current number of enumerated variables per type
+ std::map< TypeNode, unsigned > d_var_id;
+ //the limit of number of variables per type to enumerate
+ std::map< TypeNode, unsigned > d_var_limit;
+ //the functions we can currently generate
+ std::map< TypeNode, std::vector< TNode > > d_typ_tg_funcs;
+ // whether functions must add operators
+ std::map< TNode, bool > d_tg_func_param;
+ //the equivalence classes (if applicable) that match the currently generated term
+ bool d_gen_relevant_terms;
+ //relevant equivalence classes
+ std::vector< TNode > d_relevant_eqc[2];
+ //candidate equivalence classes
+ std::vector< std::vector< TNode > > d_ccand_eqc[2];
+ //the term generation objects
+ unsigned d_tg_id;
+ std::map< unsigned, TermGenerator > d_tg_alloc;
+ unsigned d_tg_gdepth;
+ int d_tg_gdepth_limit;
+
+ //all functions
+ std::vector< TNode > d_funcs;
+ //function to kind map
+ std::map< TNode, Kind > d_func_kind;
+ //type of each argument of the function
+ std::map< TNode, std::vector< TypeNode > > d_func_args;
+
+ //access functions
+ unsigned getNumTgVars( TypeNode tn );
+ bool allowVar( TypeNode tn );
+ void addVar( TypeNode tn );
+ void removeVar( TypeNode tn );
+ unsigned getNumTgFuncs( TypeNode tn );
+ TNode getTgFunc( TypeNode tn, unsigned i );
+ Node getFreeVar( TypeNode tn, unsigned i );
+ bool considerCurrentTerm();
+ bool considerCurrentTermCanon( unsigned tg_id );
+ void changeContext( bool add );
+ bool isRelevantFunc( Node f );
+ //carry
+ TermDb * getTermDatabase();
+ Node getGroundEqc( TNode r );
+ bool isGroundEqc( TNode r );
+ bool isGroundTerm( TNode n );
+};
+
+
+
+class TheoremIndex
+{
+private:
+ void addTheorem( std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs );
+ void addTheoremNode( TNode curr, std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs );
+ void getEquivalentTerms( std::vector< TNode >& n_v, std::vector< unsigned >& n_arg,
+ std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs,
+ std::vector< Node >& terms );
+ void getEquivalentTermsNode( Node curr, std::vector< TNode >& n_v, std::vector< unsigned >& n_arg,
+ std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs,
+ std::vector< Node >& terms );
+public:
+ std::map< TypeNode, TNode > d_var;
+ std::map< TNode, TheoremIndex > d_children;
+ std::vector< Node > d_terms;
+
+ void addTheorem( TNode lhs, TNode rhs ) {
+ std::vector< TNode > v;
+ std::vector< unsigned > a;
+ addTheoremNode( lhs, v, a, rhs );
+ }
+ void getEquivalentTerms( TNode n, std::vector< Node >& terms ) {
+ std::vector< TNode > nv;
+ std::vector< unsigned > na;
+ std::map< TNode, TNode > smap;
+ std::vector< TNode > vars;
+ std::vector< TNode > subs;
+ getEquivalentTermsNode( n, nv, na, smap, vars, subs, terms );
+ }
+ void clear(){
+ d_var.clear();
+ d_children.clear();
+ d_terms.clear();
+ }
+ void debugPrint( const char * c, unsigned ind = 0 );
+};
+
+
+
+class ConjectureGenerator : public QuantifiersModule
+{
+ friend class OpArgIndex;
+ friend class PatGen;
+ friend class PatternGenEqc;
+ friend class PatternGen;
+ friend class SubsEqcIndex;
+ friend class TermGenerator;
+ friend class TermGenEnv;
+ typedef context::CDChunkList<Node> NodeList;
+ typedef context::CDHashMap< Node, Node, NodeHashFunction > NodeMap;
+ typedef context::CDHashMap< Node, bool, NodeHashFunction > BoolMap;
+//this class maintains a congruence closure for *universal* facts
+private:
+ //notification class for equality engine
+ class NotifyClass : public eq::EqualityEngineNotify {
+ ConjectureGenerator& d_sg;
+ public:
+ NotifyClass(ConjectureGenerator& sg): d_sg(sg) {}
+ bool eqNotifyTriggerEquality(TNode equality, bool value) { return true; }
+ bool eqNotifyTriggerPredicate(TNode predicate, bool value) { return true; }
+ bool eqNotifyTriggerTermEquality(TheoryId tag, TNode t1, TNode t2, bool value) { return true; }
+ void eqNotifyConstantTermMerge(TNode t1, TNode t2) { }
+ void eqNotifyNewClass(TNode t) { d_sg.eqNotifyNewClass(t); }
+ void eqNotifyPreMerge(TNode t1, TNode t2) { d_sg.eqNotifyPreMerge(t1, t2); }
+ void eqNotifyPostMerge(TNode t1, TNode t2) { d_sg.eqNotifyPostMerge(t1, t2); }
+ void eqNotifyDisequal(TNode t1, TNode t2, TNode reason) {d_sg.eqNotifyDisequal(t1, t2, reason); }
+ };/* class ConjectureGenerator::NotifyClass */
+ /** The notify class */
+ NotifyClass d_notify;
+ class EqcInfo{
+ public:
+ EqcInfo( context::Context* c );
+ //representative
+ context::CDO< Node > d_rep;
+ };
+ /** get or make eqc info */
+ EqcInfo* getOrMakeEqcInfo( TNode n, bool doMake = false );
+ /** (universal) equaltity engine */
+ eq::EqualityEngine d_uequalityEngine;
+ /** pending adds */
+ std::vector< Node > d_upendingAdds;
+ /** relevant terms */
+ std::map< Node, bool > d_urelevant_terms;
+ /** information necessary for equivalence classes */
+ std::map< Node, EqcInfo* > d_eqc_info;
+ /** called when a new equivalance class is created */
+ void eqNotifyNewClass(TNode t);
+ /** called when two equivalance classes will merge */
+ void eqNotifyPreMerge(TNode t1, TNode t2);
+ /** called when two equivalance classes have merged */
+ void eqNotifyPostMerge(TNode t1, TNode t2);
+ /** called when two equivalence classes are made disequal */
+ void eqNotifyDisequal(TNode t1, TNode t2, TNode reason);
+ /** are universal equal */
+ bool areUniversalEqual( TNode n1, TNode n2 );
+ /** are universal disequal */
+ bool areUniversalDisequal( TNode n1, TNode n2 );
+ /** get universal representative */
+ TNode getUniversalRepresentative( TNode n, bool add = false );
+ /** set relevant */
+ void setUniversalRelevant( TNode n );
+ /** ordering for universal terms */
+ bool isUniversalLessThan( TNode rt1, TNode rt2 );
+
+ /** the nodes we have reported as canonical representative */
+ std::vector< TNode > d_ue_canon;
+ /** is reported canon */
+ bool isReportedCanon( TNode n );
+ /** mark that term has been reported as canonical rep */
+ void markReportedCanon( TNode n );
+
+private: //information regarding the conjectures
+ /** list of all conjectures */
+ std::vector< Node > d_conjectures;
+ /** list of all waiting conjectures */
+ std::vector< Node > d_waiting_conjectures_lhs;
+ std::vector< Node > d_waiting_conjectures_rhs;
+ std::vector< int > d_waiting_conjectures_score;
+ /** map of currently considered equality conjectures */
+ std::map< Node, std::vector< Node > > d_waiting_conjectures;
+ /** map of equality conjectures */
+ std::map< Node, std::vector< Node > > d_eq_conjectures;
+ /** currently existing conjectures in equality engine */
+ BoolMap d_ee_conjectures;
+ /** conjecture index */
+ TheoremIndex d_thm_index;
+private: //free variable list
+ //free variables
+ std::map< TypeNode, std::vector< Node > > d_free_var;
+ //map from free variable to FV#
+ std::map< TNode, unsigned > d_free_var_num;
+ // get canonical free variable #i of type tn
+ Node getFreeVar( TypeNode tn, unsigned i );
+ // get canonical term, return null if it contains a term apart from handled signature
+ Node getCanonicalTerm( TNode n, std::map< TypeNode, unsigned >& var_count, std::map< TNode, TNode >& subs );
+private: //information regarding the terms
+ //relevant patterns (the LHS's)
+ std::map< TypeNode, std::vector< Node > > d_rel_patterns;
+ //total number of unique variables
+ std::map< TNode, unsigned > d_rel_pattern_var_sum;
+ //by types
+ PatternTypIndex d_rel_pattern_typ_index;
+ // substitution to ground EQC index
+ std::map< TNode, SubstitutionIndex > d_rel_pattern_subs_index;
+ //patterns (the RHS's)
+ std::map< TypeNode, std::vector< Node > > d_patterns;
+ //patterns to # variables per type
+ std::map< TNode, std::map< TypeNode, unsigned > > d_pattern_var_id;
+ // # duplicated variables
+ std::map< TNode, unsigned > d_pattern_var_duplicate;
+ // is normal pattern? (variables allocated in canonical way left to right)
+ std::map< TNode, int > d_pattern_is_normal;
+ std::map< TNode, int > d_pattern_is_relevant;
+ // patterns to a count of # operators (variables and functions)
+ std::map< TNode, std::map< TNode, unsigned > > d_pattern_fun_id;
+ // term size
+ std::map< TNode, unsigned > d_pattern_fun_sum;
+ // collect functions
+ unsigned collectFunctions( TNode opat, TNode pat, std::map< TNode, unsigned >& funcs,
+ std::map< TypeNode, unsigned >& mnvn, std::map< TypeNode, unsigned >& mxvn );
+ // add pattern
+ void registerPattern( Node pat, TypeNode tpat );
+private: //for debugging
+ std::map< TNode, unsigned > d_em;
+ unsigned d_conj_count;
+public:
+ //term generation environment
+ TermGenEnv d_tge;
+ //consider term canon
+ bool considerTermCanon( Node ln, bool genRelevant );
+public: //for generalization
+ //generalizations
+ bool isGeneralization( TNode patg, TNode pat ) {
+ std::map< TNode, TNode > subs;
+ return isGeneralization( patg, pat, subs );
+ }
+ bool isGeneralization( TNode patg, TNode pat, std::map< TNode, TNode >& subs );
+ // get generalization depth
+ int calculateGeneralizationDepth( TNode n, std::vector< TNode >& fv );
+private:
+ //predicate for type
+ std::map< TypeNode, Node > d_typ_pred;
+ //get predicate for type
+ Node getPredicateForType( TypeNode tn );
+ //
+ void getEnumerateUfTerm( Node n, unsigned num, std::vector< Node >& terms );
+ //
+ void getEnumeratePredUfTerm( Node n, unsigned num, std::vector< Node >& terms );
+ // uf operators enumerated
+ std::map< Node, bool > d_uf_enum;
+public: //for property enumeration
+ //process this candidate conjecture
+ void processCandidateConjecture( TNode lhs, TNode rhs, unsigned lhs_depth, unsigned rhs_depth );
+ //whether it should be considered, negative : no, positive returns score
+ int considerCandidateConjecture( TNode lhs, TNode rhs );
+ //notified of a substitution
+ bool notifySubstitution( TNode glhs, std::map< TNode, TNode >& subs, TNode rhs );
+ //confirmation count
+ unsigned d_subs_confirmCount;
+ //individual witnesses (for range)
+ std::vector< TNode > d_subs_confirmWitnessRange;
+ //individual witnesses (for domain)
+ std::map< TNode, std::vector< TNode > > d_subs_confirmWitnessDomain;
+ //number of ground substitutions whose equality is unknown
+ unsigned d_subs_unkCount;
+private: //information about ground equivalence classes
+ TNode d_bool_eqc[2];
+ std::map< TNode, Node > d_ground_eqc_map;
+ std::vector< TNode > d_ground_terms;
+ //operator independent term index
+ std::map< TNode, OpArgIndex > d_op_arg_index;
+ //is handled term
+ bool isHandledTerm( TNode n );
+ Node getGroundEqc( TNode r );
+ bool isGroundEqc( TNode r );
+ bool isGroundTerm( TNode n );
+ //has enumerated UF
+ bool hasEnumeratedUf( Node n );
+ // count of full effort checks
+ unsigned d_fullEffortCount;
+ // has added lemma
+ bool d_hasAddedLemma;
+ //flush the waiting conjectures
+ unsigned flushWaitingConjectures( unsigned& addedLemmas, int ldepth, int rdepth );
+public:
+ ConjectureGenerator( QuantifiersEngine * qe, context::Context* c );
+ ~ConjectureGenerator() throw() {}
+ /* needs check */
+ bool needsCheck( Theory::Effort e );
+ /* reset at a round */
+ void reset_round( 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 );
+ /** Identify this module (for debugging, dynamic configuration, etc..) */
+ std::string identify() const { return "ConjectureGenerator"; }
+//options
+private:
+ bool optReqDistinctVarPatterns();
+ bool optFilterUnknown();
+ int optFilterScoreThreshold();
+ unsigned optFullCheckFrequency();
+ unsigned optFullCheckConjectures();
+
+ bool optStatsOnly();
+};
+
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/quant_conflict_find.cpp b/src/theory/quantifiers/quant_conflict_find.cpp
index d465df4c0..18bffe908 100644
--- a/src/theory/quantifiers/quant_conflict_find.cpp
+++ b/src/theory/quantifiers/quant_conflict_find.cpp
@@ -1,2227 +1,2227 @@
-/********************* */
-/*! \file quant_conflict_find.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 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 {
-
-
-
-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] );
- d_var_types.push_back( q[0][i].getType() );
- }
-
- 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_var_types.push_back( n.getType() );
- 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->getTermDatabase()->d_vars[d_q].begin(),
- p->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;
- TermArgTrie * qni = p->getTermDatabase()->getTermArgTrie( 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->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, TermArgTrie >::iterator it = d_qn[index]->d_data.begin();
- if( it != d_qn[index]->d_data.end() ) {
- d_qni.push_back( it );
- //set the match
- if( it->first.getType().isSubtypeOf( qi->d_var_types[repVar] ) && 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, TermArgTrie >::iterator it = d_qn[index]->d_data.find( val );
- if( it!=d_qn[index]->d_data.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_data.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_data.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_data.empty() );
- TNode t = d_qni[d_qni.size()-1]->second.d_data.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->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_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( d_quantEngine->hasOwnership( q, this ) ){
- 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( d_quantEngine->hasOwnership( q, this ) ){
- 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 );
- //}
- }
-}
-
-Node QuantConflictFind::evaluateTerm( Node n ) {
- if( MatchGen::isHandledUfTerm( n ) ){
- Node f = MatchGen::getOperator( this, n );
- Node nn;
- if( getEqualityEngine()->hasTerm( n ) ){
- nn = getTermDatabase()->existsTerm( f, n );
- }else{
- std::vector< TNode > args;
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- Node c = evaluateTerm( n[i] );
- args.push_back( c );
- }
- nn = getTermDatabase()->d_func_map_trie[f].existsTerm( 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 );
-}
-
-/** new node */
-void QuantConflictFind::newEqClass( Node n ) {
-
-}
-
-/** merge */
-void QuantConflictFind::merge( Node a, Node b ) {
-
-}
-
-/** assert disequal */
-void QuantConflictFind::assertDisequal( Node a, Node b ) {
-
-}
-
-//-------------------------------------------------- check function
-
-bool QuantConflictFind::needsCheck( Theory::Effort level ) {
- bool performCheck = false;
- if( options::quantConflictFind() && !d_conflict ){
- if( level==Theory::EFFORT_LAST_CALL ){
- performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_LAST_CALL;
- }else if( level==Theory::EFFORT_FULL ){
- performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_DEFAULT;
- }else if( level==Theory::EFFORT_STANDARD ){
- performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_STD;
- }
- }
- return performCheck;
-}
-
-void QuantConflictFind::reset_round( Theory::Effort level ) {
- d_needs_computeRelEqr = true;
-}
-
-/** check */
-void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
- if( quant_e==QuantifiersEngine::QEFFORT_CONFLICT ){
- 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;
- ++(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-inst") << "*** Produced match at effort " << e << " : " << std::endl;
- qi->debugPrintMatch("qcf-inst");
- Trace("qcf-inst") << std::endl;
- std::vector< int > assigned;
- if( !qi->isMatchSpurious( this ) ){
- if( qi->completeMatch( this, assigned ) ){
- 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-inst") << " ... Failed to add instantiation" << std::endl;
- //Assert( false );
- }
- }
- //clean up assigned
- qi->revertMatch( assigned );
- d_tempCache.clear();
- }else{
- Trace("qcf-inst") << " ... Spurious instantiation (cannot assign unassigned variables)" << std::endl;
- }
- }else{
- Trace("qcf-inst") << " ... Spurious instantiation (match is inconsistent)" << std::endl;
- }
- }
- if( d_conflict ){
- break;
- }
- }
- }
- if( addedLemmas>0 ){
- 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;
- }
- }
-}
-
-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);
- if( getTermDatabase()->hasTermCurrent( r ) ){
- 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 = 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 );
- }
- }
- ++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;
- }
- */
- }
-}
-
-
-//-------------------------------------------------- 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;
- }
-}
-
-
-}
+/********************* */
+/*! \file quant_conflict_find.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 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 {
+
+
+
+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] );
+ d_var_types.push_back( q[0][i].getType() );
+ }
+
+ 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_var_types.push_back( n.getType() );
+ 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->getTermDatabase()->d_vars[d_q].begin(),
+ p->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;
+ TermArgTrie * qni = p->getTermDatabase()->getTermArgTrie( 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->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, TermArgTrie >::iterator it = d_qn[index]->d_data.begin();
+ if( it != d_qn[index]->d_data.end() ) {
+ d_qni.push_back( it );
+ //set the match
+ if( it->first.getType().isSubtypeOf( qi->d_var_types[repVar] ) && 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, TermArgTrie >::iterator it = d_qn[index]->d_data.find( val );
+ if( it!=d_qn[index]->d_data.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_data.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_data.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_data.empty() );
+ TNode t = d_qni[d_qni.size()-1]->second.d_data.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->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_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( d_quantEngine->hasOwnership( q, this ) ){
+ 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( d_quantEngine->hasOwnership( q, this ) ){
+ 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 );
+ //}
+ }
+}
+
+Node QuantConflictFind::evaluateTerm( Node n ) {
+ if( MatchGen::isHandledUfTerm( n ) ){
+ Node f = MatchGen::getOperator( this, n );
+ Node nn;
+ if( getEqualityEngine()->hasTerm( n ) ){
+ nn = getTermDatabase()->existsTerm( f, n );
+ }else{
+ std::vector< TNode > args;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ Node c = evaluateTerm( n[i] );
+ args.push_back( c );
+ }
+ nn = getTermDatabase()->d_func_map_trie[f].existsTerm( 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 );
+}
+
+/** new node */
+void QuantConflictFind::newEqClass( Node n ) {
+
+}
+
+/** merge */
+void QuantConflictFind::merge( Node a, Node b ) {
+
+}
+
+/** assert disequal */
+void QuantConflictFind::assertDisequal( Node a, Node b ) {
+
+}
+
+//-------------------------------------------------- check function
+
+bool QuantConflictFind::needsCheck( Theory::Effort level ) {
+ bool performCheck = false;
+ if( options::quantConflictFind() && !d_conflict ){
+ if( level==Theory::EFFORT_LAST_CALL ){
+ performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_LAST_CALL;
+ }else if( level==Theory::EFFORT_FULL ){
+ performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_DEFAULT;
+ }else if( level==Theory::EFFORT_STANDARD ){
+ performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_STD;
+ }
+ }
+ return performCheck;
+}
+
+void QuantConflictFind::reset_round( Theory::Effort level ) {
+ d_needs_computeRelEqr = true;
+}
+
+/** check */
+void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
+ if( quant_e==QuantifiersEngine::QEFFORT_CONFLICT ){
+ 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;
+ ++(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-inst") << "*** Produced match at effort " << e << " : " << std::endl;
+ qi->debugPrintMatch("qcf-inst");
+ Trace("qcf-inst") << std::endl;
+ std::vector< int > assigned;
+ if( !qi->isMatchSpurious( this ) ){
+ if( qi->completeMatch( this, assigned ) ){
+ 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-inst") << " ... Failed to add instantiation" << std::endl;
+ //Assert( false );
+ }
+ }
+ //clean up assigned
+ qi->revertMatch( assigned );
+ d_tempCache.clear();
+ }else{
+ Trace("qcf-inst") << " ... Spurious instantiation (cannot assign unassigned variables)" << std::endl;
+ }
+ }else{
+ Trace("qcf-inst") << " ... Spurious instantiation (match is inconsistent)" << std::endl;
+ }
+ }
+ if( d_conflict ){
+ break;
+ }
+ }
+ }
+ if( addedLemmas>0 ){
+ 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;
+ }
+ }
+}
+
+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);
+ if( getTermDatabase()->hasTermCurrent( r ) ){
+ 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 = 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 );
+ }
+ }
+ ++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;
+ }
+ */
+ }
+}
+
+
+//-------------------------------------------------- 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;
+ }
+}
+
+
+}
diff --git a/src/theory/quantifiers/quant_conflict_find.h b/src/theory/quantifiers/quant_conflict_find.h
index 829b67777..d2a982781 100644
--- a/src/theory/quantifiers/quant_conflict_find.h
+++ b/src/theory/quantifiers/quant_conflict_find.h
@@ -1,255 +1,255 @@
-/********************* */
-/*! \file quant_conflict_find.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 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"
-#include "theory/quantifiers/term_database.h"
-
-namespace CVC4 {
-namespace theory {
-namespace quantifiers {
-
-class QuantConflictFind;
-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< TermArgTrie * > d_qn;
- std::vector< std::map< TNode, TermArgTrie >::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::vector< TypeNode > d_var_types;
- 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 MatchGen;
- friend class QuantInfo;
- typedef context::CDChunkList<Node> NodeList;
- typedef context::CDHashMap<Node, bool, NodeHashFunction> NodeBoolMap;
-private:
- context::CDO< bool > d_conflict;
- 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
- // type -> list(eqc)
- std::map< TypeNode, std::vector< TNode > > d_eqcs;
- std::map< TypeNode, Node > d_model_basis;
-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 );
- ~QuantConflictFind() throw() {}
- /** 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 );
- /** needs check */
- bool needsCheck( Theory::Effort level );
- /** reset round */
- void reset_round( Theory::Effort level );
- /** check */
- void check( Theory::Effort level, unsigned quant_e );
-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
+/********************* */
+/*! \file quant_conflict_find.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 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"
+#include "theory/quantifiers/term_database.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+class QuantConflictFind;
+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< TermArgTrie * > d_qn;
+ std::vector< std::map< TNode, TermArgTrie >::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::vector< TypeNode > d_var_types;
+ 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 MatchGen;
+ friend class QuantInfo;
+ typedef context::CDChunkList<Node> NodeList;
+ typedef context::CDHashMap<Node, bool, NodeHashFunction> NodeBoolMap;
+private:
+ context::CDO< bool > d_conflict;
+ 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
+ // type -> list(eqc)
+ std::map< TypeNode, std::vector< TNode > > d_eqcs;
+ std::map< TypeNode, Node > d_model_basis;
+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 );
+ ~QuantConflictFind() throw() {}
+ /** 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 );
+ /** needs check */
+ bool needsCheck( Theory::Effort level );
+ /** reset round */
+ void reset_round( Theory::Effort level );
+ /** check */
+ void check( Theory::Effort level, unsigned quant_e );
+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
diff --git a/test/regress/regress0/fmf/fc-pigeonhole19.smt2 b/test/regress/regress0/fmf/fc-pigeonhole19.smt2
index 15c36682c..f145013d8 100644
--- a/test/regress/regress0/fmf/fc-pigeonhole19.smt2
+++ b/test/regress/regress0/fmf/fc-pigeonhole19.smt2
@@ -1,20 +1,20 @@
-(set-logic UFC)
-(set-info :status unsat)
-
-(declare-sort P 0)
-(declare-sort H 0)
-
-(declare-fun p () P)
-(declare-fun h () H)
-
-; pigeonhole using native cardinality constraints
-(assert (fmf.card p 19))
-(assert (not (fmf.card p 18)))
-(assert (fmf.card h 18))
-(assert (not (fmf.card h 17)))
-
-; each pigeon has different holes
-(declare-fun f (P) H)
-(assert (forall ((p1 P) (p2 P)) (=> (not (= p1 p2)) (not (= (f p1) (f p2))))))
-
+(set-logic UFC)
+(set-info :status unsat)
+
+(declare-sort P 0)
+(declare-sort H 0)
+
+(declare-fun p () P)
+(declare-fun h () H)
+
+; pigeonhole using native cardinality constraints
+(assert (fmf.card p 19))
+(assert (not (fmf.card p 18)))
+(assert (fmf.card h 18))
+(assert (not (fmf.card h 17)))
+
+; each pigeon has different holes
+(declare-fun f (P) H)
+(assert (forall ((p1 P) (p2 P)) (=> (not (= p1 p2)) (not (= (f p1) (f p2))))))
+
(check-sat) \ No newline at end of file
diff --git a/test/regress/regress0/fmf/fc-unsat-pent.smt2 b/test/regress/regress0/fmf/fc-unsat-pent.smt2
index f1721cb04..2d4000e6e 100644
--- a/test/regress/regress0/fmf/fc-unsat-pent.smt2
+++ b/test/regress/regress0/fmf/fc-unsat-pent.smt2
@@ -1,20 +1,20 @@
-(set-logic QF_UFC)
-(set-info :status unsat)
-
-(declare-sort U 0)
-
-(declare-fun a () U)
-(declare-fun b () U)
-(declare-fun c () U)
-(declare-fun d () U)
-(declare-fun e () U)
-
-(assert (not (= a b)))
-(assert (not (= b c)))
-(assert (not (= c d)))
-(assert (not (= d e)))
-(assert (not (= e a)))
-
-(assert (fmf.card c 2))
-
+(set-logic QF_UFC)
+(set-info :status unsat)
+
+(declare-sort U 0)
+
+(declare-fun a () U)
+(declare-fun b () U)
+(declare-fun c () U)
+(declare-fun d () U)
+(declare-fun e () U)
+
+(assert (not (= a b)))
+(assert (not (= b c)))
+(assert (not (= c d)))
+(assert (not (= d e)))
+(assert (not (= e a)))
+
+(assert (fmf.card c 2))
+
(check-sat) \ No newline at end of file
diff --git a/test/regress/regress0/fmf/fc-unsat-tot-2.smt2 b/test/regress/regress0/fmf/fc-unsat-tot-2.smt2
index d946974ed..0d438f718 100644
--- a/test/regress/regress0/fmf/fc-unsat-tot-2.smt2
+++ b/test/regress/regress0/fmf/fc-unsat-tot-2.smt2
@@ -1,14 +1,14 @@
-(set-logic UFC)
-(set-info :status unsat)
-
-(declare-sort U 0)
-
-(declare-fun a () U)
-(declare-fun b () U)
-(declare-fun c () U)
-
-(assert (not (fmf.card a 2)))
-
-(assert (forall ((x U)) (or (= x a) (= x b))))
-
+(set-logic UFC)
+(set-info :status unsat)
+
+(declare-sort U 0)
+
+(declare-fun a () U)
+(declare-fun b () U)
+(declare-fun c () U)
+
+(assert (not (fmf.card a 2)))
+
+(assert (forall ((x U)) (or (= x a) (= x b))))
+
(check-sat) \ No newline at end of file
diff --git a/test/regress/regress0/quantifiers/simp-typ-test.smt2 b/test/regress/regress0/quantifiers/simp-typ-test.smt2
index 366559b9d..380a66aac 100644
--- a/test/regress/regress0/quantifiers/simp-typ-test.smt2
+++ b/test/regress/regress0/quantifiers/simp-typ-test.smt2
@@ -1,7 +1,7 @@
-(set-logic UFLIRA)
-(set-info :status unsat)
-; ensure that E-matching matches on sub-types
-(declare-fun P (Real) Bool)
-(assert (forall ((x Real)) (P x)))
-(assert (not (P 5)))
+(set-logic UFLIRA)
+(set-info :status unsat)
+; ensure that E-matching matches on sub-types
+(declare-fun P (Real) Bool)
+(assert (forall ((x Real)) (P x)))
+(assert (not (P 5)))
(check-sat) \ No newline at end of file
diff --git a/test/regress/regress0/strings/at001.smt2 b/test/regress/regress0/strings/at001.smt2
index 616189d96..2ecbcc993 100644
--- a/test/regress/regress0/strings/at001.smt2
+++ b/test/regress/regress0/strings/at001.smt2
@@ -1,12 +1,12 @@
-(set-logic QF_S)
-(set-info :status sat)
-
-(declare-fun x () String)
-(declare-fun i () Int)
-
-(assert (= (str.at x i) "b"))
-(assert (and (>= i 4) (< i (str.len x))))
-(assert (< (str.len x) 7))
-(assert (> (str.len x) 2))
-
-(check-sat)
+(set-logic QF_S)
+(set-info :status sat)
+
+(declare-fun x () String)
+(declare-fun i () Int)
+
+(assert (= (str.at x i) "b"))
+(assert (and (>= i 4) (< i (str.len x))))
+(assert (< (str.len x) 7))
+(assert (> (str.len x) 2))
+
+(check-sat)
diff --git a/test/regress/regress0/strings/bug001.smt2 b/test/regress/regress0/strings/bug001.smt2
index 49568329e..cdeebd20b 100644
--- a/test/regress/regress0/strings/bug001.smt2
+++ b/test/regress/regress0/strings/bug001.smt2
@@ -1,15 +1,15 @@
-(set-logic QF_S)
-(set-info :status sat)
-
-(declare-fun x () String)
-(declare-fun y () String)
-(declare-fun z () String)
-
-(assert (= "\x4a" x))
-(assert (= "\x6a" y))
-
-(assert (= "\x4A" z))
-
-(assert (= x z))
-
-(check-sat)
+(set-logic QF_S)
+(set-info :status sat)
+
+(declare-fun x () String)
+(declare-fun y () String)
+(declare-fun z () String)
+
+(assert (= "\x4a" x))
+(assert (= "\x6a" y))
+
+(assert (= "\x4A" z))
+
+(assert (= x z))
+
+(check-sat)
diff --git a/test/regress/regress0/strings/bug002.smt2 b/test/regress/regress0/strings/bug002.smt2
index 15d1ea5a2..f8a481e14 100644
--- a/test/regress/regress0/strings/bug002.smt2
+++ b/test/regress/regress0/strings/bug002.smt2
@@ -1,10 +1,10 @@
-(set-logic ASLIA)
-(set-info :smt-lib-version 2.0)
-(set-option :strings-exp true)
-(set-info :status sat)
-
-; regex = [\*-,\t\*-\|](.{6,}()?)+
-(define-fun strinre ((?s String)) Bool (str.in.re ?s (re.union re.nostr (re.++ (str.to.re "") (str.to.re "") (re.union re.nostr (re.range "*" ",") (str.to.re "\t") (re.range "*" "|") ) (re.+ (re.union re.nostr (re.++ (str.to.re "") (str.to.re "") (re.loop re.allchar 6 ) (re.opt (re.union re.nostr (re.++ (str.to.re "") (str.to.re "") ) ) ) ) ) ) ) ) ) )
-(assert (not (strinre "6O\1\127\n?")))
-
+(set-logic ASLIA)
+(set-info :smt-lib-version 2.0)
+(set-option :strings-exp true)
+(set-info :status sat)
+
+; regex = [\*-,\t\*-\|](.{6,}()?)+
+(define-fun strinre ((?s String)) Bool (str.in.re ?s (re.union re.nostr (re.++ (str.to.re "") (str.to.re "") (re.union re.nostr (re.range "*" ",") (str.to.re "\t") (re.range "*" "|") ) (re.+ (re.union re.nostr (re.++ (str.to.re "") (str.to.re "") (re.loop re.allchar 6 ) (re.opt (re.union re.nostr (re.++ (str.to.re "") (str.to.re "") ) ) ) ) ) ) ) ) ) )
+(assert (not (strinre "6O\1\127\n?")))
+
(check-sat) \ No newline at end of file
diff --git a/test/regress/regress0/strings/escchar.smt2 b/test/regress/regress0/strings/escchar.smt2
index aa2afb7e4..67a184ade 100644
--- a/test/regress/regress0/strings/escchar.smt2
+++ b/test/regress/regress0/strings/escchar.smt2
@@ -1,12 +1,12 @@
-(set-logic QF_S)
-(set-info :status sat)
-(set-info :smt-lib-version 2.0)
-
-(declare-fun x () String)
-(declare-const I Int)
-
-(assert (= x "\0\1\2\3\04\005\x06\7\8\9ABC\\\"\t\a\b"))
-(assert (= I (str.len x)))
-
-
-(check-sat)
+(set-logic QF_S)
+(set-info :status sat)
+(set-info :smt-lib-version 2.0)
+
+(declare-fun x () String)
+(declare-const I Int)
+
+(assert (= x "\0\1\2\3\04\005\x06\7\8\9ABC\\\"\t\a\b"))
+(assert (= I (str.len x)))
+
+
+(check-sat)
diff --git a/test/regress/regress0/strings/escchar_25.smt2 b/test/regress/regress0/strings/escchar_25.smt2
index f48995344..af93a7ae5 100644
--- a/test/regress/regress0/strings/escchar_25.smt2
+++ b/test/regress/regress0/strings/escchar_25.smt2
@@ -1,12 +1,12 @@
-(set-logic QF_S)
-(set-info :status sat)
-(set-info :smt-lib-version 2.5)
-
-(declare-fun x () String)
-(declare-const I Int)
-
-(assert (= x "\0\1\2\3\04\005\x06\7\8\9ABC\\""\t\a\b"))
-(assert (= I (str.len x)))
-
-
-(check-sat)
+(set-logic QF_S)
+(set-info :status sat)
+(set-info :smt-lib-version 2.5)
+
+(declare-fun x () String)
+(declare-const I Int)
+
+(assert (= x "\0\1\2\3\04\005\x06\7\8\9ABC\\""\t\a\b"))
+(assert (= I (str.len x)))
+
+
+(check-sat)
diff --git a/test/regress/regress0/strings/fmf001.smt2 b/test/regress/regress0/strings/fmf001.smt2
index 05bbab586..6081c8e06 100644
--- a/test/regress/regress0/strings/fmf001.smt2
+++ b/test/regress/regress0/strings/fmf001.smt2
@@ -1,20 +1,20 @@
-(set-logic QF_S)
-(set-option :strings-exp true)
-(set-option :strings-fmf true)
-(set-info :status sat)
-
-(declare-fun x () String)
-(declare-fun y () String)
-
-(assert (str.in.re x
- (re.* (re.++ (re.* (str.to.re "a") ) (str.to.re "b") ))
- ))
-
-(assert (str.in.re y
- (re.* (re.++ (re.* (str.to.re "a") ) (str.to.re "b") ))
- ))
-
-(assert (not (= x y)))
-(assert (= (str.len x) (str.len y)))
-
-(check-sat)
+(set-logic QF_S)
+(set-option :strings-exp true)
+(set-option :strings-fmf true)
+(set-info :status sat)
+
+(declare-fun x () String)
+(declare-fun y () String)
+
+(assert (str.in.re x
+ (re.* (re.++ (re.* (str.to.re "a") ) (str.to.re "b") ))
+ ))
+
+(assert (str.in.re y
+ (re.* (re.++ (re.* (str.to.re "a") ) (str.to.re "b") ))
+ ))
+
+(assert (not (= x y)))
+(assert (= (str.len x) (str.len y)))
+
+(check-sat)
diff --git a/test/regress/regress0/strings/fmf002.smt2 b/test/regress/regress0/strings/fmf002.smt2
index 1d41b1085..d52dae2d2 100644
--- a/test/regress/regress0/strings/fmf002.smt2
+++ b/test/regress/regress0/strings/fmf002.smt2
@@ -1,17 +1,17 @@
-(set-logic QF_S)
-(set-option :strings-exp true)
-(set-option :strings-fmf true)
-(set-info :status sat)
-
-(declare-fun x () String)
-(declare-fun y () String)
-(declare-fun z () String)
-
-(assert (str.in.re x
- (re.+ (re.range "a" "c"))
- ))
-
-(assert (= x (str.++ y "c" z "b")))
-(assert (> (str.len z) 1))
-
-(check-sat)
+(set-logic QF_S)
+(set-option :strings-exp true)
+(set-option :strings-fmf true)
+(set-info :status sat)
+
+(declare-fun x () String)
+(declare-fun y () String)
+(declare-fun z () String)
+
+(assert (str.in.re x
+ (re.+ (re.range "a" "c"))
+ ))
+
+(assert (= x (str.++ y "c" z "b")))
+(assert (> (str.len z) 1))
+
+(check-sat)
diff --git a/test/regress/regress0/strings/leadingzero001.smt2 b/test/regress/regress0/strings/leadingzero001.smt2
index ae61b5f5b..2889348c1 100644
--- a/test/regress/regress0/strings/leadingzero001.smt2
+++ b/test/regress/regress0/strings/leadingzero001.smt2
@@ -1,11 +1,11 @@
-(set-logic QF_S)
-(set-option :strings-exp true)
-(set-info :status sat)
-
-(declare-fun Y () String)
-
-(assert (= Y "0001"))
-;(assert (= (str.to.int Y) (- 1)))
-(assert (= (str.to.int Y) 1))
-
-(check-sat)
+(set-logic QF_S)
+(set-option :strings-exp true)
+(set-info :status sat)
+
+(declare-fun Y () String)
+
+(assert (= Y "0001"))
+;(assert (= (str.to.int Y) (- 1)))
+(assert (= (str.to.int Y) 1))
+
+(check-sat)
diff --git a/test/regress/regress0/strings/loop008.smt2 b/test/regress/regress0/strings/loop008.smt2
index 113577e48..f84ba442b 100644
--- a/test/regress/regress0/strings/loop008.smt2
+++ b/test/regress/regress0/strings/loop008.smt2
@@ -1,10 +1,10 @@
-(set-logic QF_S)
-(set-option :strings-exp true)
-(set-info :status sat)
-
-(declare-fun x () String)
-
-(assert (= (str.++ x "ab") (str.++ "ba" x)))
-(assert (> (str.len x) 5))
-
-(check-sat)
+(set-logic QF_S)
+(set-option :strings-exp true)
+(set-info :status sat)
+
+(declare-fun x () String)
+
+(assert (= (str.++ x "ab") (str.++ "ba" x)))
+(assert (> (str.len x) 5))
+
+(check-sat)
diff --git a/test/regress/regress0/strings/loop009.smt2 b/test/regress/regress0/strings/loop009.smt2
index 9ccc6de6e..30fc6cebc 100644
--- a/test/regress/regress0/strings/loop009.smt2
+++ b/test/regress/regress0/strings/loop009.smt2
@@ -1,10 +1,10 @@
-(set-logic QF_S)
-(set-option :strings-exp true)
-(set-info :status sat)
-
-(declare-fun x () String)
-
-(assert (= (str.++ x "aa") (str.++ "aa" x)))
-(assert (= (str.len x) 7))
-
-(check-sat)
+(set-logic QF_S)
+(set-option :strings-exp true)
+(set-info :status sat)
+
+(declare-fun x () String)
+
+(assert (= (str.++ x "aa") (str.++ "aa" x)))
+(assert (= (str.len x) 7))
+
+(check-sat)
diff --git a/test/regress/regress0/strings/regexp001.smt2 b/test/regress/regress0/strings/regexp001.smt2
index 6a2044ea8..62c142d1d 100644
--- a/test/regress/regress0/strings/regexp001.smt2
+++ b/test/regress/regress0/strings/regexp001.smt2
@@ -1,13 +1,13 @@
-(set-logic QF_S)
-(set-info :status sat)
-(set-option :strings-exp true)
-
-(declare-fun x () String)
-
-(assert (str.in.re x
- (re.* (re.++ (re.* (str.to.re "a") ) (str.to.re "b") ))
- ))
-
-(assert (= (str.len x) 3))
-
-(check-sat)
+(set-logic QF_S)
+(set-info :status sat)
+(set-option :strings-exp true)
+
+(declare-fun x () String)
+
+(assert (str.in.re x
+ (re.* (re.++ (re.* (str.to.re "a") ) (str.to.re "b") ))
+ ))
+
+(assert (= (str.len x) 3))
+
+(check-sat)
diff --git a/test/regress/regress0/strings/regexp002.smt2 b/test/regress/regress0/strings/regexp002.smt2
index 8c29ccb38..a8bd2187a 100644
--- a/test/regress/regress0/strings/regexp002.smt2
+++ b/test/regress/regress0/strings/regexp002.smt2
@@ -1,24 +1,24 @@
-(set-logic QF_S)
-(set-info :status sat)
-(set-option :strings-exp true)
-; this option requires user to check whether the constraint is in the fragment
-; currently we do not provide only positive membership constraint checking
-; if users use this option but the constraint is not in this fragment, the result will fail
-(set-option :strings-inm true)
-
-(declare-fun x () String)
-(declare-fun y () String)
-
-(assert (str.in.re x
- (re.* (re.++ (re.* (str.to.re "a") ) (str.to.re "b") ))
- ))
-
-(assert (str.in.re y
- (re.* (re.++ (re.* (str.to.re "a") ) (str.to.re "b") ))
- ))
-
-(assert (not (= x y)))
-(assert (= (str.len x) (str.len y)))
-(assert (= (str.len y) 3))
-
-(check-sat)
+(set-logic QF_S)
+(set-info :status sat)
+(set-option :strings-exp true)
+; this option requires user to check whether the constraint is in the fragment
+; currently we do not provide only positive membership constraint checking
+; if users use this option but the constraint is not in this fragment, the result will fail
+(set-option :strings-inm true)
+
+(declare-fun x () String)
+(declare-fun y () String)
+
+(assert (str.in.re x
+ (re.* (re.++ (re.* (str.to.re "a") ) (str.to.re "b") ))
+ ))
+
+(assert (str.in.re y
+ (re.* (re.++ (re.* (str.to.re "a") ) (str.to.re "b") ))
+ ))
+
+(assert (not (= x y)))
+(assert (= (str.len x) (str.len y)))
+(assert (= (str.len y) 3))
+
+(check-sat)
diff --git a/test/regress/regress0/strings/regexp003.smt2 b/test/regress/regress0/strings/regexp003.smt2
index 601689958..7696838fe 100644
--- a/test/regress/regress0/strings/regexp003.smt2
+++ b/test/regress/regress0/strings/regexp003.smt2
@@ -1,13 +1,13 @@
-(set-logic QF_S)
-(set-info :status sat)
-(set-option :strings-exp true)
-
-(declare-const s String)
-
-(assert (str.in.re s (re.inter
- (re.++ (str.to.re "a") (re.* (str.to.re "b"))
- (re.inter (str.to.re "c") (re.* (str.to.re "c"))))
- (re.++ (str.to.re "a") (re.* (str.to.re "b")) (re.* (str.to.re "c")))
- )))
-
-(check-sat)
+(set-logic QF_S)
+(set-info :status sat)
+(set-option :strings-exp true)
+
+(declare-const s String)
+
+(assert (str.in.re s (re.inter
+ (re.++ (str.to.re "a") (re.* (str.to.re "b"))
+ (re.inter (str.to.re "c") (re.* (str.to.re "c"))))
+ (re.++ (str.to.re "a") (re.* (str.to.re "b")) (re.* (str.to.re "c")))
+ )))
+
+(check-sat)
diff --git a/test/regress/regress0/strings/reloop.smt2 b/test/regress/regress0/strings/reloop.smt2
index 39b2b76b1..9915504ae 100644
--- a/test/regress/regress0/strings/reloop.smt2
+++ b/test/regress/regress0/strings/reloop.smt2
@@ -1,18 +1,18 @@
-(set-logic QF_S)
-(set-option :strings-exp true)
-(set-info :status sat)
-
-(declare-fun x () String)
-(declare-fun y () String)
-(declare-fun z () String)
-(declare-fun w () String)
-
-(assert (str.in.re x (re.loop (str.to.re "a") 5)))
-(assert (str.in.re y (re.loop (str.to.re "b") 2 5)))
-(assert (str.in.re z (re.loop (str.to.re "c") 5)))
-(assert (> (str.len z) 7))
-(assert (str.in.re w (re.loop (str.to.re "b") 2 7)))
-(assert (> (str.len w) 2))
-(assert (< (str.len w) 5))
-
-(check-sat)
+(set-logic QF_S)
+(set-option :strings-exp true)
+(set-info :status sat)
+
+(declare-fun x () String)
+(declare-fun y () String)
+(declare-fun z () String)
+(declare-fun w () String)
+
+(assert (str.in.re x (re.loop (str.to.re "a") 5)))
+(assert (str.in.re y (re.loop (str.to.re "b") 2 5)))
+(assert (str.in.re z (re.loop (str.to.re "c") 5)))
+(assert (> (str.len z) 7))
+(assert (str.in.re w (re.loop (str.to.re "b") 2 7)))
+(assert (> (str.len w) 2))
+(assert (< (str.len w) 5))
+
+(check-sat)
diff --git a/test/regress/regress0/strings/str006.smt2 b/test/regress/regress0/strings/str006.smt2
index 592ef6a7f..2bdf9b1b5 100644
--- a/test/regress/regress0/strings/str006.smt2
+++ b/test/regress/regress0/strings/str006.smt2
@@ -1,14 +1,14 @@
-(set-logic QF_S)
-(set-info :status sat)
-
-(declare-fun x () String)
-(declare-fun y () String)
-(declare-fun z () String)
-
-;plandowski p469 1
-(assert (= (str.++ x "ab" y) (str.++ y "ba" z)))
-(assert (= z (str.++ x y)))
-(assert (not (= (str.++ x "a") (str.++ "a" x))))
-
-(check-sat)
-
+(set-logic QF_S)
+(set-info :status sat)
+
+(declare-fun x () String)
+(declare-fun y () String)
+(declare-fun z () String)
+
+;plandowski p469 1
+(assert (= (str.++ x "ab" y) (str.++ y "ba" z)))
+(assert (= z (str.++ x y)))
+(assert (not (= (str.++ x "a") (str.++ "a" x))))
+
+(check-sat)
+
diff --git a/test/regress/regress0/strings/str007.smt2 b/test/regress/regress0/strings/str007.smt2
index 0ca2ec4c3..a7173701a 100644
--- a/test/regress/regress0/strings/str007.smt2
+++ b/test/regress/regress0/strings/str007.smt2
@@ -1,13 +1,13 @@
-(set-logic QF_S)
-(set-info :status unsat)
-
-(declare-fun x () String)
-(declare-fun y () String)
-
-
-(assert (or (= x y) (= x y)))
-
-(assert (= (str.++ x "ba") (str.++ "ab" x)))
-(assert (= (str.++ y "ab") (str.++ "ab" y)))
-
-(check-sat)
+(set-logic QF_S)
+(set-info :status unsat)
+
+(declare-fun x () String)
+(declare-fun y () String)
+
+
+(assert (or (= x y) (= x y)))
+
+(assert (= (str.++ x "ba") (str.++ "ab" x)))
+(assert (= (str.++ y "ab") (str.++ "ab" y)))
+
+(check-sat)
diff --git a/test/regress/regress0/strings/substr001.smt2 b/test/regress/regress0/strings/substr001.smt2
index bdfa33afb..78f3ffee7 100644
--- a/test/regress/regress0/strings/substr001.smt2
+++ b/test/regress/regress0/strings/substr001.smt2
@@ -1,16 +1,16 @@
-(set-logic QF_S)
-(set-info :status sat)
-
-(declare-fun x () String)
-(declare-fun i1 () Int)
-(declare-fun i2 () Int)
-(declare-fun i3 () Int)
-(declare-fun i4 () Int)
-
-(assert (and (>= i1 0) (>= i2 0) (< (+ i1 i2) (str.len x))))
-(assert (and (>= i3 0) (>= i4 0) (< (+ i3 i4) (str.len x))))
-(assert (= "efg" (str.substr x i1 i2) ) )
-(assert (= "bef" (str.substr x i3 i4) ) )
-(assert (> (str.len x) 5))
-
-(check-sat)
+(set-logic QF_S)
+(set-info :status sat)
+
+(declare-fun x () String)
+(declare-fun i1 () Int)
+(declare-fun i2 () Int)
+(declare-fun i3 () Int)
+(declare-fun i4 () Int)
+
+(assert (and (>= i1 0) (>= i2 0) (< (+ i1 i2) (str.len x))))
+(assert (and (>= i3 0) (>= i4 0) (< (+ i3 i4) (str.len x))))
+(assert (= "efg" (str.substr x i1 i2) ) )
+(assert (= "bef" (str.substr x i3 i4) ) )
+(assert (> (str.len x) 5))
+
+(check-sat)
diff --git a/test/regress/regress0/strings/type001.smt2 b/test/regress/regress0/strings/type001.smt2
index ca93b00e5..77eabcccc 100644
--- a/test/regress/regress0/strings/type001.smt2
+++ b/test/regress/regress0/strings/type001.smt2
@@ -1,21 +1,21 @@
-(set-logic QF_S)
-(set-info :status sat)
-(set-option :strings-exp true)
-
-(declare-fun x () String)
-(declare-fun y () String)
-(declare-fun i () Int)
-(declare-fun j () Int)
-(declare-fun z () String)
-
-;big num test
-(assert (= x (int.to.str 4785582390527685649)))
-;should be ""
-(assert (= y (int.to.str (- 9))))
-
-;big num
-(assert (= i (str.to.int "783914785582390527685649")))
-;should be -1
-(assert (= j (str.to.int "-783914785582390527685649")))
-
+(set-logic QF_S)
+(set-info :status sat)
+(set-option :strings-exp true)
+
+(declare-fun x () String)
+(declare-fun y () String)
+(declare-fun i () Int)
+(declare-fun j () Int)
+(declare-fun z () String)
+
+;big num test
+(assert (= x (int.to.str 4785582390527685649)))
+;should be ""
+(assert (= y (int.to.str (- 9))))
+
+;big num
+(assert (= i (str.to.int "783914785582390527685649")))
+;should be -1
+(assert (= j (str.to.int "-783914785582390527685649")))
+
(check-sat) \ No newline at end of file
diff --git a/test/regress/regress0/strings/type002.smt2 b/test/regress/regress0/strings/type002.smt2
index cbad2226a..296057a76 100644
--- a/test/regress/regress0/strings/type002.smt2
+++ b/test/regress/regress0/strings/type002.smt2
@@ -1,18 +1,18 @@
-(set-logic QF_S)
-(set-info :status sat)
-(set-option :strings-exp true)
-
-(declare-fun x () String)
-(declare-fun y () String)
-(declare-fun z () String)
-(declare-fun i () Int)
-
-(assert (>= i 420))
-(assert (= x (u16.to.str i)))
-(assert (= x (str.++ y "0" z)))
-(assert (not (= y "")))
-(assert (not (= z "")))
-
-
-
+(set-logic QF_S)
+(set-info :status sat)
+(set-option :strings-exp true)
+
+(declare-fun x () String)
+(declare-fun y () String)
+(declare-fun z () String)
+(declare-fun i () Int)
+
+(assert (>= i 420))
+(assert (= x (u16.to.str i)))
+(assert (= x (str.++ y "0" z)))
+(assert (not (= y "")))
+(assert (not (= z "")))
+
+
+
(check-sat) \ No newline at end of file
diff --git a/test/regress/regress0/strings/type003.smt2 b/test/regress/regress0/strings/type003.smt2
index b8f0ac5ae..c2d4792cc 100644
--- a/test/regress/regress0/strings/type003.smt2
+++ b/test/regress/regress0/strings/type003.smt2
@@ -1,12 +1,12 @@
-(set-logic QF_S)
-(set-info :status sat)
-(set-option :strings-exp true)
-
-(declare-fun i () Int)
-(declare-fun s () String)
-
-(assert (< 67 (str.to.int s)))
-(assert (= (str.len s) 2))
-(assert (not (= s "68")))
-
-(check-sat)
+(set-logic QF_S)
+(set-info :status sat)
+(set-option :strings-exp true)
+
+(declare-fun i () Int)
+(declare-fun s () String)
+
+(assert (< 67 (str.to.int s)))
+(assert (= (str.len s) 2))
+(assert (not (= s "68")))
+
+(check-sat)
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback