summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorajreynol <andrew.j.reynolds@gmail.com>2021-06-11 10:52:53 -0500
committerajreynol <andrew.j.reynolds@gmail.com>2021-06-11 10:52:53 -0500
commitee73990f8d383fc3848a44460b537667c4a2ce25 (patch)
treeba6413da7b93e882da73027c710f7f43d7dd8f76
parent60007a036188c955d62de18c41be0b97f9b8413e (diff)
parentf10087c3b347da6ef625a2ad92846551ad324d73 (diff)
Merge branch 'master' of https://github.com/CVC4/CVC4 into proof-new
-rw-r--r--.github/workflows/docs_cleanup.yml10
-rwxr-xr-xcontrib/competitions/smt-comp/run-script-smtcomp-current36
-rwxr-xr-xcontrib/competitions/smt-comp/run-script-smtcomp-current-incremental8
-rwxr-xr-xcontrib/competitions/smt-comp/run-script-smtcomp-current-model-validation2
-rwxr-xr-xcontrib/competitions/smt-comp/run-script-smtcomp-current-unsat-cores8
-rw-r--r--docs/api/cpp/kind.rst10
-rw-r--r--docs/examples/examples.rst3
-rw-r--r--docs/examples/relations.rst7
-rw-r--r--docs/examples/sets.rst1
-rw-r--r--docs/ext/examples.py2
-rw-r--r--docs/ext/smtliblexer.py35
-rw-r--r--docs/theories/datatypes.rst2
-rw-r--r--docs/theories/separation-logic.rst154
-rw-r--r--docs/theories/sets-and-relations.rst201
-rw-r--r--docs/theory.rst2
-rw-r--r--examples/api/cpp/sets.cpp2
-rw-r--r--examples/api/smtlib/relations.smt241
-rw-r--r--examples/api/smtlib/sets.smt234
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/api/cpp/cvc5.h6
-rw-r--r--src/api/cpp/cvc5_kind.h17
-rw-r--r--src/api/java/cvc5/Result.java6
-rw-r--r--src/api/python/cvc5.pxi19
-rw-r--r--src/base/configuration.cpp6
-rw-r--r--src/decision/decision_engine_old.h6
-rw-r--r--src/expr/dtype.cpp7
-rw-r--r--src/expr/node.h2
-rw-r--r--src/expr/node_manager.cpp8
-rw-r--r--src/expr/node_manager.h12
-rw-r--r--src/main/command_executor.cpp8
-rw-r--r--src/main/driver_unified.cpp10
-rw-r--r--src/main/main.h2
-rw-r--r--src/main/signal_handlers.cpp8
-rw-r--r--src/omt/integer_optimizer.h9
-rw-r--r--src/omt/omt_optimizer.cpp16
-rw-r--r--src/omt/omt_optimizer.h6
-rw-r--r--src/options/base_options.toml5
-rw-r--r--src/options/bv_options.toml16
-rw-r--r--src/options/options_handler.cpp15
-rw-r--r--src/options/options_public.cpp4
-rw-r--r--src/options/options_public.h1
-rw-r--r--src/options/options_template.cpp5
-rw-r--r--src/options/options_template.h3
-rw-r--r--src/preprocessing/learned_literal_manager.cpp52
-rw-r--r--src/preprocessing/learned_literal_manager.h71
-rw-r--r--src/preprocessing/passes/bv_to_int.cpp8
-rw-r--r--src/preprocessing/passes/int_to_bv.cpp24
-rw-r--r--src/preprocessing/passes/non_clausal_simp.cpp4
-rw-r--r--src/preprocessing/preprocessing_pass_context.cpp13
-rw-r--r--src/preprocessing/preprocessing_pass_context.h19
-rw-r--r--src/printer/smt2/smt2_printer.cpp52
-rw-r--r--src/smt/command.cpp18
-rw-r--r--src/smt/command.h1
-rw-r--r--src/smt/env.cpp3
-rw-r--r--src/smt/env.h9
-rw-r--r--src/smt/optimization_solver.cpp20
-rw-r--r--src/smt/optimization_solver.h21
-rw-r--r--src/smt/set_defaults.cpp25
-rw-r--r--src/theory/arith/nl/cad/lazard_evaluation.cpp46
-rw-r--r--src/theory/arith/nl/cad/lazard_evaluation.h109
-rw-r--r--src/theory/booleans/theory_bool_rewriter.cpp47
-rw-r--r--src/theory/bv/bv_solver_lazy.cpp33
-rw-r--r--src/theory/bv/bv_solver_lazy.h2
-rw-r--r--src/theory/bv/bv_subtheory_core.cpp214
-rw-r--r--src/theory/bv/bv_subtheory_core.h56
-rw-r--r--src/theory/bv/theory_bv_rewriter.cpp17
-rw-r--r--src/theory/quantifiers/fmf/bounded_integers.cpp17
-rw-r--r--src/theory/rep_set.cpp3
-rw-r--r--src/theory/strings/theory_strings_preprocess.cpp8
-rw-r--r--src/theory/uf/theory_uf.cpp66
-rw-r--r--src/theory/uf/theory_uf.h6
-rw-r--r--test/python/unit/api/test_term.py26
-rw-r--r--test/python/unit/api/test_to_python_obj.py6
-rw-r--r--test/regress/CMakeLists.txt12
-rw-r--r--test/regress/regress0/bool/issue6717-ite-rewrite.smt27
-rw-r--r--test/regress/regress0/bv/bv-int-collapse1.smt22
-rw-r--r--test/regress/regress0/bv/bv-int-collapse2.smt22
-rw-r--r--test/regress/regress0/bv/bv2nat-simp-range.smt21
-rw-r--r--test/regress/regress0/int-to-bv/basic.smt210
-rw-r--r--test/regress/regress0/int-to-bv/neg-consts.smt29
-rw-r--r--test/regress/regress0/int-to-bv/not-enough-bits.smt211
-rw-r--r--test/regress/regress0/int-to-bv/overflow.smt29
-rw-r--r--test/regress/regress0/options/statistics.smt243
-rw-r--r--test/regress/regress1/bv/bv2nat-ground.smt22
-rw-r--r--test/regress/regress1/bv/bv2nat-simp-range-sat.smt22
-rw-r--r--test/regress/regress1/bv2int-isabelle.smt216
-rw-r--r--test/regress/regress1/strings/issue6635-rre.smt26
-rw-r--r--test/regress/regress1/strings/issue6653-2-update-c-len.smt27
-rw-r--r--test/regress/regress1/strings/issue6653-4-rre.smt26
-rw-r--r--test/regress/regress1/strings/issue6653-rre-small.smt26
-rw-r--r--test/regress/regress1/strings/issue6653-rre.smt28
-rw-r--r--test/regress/regress2/bv_to_int_mask_array_1.smt22
-rw-r--r--test/unit/node/node_black.cpp3
-rw-r--r--test/unit/theory/theory_bv_opt_white.cpp10
-rw-r--r--test/unit/theory/theory_int_opt_white.cpp8
-rw-r--r--test/unit/theory/theory_opt_multigoal_white.cpp64
96 files changed, 1370 insertions, 631 deletions
diff --git a/.github/workflows/docs_cleanup.yml b/.github/workflows/docs_cleanup.yml
index 761736e75..6632cbf45 100644
--- a/.github/workflows/docs_cleanup.yml
+++ b/.github/workflows/docs_cleanup.yml
@@ -44,15 +44,19 @@ jobs:
SSH_AUTH_SOCK: /tmp/ssh_agent.sock
run: |
cd target
- git log
first=`git rev-list --max-parents=0 HEAD`
last=`git rev-list --until=1.month.ago -n1 HEAD`
if [ -n "$last" ]; then
git checkout $last
+ ts=`git log -1 --format=%ct`
git reset --soft $first
- git commit -m "Squash old history"
+ if git diff --cached --exit-code
+ then
+ echo "Nothing to squash"
+ else
+ git commit -m "Squash old history" --date=$ts
+ fi
git cherry-pick $last..main
- git log
fi
- name: Push
diff --git a/contrib/competitions/smt-comp/run-script-smtcomp-current b/contrib/competitions/smt-comp/run-script-smtcomp-current
index ea3b2dde1..ecc6ce5fe 100755
--- a/contrib/competitions/smt-comp/run-script-smtcomp-current
+++ b/contrib/competitions/smt-comp/run-script-smtcomp-current
@@ -56,23 +56,23 @@ QF_LIA)
finishwith --miplib-trick --miplib-trick-subs=4 --use-approx --lemmas-on-replay-failure --replay-early-close-depth=4 --replay-lemma-reject-cut=128 --replay-reject-cut=512 --unconstrained-simp --use-soi --pb-rewrites --ite-simp --simp-ite-compress
;;
QF_NIA)
- trywith 480 --nl-ext-tplanes --decision=internal
- trywith 60 --nl-ext-tplanes --decision=justification
+ trywith 420 --nl-ext-tplanes --decision=justification
+ trywith 60 --nl-ext-tplanes --decision=internal
+ trywith 60 --nl-ext-tplanes --decision=justification-old
trywith 60 --no-nl-ext-tplanes --decision=internal
trywith 60 --no-arith-brab --nl-ext-tplanes --decision=internal
# this totals up to more than 20 minutes, although notice that smaller bit-widths may quickly fail
- trywith 300 --solve-int-as-bv=2 --bitblast=eager --bv-sat-solver=cadical --no-bv-abstraction
- trywith 300 --solve-int-as-bv=4 --bitblast=eager --bv-sat-solver=cadical --no-bv-abstraction
- trywith 300 --solve-int-as-bv=8 --bitblast=eager --bv-sat-solver=cadical --no-bv-abstraction
- trywith 300 --solve-int-as-bv=16 --bitblast=eager --bv-sat-solver=cadical --no-bv-abstraction
- trywith 600 --solve-int-as-bv=32 --bitblast=eager --bv-sat-solver=cadical --no-bv-abstraction
+ trywith 300 --solve-int-as-bv=2 --bitblast=eager
+ trywith 300 --solve-int-as-bv=4 --bitblast=eager
+ trywith 300 --solve-int-as-bv=8 --bitblast=eager
+ trywith 300 --solve-int-as-bv=16 --bitblast=eager
+ trywith 600 --solve-int-as-bv=32 --bitblast=eager
finishwith --nl-ext-tplanes --decision=internal
;;
QF_NRA)
- trywith 300 --nl-ext-tplanes --decision=internal
- trywith 300 --nl-ext-tplanes --decision=justification --no-nl-ext-factor
- trywith 30 --nl-ext-tplanes --decision=internal --solve-real-as-int
- finishwith --nl-ext-tplanes --decision=justification
+ trywith 600 --decision=justification
+ trywith 300 --decision=internal --no-nl-cad --nl-ext=full --nl-ext-tplanes
+ finishwith --decision=internal --nl-ext=none
;;
# all logics with UF + quantifiers should either fall under this or special cases below
ALIA|AUFLIA|AUFLIRA|AUFNIRA|UF|UFIDL|UFLIA|UFLRA|UFNIA|UFDT|UFDTLIA|AUFDTLIA|AUFBVDTLIA|AUFNIA|UFFPDTLIRA|UFFPDTNIRA)
@@ -139,14 +139,8 @@ QF_ABV)
trywith 500 --arrays-weak-equiv
finishwith --ite-simp --simp-with-care --repeat-simp --arrays-weak-equiv
;;
-QF_UFBV)
- # Benchmarks with uninterpreted sorts cannot be solved with eager
- # bit-blasting currently
- trywith 1200 --bitblast=eager --bv-sat-solver=cadical
- finishwith
- ;;
-QF_BV)
- finishwith --bv-div-zero-const --bitblast=eager --bv-sat-solver=cadical --no-bv-abstraction
+QF_BV|QF_UFBV)
+ finishwith --bitblast=eager --bv-assert-input
;;
QF_AUFLIA)
finishwith --no-arrays-eager-index --arrays-eager-lemmas --decision=justification
@@ -162,8 +156,8 @@ QF_ALIA)
finishwith --decision=justification-stoponly --no-arrays-eager-index --arrays-eager-lemmas
;;
QF_S|QF_SLIA)
- trywith 300 --strings-exp --rewrite-divk --strings-fmf --no-jh-rlv-order
- finishwith --strings-exp --rewrite-divk --no-jh-rlv-order
+ trywith 300 --strings-exp --strings-fmf --no-jh-rlv-order
+ finishwith --strings-exp --no-jh-rlv-order
;;
QF_ABVFP|QF_ABVFPLRA)
finishwith --fp-exp
diff --git a/contrib/competitions/smt-comp/run-script-smtcomp-current-incremental b/contrib/competitions/smt-comp/run-script-smtcomp-current-incremental
index e0b51bc46..21bb2f6e0 100755
--- a/contrib/competitions/smt-comp/run-script-smtcomp-current-incremental
+++ b/contrib/competitions/smt-comp/run-script-smtcomp-current-incremental
@@ -38,19 +38,19 @@ QF_AUFLIA)
runcvc5 --tear-down-incremental=1 --no-arrays-eager-index --arrays-eager-lemmas
;;
QF_BV)
- runcvc5 --incremental --bitblast=eager --bv-sat-solver=cadical
+ runcvc5 --incremental --bitblast=eager --bv-assert-input
;;
QF_UFBV)
- runcvc5 --incremental
+ runcvc5 --incremental --bv-assert-input
;;
QF_UF)
runcvc5 --incremental
;;
QF_AUFBV)
- runcvc5 --incremental
+ runcvc5 --incremental --bv-assert-input
;;
QF_ABV)
- runcvc5 --incremental
+ runcvc5 --incremental --bv-assert-input
;;
ABVFP)
runcvc5 --incremental
diff --git a/contrib/competitions/smt-comp/run-script-smtcomp-current-model-validation b/contrib/competitions/smt-comp/run-script-smtcomp-current-model-validation
index b5df43b72..fe8d4ae44 100755
--- a/contrib/competitions/smt-comp/run-script-smtcomp-current-model-validation
+++ b/contrib/competitions/smt-comp/run-script-smtcomp-current-model-validation
@@ -20,7 +20,7 @@ QF_LIA)
finishwith --miplib-trick --miplib-trick-subs=4 --use-approx --lemmas-on-replay-failure --replay-early-close-depth=4 --replay-lemma-reject-cut=128 --replay-reject-cut=512 --use-soi --pb-rewrites --ite-simp --simp-ite-compress
;;
QF_BV)
- finishwith --bitblast=eager --bv-sat-solver=cadical --no-bv-abstraction
+ finishwith --bitblast=eager --bv-assert-input
;;
*)
# just run the default
diff --git a/contrib/competitions/smt-comp/run-script-smtcomp-current-unsat-cores b/contrib/competitions/smt-comp/run-script-smtcomp-current-unsat-cores
index d87e83257..e9753781d 100755
--- a/contrib/competitions/smt-comp/run-script-smtcomp-current-unsat-cores
+++ b/contrib/competitions/smt-comp/run-script-smtcomp-current-unsat-cores
@@ -17,7 +17,7 @@ QF_LRA)
finishwith --no-restrict-pivots --use-soi --new-prop
;;
QF_LIA)
- finishwith --miplib-trick --miplib-trick-subs=4 --use-approx --lemmas-on-replay-failure --replay-early-close-depth=4 --replay-lemma-reject-cut=128 --replay-reject-cut=512 --use-soi --ite-simp --simp-ite-compress
+ finishwith --miplib-trick --miplib-trick-subs=4 --use-approx --lemmas-on-replay-failure --replay-early-close-depth=4 --replay-lemma-reject-cut=128 --replay-reject-cut=512 --use-soi
;;
QF_NIA)
finishwith --nl-ext --nl-ext-tplanes
@@ -42,16 +42,16 @@ NIA|NRA)
finishwith --full-saturate-quant --cegqi-nested-qe --decision=internal
;;
QF_AUFBV)
- finishwith --decision=justification-stoponly --ite-simp
+ finishwith --decision=justification-stoponly
;;
QF_ABV)
- finishwith --ite-simp --simp-with-care --arrays-weak-equiv
+ finishwith --arrays-weak-equiv
;;
QF_UFBV)
finishwith
;;
QF_BV)
- finishwith --no-bv-abstraction
+ finishwith
;;
QF_AUFLIA)
finishwith --no-arrays-eager-index --arrays-eager-lemmas --decision=justification
diff --git a/docs/api/cpp/kind.rst b/docs/api/cpp/kind.rst
index 579407c85..4c07804a4 100644
--- a/docs/api/cpp/kind.rst
+++ b/docs/api/cpp/kind.rst
@@ -4,14 +4,8 @@ Kind
Every :cpp:class:`Term <cvc5::api::Term>` has a kind which represents its type,
for example whether it is an equality (:cpp:enumerator:`EQUAL
<cvc5::api::Kind::EQUAL>`), a conjunction (:cpp:enumerator:`AND
-<cvc5::api::Kind::AND>`), or a bitvector addition
-(:cpp:enumerator:`BITVECTOR_PLUS <cvc5::api::Kind::BITVECTOR_PLUS>`).
-#ifndef DOXYGEN_SKIP
-Note that the API type :cpp:enum:`cvc5::api::Kind` roughly corresponds to
-:cpp:enum:`cvc5::Kind`, but is a different type. It hides internal kinds that
-should not be exported to the API, and maps all kinds that we want to export
-to its corresponding internal kinds.
-#endif
+<cvc5::api::Kind::AND>`), or a bit-vector addition
+(:cpp:enumerator:`BITVECTOR_ADD <cvc5::api::Kind::BITVECTOR_ADD>`).
.. doxygenenum:: cvc5::api::Kind
:project: cvc5
diff --git a/docs/examples/examples.rst b/docs/examples/examples.rst
index 528566a3e..5e17d524b 100644
--- a/docs/examples/examples.rst
+++ b/docs/examples/examples.rst
@@ -16,10 +16,11 @@ For every example, the same problem is constructed and solved using different in
datatypes
floatingpoint
lineararith
+ relations
sequences
sets
strings
combination
sygus-fun
sygus-grammar
- sygus-inv \ No newline at end of file
+ sygus-inv
diff --git a/docs/examples/relations.rst b/docs/examples/relations.rst
new file mode 100644
index 000000000..d94fa0aa7
--- /dev/null
+++ b/docs/examples/relations.rst
@@ -0,0 +1,7 @@
+Theory of Relations
+===================
+
+
+.. api-examples::
+ ../../examples/api/smtlib/relations.smt2
+
diff --git a/docs/examples/sets.rst b/docs/examples/sets.rst
index 71a6843c3..b0f1fc1da 100644
--- a/docs/examples/sets.rst
+++ b/docs/examples/sets.rst
@@ -5,3 +5,4 @@ Theory of Sets
.. api-examples::
../../examples/api/cpp/sets.cpp
../../examples/api/python/sets.py
+ ../../examples/api/smtlib/sets.smt2
diff --git a/docs/ext/examples.py b/docs/ext/examples.py
index 003726de4..9f8f7294e 100644
--- a/docs/ext/examples.py
+++ b/docs/ext/examples.py
@@ -22,7 +22,7 @@ class APIExamples(Directive):
'.cpp': {'title': 'C++', 'lang': 'c++'},
'.java': {'title': 'Java', 'lang': 'java'},
'.py': {'title': 'Python', 'lang': 'python'},
- '.smt2': {'title': 'SMT-LIBv2', 'lang': 'lisp'},
+ '.smt2': {'title': 'SMT-LIBv2', 'lang': 'smtlib'},
}
# The "arguments" are actually the content of the directive
diff --git a/docs/ext/smtliblexer.py b/docs/ext/smtliblexer.py
index 5dd54d006..e796e2404 100644
--- a/docs/ext/smtliblexer.py
+++ b/docs/ext/smtliblexer.py
@@ -7,15 +7,20 @@ class SmtLibLexer(RegexLexer):
tokens = {
'root': [
+ (r'ALL', token.Text),
+ (r'QF_ALL', token.Text),
(r'QF_BV', token.Text),
(r'QF_UFDT', token.Text),
- (r'ALL_SUPPORTED', token.Text),
+ (r'QF_UFLIAFS', token.Text),
+ (r'set-info', token.Keyword),
(r'set-logic', token.Keyword),
(r'set-option', token.Keyword),
(r'declare-codatatypes', token.Keyword),
(r'declare-const', token.Keyword),
+ (r'declare-datatype', token.Keyword),
(r'declare-datatypes', token.Keyword),
(r'declare-fun', token.Keyword),
+ (r'declare-sort', token.Keyword),
(r'define-fun', token.Keyword),
(r'assert\b', token.Keyword),
(r'check-sat-assuming', token.Keyword),
@@ -32,14 +37,21 @@ class SmtLibLexer(RegexLexer):
(r':produce-models', token.Name.Attribute),
(r':produce-unsat-cores', token.Name.Attribute),
(r':produce-unsat-assumptions', token.Name.Attribute),
+ (r':status', token.Name.Attribute),
(r'!', token.Name.Attribute),
+ (r'Array', token.Name.Attribute),
(r'BitVec', token.Name.Attribute),
+ (r'Int', token.Name.Attribute),
(r'RNE', token.Name.Attribute),
+ (r'Set', token.Name.Attribute),
+ (r'String', token.Name.Attribute),
(r'Tuple', token.Name.Attribute),
+ (r'tupSel', token.Name.Attribute),
(r'true', token.String),
(r'distinct', token.Operator),
(r'=', token.Operator),
(r'>', token.Operator),
+ (r'\*', token.Operator),
(r'and', token.Operator),
(r'bvadd', token.Operator),
(r'bvashr', token.Operator),
@@ -48,11 +60,30 @@ class SmtLibLexer(RegexLexer):
(r'bvult', token.Operator),
(r'bvule', token.Operator),
(r'bvsdiv', token.Operator),
+ (r'card', token.Operator),
+ (r'emp', token.Operator),
+ (r'emptyset', token.Operator),
+ (r'exists', token.Operator),
(r'extract', token.Operator),
+ (r'forall', token.Operator),
(r'fp.gt', token.Operator),
+ (r'insert', token.Operator),
+ (r'intersection', token.Operator),
(r'ite', token.Operator),
+ (r'member', token.Operator),
(r'mkTuple', token.Operator),
+ (r'not', token.Operator),
+ (r'product', token.Operator),
+ (r'pto', token.Operator),
+ (r'sep', token.Operator),
+ (r'singleton', token.Operator),
+ (r'subset', token.Operator),
+ (r'tclosure', token.Operator),
(r'to_fp_unsigned', token.Operator),
+ (r'transpose', token.Operator),
+ (r'union', token.Operator),
+ (r'univset', token.Operator),
+ (r'wand', token.Operator),
(r'\+zero', token.Operator),
(r'#b[0-1]+', token.Text),
(r'bv[0-9]+', token.Text),
@@ -67,5 +98,3 @@ class SmtLibLexer(RegexLexer):
(r'\.\.\.', token.Text)
]
}
-
-
diff --git a/docs/theories/datatypes.rst b/docs/theories/datatypes.rst
index 7dd0e8713..5f02a8bf8 100644
--- a/docs/theories/datatypes.rst
+++ b/docs/theories/datatypes.rst
@@ -179,7 +179,7 @@ a `cvc5::api::Solver solver` object.
| | | |
| | | ``Sort s = solver.mkTupleSort(sorts);`` |
+--------------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
-| | ``(declare-const t (tuple Int Int))`` | ``Sort s_int = solver.getIntegerSort();`` |
+| | ``(declare-const t (Tuple Int Int))`` | ``Sort s_int = solver.getIntegerSort();`` |
| | | |
| | | ``Sort s = solver.mkTypleSort({s_int, s_int});`` |
| | | |
diff --git a/docs/theories/separation-logic.rst b/docs/theories/separation-logic.rst
new file mode 100644
index 000000000..c2dcda78e
--- /dev/null
+++ b/docs/theories/separation-logic.rst
@@ -0,0 +1,154 @@
+Theory Reference: Separation Logic
+==================================
+
+cvc5 supports a syntax for separation logic as an extension of the SMT-LIB 2
+language.
+
+Signature
+---------
+
+Given a (decidable) base theory :math:`T`, cvc5 has a
+`decision procedure <https://cvc4.github.io/publications/2016/RIS+16.pdf>`__
+for quantifier-free :math:`SL(T)_{Loc,Data}` formulas, where :math:`Loc` and
+:math:`Data` are any sort belonging to :math:`T`.
+
+A :math:`SL(T)_{Loc,Data}` formula is one from the following grammar:
+
+.. code::
+
+ F : L | (emp t u) | (pto t u) | (sep F1 ... Fn) | (wand F1 F2) | ~F1 | F1 op ... op Fn
+
+where ``op`` is any classical Boolean connective, ``t`` and ``u`` are terms
+built from symbols in the signature of :math:`T` of sort :math:`Loc` and
+:math:`Data` respectively, and :math:`L` is a :math:`T`-literal.
+
+The operator ``emp`` denotes the empty heap constraint, the operator ``pto``
+denotes the points-to predicate, the operator ``sep`` denotes separation start
+and is variadic, and the operator ``wand`` denote magic wand.
+
+Semantics
+---------
+
+A satisfiability relation :math:`I,h \models_{SL} \varphi` is defined for
+:math:`SL(T)_{Loc,Data}` formulas :math:`\varphi`,
+where :math:`I` is an interpretation, and :math:`h` is a heap.
+
+The semantics of separation logic operators are as follows:
+
++-------------------------------------------------------------+------+-------------------------------------------------------------------------------------+
+| :math:`I,h \models_{SL} L` | Iff | :math:`I \models L`, if :math:`L` is a :math:`T`-literal |
++-------------------------------------------------------------+------+-------------------------------------------------------------------------------------+
+| :math:`I,h \models_{SL}` (emp :math:`t \ u`) | Iff | :math:`h = \emptyset` |
++-------------------------------------------------------------+------+-------------------------------------------------------------------------------------+
+| :math:`I,h \models_{SL}` (pto :math:`t \ u`) | Iff | :math:`h = \{(t^I,u^I)\} \text{ and } t^I\not=nil^I` |
++-------------------------------------------------------------+------+-------------------------------------------------------------------------------------+
+| :math:`I,h \models_{SL}` (sep :math:`\phi_1 \ldots \phi_n)` | Iff | there exist heaps :math:`h_1,\ldots,h_n` s.t. :math:`h=h_1\uplus \ldots \uplus h_n` |
+| | | |
+| | | and :math:`I,h_i \models_{SL} \phi_i, i = 1,\ldots,n` |
++-------------------------------------------------------------+------+-------------------------------------------------------------------------------------+
+| :math:`I,h \models_{SL}` (wand :math:`\phi_1 \ \phi_2`) | Iff | for all heaps :math:`h'` if :math:`h'\#h` and :math:`I,h' \models_{SL} \phi_1` |
+| | | |
+| | | then :math:`I,h'\uplus h \models_{SL} \phi_2` |
++-------------------------------------------------------------+------+-------------------------------------------------------------------------------------+
+
+where :math:`h_1 \uplus \ldots \uplus h_n` denotes the disjoint union of heaps
+:math:`h_1, \ldots, h_n` and :math:`h'\#h` denotes that heaps :math:`h'` and
+:math:`h` are disjoint, and :math:`nil` is a distinguished variable of sort
+:math:`Loc`.
+All classical Boolean connectives are interpreted as expected.
+
+.. note::
+ The arguments of ``emp`` are used to denote the sort of the heap and have no
+ meaning otherwise.
+
+Syntax
+------
+
+Separation logic in cvc5 requires the ``QF_ALL`` logic.
+
+The syntax for the operators of separation logic is summarized in the following
+table.
+For the C++ API examples in this table, we assume that we have created
+a :cpp:class:`cvc5::api::Solver` object.
+
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| | SMTLIB language | C++ API |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Logic String | ``(set-logic QF_ALL)`` | ``solver.setLogic("QF_ALL");`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Empty Heap | ``(_ emp <Sort_1> <Sort_2>)`` | ``solver.mkTerm(Kind::SEP_EMP, x, y);`` |
+| | | |
+| | | where ``x`` and ``y`` are of sort ``<Sort_1>`` and ``<Sort_2>`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Points-To | ``(pto x y)`` | ``solver.mkTerm(Kind::SEP_PTO, x, y);`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Separation Star | ``(sep c1 .. cn)`` | ``solver.mkTerm(Kind::SEP_STAR, {c1, ..., cn});`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Magic Wand | ``(wand c1 c1)`` | ``solver.mkTerm(Kind::SEP_WAND, c1, c2);`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Nil Element | ``(as nil <Sort>)`` | ``solver.mkSepNil(cvc5::api::Sort sort);`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+
+
+Examples
+--------
+
+The following input on heaps ``Int -> Int`` is unsatisfiable:
+
+.. code:: smtlib
+
+ (set-logic QF_ALL)
+ (set-info :status unsat)
+ (declare-const x Int)
+ (declare-const a Int)
+ (declare-const b Int)
+ (assert (and (pto x a) (pto x b)))
+ (assert (not (= a b)))
+ (check-sat)
+
+
+The following input on heaps ``U -> Int`` is satisfiable. Notice that the
+formula ``(not (emp x 0))`` is satisfied by heaps ``U -> Int`` (the sorts of
+``x`` and ``0`` respectively) whose domain is non-empty.
+
+.. code:: smtlib
+
+ (set-logic QF_ALL)
+ (set-info :status sat)
+ (declare-sort U 0)
+ (declare-const x U)
+ (declare-const a Int)
+ (assert (and (not (_ emp U Int)) (pto x a)))
+ (check-sat)
+
+The following input on heaps ``Int -> Node`` is satisfiable, where ``Node``
+denotes a user-defined inductive `datatypes <datatypes>`__.
+
+.. code:: smtlib
+
+ (set-logic QF_ALL)
+ (set-info :status sat)
+ (declare-const x Int)
+ (declare-const y Int)
+ (declare-const z Int)
+ (declare-datatype Node ((node (data Int) (left Int) (right Int))))
+ (assert (pto x (node 0 y z)))
+ (check-sat)
+
+.. note::
+
+ Given a separation logic input, the sorts :math:`Loc` and :math:`Data` are
+ inferred by cvc5, and must be consistent across all predicates occurring in
+ an input.
+ cvc5 does not accept an input such as:
+
+ .. code:: smtlib
+
+ (set-logic QF_ALL)
+ (declare-sort U 0)
+ (declare-const x U)
+ (assert (and (pto x 0) (pto 1 2)))
+ (check-sat)
+
+ since the sorts of the first arguments of the points-to predicates do not
+ agree.
diff --git a/docs/theories/sets-and-relations.rst b/docs/theories/sets-and-relations.rst
new file mode 100644
index 000000000..79838334f
--- /dev/null
+++ b/docs/theories/sets-and-relations.rst
@@ -0,0 +1,201 @@
+Theory Reference: Sets and Relations
+====================================
+
+Finite Sets
+-----------
+
+cvc5 supports the theory of finite sets.
+The simplest way to get a sense of the syntax is to look at an example:
+
+.. api-examples::
+ ../../examples/api/cpp/sets.cpp
+ ../../examples/api/python/sets.py
+ ../../examples/api/smtlib/sets.smt2
+
+The source code of these examples is available at:
+
+* `SMT-LIB 2 language example <https://github.com/cvc5/cvc5/blob/master/examples/api/smtlib/sets.smt2>`__
+* `C++ API example <https://github.com/cvc5/cvc5/blob/master/examples/api/cpp/sets.cpp>`__
+* `Python API example <https://github.com/cvc5/cvc5/blob/master/examples/api/python/sets.cpp>`__
+
+
+Below is a short summary of the sorts, constants, functions and
+predicates. For more details, see
+`this paper at IJCAR 2016 <https://cvc4.github.io/publications/2016/BRBT16.pdf>`__.
+
+For the C++ API examples in the table below, we assume that we have created
+a `cvc5::api::Solver solver` object.
+
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| | SMTLIB language | C++ API |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Logic String | append `FS` for finite sets | append `FS` for finite sets |
+| | | |
+| | ``(set-logic QF_UFLIAFS)`` | ``solver.setLogic("QF_UFLIAFS");`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Sort | ``(Set <Sort>)`` | ``solver.mkSetSort(cvc5::api::Sort elementSort);`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Constants | ``(declare-const X (Set Int)`` | ``Sort s = solver.mkSetSort(solver.getIntegerSort());`` |
+| | | |
+| | | ``Term X = solver.mkConst(s, "X");`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Union | ``(union X Y)`` | ``Term Y = solver.mkConst(s, "Y");`` |
+| | | |
+| | | ``Term t = solver.mkTerm(Kind::UNION, X, Y);`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Intersection | ``(setminus X Y)`` | ``Term t = solver.mkTerm(Kind::SETMINUS, X, Y);`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Membership | ``(member x X)`` | ``Term x = solver.mkConst(solver.getIntegerSort(), "x");`` |
+| | | |
+| | | ``Term t = solver.mkTerm(Kind::MEMBER, x, X);`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Subset | ``(subset X Y)`` | ``Term t = solver.mkTerm(Kind::SUBSET, X, Y);`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Emptyset | ``(as emptyset (Set Int)`` | ``Term t = solver.mkEmptySet(s);`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Singleton Set | ``(singleton 1)`` | ``Term t = solver.mkTerm(Kind::SINGLETON, solver.mkInteger(1));`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Cardinality | ``(card X)`` | ``Term t = solver.mkTerm(Kind::CARD, X);`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Insert / Finite Sets | ``(insert 1 2 3 (singleton 4))`` | ``Term one = solver.mkInteger(1);`` |
+| | | |
+| | | ``Term two = solver.mkInteger(2);`` |
+| | | |
+| | | ``Term three = solver.mkInteger(3);`` |
+| | | |
+| | | ``Term sgl = solver.mkTerm(Kind::SINGLETON, solver.mkInteger(4));``|
+| | | |
+| | | ``Term t = solver.mkTerm(Kind::INSERT, {one, two, three, sgl});`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Complement | ``(complement X)`` | ``Term t = solver.mkTerm(Kind::COMPLEMENT, X);`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+| Universe Set | ``(as univset (Set Int))`` | ``Term t = solver.mkUniverseSet(s);`` |
++----------------------+----------------------------------------------+--------------------------------------------------------------------+
+
+
+Semantics
+^^^^^^^^^
+
+The semantics of most of the above operators (e.g., set union, intersection,
+difference) are straightforward.
+The semantics for the universe set and complement are more subtle and explained
+in the following.
+
+The universe set ``(as univset (Set T))`` is *not* interpreted as the set
+containing all elements of sort ``T``.
+Instead it may be interpreted as any set such that all sets of sort ``(Set T)``
+are interpreted as subsets of it.
+In other words, it is the union of the interpretations of all (finite) sets in
+our input.
+
+For example:
+
+.. code:: smtlib
+
+ (declare-fun x () (Set Int))
+ (declare-fun y () (Set Int))
+ (declare-fun z () (Set Int))
+ (assert (member 0 x))
+ (assert (member 1 y))
+ (assert (= z (as univset (Set Int))))
+ (check-sat)
+
+Here, a possible model is:
+
+.. code:: smtlib
+
+ (define-fun x () (singleton 0))
+ (define-fun y () (singleton 1))
+ (define-fun z () (union (singleton 1) (singleton 0)))
+
+Notice that the universe set in this example is interpreted the same as ``z``,
+and is such that all sets in this example (``x``, ``y``, and ``z``) are subsets
+of it.
+
+The set complement operator for ``(Set T)`` is interpreted relative to the
+interpretation of the universe set for ``(Set T)``, and not relative to the set
+of all elements of sort ``T``.
+That is, for all sets ``X`` of sort ``(Set T)``, the complement operator is
+such that ``(= (complement X) (setminus (as univset (Set T)) X))``
+holds in all models.
+
+The motivation for these semantics is to ensure that the universe set for sort
+``T`` and applications of set complement can always be interpreted as a finite
+set in (quantifier-free) inputs, even if the cardinality of ``T`` is infinite.
+Above, notice that we were able to find a model for the universe set of sort
+``(Set Int)`` that contained two elements only.
+
+.. note::
+ In the presence of quantifiers, cvc5's implementation of the above theory
+ allows infinite sets.
+ In particular, the following formula is SAT (even though cvc5 is not able to
+ say this):
+
+ .. code:: smtlib
+
+ (set-logic ALL)
+ (declare-fun x () (Set Int))
+ (assert (forall ((z Int) (member (* 2 z) x)))
+ (check-sat)
+
+ The reason for that is that making this formula (and similar ones) `unsat` is
+ counter-intuitive when quantifiers are present.
+
+Finite Relations
+----------------
+
+Example:
+
+.. api-examples::
+ ../../examples/api/smtlib/relations.smt2
+
+For reference, below is a short summary of the sorts, constants, functions and
+predicates.
+For more details, see
+`this paper at CADE 2017 <https://cvc4.github.io/publications/2017/MRT+17.pdf>`__.
+
++----------------------+----------------------------------------------+------------------------------------------------------------------------------------+
+| | SMTLIB language | C++ API |
++----------------------+----------------------------------------------+------------------------------------------------------------------------------------+
+| Logic String | ``(set-logic QF_ALL)`` | ``solver.setLogic("QF_ALL");`` |
++----------------------+----------------------------------------------+------------------------------------------------------------------------------------+
+| Tuple Sort | ``(Tuple <Sort_1>, ..., <Sort_n>)`` | ``std::vector<cvc5::api::Sort> sorts = { ... };`` |
+| | | |
+| | | ``Sort s = solver.mkTupleSort(sorts);`` |
++----------------------+----------------------------------------------+------------------------------------------------------------------------------------+
+| | ``(declare-const t (Tuple Int Int))`` | ``Sort s_int = solver.getIntegerSort();`` |
+| | | |
+| | | ``Sort s = solver.mkTypleSort({s_int, s_int});`` |
+| | | |
+| | | ``Term t = solver.mkConst(s, "t");`` |
++----------------------+----------------------------------------------+------------------------------------------------------------------------------------+
+| Tuple Constructor | ``(mkTuple <Term_1>, ..., <Term_n>)`` | ``Sort s = solver.mkTypleSort(sorts);`` |
+| | | |
+| | | ``Datatype dt = s.getDatatype();`` |
+| | | |
+| | | ``Term c = dt[0].getConstructor();`` |
+| | | |
+| | | ``Term t = solver.mkTerm(Kind::APPLY_CONSTRUCTOR, {c, <Term_1>, ..., <Term_n>});`` |
++----------------------+----------------------------------------------+------------------------------------------------------------------------------------+
+| Tuple Selector | ``((_ tupSel i) t)`` | ``Sort s = solver.mkTypleSort(sorts);`` |
+| | | |
+| | | ``Datatype dt = s.getDatatype();`` |
+| | | |
+| | | ``Term c = dt[0].getSelector();`` |
+| | | |
+| | | ``Term t = solver.mkTerm(Kind::APPLY_SELECTOR, {s, t});`` |
++----------------------+----------------------------------------------+------------------------------------------------------------------------------------+
+| Reation Sort | ``(Set (Tuple <Sort_1>, ..., <Sort_n>))`` | ``Sort s = solver.mkSetSort(cvc5::api::Sort tupleSort);`` |
++----------------------+----------------------------------------------+------------------------------------------------------------------------------------+
+| Constants | ``(declare-const X (Set (Tuple Int Int)`` | ``Sort s = solver.mkSetSort(solver.mkTupleSort({s_int, s_int});`` |
+| | | |
+| | | ``Term X = solver.mkConst(s, "X");`` |
++----------------------+----------------------------------------------+------------------------------------------------------------------------------------+
+| Transpose | ``(transpose X)`` | ``Term t = solver.mkTerm(Kind::TRANSPOSE, X);`` |
++----------------------+----------------------------------------------+------------------------------------------------------------------------------------+
+| Transitive Closure | ``(tclosure X)`` | ``Term t = solver.mkTerm(Kind::TCLOSURE, X);`` |
++----------------------+----------------------------------------------+------------------------------------------------------------------------------------+
+| Join | ``(join X Y)`` | ``Term t = solver.mkTerm(Kind::JOIN, X, Y);`` |
++----------------------+----------------------------------------------+------------------------------------------------------------------------------------+
+| Product | ``(product X Y)`` | ``Term t = solver.mkTerm(Kind::PRODUCT, X, Y);`` |
++----------------------+----------------------------------------------+------------------------------------------------------------------------------------+
diff --git a/docs/theory.rst b/docs/theory.rst
index 45be41b2e..2d2a949d5 100644
--- a/docs/theory.rst
+++ b/docs/theory.rst
@@ -5,3 +5,5 @@ Theory References
:maxdepth: 1
theories/datatypes
+ theories/separation-logic
+ theories/sets-and-relations
diff --git a/examples/api/cpp/sets.cpp b/examples/api/cpp/sets.cpp
index 5c9652707..c1eded4a4 100644
--- a/examples/api/cpp/sets.cpp
+++ b/examples/api/cpp/sets.cpp
@@ -10,7 +10,7 @@
* directory for licensing information.
* ****************************************************************************
*
- * A simple demonstration of reasoning about sets with CVC4.
+ * A simple demonstration of reasoning about sets with cvc5.
*/
#include <cvc5/cvc5.h>
diff --git a/examples/api/smtlib/relations.smt2 b/examples/api/smtlib/relations.smt2
new file mode 100644
index 000000000..11801a868
--- /dev/null
+++ b/examples/api/smtlib/relations.smt2
@@ -0,0 +1,41 @@
+(set-logic ALL)
+(set-info :status sat)
+
+(declare-fun r1 () (Set (Tuple String Int)))
+(declare-fun r2 () (Set (Tuple Int String)))
+(declare-fun r () (Set (Tuple String String)))
+(declare-fun s () (Set (Tuple String String)))
+(declare-fun t () (Set (Tuple String Int Int String)))
+(declare-fun lt1 () (Set (Tuple Int Int)))
+(declare-fun lt2 () (Set (Tuple Int Int)))
+(declare-fun i () Int)
+
+(assert
+ (= r1
+ (insert
+ (mkTuple "a" 1)
+ (mkTuple "b" 2)
+ (mkTuple "c" 3)
+ (singleton (mkTuple "d" 4)))))
+(assert
+ (= r2
+ (insert
+ (mkTuple 1 "1")
+ (mkTuple 2 "2")
+ (mkTuple 3 "3")
+ (singleton (mkTuple 17 "17")))))
+(assert (= r (join r1 r2)))
+(assert (= s (transpose r)))
+(assert (= t (product r1 r2)))
+(assert
+ (=
+ lt1
+ (insert
+ (mkTuple 1 2)
+ (mkTuple 2 3)
+ (mkTuple 3 4)
+ (singleton (mkTuple 4 5)))))
+(assert (= lt2 (tclosure lt1)))
+(assert (= i (card t)))
+
+(check-sat)
diff --git a/examples/api/smtlib/sets.smt2 b/examples/api/smtlib/sets.smt2
new file mode 100644
index 000000000..437c285e2
--- /dev/null
+++ b/examples/api/smtlib/sets.smt2
@@ -0,0 +1,34 @@
+(set-logic QF_UFLIAFS)
+(set-option :produce-models true)
+(set-option :incremental true)
+(declare-const A (Set Int))
+(declare-const B (Set Int))
+(declare-const C (Set Int))
+(declare-const x Int)
+
+; Verify union distributions over intersection
+(check-sat-assuming
+ (
+ (distinct
+ (intersection (union A B) C)
+ (union (intersection A C) (intersection B C)))
+ )
+)
+
+; Verify emptset is a subset of any set
+(check-sat-assuming
+ (
+ (not (subset (as emptyset (Set Int)) A))
+ )
+)
+
+; Find an element in {1, 2} intersection {2, 3}, if there is one.
+(check-sat-assuming
+ (
+ (member
+ x
+ (intersection
+ (union (singleton 1) (singleton 2))
+ (union (singleton 2) (singleton 3))))
+ )
+)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1831335ee..527912b8e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -52,6 +52,8 @@ libcvc5_add_sources(
omt/omt_optimizer.h
preprocessing/assertion_pipeline.cpp
preprocessing/assertion_pipeline.h
+ preprocessing/learned_literal_manager.cpp
+ preprocessing/learned_literal_manager.h
preprocessing/passes/ackermann.cpp
preprocessing/passes/ackermann.h
preprocessing/passes/apply_substs.cpp
@@ -415,6 +417,8 @@ libcvc5_add_sources(
theory/arith/nl/cad/cdcac_utils.h
theory/arith/nl/cad/constraints.cpp
theory/arith/nl/cad/constraints.h
+ theory/arith/nl/cad/lazard_evaluation.cpp
+ theory/arith/nl/cad/lazard_evaluation.h
theory/arith/nl/cad/projections.cpp
theory/arith/nl/cad/projections.h
theory/arith/nl/cad/proof_checker.cpp
diff --git a/src/api/cpp/cvc5.h b/src/api/cpp/cvc5.h
index 00308f11a..0e5d1d612 100644
--- a/src/api/cpp/cvc5.h
+++ b/src/api/cpp/cvc5.h
@@ -179,8 +179,8 @@ class CVC5_EXPORT Result
bool isNotEntailed() const;
/**
- * Return true if query was a checkEntailed() () query and cvc5 was not able
- * to determine if it is entailed.
+ * Return true if query was a checkEntailed() query and cvc5 was not able to
+ * determine if it is entailed.
*/
bool isEntailmentUnknown() const;
@@ -2683,7 +2683,7 @@ class CVC5_EXPORT Statistics
/**
* Retrieve the statistic with the given name.
* Asserts that a statistic with the given name actually exists and throws
- * a `CVC4ApiRecoverableException` if it does not.
+ * a `CVC5ApiRecoverableException` if it does not.
* @param name Name of the statistic.
* @return The statistic with the given name.
*/
diff --git a/src/api/cpp/cvc5_kind.h b/src/api/cpp/cvc5_kind.h
index b4596e977..2ec190360 100644
--- a/src/api/cpp/cvc5_kind.h
+++ b/src/api/cpp/cvc5_kind.h
@@ -33,9 +33,15 @@ namespace api {
/**
* The kind of a cvc5 term.
*
- * Note that the underlying type of Kind must be signed (to enable range
- * checks for validity). The size of this type depends on the size of
- * cvc5::Kind (NodeValue::NBITS_KIND, currently 10 bits, see expr/node_value.h).
+ * \internal
+ *
+ * Note that the API type `cvc5::api::Kind` roughly corresponds to
+ * `cvc5::Kind`, but is a different type. It hides internal kinds that should
+ * not be exported to the API, and maps all kinds that we want to export to its
+ * corresponding internal kinds. The underlying type of `cvc5::api::Kind` must
+ * be signed (to enable range checks for validity). The size of this type
+ * depends on the size of `cvc5::Kind` (`NodeValue::NBITS_KIND`, currently 10
+ * bits, see expr/node_value.h).
*/
enum CVC5_EXPORT Kind : int32_t
{
@@ -1844,9 +1850,10 @@ enum CVC5_EXPORT Kind : int32_t
* - `Solver::mkTerm(const Op& op, const Term& child1, const Term& child2) const`
* - `Solver::mkTerm(const Op& op, const std::vector<Term>& children) const`
*
- * Note: We currently support the creation of constant arrays, but under some
+ * @note We currently support the creation of constant arrays, but under some
* conditions when there is a chain of equalities connecting two constant
- * arrays, the solver doesn't know what to do and aborts (Issue <a href="https://github.com/CVC4/CVC4/issues/1667">#1667</a>).
+ * arrays, the solver doesn't know what to do and aborts (Issue <a
+ * href="https://github.com/cvc5/cvc5/issues/1667">#1667</a>).
*/
CONST_ARRAY,
/**
diff --git a/src/api/java/cvc5/Result.java b/src/api/java/cvc5/Result.java
index bd142b985..4399df1e4 100644
--- a/src/api/java/cvc5/Result.java
+++ b/src/api/java/cvc5/Result.java
@@ -122,7 +122,7 @@ public class Result extends AbstractPointer
/**
* Return true if query was a checkSat() or checkSatAssuming() query and
- * CVC4 was not able to determine (un)satisfiability.
+ * cvc5 was not able to determine (un)satisfiability.
*/
public boolean isSatUnknown()
{
@@ -153,8 +153,8 @@ public class Result extends AbstractPointer
private native boolean isNotEntailed(long pointer);
/**
- * Return true if query was a checkEntailed() () query and CVC4 was not able
- * to determine if it is entailed.
+ * Return true if query was a checkEntailed() query and cvc5 was not able to
+ * determine if it is entailed.
*/
public boolean isEntailmentUnknown()
{
diff --git a/src/api/python/cvc5.pxi b/src/api/python/cvc5.pxi
index 3339543f3..258005207 100644
--- a/src/api/python/cvc5.pxi
+++ b/src/api/python/cvc5.pxi
@@ -740,6 +740,21 @@ cdef class Solver:
return term
def mkReal(self, val, den=None):
+ '''
+ Make a real number term.
+
+ Really, makes a rational term.
+
+ Can be used in various forms.
+ * Given a string "N/D" constructs the corresponding rational.
+ * Given a string "W.D" constructs the reduction of (W * P + D)/P, where
+ P is the appropriate power of 10.
+ * Given a float f, constructs the rational matching f's string
+ representation. This means that mkReal(0.3) gives 3/10 and not the
+ IEEE-754 approximation of 3/10.
+ * Given a string "W" or an integer, constructs that integer.
+ * Given two strings and/or integers N and D, constructs N/D.
+ '''
cdef Term term = Term(self)
if den is None:
term.cterm = self.csolver.mkReal(str(val).encode())
@@ -1766,12 +1781,14 @@ cdef class Term:
return self.cterm.isRealValue()
def getRealValue(self):
- return float(Fraction(self.cterm.getRealValue().decode()))
+ '''Returns the value of a real term as a Fraction'''
+ return Fraction(self.cterm.getRealValue().decode())
def isBitVectorValue(self):
return self.cterm.isBitVectorValue()
def getBitVectorValue(self, base = 2):
+ '''Returns the value of a bit-vector term as a 0/1 string'''
return self.cterm.getBitVectorValue(base).decode()
def toPythonObj(self):
diff --git a/src/base/configuration.cpp b/src/base/configuration.cpp
index 80d5bac57..61951841b 100644
--- a/src/base/configuration.cpp
+++ b/src/base/configuration.cpp
@@ -99,8 +99,8 @@ std::string Configuration::getVersionExtra() { return CVC5_EXTRAVERSION; }
std::string Configuration::copyright() {
std::stringstream ss;
- ss << "Copyright (c) 2009-2020 by the authors and their institutional\n"
- << "affiliations listed at http://cvc4.cs.stanford.edu/authors\n\n";
+ ss << "Copyright (c) 2009-2021 by the authors and their institutional\n"
+ << "affiliations listed at https://cvc5.github.io/people.html\n\n";
if (Configuration::licenseIsGpl()) {
ss << "This build of cvc5 uses GPLed libraries, and is thus covered by\n"
@@ -185,7 +185,7 @@ std::string Configuration::copyright() {
ss << "cvc5 is statically linked against these libraries. To recompile\n"
"this version of cvc5 with different versions of these libraries\n"
"follow the instructions on "
- "https://github.com/CVC4/CVC4/blob/master/INSTALL.md\n\n";
+ "https://github.com/cvc5/cvc5/blob/master/INSTALL.md\n\n";
}
}
diff --git a/src/decision/decision_engine_old.h b/src/decision/decision_engine_old.h
index e9169d9b2..4e7bde4b5 100644
--- a/src/decision/decision_engine_old.h
+++ b/src/decision/decision_engine_old.h
@@ -15,8 +15,8 @@
#include "cvc5_private.h"
-#ifndef CVC4__DECISION__DECISION_ENGINE_OLD_H
-#define CVC4__DECISION__DECISION_ENGINE_OLD_H
+#ifndef CVC5__DECISION__DECISION_ENGINE_OLD_H
+#define CVC5__DECISION__DECISION_ENGINE_OLD_H
#include "base/output.h"
#include "context/cdo.h"
@@ -147,4 +147,4 @@ class DecisionEngineOld
} // namespace cvc5
-#endif /* CVC4__DECISION__DECISION_ENGINE_H */
+#endif /* CVC5__DECISION__DECISION_ENGINE_H */
diff --git a/src/expr/dtype.cpp b/src/expr/dtype.cpp
index 82bfa1d70..52d6989c4 100644
--- a/src/expr/dtype.cpp
+++ b/src/expr/dtype.cpp
@@ -260,10 +260,9 @@ void DType::setSygus(TypeNode st, Node bvl, bool allowConst, bool allowAll)
// Notice we only want to do this for sygus datatypes that are user-provided.
// At the moment, the condition !allow_all implies the grammar is
// user-provided and hence may require a default constant.
- // TODO (https://github.com/CVC4/cvc4-projects/issues/38):
- // In an API for SyGuS, it probably makes more sense for the user to
- // explicitly add the "any constant" constructor with a call instead of
- // passing a flag. This would make the block of code unnecessary.
+ // For the SyGuS API, we could consider requiring the user to explicitly add
+ // the "any constant" constructor with a call instead of passing a flag. This
+ // would make the block of code unnecessary.
if (allowConst && !allowAll)
{
// if I don't already have a constant (0-ary constructor)
diff --git a/src/expr/node.h b/src/expr/node.h
index fdcfcbe5f..5f5d3a976 100644
--- a/src/expr/node.h
+++ b/src/expr/node.h
@@ -126,7 +126,7 @@ typedef NodeTemplate<true> Node;
*
* More guidelines on when to use TNodes is available in the cvc5
* Developer's Guide:
- * https://github.com/CVC4/CVC4/wiki/Developer-Guide#dealing-with-expressions-nodes-and-tnodes
+ * https://github.com/cvc5/cvc5/wiki/Developer-Guide#dealing-with-expressions-nodes-and-tnodes
*/
typedef NodeTemplate<false> TNode;
diff --git a/src/expr/node_manager.cpp b/src/expr/node_manager.cpp
index 1e6a38815..fe7d75ca3 100644
--- a/src/expr/node_manager.cpp
+++ b/src/expr/node_manager.cpp
@@ -528,10 +528,6 @@ TypeNode NodeManager::mkBagType(TypeNode elementType)
{
CheckArgument(
!elementType.isNull(), elementType, "unexpected NULL element type");
- CheckArgument(elementType.isFirstClass(),
- elementType,
- "cannot store types that are not first-class in bags. Try "
- "option --uf-ho.");
Debug("bags") << "making bags type " << elementType << std::endl;
return mkTypeNode(kind::BAG_TYPE, elementType);
}
@@ -540,10 +536,6 @@ TypeNode NodeManager::mkSequenceType(TypeNode elementType)
{
CheckArgument(
!elementType.isNull(), elementType, "unexpected NULL element type");
- CheckArgument(elementType.isFirstClass(),
- elementType,
- "cannot store types that are not first-class in sequences. Try "
- "option --uf-ho.");
return mkTypeNode(kind::SEQUENCE_TYPE, elementType);
}
diff --git a/src/expr/node_manager.h b/src/expr/node_manager.h
index ad0593cee..b651c055a 100644
--- a/src/expr/node_manager.h
+++ b/src/expr/node_manager.h
@@ -1095,14 +1095,6 @@ inline TypeNode NodeManager::mkArrayType(TypeNode indexType,
"unexpected NULL index type");
CheckArgument(!constituentType.isNull(), constituentType,
"unexpected NULL constituent type");
- CheckArgument(indexType.isFirstClass(),
- indexType,
- "cannot index arrays by types that are not first-class. Try "
- "option --uf-ho.");
- CheckArgument(constituentType.isFirstClass(),
- constituentType,
- "cannot store types that are not first-class in arrays. Try "
- "option --uf-ho.");
Debug("arrays") << "making array type " << indexType << " "
<< constituentType << std::endl;
return mkTypeNode(kind::ARRAY_TYPE, indexType, constituentType);
@@ -1111,10 +1103,6 @@ inline TypeNode NodeManager::mkArrayType(TypeNode indexType,
inline TypeNode NodeManager::mkSetType(TypeNode elementType) {
CheckArgument(!elementType.isNull(), elementType,
"unexpected NULL element type");
- CheckArgument(elementType.isFirstClass(),
- elementType,
- "cannot store types that are not first-class in sets. Try "
- "option --uf-ho.");
Debug("sets") << "making sets type " << elementType << std::endl;
return mkTypeNode(kind::SET_TYPE, elementType);
}
diff --git a/src/main/command_executor.cpp b/src/main/command_executor.cpp
index 5759ec856..6bdc1abc9 100644
--- a/src/main/command_executor.cpp
+++ b/src/main/command_executor.cpp
@@ -173,13 +173,7 @@ bool CommandExecutor::doCommandSingleton(Command* cmd)
}
if (options::getDumpInstantiations(d_options)
- && ((options::getInstFormatMode(d_options)
- != options::InstFormatMode::SZS
- && (res.isSat()
- || (res.isSatUnknown()
- && res.getUnknownExplanation()
- == api::Result::INCOMPLETE)))
- || isResultUnsat))
+ && GetInstantiationsCommand::isEnabled(d_solver.get(), res))
{
getterCommands.emplace_back(new GetInstantiationsCommand());
}
diff --git a/src/main/driver_unified.cpp b/src/main/driver_unified.cpp
index caa0340bd..697501d13 100644
--- a/src/main/driver_unified.cpp
+++ b/src/main/driver_unified.cpp
@@ -57,7 +57,7 @@ thread_local Options* pOptions;
const char* progPath;
/** Just the basename component of argv[0] */
-const std::string* progName;
+std::string progName;
/** A pointer to the CommandExecutor (the signal handlers need it) */
std::unique_ptr<cvc5::main::CommandExecutor> pExecutor;
@@ -80,7 +80,7 @@ TotalTimer::~TotalTimer()
void printUsage(Options& opts, bool full) {
stringstream ss;
- ss << "usage: " << options::getBinaryName(opts) << " [options] [input-file]"
+ ss << "usage: " << progName << " [options] [input-file]"
<< endl
<< endl
<< "Without an input file, or with `-', cvc5 reads from standard input."
@@ -106,13 +106,11 @@ int runCvc5(int argc, char* argv[], Options& opts)
progPath = argv[0];
// Parse the options
- vector<string> filenames = Options::parseOptions(&opts, argc, argv);
+ std::vector<string> filenames =
+ Options::parseOptions(&opts, argc, argv, progName);
auto limit = install_time_limit(opts);
- string progNameStr = options::getBinaryName(opts);
- progName = &progNameStr;
-
if (opts.driver.help)
{
printUsage(opts, true);
diff --git a/src/main/main.h b/src/main/main.h
index 54abbdbe9..14d99f79c 100644
--- a/src/main/main.h
+++ b/src/main/main.h
@@ -34,7 +34,7 @@ class CommandExecutor;
extern const char* progPath;
/** Just the basename component of argv[0] */
-extern const std::string* progName;
+extern std::string progName;
/** A reference for use by the signal handlers to print statistics */
extern std::unique_ptr<cvc5::main::CommandExecutor> pExecutor;
diff --git a/src/main/signal_handlers.cpp b/src/main/signal_handlers.cpp
index d0628e2a7..b65600eb5 100644
--- a/src/main/signal_handlers.cpp
+++ b/src/main/signal_handlers.cpp
@@ -136,14 +136,14 @@ void segv_handler(int sig, siginfo_t* info, void* c)
safe_print(STDERR_FILENO,
"Spinning so that a debugger can be connected.\n");
safe_print(STDERR_FILENO, "Try: gdb ");
- safe_print(STDERR_FILENO, *progName);
+ safe_print(STDERR_FILENO, progName);
safe_print(STDERR_FILENO, " ");
safe_print<int64_t>(STDERR_FILENO, getpid());
safe_print(STDERR_FILENO, "\n");
safe_print(STDERR_FILENO, " or: gdb --pid=");
safe_print<int64_t>(STDERR_FILENO, getpid());
safe_print(STDERR_FILENO, " ");
- safe_print(STDERR_FILENO, *progName);
+ safe_print(STDERR_FILENO, progName);
safe_print(STDERR_FILENO, "\n");
for (;;)
{
@@ -191,14 +191,14 @@ void ill_handler(int sig, siginfo_t* info, void*)
safe_print(STDERR_FILENO,
"Spinning so that a debugger can be connected.\n");
safe_print(STDERR_FILENO, "Try: gdb ");
- safe_print(STDERR_FILENO, *progName);
+ safe_print(STDERR_FILENO, progName);
safe_print(STDERR_FILENO, " ");
safe_print<int64_t>(STDERR_FILENO, getpid());
safe_print(STDERR_FILENO, "\n");
safe_print(STDERR_FILENO, " or: gdb --pid=");
safe_print<int64_t>(STDERR_FILENO, getpid());
safe_print(STDERR_FILENO, " ");
- safe_print(STDERR_FILENO, *progName);
+ safe_print(STDERR_FILENO, progName);
safe_print(STDERR_FILENO, "\n");
for (;;)
{
diff --git a/src/omt/integer_optimizer.h b/src/omt/integer_optimizer.h
index 34605cc71..0b62c0816 100644
--- a/src/omt/integer_optimizer.h
+++ b/src/omt/integer_optimizer.h
@@ -36,13 +36,12 @@ class OMTOptimizerInteger : public OMTOptimizer
private:
/**
* Handles the optimization query specified by objType
- * isMinimize = true will trigger minimization,
+ * isMinimize = true will trigger minimization,
* otherwise trigger maximization
**/
- smt::OptimizationResult optimize(
- SmtEngine* optChecker,
- TNode target,
- bool isMinimize);
+ smt::OptimizationResult optimize(SmtEngine* optChecker,
+ TNode target,
+ bool isMinimize);
};
} // namespace cvc5::omt
diff --git a/src/omt/omt_optimizer.cpp b/src/omt/omt_optimizer.cpp
index 08f1809ec..2145492db 100644
--- a/src/omt/omt_optimizer.cpp
+++ b/src/omt/omt_optimizer.cpp
@@ -30,7 +30,7 @@ bool OMTOptimizer::nodeSupportsOptimization(TNode node)
}
std::unique_ptr<OMTOptimizer> OMTOptimizer::getOptimizerForObjective(
- OptimizationObjective& objective)
+ const OptimizationObjective& objective)
{
// the datatype of the target node
TypeNode objectiveType = objective.getTarget().getType(true);
@@ -53,7 +53,10 @@ std::unique_ptr<OMTOptimizer> OMTOptimizer::getOptimizerForObjective(
}
Node OMTOptimizer::mkStrongIncrementalExpression(
- NodeManager* nm, TNode lhs, TNode rhs, OptimizationObjective& objective)
+ NodeManager* nm,
+ TNode lhs,
+ TNode rhs,
+ const OptimizationObjective& objective)
{
constexpr const char lhsTypeError[] =
"lhs type does not match or is not implicitly convertable to the target "
@@ -114,10 +117,11 @@ Node OMTOptimizer::mkStrongIncrementalExpression(
Unreachable();
}
-Node OMTOptimizer::mkWeakIncrementalExpression(NodeManager* nm,
- TNode lhs,
- TNode rhs,
- OptimizationObjective& objective)
+Node OMTOptimizer::mkWeakIncrementalExpression(
+ NodeManager* nm,
+ TNode lhs,
+ TNode rhs,
+ const OptimizationObjective& objective)
{
constexpr const char lhsTypeError[] =
"lhs type does not match or is not implicitly convertable to the target "
diff --git a/src/omt/omt_optimizer.h b/src/omt/omt_optimizer.h
index 1052865b0..1e8d9e763 100644
--- a/src/omt/omt_optimizer.h
+++ b/src/omt/omt_optimizer.h
@@ -46,7 +46,7 @@ class OMTOptimizer
* and this is the optimizer for targetNode
**/
static std::unique_ptr<OMTOptimizer> getOptimizerForObjective(
- smt::OptimizationObjective& objective);
+ const smt::OptimizationObjective& objective);
/**
* Given the lhs and rhs expressions, with an optimization objective,
@@ -70,7 +70,7 @@ class OMTOptimizer
NodeManager* nm,
TNode lhs,
TNode rhs,
- smt::OptimizationObjective& objective);
+ const smt::OptimizationObjective& objective);
/**
* Given the lhs and rhs expressions, with an optimization objective,
@@ -94,7 +94,7 @@ class OMTOptimizer
NodeManager* nm,
TNode lhs,
TNode rhs,
- smt::OptimizationObjective& objective);
+ const smt::OptimizationObjective& objective);
/**
* Minimize the target node with constraints encoded in optChecker
diff --git a/src/options/base_options.toml b/src/options/base_options.toml
index 7b2cde54a..f9d1c1a18 100644
--- a/src/options/base_options.toml
+++ b/src/options/base_options.toml
@@ -2,11 +2,6 @@ id = "BASE"
name = "Base"
[[option]]
- name = "binary_name"
- category = "undocumented"
- type = "std::string"
-
-[[option]]
name = "in"
category = "undocumented"
type = "std::istream*"
diff --git a/src/options/bv_options.toml b/src/options/bv_options.toml
index fcad51ceb..8d4c2b1de 100644
--- a/src/options/bv_options.toml
+++ b/src/options/bv_options.toml
@@ -191,22 +191,6 @@ name = "Bitvector Theory"
help = "simplify formula via Gaussian Elimination if applicable"
[[option]]
- name = "bvLazyRewriteExtf"
- category = "regular"
- long = "bv-lazy-rewrite-extf"
- type = "bool"
- default = "true"
- help = "lazily rewrite extended functions like bv2nat and int2bv"
-
-[[option]]
- name = "bvLazyReduceExtf"
- category = "regular"
- long = "bv-lazy-reduce-extf"
- type = "bool"
- default = "false"
- help = "reduce extended functions like bv2nat and int2bv at last call instead of full effort"
-
-[[option]]
name = "bvAlgExtf"
category = "regular"
long = "bv-alg-extf"
diff --git a/src/options/options_handler.cpp b/src/options/options_handler.cpp
index d06c64517..c1c843802 100644
--- a/src/options/options_handler.cpp
+++ b/src/options/options_handler.cpp
@@ -252,26 +252,29 @@ void OptionsHandler::setStats(const std::string& option, bool value)
throw OptionException(ss.str());
}
#endif /* CVC5_STATISTICS_ON */
- Assert(option.substr(0, 2) == "--");
- std::string opt = option.substr(2);
+ std::string opt = option;
+ if (option.substr(0, 2) == "--")
+ {
+ opt = opt.substr(2);
+ }
if (value)
{
- if (option == options::base::statisticsAll__name)
+ if (opt == options::base::statisticsAll__name)
{
d_options->base.statistics = true;
}
- else if (option == options::base::statisticsEveryQuery__name)
+ else if (opt == options::base::statisticsEveryQuery__name)
{
d_options->base.statistics = true;
}
- else if (option == options::base::statisticsExpert__name)
+ else if (opt == options::base::statisticsExpert__name)
{
d_options->base.statistics = true;
}
}
else
{
- if (option == options::base::statistics__name)
+ if (opt == options::base::statistics__name)
{
d_options->base.statisticsAll = false;
d_options->base.statisticsEveryQuery = false;
diff --git a/src/options/options_public.cpp b/src/options/options_public.cpp
index 7d72496aa..35e891f5a 100644
--- a/src/options/options_public.cpp
+++ b/src/options/options_public.cpp
@@ -103,10 +103,6 @@ int32_t getVerbosity(const Options& opts) { return opts.base.verbosity; }
std::istream* getIn(const Options& opts) { return opts.base.in; }
std::ostream* getErr(const Options& opts) { return opts.base.err; }
std::ostream* getOut(const Options& opts) { return opts.base.out; }
-const std::string& getBinaryName(const Options& opts)
-{
- return opts.base.binary_name;
-}
void setInputLanguage(InputLanguage val, Options& opts)
{
diff --git a/src/options/options_public.h b/src/options/options_public.h
index 9b549601f..1d2f9edba 100644
--- a/src/options/options_public.h
+++ b/src/options/options_public.h
@@ -55,7 +55,6 @@ int32_t getVerbosity(const Options& opts) CVC5_EXPORT;
std::istream* getIn(const Options& opts) CVC5_EXPORT;
std::ostream* getErr(const Options& opts) CVC5_EXPORT;
std::ostream* getOut(const Options& opts) CVC5_EXPORT;
-const std::string& getBinaryName(const Options& opts) CVC5_EXPORT;
void setInputLanguage(InputLanguage val, Options& opts) CVC5_EXPORT;
void setOut(std::ostream* val, Options& opts) CVC5_EXPORT;
diff --git a/src/options/options_template.cpp b/src/options/options_template.cpp
index 0d6b7f01b..e909a5f0a 100644
--- a/src/options/options_template.cpp
+++ b/src/options/options_template.cpp
@@ -364,7 +364,8 @@ public:
*/
std::vector<std::string> Options::parseOptions(Options* options,
int argc,
- char* argv[])
+ char* argv[],
+ std::string& binaryName)
{
Assert(options != NULL);
Assert(argv != NULL);
@@ -386,7 +387,7 @@ std::vector<std::string> Options::parseOptions(Options* options,
if(x != NULL) {
progName = x + 1;
}
- options->base.binary_name = std::string(progName);
+ binaryName = std::string(progName);
std::vector<std::string> nonoptions;
options->parseOptionsRecursive(argc, argv, &nonoptions);
diff --git a/src/options/options_template.h b/src/options/options_template.h
index 76c599d23..e9a4a6999 100644
--- a/src/options/options_template.h
+++ b/src/options/options_template.h
@@ -174,7 +174,8 @@ public:
*/
static std::vector<std::string> parseOptions(Options* options,
int argc,
- char* argv[]);
+ char* argv[],
+ std::string& binaryName);
/**
* Get the setting for all options.
diff --git a/src/preprocessing/learned_literal_manager.cpp b/src/preprocessing/learned_literal_manager.cpp
new file mode 100644
index 000000000..fa6a01791
--- /dev/null
+++ b/src/preprocessing/learned_literal_manager.cpp
@@ -0,0 +1,52 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ * Andrew Reynolds
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * Learned literal manager
+ */
+
+#include "preprocessing/learned_literal_manager.h"
+
+#include "theory/rewriter.h"
+
+namespace cvc5 {
+namespace preprocessing {
+
+LearnedLiteralManager::LearnedLiteralManager(theory::TrustSubstitutionMap& tls,
+ context::UserContext* u,
+ ProofNodeManager* pnm)
+ : d_topLevelSubs(tls), d_learnedLits(u)
+{
+}
+
+void LearnedLiteralManager::notifyLearnedLiteral(TNode lit)
+{
+ d_learnedLits.insert(lit);
+ Trace("pp-llm") << "LLM:notifyLearnedLiteral: " << lit << std::endl;
+}
+
+std::vector<Node> LearnedLiteralManager::getLearnedLiterals() const
+{
+ std::vector<Node> currLearnedLits;
+ for (const auto& lit: d_learnedLits)
+ {
+ // update based on substitutions
+ Node tlsNode = d_topLevelSubs.get().apply(lit);
+ tlsNode = theory::Rewriter::rewrite(tlsNode);
+ currLearnedLits.push_back(tlsNode);
+ Trace("pp-llm") << "Learned literal : " << tlsNode << " from " << lit
+ << std::endl;
+ }
+ return currLearnedLits;
+}
+
+} // namespace preprocessing
+} // namespace cvc5
diff --git a/src/preprocessing/learned_literal_manager.h b/src/preprocessing/learned_literal_manager.h
new file mode 100644
index 000000000..2b0273628
--- /dev/null
+++ b/src/preprocessing/learned_literal_manager.h
@@ -0,0 +1,71 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ * Andrew Reynolds
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * Learned literal manager
+ */
+
+#include "cvc5_private.h"
+
+#ifndef CVC5__PREPROCESSING__LEARNED_LITERAL_MANAGER_H
+#define CVC5__PREPROCESSING__LEARNED_LITERAL_MANAGER_H
+
+#include "context/cdhashset.h"
+#include "expr/node.h"
+#include "theory/trust_substitutions.h"
+
+namespace cvc5 {
+namespace preprocessing {
+
+/**
+ * This class maintains the list of learned literals that have been inferred
+ * during preprocessing but we have not fully processed e.g. via substitutions.
+ *
+ * In particular, notice that if an equality (= x t) is learned at top level,
+ * we may add x -> t to top level substitutions if t does not contain x; we can
+ * henceforth forget that (= x t) is a learned literal. On the other hand, if
+ * a literal like (> x t) is learned at top-level, it may be useful to remember
+ * this information. This class is concerned with the latter kind of literals.
+ */
+class LearnedLiteralManager
+{
+ public:
+ LearnedLiteralManager(theory::TrustSubstitutionMap& tls,
+ context::UserContext* u,
+ ProofNodeManager* pnm);
+ /**
+ * Notify learned literal. This method is called when a literal is
+ * entailed by the current set of assertions.
+ *
+ * It should be rewritten, and such that top level substitutions have
+ * been applied to it.
+ */
+ void notifyLearnedLiteral(TNode lit);
+ /**
+ * Get learned literals, which returns the current set of learned literals
+ * provided to this class. These literals are refreshed so that the current
+ * top-level substitutions are applied to them, and then are rewritten.
+ */
+ std::vector<Node> getLearnedLiterals() const;
+
+ private:
+ /** Learned literal map */
+ typedef context::CDHashSet<Node> NodeSet;
+ /* The top level substitutions */
+ theory::TrustSubstitutionMap& d_topLevelSubs;
+ /** Learned literals */
+ NodeSet d_learnedLits;
+};
+
+} // namespace preprocessing
+} // namespace cvc5
+
+#endif /* CVC5__PREPROCESSING__LEARNED_LITERAL_MANAGER_H */
diff --git a/src/preprocessing/passes/bv_to_int.cpp b/src/preprocessing/passes/bv_to_int.cpp
index b6f53f8c2..ad2707035 100644
--- a/src/preprocessing/passes/bv_to_int.cpp
+++ b/src/preprocessing/passes/bv_to_int.cpp
@@ -408,6 +408,14 @@ Node BVToInt::translateWithChildren(Node original,
returnNode = translated_children[0];
break;
}
+ case kind::INT_TO_BITVECTOR:
+ {
+ // ((_ int2bv n) t) ---> (mod t 2^n)
+ size_t sz = original.getOperator().getConst<IntToBitVector>().d_size;
+ returnNode = d_nm->mkNode(
+ kind::INTS_MODULUS_TOTAL, translated_children[0], pow2(sz));
+ }
+ break;
case kind::BITVECTOR_AND:
{
// We support three configurations:
diff --git a/src/preprocessing/passes/int_to_bv.cpp b/src/preprocessing/passes/int_to_bv.cpp
index 7f03b9459..15a16888d 100644
--- a/src/preprocessing/passes/int_to_bv.cpp
+++ b/src/preprocessing/passes/int_to_bv.cpp
@@ -69,7 +69,8 @@ Node intToBVMakeBinary(TNode n, NodeMap& cache)
}
else if (current.getNumChildren() > 2
&& (current.getKind() == kind::PLUS
- || current.getKind() == kind::MULT))
+ || current.getKind() == kind::MULT
+ || current.getKind() == kind::NONLINEAR_MULT))
{
Assert(cache.find(current[0]) != cache.end());
result = cache[current[0]];
@@ -118,15 +119,15 @@ Node intToBV(TNode n, NodeMap& cache)
{
// Not a leaf
vector<Node> children;
- unsigned max = 0;
- for (unsigned i = 0; i < current.getNumChildren(); ++i)
+ uint64_t max = 0;
+ for (const Node& nc : current)
{
- Assert(cache.find(current[i]) != cache.end());
- TNode childRes = cache[current[i]];
+ Assert(cache.find(nc) != cache.end());
+ TNode childRes = cache[nc];
TypeNode type = childRes.getType();
if (type.isBitVector())
{
- unsigned bvsize = type.getBitVectorSize();
+ uint32_t bvsize = type.getBitVectorSize();
if (bvsize > max)
{
max = bvsize;
@@ -146,6 +147,7 @@ Node intToBV(TNode n, NodeMap& cache)
max = max + 1;
break;
case kind::MULT:
+ case kind::NONLINEAR_MULT:
Assert(children.size() == 2);
newKind = kind::BITVECTOR_MULT;
max = max * 2;
@@ -174,14 +176,14 @@ Node intToBV(TNode n, NodeMap& cache)
}
break;
}
- for (unsigned i = 0; i < children.size(); ++i)
+ for (size_t i = 0, csize = children.size(); i < csize; ++i)
{
TypeNode type = children[i].getType();
if (!type.isBitVector())
{
continue;
}
- unsigned bvsize = type.getBitVectorSize();
+ uint32_t bvsize = type.getBitVectorSize();
if (bvsize < max)
{
// sign extend
@@ -195,10 +197,7 @@ Node intToBV(TNode n, NodeMap& cache)
if (current.getMetaKind() == kind::metakind::PARAMETERIZED) {
builder << current.getOperator();
}
- for (unsigned i = 0; i < children.size(); ++i)
- {
- builder << children[i];
- }
+ builder.append(children);
// Mark the substitution and continue
Node result = builder;
@@ -226,7 +225,6 @@ Node intToBV(TNode n, NodeMap& cache)
{
Rational constant = current.getConst<Rational>();
if (constant.isIntegral()) {
- AlwaysAssert(constant >= 0);
BitVector bv(size, constant.getNumerator());
if (bv.toSignedInteger() != constant.getNumerator())
{
diff --git a/src/preprocessing/passes/non_clausal_simp.cpp b/src/preprocessing/passes/non_clausal_simp.cpp
index b05dbbe1c..5610b0117 100644
--- a/src/preprocessing/passes/non_clausal_simp.cpp
+++ b/src/preprocessing/passes/non_clausal_simp.cpp
@@ -249,6 +249,10 @@ PreprocessingPassResult NonClausalSimp::applyInternal(
{
// Keep the literal
learned_literals[j++] = learned_literals[i];
+ // Its a literal that could not be processed as a substitution or
+ // conflict. In this case, we notify the context of the learned
+ // literal, which will process it with the learned literal manager.
+ d_preprocContext->notifyLearnedLiteral(learnedLiteral);
}
break;
}
diff --git a/src/preprocessing/preprocessing_pass_context.cpp b/src/preprocessing/preprocessing_pass_context.cpp
index eaccce1a9..b21fcb261 100644
--- a/src/preprocessing/preprocessing_pass_context.cpp
+++ b/src/preprocessing/preprocessing_pass_context.cpp
@@ -30,6 +30,9 @@ PreprocessingPassContext::PreprocessingPassContext(
: d_smt(smt),
d_env(env),
d_circuitPropagator(circuitPropagator),
+ d_llm(env.getTopLevelSubstitutions(),
+ env.getUserContext(),
+ env.getProofNodeManager()),
d_symsInAssertions(env.getUserContext())
{
}
@@ -67,6 +70,16 @@ void PreprocessingPassContext::recordSymbolsInAssertions(
}
}
+void PreprocessingPassContext::notifyLearnedLiteral(TNode lit)
+{
+ d_llm.notifyLearnedLiteral(lit);
+}
+
+std::vector<Node> PreprocessingPassContext::getLearnedLiterals()
+{
+ return d_llm.getLearnedLiterals();
+}
+
void PreprocessingPassContext::addSubstitution(const Node& lhs,
const Node& rhs,
ProofGenerator* pg)
diff --git a/src/preprocessing/preprocessing_pass_context.h b/src/preprocessing/preprocessing_pass_context.h
index 722c82f6b..1af73e453 100644
--- a/src/preprocessing/preprocessing_pass_context.h
+++ b/src/preprocessing/preprocessing_pass_context.h
@@ -23,8 +23,8 @@
#define CVC5__PREPROCESSING__PREPROCESSING_PASS_CONTEXT_H
#include "context/cdhashset.h"
+#include "preprocessing/learned_literal_manager.h"
#include "smt/smt_engine.h"
-#include "theory/trust_substitutions.h"
#include "util/resource_manager.h"
namespace cvc5 {
@@ -75,6 +75,18 @@ class PreprocessingPassContext
void recordSymbolsInAssertions(const std::vector<Node>& assertions);
/**
+ * Notify learned literal. This method is called when a literal is
+ * entailed by the current set of assertions.
+ *
+ * It should be rewritten, and such that top level substitutions have
+ * been applied to it.
+ */
+ void notifyLearnedLiteral(TNode lit);
+ /**
+ * Get the learned literals
+ */
+ std::vector<Node> getLearnedLiterals();
+ /**
* Add substitution to the top-level substitutions, which also as a
* consequence is used by the theory model.
* @param lhs The node replaced by node 'rhs'
@@ -101,6 +113,11 @@ class PreprocessingPassContext
/** Instance of the circuit propagator */
theory::booleans::CircuitPropagator* d_circuitPropagator;
/**
+ * The learned literal manager
+ */
+ LearnedLiteralManager d_llm;
+
+ /**
* The (user-context-dependent) set of symbols that occur in at least one
* assertion in the current user context.
*/
diff --git a/src/printer/smt2/smt2_printer.cpp b/src/printer/smt2/smt2_printer.cpp
index 426f60a60..076093bce 100644
--- a/src/printer/smt2/smt2_printer.cpp
+++ b/src/printer/smt2/smt2_printer.cpp
@@ -951,10 +951,43 @@ void Smt2Printer::toStream(std::ostream& out,
return;
break;
}
- case kind::APPLY_TESTER:
case kind::APPLY_SELECTOR:
- case kind::APPLY_SELECTOR_TOTAL:
+ {
+ Node op = n.getOperator();
+ const DType& dt = DType::datatypeOf(op);
+ if (dt.isTuple())
+ {
+ stillNeedToPrintParams = false;
+ out << "(_ tupSel " << DType::indexOf(op) << ") ";
+ }
+ }
+ break;
+ case kind::APPLY_TESTER:
+ {
+ stillNeedToPrintParams = false;
+ Node op = n.getOperator();
+ size_t cindex = DType::indexOf(op);
+ const DType& dt = DType::datatypeOf(op);
+ out << "(_ is ";
+ toStream(
+ out, dt[cindex].getConstructor(), toDepth < 0 ? toDepth : toDepth - 1);
+ out << ") ";
+ }
+ break;
case kind::APPLY_UPDATER:
+ {
+ Node op = n.getOperator();
+ size_t index = DType::indexOf(op);
+ const DType& dt = DType::datatypeOf(op);
+ size_t cindex = DType::cindexOf(op);
+ out << "(_ update ";
+ toStream(out,
+ dt[cindex][index].getSelector(),
+ toDepth < 0 ? toDepth : toDepth - 1);
+ out << ") ";
+ }
+ break;
+ case kind::APPLY_SELECTOR_TOTAL:
case kind::PARAMETRIC_DATATYPE: break;
// separation logic
@@ -1037,19 +1070,8 @@ void Smt2Printer::toStream(std::ostream& out,
if( n.getMetaKind() == kind::metakind::PARAMETERIZED &&
stillNeedToPrintParams ) {
if(toDepth != 0) {
- if (n.getKind() == kind::APPLY_TESTER)
- {
- unsigned cindex = DType::indexOf(n.getOperator());
- const DType& dt = DType::datatypeOf(n.getOperator());
- out << "(_ is ";
- toStream(out,
- dt[cindex].getConstructor(),
- toDepth < 0 ? toDepth : toDepth - 1);
- out << ")";
- }else{
- toStream(
- out, n.getOperator(), toDepth < 0 ? toDepth : toDepth - 1, lbind);
- }
+ toStream(
+ out, n.getOperator(), toDepth < 0 ? toDepth : toDepth - 1, lbind);
} else {
out << "(...)";
}
diff --git a/src/smt/command.cpp b/src/smt/command.cpp
index bf7d5ef3d..d672b79a6 100644
--- a/src/smt/command.cpp
+++ b/src/smt/command.cpp
@@ -31,6 +31,7 @@
#include "expr/symbol_manager.h"
#include "expr/type_node.h"
#include "options/options.h"
+#include "options/printer_options.h"
#include "options/smt_options.h"
#include "printer/printer.h"
#include "proof/unsat_core.h"
@@ -1403,11 +1404,16 @@ void DefineFunctionCommand::toStream(std::ostream& out,
size_t dag,
OutputLanguage language) const
{
+ TypeNode rangeType = termToNode(d_func).getType();
+ if (rangeType.isFunction())
+ {
+ rangeType = rangeType.getRangeType();
+ }
Printer::getPrinter(language)->toStreamCmdDefineFunction(
out,
d_func.toString(),
termVectorToNodes(d_formals),
- termToNode(d_func).getType().getRangeType(),
+ rangeType,
termToNode(d_formula));
}
@@ -2041,6 +2047,16 @@ void GetProofCommand::toStream(std::ostream& out,
/* -------------------------------------------------------------------------- */
GetInstantiationsCommand::GetInstantiationsCommand() : d_solver(nullptr) {}
+bool GetInstantiationsCommand::isEnabled(api::Solver* solver,
+ const api::Result& res)
+{
+ return (solver->getOptions().printer.instFormatMode
+ != options::InstFormatMode::SZS
+ && (res.isSat()
+ || (res.isSatUnknown()
+ && res.getUnknownExplanation() == api::Result::INCOMPLETE)))
+ || res.isUnsat() || res.isEntailed();
+}
void GetInstantiationsCommand::invoke(api::Solver* solver, SymbolManager* sm)
{
try
diff --git a/src/smt/command.h b/src/smt/command.h
index 21ecd1964..2d32062e2 100644
--- a/src/smt/command.h
+++ b/src/smt/command.h
@@ -1077,6 +1077,7 @@ class CVC5_EXPORT GetInstantiationsCommand : public Command
public:
GetInstantiationsCommand();
+ static bool isEnabled(api::Solver* solver, const api::Result& res);
void invoke(api::Solver* solver, SymbolManager* sm) override;
void printResult(std::ostream& out, uint32_t verbosity = 2) const override;
Command* clone() const override;
diff --git a/src/smt/env.cpp b/src/smt/env.cpp
index 1381ef87c..b6cdfb67b 100644
--- a/src/smt/env.cpp
+++ b/src/smt/env.cpp
@@ -43,6 +43,7 @@ Env::Env(NodeManager* nm, Options* opts)
d_logic(),
d_statisticsRegistry(std::make_unique<StatisticsRegistry>()),
d_options(),
+ d_originalOptions(opts),
d_resourceManager()
{
if (opts != nullptr)
@@ -97,6 +98,8 @@ StatisticsRegistry& Env::getStatisticsRegistry()
const Options& Env::getOptions() const { return d_options; }
+const Options& Env::getOriginalOptions() const { return *d_originalOptions; }
+
ResourceManager* Env::getResourceManager() const
{
return d_resourceManager.get();
diff --git a/src/smt/env.h b/src/smt/env.h
index 29a360209..57b5ad9c7 100644
--- a/src/smt/env.h
+++ b/src/smt/env.h
@@ -94,6 +94,9 @@ class Env
/** Get the options object (const version only) owned by this Env. */
const Options& getOptions() const;
+ /** Get the original options object (const version only). */
+ const Options& getOriginalOptions() const;
+
/** Get the resource manager owned by this Env. */
ResourceManager* getResourceManager() const;
@@ -180,6 +183,12 @@ class Env
* consider during solving and initialization.
*/
Options d_options;
+ /**
+ * A pointer to the original options object as stored in the api::Solver.
+ * The referenced objects holds the options as initially parsed before being
+ * changed, e.g., by setDefaults().
+ */
+ const Options* d_originalOptions;
/** Manager for limiting time and abstract resource usage. */
std::unique_ptr<ResourceManager> d_resourceManager;
}; /* class Env */
diff --git a/src/smt/optimization_solver.cpp b/src/smt/optimization_solver.cpp
index ffc49710a..e85ea82ef 100644
--- a/src/smt/optimization_solver.cpp
+++ b/src/smt/optimization_solver.cpp
@@ -15,6 +15,8 @@
#include "smt/optimization_solver.h"
+#include "context/cdhashmap.h"
+#include "context/cdlist.h"
#include "omt/omt_optimizer.h"
#include "options/smt_options.h"
#include "smt/assertions.h"
@@ -29,7 +31,7 @@ namespace smt {
OptimizationSolver::OptimizationSolver(SmtEngine* parent)
: d_parent(parent),
d_optChecker(),
- d_objectives(),
+ d_objectives(parent->getUserContext()),
d_results(),
d_objectiveCombination(LEXICOGRAPHIC)
{
@@ -37,10 +39,14 @@ OptimizationSolver::OptimizationSolver(SmtEngine* parent)
OptimizationResult::ResultType OptimizationSolver::checkOpt()
{
+ // if the results of the previous call have different size than the
+ // objectives, then we should clear the pareto optimization context
+ if (d_results.size() != d_objectives.size()) d_optChecker.reset();
+ // initialize the result vector
+ d_results.clear();
for (size_t i = 0, numObj = d_objectives.size(); i < numObj; ++i)
{
- // reset the optimization results
- d_results[i] = OptimizationResult();
+ d_results.emplace_back();
}
switch (d_objectiveCombination)
{
@@ -66,14 +72,6 @@ void OptimizationSolver::addObjective(TNode target,
}
d_optChecker.reset();
d_objectives.emplace_back(target, type, bvSigned);
- d_results.emplace_back(OptimizationResult::UNKNOWN, Node());
-}
-
-void OptimizationSolver::resetObjectives()
-{
- d_optChecker.reset();
- d_objectives.clear();
- d_results.clear();
}
std::vector<OptimizationResult> OptimizationSolver::getValues()
diff --git a/src/smt/optimization_solver.h b/src/smt/optimization_solver.h
index 64591d8f1..6d138deb2 100644
--- a/src/smt/optimization_solver.h
+++ b/src/smt/optimization_solver.h
@@ -18,6 +18,8 @@
#ifndef CVC5__SMT__OPTIMIZATION_SOLVER_H
#define CVC5__SMT__OPTIMIZATION_SOLVER_H
+#include "context/cdhashmap_forward.h"
+#include "context/cdlist.h"
#include "expr/node.h"
#include "expr/type_node.h"
#include "util/result.h"
@@ -74,14 +76,14 @@ class OptimizationResult
* @return an enum showing whether the result is optimal, unbounded,
* unsat or unknown.
**/
- ResultType getType() { return d_type; }
+ ResultType getType() const { return d_type; }
/**
* Returns the optimal value.
* @return Node containing the optimal value,
* if getType() is not OPTIMAL, it might return an empty node or a node
* containing non-optimal value
**/
- Node getValue() { return d_value; }
+ Node getValue() const { return d_value; }
private:
/** the indicating whether the result is optimal or something else **/
@@ -124,13 +126,13 @@ class OptimizationObjective
~OptimizationObjective() = default;
/** A getter for d_type **/
- ObjectiveType getType() { return d_type; }
+ ObjectiveType getType() const { return d_type; }
/** A getter for d_target **/
- Node getTarget() { return d_target; }
+ Node getTarget() const { return d_target; }
/** A getter for d_bvSigned **/
- bool bvIsSigned() { return d_bvSigned; }
+ bool bvIsSigned() const { return d_bvSigned; }
private:
/**
@@ -173,7 +175,7 @@ class OptimizationSolver
*
* Lexicographic: optimize the objectives one-by-one, in the order they are
* added:
- * v_x = max(x) s.t. phi(x, y) = sat
+ * v_x = max(x) s.t. phi(x, y) = sat
* v_y = max(y) s.t. phi(v_x, y) = sat
*
* Pareto: optimize multiple goals to a state such that
@@ -215,11 +217,6 @@ class OptimizationSolver
bool bvSigned = false);
/**
- * Clear all the added optimization objectives
- **/
- void resetObjectives();
-
- /**
* Returns the values of the optimized objective after checkOpt is called
* @return a vector of Optimization Result,
* each containing the outcome and the value.
@@ -293,7 +290,7 @@ class OptimizationSolver
std::unique_ptr<SmtEngine> d_optChecker;
/** The objectives to optimize for **/
- std::vector<OptimizationObjective> d_objectives;
+ context::CDList<OptimizationObjective> d_objectives;
/** The results of the optimizations from the last checkOpt call **/
std::vector<OptimizationResult> d_results;
diff --git a/src/smt/set_defaults.cpp b/src/smt/set_defaults.cpp
index c245fa769..e3bbb6c5c 100644
--- a/src/smt/set_defaults.cpp
+++ b/src/smt/set_defaults.cpp
@@ -173,15 +173,6 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
}
}
- /* Only BVSolver::LAZY natively supports int2bv and nat2bv, for other solvers
- * we need to eagerly eliminate the operators. */
- if (options::bvSolver() == options::BVSolver::SIMPLE
- || options::bvSolver() == options::BVSolver::BITBLAST)
- {
- opts.bv.bvLazyReduceExtf = false;
- opts.bv.bvLazyRewriteExtf = false;
- }
-
/* Disable bit-level propagation by default for the BITBLAST solver. */
if (options::bvSolver() == options::BVSolver::BITBLAST)
{
@@ -1420,22 +1411,6 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
opts.arrays.arraysOptimizeLinear = false;
}
- if (!options::bitvectorEqualitySolver())
- {
- if (options::bvLazyRewriteExtf())
- {
- if (opts.bv.bvLazyRewriteExtfWasSetByUser)
- {
- throw OptionException(
- "--bv-lazy-rewrite-extf requires --bv-eq-solver to be set");
- }
- }
- Trace("smt")
- << "disabling bvLazyRewriteExtf since equality solver is disabled"
- << std::endl;
- opts.bv.bvLazyRewriteExtf = false;
- }
-
if (options::stringFMF() && !opts.strings.stringProcessLoopModeWasSetByUser)
{
Trace("smt") << "settting stringProcessLoopMode to 'simple' since "
diff --git a/src/theory/arith/nl/cad/lazard_evaluation.cpp b/src/theory/arith/nl/cad/lazard_evaluation.cpp
new file mode 100644
index 000000000..82b127ed0
--- /dev/null
+++ b/src/theory/arith/nl/cad/lazard_evaluation.cpp
@@ -0,0 +1,46 @@
+#include "theory/arith/nl/cad/lazard_evaluation.h"
+
+#include "base/check.h"
+#include "base/output.h"
+
+namespace cvc5::theory::arith::nl::cad {
+
+/**
+ * Do a very simple wrapper around the regular poly::infeasible_regions.
+ * Warn the user about doing this.
+ * This allows for a graceful fallback (albeit with a warning) if CoCoA is not
+ * available.
+ */
+struct LazardEvaluationState
+{
+ poly::Assignment d_assignment;
+};
+LazardEvaluation::LazardEvaluation()
+ : d_state(std::make_unique<LazardEvaluationState>())
+{
+}
+LazardEvaluation::~LazardEvaluation() {}
+
+void LazardEvaluation::add(const poly::Variable& var, const poly::Value& val)
+{
+ d_state->d_assignment.set(var, val);
+}
+
+void LazardEvaluation::addFreeVariable(const poly::Variable& var) {}
+
+std::vector<poly::Polynomial> LazardEvaluation::reducePolynomial(
+ const poly::Polynomial& p) const
+{
+ return {p};
+}
+std::vector<poly::Interval> LazardEvaluation::infeasibleRegions(
+ const poly::Polynomial& q, poly::SignCondition sc) const
+{
+ WarningOnce()
+ << "CAD::LazardEvaluation is disabled because CoCoA is not available. "
+ "Falling back to regular calculation of infeasible regions."
+ << std::endl;
+ return poly::infeasible_regions(q, d_state->d_assignment, sc);
+}
+
+} // namespace cvc5::theory::arith::nl::cad
diff --git a/src/theory/arith/nl/cad/lazard_evaluation.h b/src/theory/arith/nl/cad/lazard_evaluation.h
new file mode 100644
index 000000000..0edb12010
--- /dev/null
+++ b/src/theory/arith/nl/cad/lazard_evaluation.h
@@ -0,0 +1,109 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ * Gereon Kremer
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * Implements the CDCAC approach as described in
+ * https://arxiv.org/pdf/2003.05633.pdf.
+ */
+
+#include "cvc5_private.h"
+
+#ifndef CVC5__THEORY__ARITH__NL__CAD__LAZARD_EVALUATION_H
+#define CVC5__THEORY__ARITH__NL__CAD__LAZARD_EVALUATION_H
+
+#include <poly/polyxx.h>
+
+#include <memory>
+
+namespace cvc5::theory::arith::nl::cad {
+
+struct LazardEvaluationState;
+/**
+ * This class does the heavy lifting for the modified lifting procedure that is
+ * required for Lazard's projection.
+ *
+ * Let p \in Q[x_0, ..., x_n] a multivariate polynomial whose roots we want to
+ * isolate over the partial sample point A = [x_0 = a_0, ... x_{n-1} = a_{n-1}]
+ * where a_0, ... a_{n-1} are real algebraic numbers and x_n is the last free
+ * variable.
+ *
+ * The modified lifting procedure conceptually works as follows:
+ *
+ * for (x = a) in A:
+ * while p[x // a] = 0:
+ * p = p / (x - a)
+ * p = p[x // a]
+ * return roots(p)
+ *
+ * As the assignment contains real algebraic numbers, though, we can not do any
+ * of the computations directly, as our polynomials only support coefficients
+ * from Z or Q, but not extensions (in the algebraic sense) thereof.
+ *
+ * Our approach is as follows:
+ * Let pk be the minimal polynomial for a_k.
+ * Instead of substituting p[x_k // a_k] we (canonically) embed p into the
+ * quotient ring Q[x_k]/<p_k> and recursively build a tower of such quotient
+ * rings that is isomorphic to nesting the corresponding field extensions
+ * Q(a_1)(a_2)... When we have done that, we obtain p that is reduced with
+ * respect to all minimal polynomials, but may still contain x_0,... x_{n-1}. To
+ * get rid of these, we compute a Gröbner basis of p and the minimal polynomials
+ * (using a suitable elimination order) and extract the polynomial in x_n. This
+ * polynomial has all roots (and possibly some more) that we are looking for.
+ * Instead of a Gröbner basis, we can also compute the iterated resultant as
+ * follows: Res(Res(p, p_{n-1}, x_{n-1}), p_{n-2}, x_{n-2})...
+ *
+ * Consider
+ * http://sunsite.informatik.rwth-aachen.de/Publications/AIB/2020/2020-04.pdf
+ * Section 2.5.1 for a full discussion.
+ *
+ * !!! WARNING !!!
+ * If CoCoALib is not available, this class will simply fall back to
+ * poly::infeasible_regions and issue a warning about this.
+ */
+class LazardEvaluation
+{
+ public:
+ LazardEvaluation();
+ ~LazardEvaluation();
+
+ /**
+ * Add the next assigned variable x_k = a_k to this construction.
+ */
+ void add(const poly::Variable& var, const poly::Value& val);
+ /**
+ * Finish by adding the free variable x_n.
+ */
+ void addFreeVariable(const poly::Variable& var);
+ /**
+ * Reduce the polynomial q. Compared to the above description, there may
+ * actually be multiple polynomials in the Gröbner basis and instead of
+ * loosing this knowledge and returning their product, we return them as a
+ * vector.
+ */
+ std::vector<poly::Polynomial> reducePolynomial(
+ const poly::Polynomial& q) const;
+
+ /**
+ * Compute the infeasible regions of q under the given sign condition.
+ * Uses reducePolynomial and then performs real root isolation on the
+ * resulting polynomials to obtain the intervals. Mimics
+ * poly::infeasible_regions, but uses Lazard's evaluation.
+ */
+ std::vector<poly::Interval> infeasibleRegions(const poly::Polynomial& q,
+ poly::SignCondition sc) const;
+
+ private:
+ std::unique_ptr<LazardEvaluationState> d_state;
+};
+
+} // namespace cvc5::theory::arith::nl::cad
+
+#endif \ No newline at end of file
diff --git a/src/theory/booleans/theory_bool_rewriter.cpp b/src/theory/booleans/theory_bool_rewriter.cpp
index a5c63522d..8f6d9d3b7 100644
--- a/src/theory/booleans/theory_bool_rewriter.cpp
+++ b/src/theory/booleans/theory_bool_rewriter.cpp
@@ -345,16 +345,6 @@ RewriteResponse TheoryBoolRewriter::preRewrite(TNode n) {
<< n << ": " << n[0].notNode() << std::endl;
return RewriteResponse(REWRITE_AGAIN, makeNegation(n[0]));
}
- if (n[1] == tt || n[1] == ff)
- {
- // ITE C true y --> C v y
- // ITE C false y --> ~C ^ y
- Node resp =
- n[1] == tt ? n[0].orNode(n[2]) : (n[0].negate()).andNode(n[2]);
- Debug("bool-ite") << "TheoryBoolRewriter::preRewrite_ITE: n[1] const "
- << n << ": " << resp << std::endl;
- return RewriteResponse(REWRITE_AGAIN, resp);
- }
}
if (n[0].getKind() == kind::NOT)
@@ -364,17 +354,6 @@ RewriteResponse TheoryBoolRewriter::preRewrite(TNode n) {
REWRITE_AGAIN, nodeManager->mkNode(kind::ITE, n[0][0], n[2], n[1]));
}
- if (n[2].isConst() && (n[2] == tt || n[2] == ff))
- {
- // ITE C x true --> ~C v x
- // ITE C x false --> C ^ x
- Node resp =
- n[2] == tt ? (n[0].negate()).orNode(n[1]) : n[0].andNode(n[1]);
- Debug("bool-ite") << "TheoryBoolRewriter::preRewrite_ITE: n[2] const "
- << n << ": " << resp << std::endl;
- return RewriteResponse(REWRITE_AGAIN, resp);
- }
-
int parityTmp;
if ((parityTmp = equalityParity(n[1], n[2])) != 0) {
Node resp = (parityTmp == 1) ? (Node)n[1] : n[0].eqNode(n[1]);
@@ -424,6 +403,32 @@ RewriteResponse TheoryBoolRewriter::preRewrite(TNode n) {
<< parityTmp << " " << n << ": " << resp << std::endl;
return RewriteResponse(REWRITE_AGAIN, resp);
}
+
+ // Rewrites for ITEs with a constant branch. These rewrites are applied
+ // after the parity rewrites above because they may simplify ITEs such as
+ // `(ite c c true)` to `(ite c true true)`. As a result, we avoid
+ // introducing an unnecessary conjunction/disjunction here.
+ if (n[1].isConst() && (n[1] == tt || n[1] == ff))
+ {
+ // ITE C true y --> C v y
+ // ITE C false y --> ~C ^ y
+ Node resp =
+ n[1] == tt ? n[0].orNode(n[2]) : (n[0].negate()).andNode(n[2]);
+ Debug("bool-ite") << "TheoryBoolRewriter::preRewrite_ITE: n[1] const "
+ << n << ": " << resp << std::endl;
+ return RewriteResponse(REWRITE_AGAIN, resp);
+ }
+ else if (n[2].isConst() && (n[2] == tt || n[2] == ff))
+ {
+ // ITE C x true --> ~C v x
+ // ITE C x false --> C ^ x
+ Node resp =
+ n[2] == tt ? (n[0].negate()).orNode(n[1]) : n[0].andNode(n[1]);
+ Debug("bool-ite") << "TheoryBoolRewriter::preRewrite_ITE: n[2] const "
+ << n << ": " << resp << std::endl;
+ return RewriteResponse(REWRITE_AGAIN, resp);
+ }
+
break;
}
default:
diff --git a/src/theory/bv/bv_solver_lazy.cpp b/src/theory/bv/bv_solver_lazy.cpp
index fbd910bee..5210117b8 100644
--- a/src/theory/bv/bv_solver_lazy.cpp
+++ b/src/theory/bv/bv_solver_lazy.cpp
@@ -233,18 +233,6 @@ void BVSolverLazy::check(Theory::Effort e)
return;
}
- // last call : do reductions on extended bitvector functions
- if (e == Theory::EFFORT_LAST_CALL)
- {
- CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
- if (core)
- {
- // check extended functions at last call effort
- core->checkExtf(e);
- }
- return;
- }
-
Debug("bitvector") << "BVSolverLazy::check(" << e << ")" << std::endl;
TimerStat::CodeTimer codeTimer(d_statistics.d_solveTimer);
// we may be getting new assertions so the model cache may not be sound
@@ -331,27 +319,6 @@ void BVSolverLazy::check(Theory::Effort e)
break;
}
}
-
- // check extended functions
- if (Theory::fullEffort(e))
- {
- CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
- if (core)
- {
- // check extended functions at full effort
- core->checkExtf(e);
- }
- }
-}
-
-bool BVSolverLazy::needsCheckLastEffort()
-{
- CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
- if (core)
- {
- return core->needsCheckLastEffort();
- }
- return false;
}
bool BVSolverLazy::collectModelValues(TheoryModel* m,
diff --git a/src/theory/bv/bv_solver_lazy.h b/src/theory/bv/bv_solver_lazy.h
index 9b3a2f1fa..4f73354bc 100644
--- a/src/theory/bv/bv_solver_lazy.h
+++ b/src/theory/bv/bv_solver_lazy.h
@@ -82,8 +82,6 @@ class BVSolverLazy : public BVSolver
bool preCheck(Theory::Effort e) override;
- bool needsCheckLastEffort() override;
-
void propagate(Theory::Effort e) override;
TrustNode explain(TNode n) override;
diff --git a/src/theory/bv/bv_subtheory_core.cpp b/src/theory/bv/bv_subtheory_core.cpp
index 2589418cc..fa71641ad 100644
--- a/src/theory/bv/bv_subtheory_core.cpp
+++ b/src/theory/bv/bv_subtheory_core.cpp
@@ -32,64 +32,6 @@ using namespace cvc5::theory;
using namespace cvc5::theory::bv;
using namespace cvc5::theory::bv::utils;
-bool CoreSolverExtTheoryCallback::getCurrentSubstitution(
- int effort,
- const std::vector<Node>& vars,
- std::vector<Node>& subs,
- std::map<Node, std::vector<Node> >& exp)
-{
- if (d_equalityEngine == nullptr)
- {
- return false;
- }
- // get the constant equivalence classes
- bool retVal = false;
- for (const Node& n : vars)
- {
- if (d_equalityEngine->hasTerm(n))
- {
- Node nr = d_equalityEngine->getRepresentative(n);
- if (nr.isConst())
- {
- subs.push_back(nr);
- exp[n].push_back(n.eqNode(nr));
- retVal = true;
- }
- else
- {
- subs.push_back(n);
- }
- }
- else
- {
- subs.push_back(n);
- }
- }
- // return true if the substitution is non-trivial
- return retVal;
-}
-
-bool CoreSolverExtTheoryCallback::getReduction(int effort,
- Node n,
- Node& nr,
- bool& satDep)
-{
- Trace("bv-ext") << "TheoryBV::checkExt : non-reduced : " << n << std::endl;
- if (n.getKind() == kind::BITVECTOR_TO_NAT)
- {
- nr = utils::eliminateBv2Nat(n);
- satDep = false;
- return true;
- }
- else if (n.getKind() == kind::INT_TO_BITVECTOR)
- {
- nr = utils::eliminateInt2Bv(n);
- satDep = false;
- return true;
- }
- return false;
-}
-
CoreSolver::CoreSolver(context::Context* c, BVSolverLazy* bv)
: SubtheorySolver(c, bv),
d_notify(*this),
@@ -98,18 +40,8 @@ CoreSolver::CoreSolver(context::Context* c, BVSolverLazy* bv)
d_preregisterCalled(false),
d_checkCalled(false),
d_bv(bv),
- d_extTheoryCb(),
- d_extTheory(new ExtTheory(d_extTheoryCb,
- bv->d_bv.getSatContext(),
- bv->d_bv.getUserContext(),
- bv->d_bv.getOutputChannel())),
- d_reasons(c),
- d_needsLastCallCheck(false),
- d_extf_range_infer(bv->d_bv.getUserContext()),
- d_extf_collapse_infer(bv->d_bv.getUserContext())
+ d_reasons(c)
{
- d_extTheory->addFunctionKind(kind::BITVECTOR_TO_NAT);
- d_extTheory->addFunctionKind(kind::INT_TO_BITVECTOR);
}
CoreSolver::~CoreSolver() {}
@@ -167,11 +99,6 @@ void CoreSolver::preRegister(TNode node) {
d_equalityEngine->addTriggerPredicate(node);
} else {
d_equalityEngine->addTerm(node);
- // Register with the extended theory, for context-dependent simplification.
- // Notice we do this for registered terms but not internally generated
- // equivalence classes. The two should roughly cooincide. Since ExtTheory is
- // being used as a heuristic, it is good enough to be registered here.
- d_extTheory->registerTerm(node);
}
}
@@ -489,142 +416,3 @@ CoreSolver::Statistics::Statistics()
"theory::bv::CoreSolver::NumCallsToCheck"))
{
}
-
-void CoreSolver::checkExtf(Theory::Effort e)
-{
- if (e == Theory::EFFORT_LAST_CALL)
- {
- std::vector<Node> nred = d_extTheory->getActive();
- doExtfReductions(nred);
- }
- Assert(e == Theory::EFFORT_FULL);
- // do inferences (adds external lemmas) TODO: this can be improved to add
- // internal inferences
- std::vector<Node> nred;
- if (d_extTheory->doInferences(0, nred))
- {
- return;
- }
- d_needsLastCallCheck = false;
- if (!nred.empty())
- {
- // other inferences involving bv2nat, int2bv
- if (options::bvAlgExtf())
- {
- if (doExtfInferences(nred))
- {
- return;
- }
- }
- if (!options::bvLazyReduceExtf())
- {
- if (doExtfReductions(nred))
- {
- return;
- }
- }
- else
- {
- d_needsLastCallCheck = true;
- }
- }
-}
-
-bool CoreSolver::needsCheckLastEffort() const { return d_needsLastCallCheck; }
-
-bool CoreSolver::doExtfInferences(std::vector<Node>& terms)
-{
- NodeManager* nm = NodeManager::currentNM();
- SkolemManager* sm = nm->getSkolemManager();
- bool sentLemma = false;
- eq::EqualityEngine* ee = d_equalityEngine;
- std::map<Node, Node> op_map;
- for (unsigned j = 0; j < terms.size(); j++)
- {
- TNode n = terms[j];
- Assert(n.getKind() == kind::BITVECTOR_TO_NAT
- || n.getKind() == kind::INT_TO_BITVECTOR);
- if (n.getKind() == kind::BITVECTOR_TO_NAT)
- {
- // range lemmas
- if (d_extf_range_infer.find(n) == d_extf_range_infer.end())
- {
- d_extf_range_infer.insert(n);
- unsigned bvs = n[0].getType().getBitVectorSize();
- Node min = nm->mkConst(Rational(0));
- Node max = nm->mkConst(Rational(Integer(1).multiplyByPow2(bvs)));
- Node lem = nm->mkNode(kind::AND,
- nm->mkNode(kind::GEQ, n, min),
- nm->mkNode(kind::LT, n, max));
- Trace("bv-extf-lemma")
- << "BV extf lemma (range) : " << lem << std::endl;
- d_bv->d_im.lemma(lem, InferenceId::BV_EXTF_LEMMA);
- sentLemma = true;
- }
- }
- Node r = (ee && ee->hasTerm(n[0])) ? ee->getRepresentative(n[0]) : n[0];
- op_map[r] = n;
- }
- for (unsigned j = 0; j < terms.size(); j++)
- {
- TNode n = terms[j];
- Node r = (ee && ee->hasTerm(n[0])) ? ee->getRepresentative(n) : n;
- std::map<Node, Node>::iterator it = op_map.find(r);
- if (it != op_map.end())
- {
- Node parent = it->second;
- // Node cterm = parent[0]==n ? parent : nm->mkNode( parent.getOperator(),
- // n );
- Node cterm = parent[0].eqNode(n);
- Trace("bv-extf-lemma-debug")
- << "BV extf collapse based on : " << cterm << std::endl;
- if (d_extf_collapse_infer.find(cterm) == d_extf_collapse_infer.end())
- {
- d_extf_collapse_infer.insert(cterm);
-
- Node t = n[0];
- if (t.getType() == parent.getType())
- {
- if (n.getKind() == kind::INT_TO_BITVECTOR)
- {
- Assert(t.getType().isInteger());
- // congruent modulo 2^( bv width )
- unsigned bvs = n.getType().getBitVectorSize();
- Node coeff = nm->mkConst(Rational(Integer(1).multiplyByPow2(bvs)));
- Node k = sm->mkDummySkolem(
- "int_bv_cong", t.getType(), "for int2bv/bv2nat congruence");
- t = nm->mkNode(kind::PLUS, t, nm->mkNode(kind::MULT, coeff, k));
- }
- Node lem = parent.eqNode(t);
-
- if (parent[0] != n)
- {
- Assert(ee->areEqual(parent[0], n));
- lem = nm->mkNode(kind::IMPLIES, parent[0].eqNode(n), lem);
- }
- // this handles inferences of the form, e.g.:
- // ((_ int2bv w) (bv2nat x)) == x (if x is bit-width w)
- // (bv2nat ((_ int2bv w) x)) == x + k*2^w for some k
- Trace("bv-extf-lemma")
- << "BV extf lemma (collapse) : " << lem << std::endl;
- d_bv->d_im.lemma(lem, InferenceId::BV_EXTF_COLLAPSE);
- sentLemma = true;
- }
- }
- Trace("bv-extf-lemma-debug")
- << "BV extf f collapse based on : " << cterm << std::endl;
- }
- }
- return sentLemma;
-}
-
-bool CoreSolver::doExtfReductions(std::vector<Node>& terms)
-{
- std::vector<Node> nredr;
- if (d_extTheory->doReductions(0, terms, nredr))
- {
- return true;
- }
- Assert(nredr.empty());
- return false;
-}
diff --git a/src/theory/bv/bv_subtheory_core.h b/src/theory/bv/bv_subtheory_core.h
index 0dfcfdde4..46c4559ea 100644
--- a/src/theory/bv/bv_subtheory_core.h
+++ b/src/theory/bv/bv_subtheory_core.h
@@ -22,30 +22,11 @@
#include "context/cdhashset.h"
#include "theory/bv/bv_subtheory.h"
-#include "theory/ext_theory.h"
namespace cvc5 {
namespace theory {
namespace bv {
-class Base;
-
-/** An extended theory callback used by the core solver */
-class CoreSolverExtTheoryCallback : public ExtTheoryCallback
-{
- public:
- CoreSolverExtTheoryCallback() : d_equalityEngine(nullptr) {}
- /** Get current substitution based on the underlying equality engine. */
- bool getCurrentSubstitution(int effort,
- const std::vector<Node>& vars,
- std::vector<Node>& subs,
- std::map<Node, std::vector<Node> >& exp) override;
- /** Get reduction. */
- bool getReduction(int effort, Node n, Node& nr, bool& satDep) override;
- /** The underlying equality engine */
- eq::EqualityEngine* d_equalityEngine;
-};
-
/**
* Bitvector equality solver
*/
@@ -96,10 +77,6 @@ class CoreSolver : public SubtheorySolver {
BVSolverLazy* d_bv;
/** Pointer to the equality engine of the parent */
eq::EqualityEngine* d_equalityEngine;
- /** The extended theory callback */
- CoreSolverExtTheoryCallback d_extTheoryCb;
- /** Extended theory module, for context-dependent simplification. */
- std::unique_ptr<ExtTheory> d_extTheory;
/** To make sure we keep the explanations */
context::CDHashSet<Node> d_reasons;
@@ -109,36 +86,6 @@ class CoreSolver : public SubtheorySolver {
bool isCompleteForTerm(TNode term, TNodeBoolMap& seen);
Statistics d_statistics;
- /** Whether we need a last call effort check */
- bool d_needsLastCallCheck;
- /** For extended functions */
- context::CDHashSet<Node> d_extf_range_infer;
- context::CDHashSet<Node> d_extf_collapse_infer;
-
- /** do extended function inferences
- *
- * This method adds lemmas on the output channel of TheoryBV based on
- * reasoning about extended functions, such as bv2nat and int2bv. Examples
- * of lemmas added by this method include:
- * 0 <= ((_ int2bv w) x) < 2^w
- * ((_ int2bv w) (bv2nat x)) = x
- * (bv2nat ((_ int2bv w) x)) == x + k*2^w
- * The purpose of these lemmas is to recognize easy conflicts before fully
- * reducing extended functions based on their full semantics.
- */
- bool doExtfInferences(std::vector<Node>& terms);
- /** do extended function reductions
- *
- * This method adds lemmas on the output channel of TheoryBV based on
- * reducing all extended function applications that are preregistered to
- * this theory and have not already been reduced by context-dependent
- * simplification (see theory/ext_theory.h). Examples of lemmas added by
- * this method include:
- * (bv2nat x) = (ite ((_ extract w w-1) x) 2^{w-1} 0) + ... +
- * (ite ((_ extract 1 0) x) 1 0)
- */
- bool doExtfReductions(std::vector<Node>& terms);
-
public:
CoreSolver(context::Context* c, BVSolverLazy* bv);
~CoreSolver();
@@ -154,9 +101,6 @@ class CoreSolver : public SubtheorySolver {
EqualityStatus getEqualityStatus(TNode a, TNode b) override;
bool hasTerm(TNode node) const;
void addTermToEqualityEngine(TNode node);
- /** check extended functions at the given effort */
- void checkExtf(Theory::Effort e);
- bool needsCheckLastEffort() const;
};
}
diff --git a/src/theory/bv/theory_bv_rewriter.cpp b/src/theory/bv/theory_bv_rewriter.cpp
index 476803c59..97ca24437 100644
--- a/src/theory/bv/theory_bv_rewriter.cpp
+++ b/src/theory/bv/theory_bv_rewriter.cpp
@@ -64,7 +64,16 @@ TrustNode TheoryBVRewriter::expandDefinition(Node node)
case kind::BITVECTOR_SDIV:
case kind::BITVECTOR_SREM:
case kind::BITVECTOR_SMOD: ret = eliminateBVSDiv(node); break;
+ case kind::BITVECTOR_TO_NAT:
+ ret = utils::eliminateBv2Nat(node);
+
+ break;
+ case kind::INT_TO_BITVECTOR:
+
+ ret = utils::eliminateInt2Bv(node);
+
+ break;
default: break;
}
if (!ret.isNull() && node != ret)
@@ -635,8 +644,8 @@ RewriteResponse TheoryBVRewriter::RewriteRedand(TNode node, bool prerewrite){
}
RewriteResponse TheoryBVRewriter::RewriteBVToNat(TNode node, bool prerewrite) {
- //do not use lazy rewrite strategy if equality solver is disabled
- if( node[0].isConst() || !options::bvLazyRewriteExtf() ){
+ if (node[0].isConst())
+ {
Node resultNode = LinearRewriteStrategy
< RewriteRule<BVToNatEliminate>
>::apply(node);
@@ -647,8 +656,8 @@ RewriteResponse TheoryBVRewriter::RewriteBVToNat(TNode node, bool prerewrite) {
}
RewriteResponse TheoryBVRewriter::RewriteIntToBV(TNode node, bool prerewrite) {
- //do not use lazy rewrite strategy if equality solver is disabled
- if( node[0].isConst() || !options::bvLazyRewriteExtf() ){
+ if (node[0].isConst())
+ {
Node resultNode = LinearRewriteStrategy
< RewriteRule<IntToBVEliminate>
>::apply(node);
diff --git a/src/theory/quantifiers/fmf/bounded_integers.cpp b/src/theory/quantifiers/fmf/bounded_integers.cpp
index b0f6e63bf..5ecc33778 100644
--- a/src/theory/quantifiers/fmf/bounded_integers.cpp
+++ b/src/theory/quantifiers/fmf/bounded_integers.cpp
@@ -716,7 +716,22 @@ bool BoundedIntegers::getRsiSubsitution( Node q, Node v, std::vector< Node >& va
Trace("bound-int-rsi") << "Look up the value for " << d_set[q][i] << " " << i << std::endl;
int vo = rsi->getVariableOrder(i);
Assert(q[0][vo] == d_set[q][i]);
- Node t = rsi->getCurrentTerm(vo, true);
+ TypeNode tn = d_set[q][i].getType();
+ // If the type of tn is not closed enumerable, we must map the value back
+ // to a term that appears in the same equivalence class as the constant.
+ // Notice that this is to ensure that unhandled values (e.g. uninterpreted
+ // constants, datatype values) do not enter instantiations/lemmas, which
+ // can lead to refutation unsoundness. However, it is important that we
+ // conversely do *not* map terms to values in other cases. In particular,
+ // replacing a constant c with a term t can lead to solution unsoundness
+ // if we are instantiating a quantified formula that corresponds to a
+ // reduction for t, since then the reduction is using circular reasoning:
+ // the current value of t is being used to reason about the range of
+ // its axiomatization. This is limited to reductions in the theory of
+ // strings, which use quantification on integers only. Note this
+ // impacts only quantified formulas with 2+ dimensions and dependencies
+ // between dimensions, e.g. str.indexof_re reduction.
+ Node t = rsi->getCurrentTerm(vo, !tn.isClosedEnumerable());
Trace("bound-int-rsi") << "term : " << t << std::endl;
vars.push_back( d_set[q][i] );
subs.push_back( t );
diff --git a/src/theory/rep_set.cpp b/src/theory/rep_set.cpp
index d0eee1886..f6af5b680 100644
--- a/src/theory/rep_set.cpp
+++ b/src/theory/rep_set.cpp
@@ -429,14 +429,17 @@ Node RepSetIterator::getCurrentTerm(unsigned i, bool valTerm) const
<< d_domain_elements[i].size() << std::endl;
Assert(0 <= curr && curr < d_domain_elements[i].size());
Node t = d_domain_elements[i][curr];
+ Trace("rsi-debug") << "rsi : term = " << t << std::endl;
if (valTerm)
{
Node tt = d_rs->getTermForRepresentative(t);
if (!tt.isNull())
{
+ Trace("rsi-debug") << "rsi : return rep term = " << tt << std::endl;
return tt;
}
}
+ Trace("rsi-debug") << "rsi : return" << std::endl;
return t;
}
diff --git a/src/theory/strings/theory_strings_preprocess.cpp b/src/theory/strings/theory_strings_preprocess.cpp
index 152a3e180..dbb6d4cf3 100644
--- a/src/theory/strings/theory_strings_preprocess.cpp
+++ b/src/theory/strings/theory_strings_preprocess.cpp
@@ -163,8 +163,9 @@ Node StringsPreprocess::reduce(Node t,
Node a2 = s.eqNode(nm->mkNode(STRING_CONCAT, sk1, sk3, sk2));
// length of first skolem is second argument
Node a3 = nm->mkNode(STRING_LENGTH, sk1).eqNode(n);
+ Node a4 = nm->mkNode(STRING_LENGTH, rs).eqNode(nm->mkNode(STRING_LENGTH, sk3));
- Node b1 = nm->mkNode(AND, a1, a2, a3);
+ Node b1 = nm->mkNode(AND, {a1, a2, a3, a4});
Node b2 = skt.eqNode(s);
Node lemma = nm->mkNode(ITE, cond, b1, b2);
@@ -172,7 +173,8 @@ Node StringsPreprocess::reduce(Node t,
// IF n >=0 AND n < len( s )
// THEN: skt = sk1 ++ substr(r,0,len(s)-n) ++ sk2 AND
// s = sk1 ++ sk3 ++ sk2 AND
- // len( sk1 ) = n
+ // len( sk1 ) = n AND
+ // len( substr(r,0,len(s)-n) ) = len( sk3 )
// ELSE: skt = s
// We use an optimization where r is used instead of substr(r,0,len(s)-n)
// if r is a constant of length one.
@@ -321,7 +323,7 @@ Node StringsPreprocess::reduce(Node t,
// n <= i < ite(skk = -1, len(s), skk) ^ 0 < l <= len(s) - i =>
// ~in_re(substr(s, i, l), r)) ^
// (skk != -1 =>
- // exists l. 0 <= l < len(s) - skk ^ in_re(substr(s, skk, l), r))
+ // exists l. 0 <= l <= len(s) - skk ^ in_re(substr(s, skk, l), r))
//
// Note that this reduction relies on eager reduction lemmas being sent to
// properly limit the range of skk.
diff --git a/src/theory/uf/theory_uf.cpp b/src/theory/uf/theory_uf.cpp
index 1afb8cc31..36b05b145 100644
--- a/src/theory/uf/theory_uf.cpp
+++ b/src/theory/uf/theory_uf.cpp
@@ -148,56 +148,54 @@ void TheoryUF::postCheck(Effort level)
}
}
-bool TheoryUF::preNotifyFact(
- TNode atom, bool pol, TNode fact, bool isPrereg, bool isInternal)
+void TheoryUF::notifyFact(TNode atom, bool pol, TNode fact, bool isInternal)
{
+ if (d_state.isInConflict())
+ {
+ return;
+ }
if (d_thss != nullptr)
{
bool isDecision =
d_valuation.isSatLiteral(fact) && d_valuation.isDecision(fact);
d_thss->assertNode(fact, isDecision);
- if (d_state.isInConflict())
- {
- return true;
- }
}
- if (atom.getKind() == kind::CARDINALITY_CONSTRAINT
- || atom.getKind() == kind::COMBINED_CARDINALITY_CONSTRAINT)
+ switch (atom.getKind())
{
- if (d_thss == nullptr)
+ case kind::EQUAL:
{
- if (!getLogicInfo().hasCardinalityConstraints())
+ if (options::ufHo() && options::ufHoExt())
{
- std::stringstream ss;
- ss << "Cardinality constraint " << atom
- << " was asserted, but the logic does not allow it." << std::endl;
- ss << "Try using a logic containing \"UFC\"." << std::endl;
- throw Exception(ss.str());
- }
- else
- {
- // support for cardinality constraints is not enabled, set incomplete
- d_im.setIncomplete(IncompleteId::UF_CARD_DISABLED);
+ if (!pol && !d_state.isInConflict() && atom[0].getType().isFunction())
+ {
+ // apply extensionality eagerly using the ho extension
+ d_ho->applyExtensionality(fact);
+ }
}
}
- // don't need to assert cardinality constraints if not producing models
- return !options::produceModels();
- }
- return false;
-}
-
-void TheoryUF::notifyFact(TNode atom, bool pol, TNode fact, bool isInternal)
-{
- if (!d_state.isInConflict() && atom.getKind() == kind::EQUAL)
- {
- if (options::ufHo() && options::ufHoExt())
+ break;
+ case kind::CARDINALITY_CONSTRAINT:
+ case kind::COMBINED_CARDINALITY_CONSTRAINT:
{
- if (!pol && !d_state.isInConflict() && atom[0].getType().isFunction())
+ if (d_thss == nullptr)
{
- // apply extensionality eagerly using the ho extension
- d_ho->applyExtensionality(fact);
+ if (!getLogicInfo().hasCardinalityConstraints())
+ {
+ std::stringstream ss;
+ ss << "Cardinality constraint " << atom
+ << " was asserted, but the logic does not allow it." << std::endl;
+ ss << "Try using a logic containing \"UFC\"." << std::endl;
+ throw Exception(ss.str());
+ }
+ else
+ {
+ // support for cardinality constraints is not enabled, set incomplete
+ d_im.setIncomplete(IncompleteId::UF_CARD_DISABLED);
+ }
}
}
+ break;
+ default: break;
}
}
//--------------------------------- end standard check
diff --git a/src/theory/uf/theory_uf.h b/src/theory/uf/theory_uf.h
index c811e08e8..c953cfe5c 100644
--- a/src/theory/uf/theory_uf.h
+++ b/src/theory/uf/theory_uf.h
@@ -128,12 +128,6 @@ private:
bool needsCheckLastEffort() override;
/** Post-check, called after the fact queue of the theory is processed. */
void postCheck(Effort level) override;
- /** Pre-notify fact, return true if processed. */
- bool preNotifyFact(TNode atom,
- bool pol,
- TNode fact,
- bool isPrereg,
- bool isInternal) override;
/** Notify fact */
void notifyFact(TNode atom, bool pol, TNode fact, bool isInternal) override;
//--------------------------------- end standard check
diff --git a/test/python/unit/api/test_term.py b/test/python/unit/api/test_term.py
index 32813e17f..e78188079 100644
--- a/test/python/unit/api/test_term.py
+++ b/test/python/unit/api/test_term.py
@@ -15,6 +15,7 @@ import pytest
import pycvc5
from pycvc5 import kinds
from pycvc5 import Sort, Term
+from fractions import Fraction
@pytest.fixture
@@ -1145,12 +1146,27 @@ def test_get_real(solver):
assert 0 == real1.getRealValue()
assert 0 == real2.getRealValue()
assert -17 == real3.getRealValue()
- assert -3 / 5 == real4.getRealValue()
- assert 127 / 10 == real5.getRealValue()
- assert 1 / 4294967297 == real6.getRealValue()
+ assert Fraction(-3, 5) == real4.getRealValue()
+ assert Fraction(127, 10) == real5.getRealValue()
+ assert Fraction(1, 4294967297) == real6.getRealValue()
assert 4294967297 == real7.getRealValue()
- assert 1 / 18446744073709551617 == real8.getRealValue()
- assert float(18446744073709551617) == real9.getRealValue()
+ assert Fraction(1, 18446744073709551617) == real8.getRealValue()
+ assert Fraction(18446744073709551617, 1) == real9.getRealValue()
+
+ # Check denominator too large for float
+ num = 1
+ den = 2 ** 64 + 1
+ real_big = solver.mkReal(num, den)
+ assert real_big.isRealValue()
+ assert Fraction(num, den) == real_big.getRealValue()
+
+ # Check that we're treating floats as decimal aproximations rather than
+ # IEEE-754-specified values.
+ real_decimal = solver.mkReal(0.3)
+ assert real_decimal.isRealValue()
+ assert Fraction("0.3") == real_decimal.getRealValue()
+ assert Fraction(0.3) == Fraction(5404319552844595, 18014398509481984)
+ assert Fraction(0.3) != real_decimal.getRealValue()
def test_get_boolean(solver):
diff --git a/test/python/unit/api/test_to_python_obj.py b/test/python/unit/api/test_to_python_obj.py
index 2ba685d50..bb30fae8f 100644
--- a/test/python/unit/api/test_to_python_obj.py
+++ b/test/python/unit/api/test_to_python_obj.py
@@ -22,8 +22,8 @@ def testGetBool():
solver = pycvc5.Solver()
t = solver.mkTrue()
f = solver.mkFalse()
- assert t.toPythonObj() == True
- assert f.toPythonObj() == False
+ assert t.toPythonObj() is True
+ assert f.toPythonObj() is False
def testGetInt():
@@ -115,4 +115,4 @@ def testGetValueReal():
xval = solver.getValue(x)
yval = solver.getValue(y)
assert xval.toPythonObj() == Fraction("6")
- assert yval.toPythonObj() == float(Fraction("8.33"))
+ assert yval.toPythonObj() == Fraction("8.33")
diff --git a/test/regress/CMakeLists.txt b/test/regress/CMakeLists.txt
index bd90627f8..1da2630af 100644
--- a/test/regress/CMakeLists.txt
+++ b/test/regress/CMakeLists.txt
@@ -163,6 +163,7 @@ set(regress_0_tests
regress0/auflia/fuzz05.smtv1.smt2
regress0/auflia/x2.smtv1.smt2
regress0/bool/issue1978.smt2
+ regress0/bool/issue6717-ite-rewrite.smt2
regress0/boolean-prec.cvc
regress0/boolean-terms-bug-array.smt2
regress0/boolean-terms-kernel1.smt2
@@ -644,6 +645,10 @@ set(regress_0_tests
regress0/incorrect1.smtv1.smt2
regress0/ineq_basic.smtv1.smt2
regress0/ineq_slack.smtv1.smt2
+ regress0/int-to-bv/basic.smt2
+ regress0/int-to-bv/neg-consts.smt2
+ regress0/int-to-bv/not-enough-bits.smt2
+ regress0/int-to-bv/overflow.smt2
regress0/issue1063-overloading-dt-cons.smt2
regress0/issue1063-overloading-dt-fun.smt2
regress0/issue1063-overloading-dt-sel.smt2
@@ -737,6 +742,7 @@ set(regress_0_tests
regress0/options/ast-and-sexpr.smt2
regress0/options/invalid_dump.smt2
regress0/options/set-and-get-options.smt2
+ regress0/options/statistics.smt2
regress0/parallel-let.smt2
regress0/parser/as.smt2
regress0/parser/bv_arity_smt2.6.smt2
@@ -1491,6 +1497,7 @@ set(regress_1_tests
regress1/bags/union_disjoint.smt2
regress1/bags/union_max1.smt2
regress1/bags/union_max2.smt2
+ regress1/bv2int-isabelle.smt2
regress1/bv/bench_38.delta.smt2
regress1/bv/bug787.smt2
regress1/bv/bug_extract_mult_leading_bit.smt2
@@ -2127,6 +2134,11 @@ set(regress_1_tests
regress1/strings/issue6337-replace-re.smt2
regress1/strings/issue6567-empty-re-range.smt2
regress1/strings/issue6604-2.smt2
+ regress1/strings/issue6635-rre.smt2
+ regress1/strings/issue6653-2-update-c-len.smt2
+ regress1/strings/issue6653-4-rre.smt2
+ regress1/strings/issue6653-rre.smt2
+ regress1/strings/issue6653-rre-small.smt2
regress1/strings/kaluza-fl.smt2
regress1/strings/loop002.smt2
regress1/strings/loop003.smt2
diff --git a/test/regress/regress0/bool/issue6717-ite-rewrite.smt2 b/test/regress/regress0/bool/issue6717-ite-rewrite.smt2
new file mode 100644
index 000000000..3f78823df
--- /dev/null
+++ b/test/regress/regress0/bool/issue6717-ite-rewrite.smt2
@@ -0,0 +1,7 @@
+(set-logic ALL)
+(declare-fun T () Bool)
+(declare-fun v () String)
+(assert (ite T T true))
+(assert (or T (and (str.prefixof v "") (exists ((x Int)) (= "t" (str.substr v 0 x))))))
+(set-info :status sat)
+(check-sat)
diff --git a/test/regress/regress0/bv/bv-int-collapse1.smt2 b/test/regress/regress0/bv/bv-int-collapse1.smt2
index 1f5015d14..60826da85 100644
--- a/test/regress/regress0/bv/bv-int-collapse1.smt2
+++ b/test/regress/regress0/bv/bv-int-collapse1.smt2
@@ -1,4 +1,4 @@
-; COMMAND-LINE: --bv-solver=lazy
+; COMMAND-LINE: --solve-bv-as-int=sum
; EXPECT: unsat
(set-logic ALL)
(set-info :status unsat)
diff --git a/test/regress/regress0/bv/bv-int-collapse2.smt2 b/test/regress/regress0/bv/bv-int-collapse2.smt2
index d56188dad..130b045d9 100644
--- a/test/regress/regress0/bv/bv-int-collapse2.smt2
+++ b/test/regress/regress0/bv/bv-int-collapse2.smt2
@@ -1,4 +1,4 @@
-; COMMAND-LINE: --bv-solver=lazy
+; COMMAND-LINE: --solve-bv-as-int=sum
; EXPECT: unsat
(set-logic ALL)
(set-info :status unsat)
diff --git a/test/regress/regress0/bv/bv2nat-simp-range.smt2 b/test/regress/regress0/bv/bv2nat-simp-range.smt2
index 31e2b7bd1..daae6a1c3 100644
--- a/test/regress/regress0/bv/bv2nat-simp-range.smt2
+++ b/test/regress/regress0/bv/bv2nat-simp-range.smt2
@@ -1,3 +1,4 @@
+; COMMAND-LINE: --solve-bv-as-int=sum
; EXPECT: unsat
(set-logic ALL)
(set-info :status unsat)
diff --git a/test/regress/regress0/int-to-bv/basic.smt2 b/test/regress/regress0/int-to-bv/basic.smt2
new file mode 100644
index 000000000..1e30a7ee8
--- /dev/null
+++ b/test/regress/regress0/int-to-bv/basic.smt2
@@ -0,0 +1,10 @@
+; COMMAND-LINE: --solve-int-as-bv=5 --no-check-models
+(set-logic QF_NIA)
+(declare-const x Int)
+(declare-const y Int)
+; Tests the conversion of negative constants and non-linear multiplication
+(assert (= (- 2) (* x y)))
+; Operators with more than two children
+(assert (= 8 (* x x x)))
+(set-info :status sat)
+(check-sat)
diff --git a/test/regress/regress0/int-to-bv/neg-consts.smt2 b/test/regress/regress0/int-to-bv/neg-consts.smt2
new file mode 100644
index 000000000..46c08dad5
--- /dev/null
+++ b/test/regress/regress0/int-to-bv/neg-consts.smt2
@@ -0,0 +1,9 @@
+; COMMAND-LINE: --solve-int-as-bv=4 --no-check-models
+(set-logic QF_NIA)
+(declare-const x Int)
+(declare-const y Int)
+(assert (> (- 1) x))
+(assert (>= y x))
+(assert (< 0 y))
+(set-info :status sat)
+(check-sat)
diff --git a/test/regress/regress0/int-to-bv/not-enough-bits.smt2 b/test/regress/regress0/int-to-bv/not-enough-bits.smt2
new file mode 100644
index 000000000..49711ecc9
--- /dev/null
+++ b/test/regress/regress0/int-to-bv/not-enough-bits.smt2
@@ -0,0 +1,11 @@
+; COMMAND-LINE: --solve-int-as-bv=3
+; SCRUBBER: sed -n "s/.*\(Not enough bits\).*: 4.*/\1/p"
+; EXPECT: Not enough bits
+; EXIT: 1
+(set-logic QF_NIA)
+(declare-const x Int)
+(declare-const y Int)
+; The negative constant fits, the positive does not
+(assert (= (- 4) (* x y)))
+(assert (= 4 (* x y)))
+(check-sat)
diff --git a/test/regress/regress0/int-to-bv/overflow.smt2 b/test/regress/regress0/int-to-bv/overflow.smt2
new file mode 100644
index 000000000..30e47adb3
--- /dev/null
+++ b/test/regress/regress0/int-to-bv/overflow.smt2
@@ -0,0 +1,9 @@
+; COMMAND-LINE: --solve-int-as-bv=4
+; EXPECT: unknown
+(set-logic QF_NIA)
+(declare-const x Int)
+(declare-const y Int)
+(assert (= (- 1) (+ x y)))
+(assert (> x 0))
+(assert (> y 0))
+(check-sat)
diff --git a/test/regress/regress0/options/statistics.smt2 b/test/regress/regress0/options/statistics.smt2
new file mode 100644
index 000000000..ae9d93b6f
--- /dev/null
+++ b/test/regress/regress0/options/statistics.smt2
@@ -0,0 +1,43 @@
+; REQUIRES: statistics
+; EXPECT: false
+; EXPECT: false
+; EXPECT: false
+; EXPECT: false
+; EXPECT: true
+; EXPECT: true
+; EXPECT: false
+; EXPECT: false
+; EXPECT: false
+; EXPECT: false
+; EXPECT: false
+; EXPECT: false
+; EXPECT: true
+; EXPECT: false
+; EXPECT: false
+; EXPECT: true
+(set-logic QF_UF)
+(get-option :stats)
+(get-option :stats-all)
+(get-option :stats-every-query)
+(get-option :stats-expert)
+
+(set-option :stats-all true)
+
+(get-option :stats)
+(get-option :stats-all)
+(get-option :stats-every-query)
+(get-option :stats-expert)
+
+(set-option :stats false)
+
+(get-option :stats)
+(get-option :stats-all)
+(get-option :stats-every-query)
+(get-option :stats-expert)
+
+(set-option :stats-expert true)
+
+(get-option :stats)
+(get-option :stats-all)
+(get-option :stats-every-query)
+(get-option :stats-expert) \ No newline at end of file
diff --git a/test/regress/regress1/bv/bv2nat-ground.smt2 b/test/regress/regress1/bv/bv2nat-ground.smt2
index 7e0da282e..b68051719 100644
--- a/test/regress/regress1/bv/bv2nat-ground.smt2
+++ b/test/regress/regress1/bv/bv2nat-ground.smt2
@@ -1,4 +1,4 @@
-; COMMAND-LINE: --bv-solver=lazy
+; COMMAND-LINE: --solve-bv-as-int=sum
; EXPECT: unsat
(set-logic QF_BVLIA)
(set-info :status unsat)
diff --git a/test/regress/regress1/bv/bv2nat-simp-range-sat.smt2 b/test/regress/regress1/bv/bv2nat-simp-range-sat.smt2
index 9da8d4ca8..66b286da1 100644
--- a/test/regress/regress1/bv/bv2nat-simp-range-sat.smt2
+++ b/test/regress/regress1/bv/bv2nat-simp-range-sat.smt2
@@ -1,3 +1,5 @@
+; COMMAND-LINE: --solve-bv-as-int=sum
+; EXPECT: sat
(set-logic ALL)
(set-info :status sat)
(declare-fun t () (_ BitVec 16))
diff --git a/test/regress/regress1/bv2int-isabelle.smt2 b/test/regress/regress1/bv2int-isabelle.smt2
new file mode 100644
index 000000000..e8d1efe51
--- /dev/null
+++ b/test/regress/regress1/bv2int-isabelle.smt2
@@ -0,0 +1,16 @@
+; COMMAND-LINE: --solve-bv-as-int=sum --no-check-unsat-cores
+; EXPECT: unsat
+(set-logic ALL)
+(declare-fun s$ () (_ BitVec 32))
+(declare-fun x$ () (_ BitVec 32))
+(declare-fun i$ () (_ BitVec 32))
+(define-fun bound () Int (bv2nat ((_ int2bv 32) 2048)))
+(define-fun bseg ((x (_ BitVec 32)) (s (_ BitVec 32))) Bool (and (< (bv2nat x) bound) (<= (+ (bv2nat x) (bv2nat s)) bound)))
+
+;assumptions
+(assert (bseg x$ s$))
+(assert (<= (bv2nat i$) (bv2nat s$)))
+
+;conclusion
+(assert (not (= (bv2nat (bvadd x$ i$)) (+ (bv2nat x$) (bv2nat i$)))))
+(check-sat)
diff --git a/test/regress/regress1/strings/issue6635-rre.smt2 b/test/regress/regress1/strings/issue6635-rre.smt2
new file mode 100644
index 000000000..cbca77783
--- /dev/null
+++ b/test/regress/regress1/strings/issue6635-rre.smt2
@@ -0,0 +1,6 @@
+; COMMAND-LINE: --strings-exp --re-elim --re-elim-agg
+; EXPECT: unsat
+(set-logic ALL)
+(declare-fun a () String)
+(assert (str.in_re (str.replace_re a (re.++ (str.to_re "A") (re.union (str.to_re "") (str.to_re (str.from_code (str.len a))))) "AB") (re.+ (str.to_re "A"))))
+(check-sat)
diff --git a/test/regress/regress1/strings/issue6653-2-update-c-len.smt2 b/test/regress/regress1/strings/issue6653-2-update-c-len.smt2
new file mode 100644
index 000000000..88a89b725
--- /dev/null
+++ b/test/regress/regress1/strings/issue6653-2-update-c-len.smt2
@@ -0,0 +1,7 @@
+(set-logic ALL)
+(set-info :status sat)
+(set-option :strings-lazy-pp false)
+(set-option :check-unsat-cores true)
+(declare-fun s () String)
+(assert (not (= "A" (str.substr (str.update "AAAAAA" 1 s) 5 1))))
+(check-sat)
diff --git a/test/regress/regress1/strings/issue6653-4-rre.smt2 b/test/regress/regress1/strings/issue6653-4-rre.smt2
new file mode 100644
index 000000000..8de99a334
--- /dev/null
+++ b/test/regress/regress1/strings/issue6653-4-rre.smt2
@@ -0,0 +1,6 @@
+; COMMAND-LINE: --strings-exp --re-elim --re-elim-agg
+; EXPECT: sat
+(set-logic ALL)
+(declare-fun x () String)
+(assert (str.in_re (str.replace_re x (str.to_re "A") x) (re.++ (re.comp (str.to_re "A")) (str.to_re "A") re.allchar)))
+(check-sat)
diff --git a/test/regress/regress1/strings/issue6653-rre-small.smt2 b/test/regress/regress1/strings/issue6653-rre-small.smt2
new file mode 100644
index 000000000..c4b6a497b
--- /dev/null
+++ b/test/regress/regress1/strings/issue6653-rre-small.smt2
@@ -0,0 +1,6 @@
+; COMMAND-LINE: --strings-exp --strings-fmf --re-elim --re-elim-agg
+; EXPECT: sat
+(set-logic ALL)
+(declare-fun a () String)
+(assert (str.in_re a (re.+ (str.to_re (str.replace_re a (str.to_re a) "A")))))
+(check-sat)
diff --git a/test/regress/regress1/strings/issue6653-rre.smt2 b/test/regress/regress1/strings/issue6653-rre.smt2
new file mode 100644
index 000000000..66b7dd64e
--- /dev/null
+++ b/test/regress/regress1/strings/issue6653-rre.smt2
@@ -0,0 +1,8 @@
+; COMMAND-LINE: --strings-exp --re-elim --re-elim-agg
+; EXPECT: sat
+(set-logic ALL)
+(declare-fun a () String)
+(declare-fun b () String)
+(assert (str.in_re (str.replace_re b (str.to_re (str.replace_all a (str.++ b "a") b)) (str.++ b "a")) (re.+ (str.to_re "b"))))
+(assert (str.in_re a (re.* (re.range "a" "b"))))
+(check-sat)
diff --git a/test/regress/regress2/bv_to_int_mask_array_1.smt2 b/test/regress/regress2/bv_to_int_mask_array_1.smt2
index c8cf40abf..165e39e7a 100644
--- a/test/regress/regress2/bv_to_int_mask_array_1.smt2
+++ b/test/regress/regress2/bv_to_int_mask_array_1.smt2
@@ -1,7 +1,7 @@
; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=value
; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=sum
-; COMMAND-LINE: --solve-bv-as-int=bv
+; COMMAND-LINE: --solve-bv-as-int=bv --no-check-unsat-cores
; EXPECT: unsat
(set-logic ALL)
(declare-fun A () (Array Int Int))
diff --git a/test/unit/node/node_black.cpp b/test/unit/node/node_black.cpp
index 94a2e5fb6..98fabc727 100644
--- a/test/unit/node/node_black.cpp
+++ b/test/unit/node/node_black.cpp
@@ -67,7 +67,8 @@ class TestNodeBlackNode : public TestNode
char* argv[2];
argv[0] = strdup("");
argv[1] = strdup("--output-lang=ast");
- Options::parseOptions(&opts, 2, argv);
+ std::string progName;
+ Options::parseOptions(&opts, 2, argv, progName);
free(argv[0]);
free(argv[1]);
d_smt.reset(new SmtEngine(d_nodeManager.get(), &opts));
diff --git a/test/unit/theory/theory_bv_opt_white.cpp b/test/unit/theory/theory_bv_opt_white.cpp
index 66efe7eff..c23ce79dd 100644
--- a/test/unit/theory/theory_bv_opt_white.cpp
+++ b/test/unit/theory/theory_bv_opt_white.cpp
@@ -63,7 +63,7 @@ TEST_F(TestTheoryWhiteBVOpt, unsigned_min)
ASSERT_EQ(d_optslv->getValues()[0].getValue().getConst<BitVector>(),
BitVector(32u, (uint32_t)0x3FFFFFA1));
- d_optslv->resetObjectives();
+ d_smtEngine->resetAssertions();
}
TEST_F(TestTheoryWhiteBVOpt, signed_min)
@@ -87,7 +87,7 @@ TEST_F(TestTheoryWhiteBVOpt, signed_min)
// expect the minimum x = -1
ASSERT_EQ(val, BitVector(32u, (uint32_t)0x80000000));
- d_optslv->resetObjectives();
+ d_smtEngine->resetAssertions();
}
TEST_F(TestTheoryWhiteBVOpt, unsigned_max)
@@ -114,7 +114,7 @@ TEST_F(TestTheoryWhiteBVOpt, unsigned_max)
ASSERT_EQ(d_optslv->getValues()[0].getValue().getConst<BitVector>(),
BitVector(32u, 2u));
- d_optslv->resetObjectives();
+ d_smtEngine->resetAssertions();
}
TEST_F(TestTheoryWhiteBVOpt, signed_max)
@@ -137,7 +137,7 @@ TEST_F(TestTheoryWhiteBVOpt, signed_max)
// expect the maxmum x =
ASSERT_EQ(d_optslv->getValues()[0].getValue().getConst<BitVector>(),
BitVector(32u, 10u));
- d_optslv->resetObjectives();
+ d_smtEngine->resetAssertions();
}
TEST_F(TestTheoryWhiteBVOpt, min_boundary)
@@ -161,7 +161,7 @@ TEST_F(TestTheoryWhiteBVOpt, min_boundary)
// expect the maximum x = 18
ASSERT_EQ(d_optslv->getValues()[0].getValue().getConst<BitVector>(),
BitVector(32u, 18u));
- d_optslv->resetObjectives();
+ d_smtEngine->resetAssertions();
}
} // namespace test
diff --git a/test/unit/theory/theory_int_opt_white.cpp b/test/unit/theory/theory_int_opt_white.cpp
index f16db0c0e..cf0434ddc 100644
--- a/test/unit/theory/theory_int_opt_white.cpp
+++ b/test/unit/theory/theory_int_opt_white.cpp
@@ -70,7 +70,7 @@ TEST_F(TestTheoryWhiteIntOpt, max)
ASSERT_EQ(d_optslv->getValues()[0].getValue().getConst<Rational>(),
Rational("99"));
- d_optslv->resetObjectives();
+ d_smtEngine->resetAssertions();
}
TEST_F(TestTheoryWhiteIntOpt, min)
@@ -101,7 +101,7 @@ TEST_F(TestTheoryWhiteIntOpt, min)
ASSERT_EQ(d_optslv->getValues()[0].getValue().getConst<Rational>(),
Rational("1"));
- d_optslv->resetObjectives();
+ d_smtEngine->resetAssertions();
}
TEST_F(TestTheoryWhiteIntOpt, result)
@@ -129,7 +129,7 @@ TEST_F(TestTheoryWhiteIntOpt, result)
// We expect our check to have returned UNSAT
ASSERT_EQ(r, OptimizationResult::UNSAT);
- d_optslv->resetObjectives();
+ d_smtEngine->resetAssertions();
}
TEST_F(TestTheoryWhiteIntOpt, open_interval)
@@ -164,7 +164,7 @@ TEST_F(TestTheoryWhiteIntOpt, open_interval)
// expect the minimum result of cost3 = cost1 + cost2 to be 1 + 111 = 112
ASSERT_EQ(d_optslv->getValues()[0].getValue().getConst<Rational>(),
Rational("112"));
- d_optslv->resetObjectives();
+ d_smtEngine->resetAssertions();
}
} // namespace test
diff --git a/test/unit/theory/theory_opt_multigoal_white.cpp b/test/unit/theory/theory_opt_multigoal_white.cpp
index 1950d9ae2..73c6d9e7e 100644
--- a/test/unit/theory/theory_opt_multigoal_white.cpp
+++ b/test/unit/theory/theory_opt_multigoal_white.cpp
@@ -240,5 +240,69 @@ TEST_F(TestTheoryWhiteOptMultigoal, pareto)
ASSERT_EQ(possibleResults.size(), 0);
}
+TEST_F(TestTheoryWhiteOptMultigoal, pushpop)
+{
+ d_smtEngine->resetAssertions();
+ Node x = d_nodeManager->mkVar(*d_BV32Type);
+ Node y = d_nodeManager->mkVar(*d_BV32Type);
+ Node z = d_nodeManager->mkVar(*d_BV32Type);
+
+ // 18 <= x
+ d_smtEngine->assertFormula(d_nodeManager->mkNode(
+ kind::BITVECTOR_ULE, d_nodeManager->mkConst(BitVector(32u, 18u)), x));
+
+ // y <= x
+ d_smtEngine->assertFormula(d_nodeManager->mkNode(kind::BITVECTOR_SLE, y, x));
+
+ // Lexico optimization
+ OptimizationSolver optSolver(d_smtEngine.get());
+
+ optSolver.setObjectiveCombination(OptimizationSolver::LEXICOGRAPHIC);
+
+ // minimize x
+ optSolver.addObjective(x, OptimizationObjective::MINIMIZE, false);
+
+ // push
+ d_smtEngine->push();
+
+ // maximize y with `signed` comparison over bit-vectors.
+ optSolver.addObjective(y, OptimizationObjective::MAXIMIZE, true);
+ // maximize z
+ optSolver.addObjective(z, OptimizationObjective::MAXIMIZE, false);
+
+ OptimizationResult::ResultType r = optSolver.checkOpt();
+
+ ASSERT_EQ(r, OptimizationResult::OPTIMAL);
+
+ std::vector<OptimizationResult> results = optSolver.getValues();
+
+ // x == 18
+ ASSERT_EQ(results[0].getValue().getConst<BitVector>(), BitVector(32u, 18u));
+
+ // y == 18
+ ASSERT_EQ(results[1].getValue().getConst<BitVector>(), BitVector(32u, 18u));
+
+ // z == 0xFFFFFFFF
+ ASSERT_EQ(results[2].getValue().getConst<BitVector>(),
+ BitVector(32u, (unsigned)0xFFFFFFFF));
+
+ // pop
+ d_smtEngine->pop();
+
+ // now we only have one objective: (minimize x)
+ r = optSolver.checkOpt();
+ ASSERT_EQ(r, OptimizationResult::OPTIMAL);
+ results = optSolver.getValues();
+ ASSERT_EQ(results.size(), 1);
+ ASSERT_EQ(results[0].getValue().getConst<BitVector>(), BitVector(32u, 18u));
+
+ // resetting the assertions also resets the optimization objectives
+ d_smtEngine->resetAssertions();
+ r = optSolver.checkOpt();
+ ASSERT_EQ(r, OptimizationResult::OPTIMAL);
+ results = optSolver.getValues();
+ ASSERT_EQ(results.size(), 0);
+}
+
} // namespace test
} // namespace cvc5
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback