summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.mailmap1
-rw-r--r--AUTHORS38
-rw-r--r--COPYING36
-rw-r--r--Makefile4
-rw-r--r--contrib/alttheoryskel/theory_DIR.cpp5
-rwxr-xr-xcontrib/get-bug-attachments4
-rw-r--r--contrib/theoryskel/theory_DIR.cpp2
-rw-r--r--src/Makefile.am9
-rw-r--r--src/context/cdhashmap.h6
-rw-r--r--src/context/cdhashset.h6
-rw-r--r--src/cvc4.i3
-rw-r--r--src/decision/decision_engine.h2
-rw-r--r--src/expr/command.cpp21
-rw-r--r--src/expr/command.h12
-rw-r--r--src/expr/expr_manager_template.cpp4
-rw-r--r--src/expr/expr_manager_template.h6
-rw-r--r--src/expr/node_manager.cpp33
-rw-r--r--src/expr/node_manager.h7
-rw-r--r--src/main/driver_unified.cpp91
-rw-r--r--src/main/interactive_shell.cpp2
-rw-r--r--src/main/interactive_shell.h3
-rw-r--r--src/options/options_template.cpp14
-rw-r--r--src/parser/parser.cpp16
-rw-r--r--src/parser/parser.h8
-rw-r--r--src/parser/smt2/Smt2.g54
-rw-r--r--src/printer/ast/ast_printer.cpp7
-rw-r--r--src/printer/cvc/cvc_printer.cpp7
-rw-r--r--src/printer/smt2/smt2_printer.cpp7
-rw-r--r--src/prop/bvminisat/bvminisat.cpp9
-rw-r--r--src/prop/bvminisat/bvminisat.h9
-rw-r--r--src/prop/bvminisat/core/Solver.h30
-rw-r--r--src/prop/bvminisat/simp/SimpSolver.h44
-rw-r--r--src/prop/cnf_stream.cpp7
-rw-r--r--src/prop/cnf_stream.h6
-rw-r--r--src/prop/minisat/core/Solver.cc14
-rw-r--r--src/prop/minisat/core/Solver.h31
-rw-r--r--src/prop/minisat/minisat.cpp9
-rw-r--r--src/prop/minisat/minisat.h3
-rw-r--r--src/prop/minisat/simp/SimpSolver.h54
-rw-r--r--src/prop/options3
-rw-r--r--src/prop/options_handlers.h47
-rw-r--r--src/prop/prop_engine.cpp34
-rw-r--r--src/prop/prop_engine.h108
-rw-r--r--src/prop/sat_solver.h7
-rw-r--r--src/prop/sat_solver_factory.cpp21
-rw-r--r--src/prop/sat_solver_factory.h14
-rw-r--r--src/prop/sat_solver_registry.cpp59
-rw-r--r--src/prop/sat_solver_registry.h116
-rw-r--r--src/prop/theory_proxy.cpp6
-rw-r--r--src/prop/theory_proxy.h2
-rw-r--r--src/smt/boolean_terms.cpp36
-rw-r--r--src/smt/model_postprocessor.cpp46
-rw-r--r--src/smt/options12
-rw-r--r--src/smt/options_handlers.h58
-rw-r--r--src/smt/smt_engine.cpp392
-rw-r--r--src/smt/smt_engine.h34
-rw-r--r--src/smt/smt_engine_scope.h3
-rw-r--r--src/theory/arith/theory_arith_private.cpp6
-rw-r--r--src/theory/arrays/theory_arrays.cpp252
-rw-r--r--src/theory/arrays/theory_arrays.h35
-rw-r--r--src/theory/bv/bitblaster_template.h19
-rw-r--r--src/theory/bv/bv_eager_solver.cpp1
-rw-r--r--src/theory/bv/bv_inequality_graph.cpp1
-rw-r--r--src/theory/bv/bv_quick_check.cpp26
-rw-r--r--src/theory/bv/bv_quick_check.h10
-rw-r--r--src/theory/bv/bv_subtheory_algebraic.cpp16
-rw-r--r--src/theory/bv/bv_subtheory_bitblast.cpp14
-rw-r--r--src/theory/bv/bv_subtheory_core.cpp3
-rw-r--r--src/theory/bv/bv_subtheory_inequality.cpp15
-rw-r--r--src/theory/bv/bv_subtheory_inequality.h11
-rw-r--r--src/theory/bv/eager_bitblaster.cpp1
-rw-r--r--src/theory/bv/lazy_bitblaster.cpp24
-rw-r--r--src/theory/bv/options3
-rw-r--r--src/theory/bv/theory_bv.cpp7
-rw-r--r--src/theory/bv/theory_bv.h2
-rw-r--r--src/theory/bv/theory_bv_rewriter.cpp11
-rw-r--r--src/theory/datatypes/theory_datatypes.cpp279
-rw-r--r--src/theory/datatypes/theory_datatypes.h16
-rw-r--r--src/theory/example/theory_uf_tim.cpp5
-rw-r--r--src/theory/idl/theory_idl.cpp9
-rw-r--r--src/theory/output_channel.h23
-rw-r--r--src/theory/quantifiers/candidate_generator.cpp64
-rw-r--r--src/theory/quantifiers/candidate_generator.h2
-rw-r--r--src/theory/quantifiers/ce_guided_instantiation.cpp21
-rw-r--r--src/theory/quantifiers/ce_guided_instantiation.h3
-rwxr-xr-xsrc/theory/quantifiers/conjecture_generator.cpp52
-rwxr-xr-xsrc/theory/quantifiers/conjecture_generator.h1
-rw-r--r--src/theory/quantifiers/first_order_model.cpp180
-rw-r--r--src/theory/quantifiers/first_order_model.h44
-rw-r--r--src/theory/quantifiers/fun_def_process.cpp197
-rw-r--r--src/theory/quantifiers/fun_def_process.h54
-rw-r--r--src/theory/quantifiers/inst_gen.cpp300
-rw-r--r--src/theory/quantifiers/inst_gen.h60
-rw-r--r--src/theory/quantifiers/inst_match_generator.cpp9
-rw-r--r--src/theory/quantifiers/inst_match_generator.h6
-rw-r--r--src/theory/quantifiers/inst_strategy_e_matching.cpp98
-rw-r--r--src/theory/quantifiers/inst_strategy_e_matching.h25
-rw-r--r--src/theory/quantifiers/instantiation_engine.cpp100
-rw-r--r--src/theory/quantifiers/instantiation_engine.h36
-rw-r--r--src/theory/quantifiers/kinds3
-rw-r--r--src/theory/quantifiers/model_builder.cpp387
-rw-r--r--src/theory/quantifiers/model_builder.h52
-rw-r--r--src/theory/quantifiers/model_engine.cpp5
-rw-r--r--src/theory/quantifiers/modes.cpp6
-rw-r--r--src/theory/quantifiers/modes.h11
-rw-r--r--src/theory/quantifiers/options28
-rw-r--r--src/theory/quantifiers/options_handlers.h44
-rw-r--r--src/theory/quantifiers/qinterval_builder.cpp1111
-rw-r--r--src/theory/quantifiers/qinterval_builder.h155
-rwxr-xr-xsrc/theory/quantifiers/quant_conflict_find.cpp51
-rwxr-xr-xsrc/theory/quantifiers/quant_conflict_find.h1
-rw-r--r--src/theory/quantifiers/quant_util.cpp1
-rw-r--r--src/theory/quantifiers/quantifiers_attributes.cpp4
-rw-r--r--src/theory/quantifiers/quantifiers_rewriter.cpp182
-rw-r--r--src/theory/quantifiers/quantifiers_rewriter.h6
-rw-r--r--src/theory/quantifiers/term_database.cpp308
-rw-r--r--src/theory/quantifiers/term_database.h41
-rw-r--r--src/theory/quantifiers/theory_quantifiers.cpp37
-rw-r--r--src/theory/quantifiers/theory_quantifiers.h9
-rw-r--r--src/theory/quantifiers/theory_quantifiers_type_rules.h20
-rw-r--r--src/theory/quantifiers/trigger.cpp36
-rw-r--r--src/theory/quantifiers/trigger.h1
-rw-r--r--src/theory/quantifiers_engine.cpp40
-rw-r--r--src/theory/quantifiers_engine.h6
-rw-r--r--src/theory/rep_set.cpp9
-rw-r--r--src/theory/rep_set.h2
-rw-r--r--src/theory/rewriter.cpp29
-rw-r--r--src/theory/rewriter.h11
-rw-r--r--src/theory/rewriter_tables_template.h2
-rw-r--r--src/theory/sets/normal_form.h60
-rw-r--r--src/theory/sets/theory_sets.cpp1
-rw-r--r--src/theory/sets/theory_sets_private.cpp119
-rw-r--r--src/theory/sets/theory_sets_private.h5
-rw-r--r--src/theory/sets/theory_sets_rewriter.cpp155
-rw-r--r--src/theory/sets/theory_sets_type_enumerator.h1
-rw-r--r--src/theory/sets/theory_sets_type_rules.h13
-rw-r--r--src/theory/strings/theory_strings.cpp120
-rw-r--r--src/theory/strings/theory_strings.h6
-rw-r--r--src/theory/term_registration_visitor.cpp76
-rw-r--r--src/theory/theory.cpp1
-rw-r--r--src/theory/theory.h8
-rw-r--r--src/theory/theory_engine.cpp60
-rw-r--r--src/theory/theory_engine.h39
-rw-r--r--src/theory/theory_model.cpp74
-rw-r--r--src/theory/theory_model.h1
-rw-r--r--src/theory/theory_test_utils.h24
-rw-r--r--src/theory/uf/equality_engine.cpp58
-rw-r--r--src/theory/uf/equality_engine.h11
-rw-r--r--src/theory/uf/theory_uf.cpp2
-rw-r--r--src/theory/uf/theory_uf_strong_solver.cpp59
-rw-r--r--src/theory/uf/theory_uf_strong_solver.h10
-rw-r--r--src/theory/uf/theory_uf_type_rules.h4
-rw-r--r--src/util/Makefile.am7
-rw-r--r--src/util/resource_manager.cpp285
-rw-r--r--src/util/resource_manager.h158
-rw-r--r--src/util/resource_manager.i5
-rw-r--r--src/util/sort_inference.cpp24
-rw-r--r--src/util/unsafe_interrupt_exception.h43
-rw-r--r--src/util/unsafe_interrupt_exception.i7
-rw-r--r--test/regress/README2
-rw-r--r--test/regress/regress0/Makefile.am10
-rw-r--r--test/regress/regress0/arrays/Makefile.am4
-rw-r--r--test/regress/regress0/bug590.smt22
-rw-r--r--test/regress/regress0/bug590.smt2.expect4
-rw-r--r--test/regress/regress0/bug593.smt220
-rw-r--r--test/regress/regress0/bug595.cvc7
-rw-r--r--test/regress/regress0/bug596.cvc7
-rw-r--r--test/regress/regress0/bug596b.cvc7
-rw-r--r--test/regress/regress0/datatypes/Makefile.am3
-rw-r--r--test/regress/regress0/datatypes/cdt-non-canon-stream.smt211
-rw-r--r--test/regress/regress0/fmf/Makefile.am6
-rw-r--r--test/regress/regress0/fmf/lst-no-self-rev-exp.smt235
-rw-r--r--test/regress/regress0/quantifiers/Makefile.am3
-rw-r--r--test/regress/regress0/quantifiers/burns4.smt22
-rw-r--r--test/regress/regress0/quantifiers/stream-x2014-09-18-unsat.smt2183
-rw-r--r--test/regress/regress0/strings/Makefile.am4
-rwxr-xr-xtest/regress/run_regression2
-rw-r--r--test/unit/theory/theory_bv_white.h13
178 files changed, 3922 insertions, 4100 deletions
diff --git a/.mailmap b/.mailmap
index 7cf2a12f0..eaae8872c 100644
--- a/.mailmap
+++ b/.mailmap
@@ -3,6 +3,7 @@ Morgan Deters <mdeters@cs.nyu.edu> <mdeters@gmail.com>
Dejan Jovanovic <dejan@cs.nyu.edu> <dejan@cs.nyu.edu>
Dejan Jovanovic <dejan@cs.nyu.edu> <dejan.jovanovic@gmail.com>
Francois Bobot <francois@bobot.eu> <francois@bobot.eu>
+Liana Hadarean <lianah@cs.nyu.edu> <lianah@cs.nyu.edu>
Liana Hadarean <lianah@cs.nyu.edu> <lianahady@gmail.com>
Andrew Reynolds <andrew.j.reynolds@gmail.com> <andrew.j.reynolds@gmail.com>
Andrew Reynolds <andrew.j.reynolds@gmail.com> <reynolds@laraserver2.epfl.ch>
diff --git a/AUTHORS b/AUTHORS
index 8db72131b..a2b6350e5 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,17 +1,27 @@
-The core authors and designers of CVC4 are:
-
- Kshitij Bansal <kshitij@cs.nyu.edu>, New York University
- Clark Barrett <barrett@cs.nyu.edu>, New York University
- Francois Bobot <bobot@lri.fr>, Commissariat a l'Energie Atomique (CEA)
- Martin Brain <martin.brain@cs.ox.ac.uk>, University of Oxford
- Christopher Conway <cconway@cs.nyu.edu>, Google
- Morgan Deters <mdeters@cs.nyu.edu>, New York University
- Liana Hadarean <lianah@cs.nyu.edu>, New York University
- Dejan Jovanovic <dejan@cs.nyu.edu>, SRI International
- Tim King <taking@cs.nyu.edu>, New York University
- Tianyi Liang <tianyi-liang@uiowa.edu>, The University of Iowa
- Andrew Reynolds <andrew.j.reynolds@gmail.com>, EPFL
- Cesare Tinelli <tinelli@cs.uiowa.edu>, The University of Iowa
+The authors, designers, and main contributors to CVC4 are listed below.
+CVC4's copyright is held by these individuals and the affiliated
+institutions at the time of their contributions (see the file COPYING).
+All rights reserved.
+
+The core designers and authors of CVC4 are:
+
+ Kshitij Bansal, New York University
+ Clark Barrett, New York University
+ Francois Bobot, The University of Iowa & Commissariat a l'Energie Atomique
+ Martin Brain, University of Oxford
+ Christopher Conway, New York University
+ Morgan Deters, New York University
+ Liana Hadarean, New York University & Mentor Graphics Corporation
+ Dejan Jovanovic, New York University & SRI International
+ Tim King, New York University
+ Tianyi Liang, The University of Iowa
+ Andrew Reynolds, The University of Iowa & EPFL
+ Cesare Tinelli, The University of Iowa
+
+Contributors to the CVC4 codebase additionally include:
+
+ Peter Collingbourne, the Multicore Programming Group at Imperial College
+ London (headed by Alastair Donaldson)
CVC4 is the fourth in the CVC series of tools (CVC, CVC Lite, CVC3) but does
not directly incorporate code from any previous version. Information about
diff --git a/COPYING b/COPYING
index dddf4ed59..87fd0147f 100644
--- a/COPYING
+++ b/COPYING
@@ -1,16 +1,32 @@
-CVC4 is copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 New York University
-and The University of Iowa. All rights reserved.
+CVC4 is copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 by its authors
+and contributors (see the file AUTHORS) and their institutional
+affiliations. All rights reserved.
The source code of CVC4 is open and available to students, researchers,
-software companies, and everyone else to study, to modify, and to
-redistribute original or modified versions; distribution is under the
-terms of the modified BSD license. However, CVC4 can be configured (and
-is, by default) to link against some GPLed libraries, and therefore the
-use of these builds may be restricted in non-GPL-compatible projects.
-See below for a discussion of CLN, GLPK, and Readline (the three GPLed
-optional library dependences for CVC4), and how to ensure you have a
+software companies, and everyone else to study, to modify, and to redistribute
+original or modified versions; distribution is under the terms of the modified
+BSD license (reproduced below). Please note that CVC4 can be configured
+(however, by default it is not) to link against some GPLed libraries, and
+therefore the use of these builds may be restricted in non-GPL-compatible
+projects. See below for a discussion of CLN, GLPK, and Readline (the three
+GPLed optional library dependences for CVC4), and how to ensure you have a
build that doesn't link against GPLed libraries.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT OWNERS AND CONTRIBUTORS
''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -23,7 +39,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- Morgan Deters <mdeters@cs.nyu.edu> Wed, 02 Jul 2014 14:44:39 -0400
+-- Morgan Deters <mdeters@cs.nyu.edu> Thu, 13 Nov 2014
CVC4 incorporates MiniSat code, excluded from the above copyright.
See src/sat/minisat. Its copyright:
diff --git a/Makefile b/Makefile
index 071bf7a3e..b4c7589fe 100644
--- a/Makefile
+++ b/Makefile
@@ -96,7 +96,7 @@ submission-main:
./autogen.sh
mkdir -p builds-smtcomp/main
( cd builds-smtcomp/main; \
- ../../configure competition --disable-shared --enable-static-binary --with-cln --with-glpk --with-abc --without-readline --enable-gpl; \
+ ../../configure competition --disable-thread-support --disable-shared --enable-static-binary --with-cln --with-glpk --with-abc --without-readline --enable-gpl; \
$(MAKE) V=1; \
strip src/main/cvc4; \
$(MAKE) check )
@@ -130,7 +130,7 @@ submission-application:
./autogen.sh
mkdir -p builds-smtcomp/application
( cd builds-smtcomp/application; \
- ../../configure competition --disable-shared --enable-static-binary --with-cln --without-glpk --with-abc --without-readline --enable-gpl CXXFLAGS=-DCVC4_SMTCOMP_APPLICATION_TRACK CFLAGS=-DCVC4_SMTCOMP_APPLICATION_TRACK; \
+ ../../configure competition --disable-thread-support --disable-shared --enable-static-binary --with-cln --without-glpk --with-abc --without-readline --enable-gpl CXXFLAGS=-DCVC4_SMTCOMP_APPLICATION_TRACK CFLAGS=-DCVC4_SMTCOMP_APPLICATION_TRACK; \
$(MAKE) V=1; \
strip src/main/cvc4; \
$(MAKE) check )
diff --git a/contrib/alttheoryskel/theory_DIR.cpp b/contrib/alttheoryskel/theory_DIR.cpp
index 83d837322..ce29fd34d 100644
--- a/contrib/alttheoryskel/theory_DIR.cpp
+++ b/contrib/alttheoryskel/theory_DIR.cpp
@@ -16,6 +16,11 @@ Theory$camel::Theory$camel(context::Context* c,
}/* Theory$camel::Theory$camel() */
void Theory$camel::check(Effort level) {
+ if (done() && !fullEffort(level)) {
+ return;
+ }
+
+ TimerStat::CodeTimer checkTimer(d_checkTime);
while(!done()) {
// Get all the assertions
diff --git a/contrib/get-bug-attachments b/contrib/get-bug-attachments
index 869eee895..80205baff 100755
--- a/contrib/get-bug-attachments
+++ b/contrib/get-bug-attachments
@@ -29,7 +29,7 @@ function webcat {
function webget {
if which wget &>/dev/null; then
tmpfile="$(mktemp get_bug_attach.$$.XXXXXXXX)"
- filename="$(wget -qS -O "$tmpfile" "$1" 2>&1 | grep 'Content-disposition: attachment' | sed 's,.*filename="\(.*\)".*,\1,')"
+ filename="$(wget -qS -O "$tmpfile" "$1" 2>&1 | grep -i 'Content-disposition: attachment' | sed 's,.*filename="\(.*\)".*,\1,')"
ext="$(echo "$filename" | sed 's,.*\.\(.*\),\1,')"
if [ -e "$2.$ext" ] && ! diff -q "$tmpfile" "$2.$ext" &>/dev/null; then
c=a
@@ -46,7 +46,7 @@ function webget {
fi
elif which curl &>/dev/null; then
tmpfile="$(mktemp get_bug_attach.$$.XXXXXXXX)"
- filename="$(curl --head "$1" 2>&1 | grep 'Content-disposition: attachment' | sed 's,.*filename="\(.*\)".*,\1,')"
+ filename="$(curl --head "$1" 2>&1 | grep -i 'Content-disposition: attachment' | sed 's,.*filename="\(.*\)".*,\1,')"
curl "$1" >"$tmpfile" 2>/dev/null
ext="$(echo "$filename" | sed 's,.*\.\(.*\),\1,')"
if [ -e "$2.$ext" ] && ! diff -q "$tmpfile" "$2.$ext" &>/dev/null; then
diff --git a/contrib/theoryskel/theory_DIR.cpp b/contrib/theoryskel/theory_DIR.cpp
index 535a54fd7..2130b21f5 100644
--- a/contrib/theoryskel/theory_DIR.cpp
+++ b/contrib/theoryskel/theory_DIR.cpp
@@ -20,6 +20,8 @@ void Theory$camel::check(Effort level) {
return;
}
+ TimerStat::CodeTimer checkTimer(d_checkTime);
+
while(!done()) {
// Get all the assertions
Assertion assertion = get();
diff --git a/src/Makefile.am b/src/Makefile.am
index d82c0945d..f88dcb3a9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -100,9 +100,6 @@ libcvc4_la_SOURCES = \
prop/sat_solver_types.h \
prop/sat_solver_factory.h \
prop/sat_solver_factory.cpp \
- prop/sat_solver_registry.h \
- prop/sat_solver_registry.cpp \
- prop/options_handlers.h \
smt/smt_engine.cpp \
smt/smt_engine_check_proof.cpp \
smt/smt_engine.h \
@@ -298,8 +295,6 @@ libcvc4_la_SOURCES = \
theory/quantifiers/model_builder.cpp \
theory/quantifiers/quantifiers_attributes.h \
theory/quantifiers/quantifiers_attributes.cpp \
- theory/quantifiers/inst_gen.h \
- theory/quantifiers/inst_gen.cpp \
theory/quantifiers/quant_util.h \
theory/quantifiers/quant_util.cpp \
theory/quantifiers/inst_match_generator.h \
@@ -322,8 +317,6 @@ libcvc4_la_SOURCES = \
theory/quantifiers/relevant_domain.cpp \
theory/quantifiers/symmetry_breaking.h \
theory/quantifiers/symmetry_breaking.cpp \
- theory/quantifiers/qinterval_builder.h \
- theory/quantifiers/qinterval_builder.cpp \
theory/quantifiers/ambqi_builder.h \
theory/quantifiers/ambqi_builder.cpp \
theory/quantifiers/quant_conflict_find.h \
@@ -332,6 +325,8 @@ libcvc4_la_SOURCES = \
theory/quantifiers/conjecture_generator.cpp \
theory/quantifiers/ce_guided_instantiation.h \
theory/quantifiers/ce_guided_instantiation.cpp \
+ theory/quantifiers/fun_def_process.h \
+ theory/quantifiers/fun_def_process.cpp \
theory/quantifiers/options_handlers.h \
theory/arith/theory_arith_type_rules.h \
theory/arith/type_enumerator.h \
diff --git a/src/context/cdhashmap.h b/src/context/cdhashmap.h
index 02f3d855c..324a5a2b4 100644
--- a/src/context/cdhashmap.h
+++ b/src/context/cdhashmap.h
@@ -168,7 +168,9 @@ class CDOhash_map : public ContextObj {
/** ensure copy ctor is only called by us */
CDOhash_map(const CDOhash_map& other) :
ContextObj(other),
- d_key(other.d_key),
+ // don't need to save the key---and if we do we can get
+ // refcounts for Node keys messed up and leak memory
+ d_key(),
d_data(other.d_data),
d_map(other.d_map),
d_prev(NULL),
@@ -591,4 +593,4 @@ public:
}/* CVC4::context namespace */
}/* CVC4 namespace */
-#endif /* __CVC4__CONTEXT__CDHashMAP_H */
+#endif /* __CVC4__CONTEXT__CDHASHMAP_H */
diff --git a/src/context/cdhashset.h b/src/context/cdhashset.h
index 548aa95d1..76bab5a94 100644
--- a/src/context/cdhashset.h
+++ b/src/context/cdhashset.h
@@ -16,8 +16,8 @@
#include "cvc4_private.h"
-#ifndef __CVC4__CONTEXT__CDSET_H
-#define __CVC4__CONTEXT__CDSET_H
+#ifndef __CVC4__CONTEXT__CDHASHSET_H
+#define __CVC4__CONTEXT__CDHASHSET_H
#include "context/context.h"
#include "context/cdinsert_hashmap.h"
@@ -157,4 +157,4 @@ public:
}/* CVC4::context namespace */
}/* CVC4 namespace */
-#endif /* __CVC4__CONTEXT__CDSET_H */
+#endif /* __CVC4__CONTEXT__CDHASHSET_H */
diff --git a/src/cvc4.i b/src/cvc4.i
index 62cd68cab..3ad08660c 100644
--- a/src/cvc4.i
+++ b/src/cvc4.i
@@ -153,6 +153,7 @@ std::set<JavaInputStreamAdapter*> CVC4::JavaInputStreamAdapter::s_adapters;
%typemap(throws) CVC4::ScopeException = CVC4::Exception;
%typemap(throws) CVC4::IllegalArgumentException = CVC4::Exception;
%typemap(throws) CVC4::AssertionException = CVC4::Exception;
+%typemap(throws) CVC4::UnsafeInterruptException = CVC4::Exception;
%typemap(throws) CVC4::parser::InputStreamException = CVC4::Exception;
%typemap(throws) CVC4::parser::ParserException = CVC4::Exception;
@@ -293,6 +294,7 @@ std::set<JavaInputStreamAdapter*> CVC4::JavaInputStreamAdapter::s_adapters;
#endif /* SWIGJAVA */
%include "util/exception.i"
+%include "util/unsafe_interrupt_exception.i"
%include "util/integer.i"
%include "util/rational.i"
%include "util/language.i"
@@ -319,6 +321,7 @@ std::set<JavaInputStreamAdapter*> CVC4::JavaInputStreamAdapter::s_adapters;
%include "util/regexp.i"
%include "util/uninterpreted_constant.i"
%include "util/proof.i"
+%include "util/resource_manager.i"
%include "expr/kind.i"
%include "expr/expr.i"
diff --git a/src/decision/decision_engine.h b/src/decision/decision_engine.h
index 39ed89a68..61900e59d 100644
--- a/src/decision/decision_engine.h
+++ b/src/decision/decision_engine.h
@@ -30,6 +30,7 @@
#include "theory/decision_attributes.h"
#include "util/ite_removal.h"
#include "util/output.h"
+#include "smt/smt_engine_scope.h"
using namespace std;
using namespace CVC4::prop;
@@ -117,6 +118,7 @@ public:
/** Gets the next decision based on strategies that are enabled */
SatLiteral getNext(bool &stopSearch) {
+ NodeManager::currentResourceManager()->spendResource();
Assert(d_cnfStream != NULL,
"Forgot to set cnfStream for decision engine?");
Assert(d_satSolver != NULL,
diff --git a/src/expr/command.cpp b/src/expr/command.cpp
index be1b06cb8..242e018f6 100644
--- a/src/expr/command.cpp
+++ b/src/expr/command.cpp
@@ -39,6 +39,7 @@ namespace CVC4 {
const int CommandPrintSuccess::s_iosIndex = std::ios_base::xalloc();
const CommandSuccess* CommandSuccess::s_instance = new CommandSuccess();
+const CommandInterrupted* CommandInterrupted::s_instance = new CommandInterrupted();
std::ostream& operator<<(std::ostream& out, const Command& c) throw() {
c.toStream(out,
@@ -97,6 +98,10 @@ bool Command::fail() const throw() {
return d_commandStatus != NULL && dynamic_cast<const CommandFailure*>(d_commandStatus) != NULL;
}
+bool Command::interrupted() const throw() {
+ return d_commandStatus != NULL && dynamic_cast<const CommandInterrupted*>(d_commandStatus) != NULL;
+}
+
void Command::invoke(SmtEngine* smtEngine, std::ostream& out) throw() {
invoke(smtEngine);
if(!(isMuted() && ok())) {
@@ -201,6 +206,8 @@ void AssertCommand::invoke(SmtEngine* smtEngine) throw() {
try {
smtEngine->assertFormula(d_expr, d_inUnsatCore);
d_commandStatus = CommandSuccess::instance();
+ } catch(UnsafeInterruptException& e) {
+ d_commandStatus = new CommandInterrupted();
} catch(exception& e) {
d_commandStatus = new CommandFailure(e.what());
}
@@ -224,6 +231,8 @@ void PushCommand::invoke(SmtEngine* smtEngine) throw() {
try {
smtEngine->push();
d_commandStatus = CommandSuccess::instance();
+ } catch(UnsafeInterruptException& e) {
+ d_commandStatus = new CommandInterrupted();
} catch(exception& e) {
d_commandStatus = new CommandFailure(e.what());
}
@@ -247,6 +256,8 @@ void PopCommand::invoke(SmtEngine* smtEngine) throw() {
try {
smtEngine->pop();
d_commandStatus = CommandSuccess::instance();
+ } catch(UnsafeInterruptException& e) {
+ d_commandStatus = new CommandInterrupted();
} catch(exception& e) {
d_commandStatus = new CommandFailure(e.what());
}
@@ -840,6 +851,8 @@ void SimplifyCommand::invoke(SmtEngine* smtEngine) throw() {
try {
d_result = smtEngine->simplify(d_term);
d_commandStatus = CommandSuccess::instance();
+ } catch(UnsafeInterruptException& e) {
+ d_commandStatus = new CommandInterrupted();
} catch(exception& e) {
d_commandStatus = new CommandFailure(e.what());
}
@@ -953,6 +966,8 @@ void GetValueCommand::invoke(SmtEngine* smtEngine) throw() {
}
d_result = em->mkExpr(kind::SEXPR, result);
d_commandStatus = CommandSuccess::instance();
+ } catch(UnsafeInterruptException& e) {
+ d_commandStatus = new CommandInterrupted();
} catch(exception& e) {
d_commandStatus = new CommandFailure(e.what());
}
@@ -1000,6 +1015,8 @@ void GetAssignmentCommand::invoke(SmtEngine* smtEngine) throw() {
try {
d_result = smtEngine->getAssignment();
d_commandStatus = CommandSuccess::instance();
+ } catch(UnsafeInterruptException& e) {
+ d_commandStatus = new CommandInterrupted();
} catch(exception& e) {
d_commandStatus = new CommandFailure(e.what());
}
@@ -1043,6 +1060,8 @@ void GetModelCommand::invoke(SmtEngine* smtEngine) throw() {
d_result = smtEngine->getModel();
d_smtEngine = smtEngine;
d_commandStatus = CommandSuccess::instance();
+ } catch(UnsafeInterruptException& e) {
+ d_commandStatus = new CommandInterrupted();
} catch(exception& e) {
d_commandStatus = new CommandFailure(e.what());
}
@@ -1089,6 +1108,8 @@ void GetProofCommand::invoke(SmtEngine* smtEngine) throw() {
try {
d_result = smtEngine->getProof();
d_commandStatus = CommandSuccess::instance();
+ } catch(UnsafeInterruptException& e) {
+ d_commandStatus = new CommandInterrupted();
} catch(exception& e) {
d_commandStatus = new CommandFailure(e.what());
}
diff --git a/src/expr/command.h b/src/expr/command.h
index c4f2fc1bc..cfa00bff4 100644
--- a/src/expr/command.h
+++ b/src/expr/command.h
@@ -168,6 +168,13 @@ public:
CommandStatus& clone() const { return const_cast<CommandSuccess&>(*this); }
};/* class CommandSuccess */
+class CVC4_PUBLIC CommandInterrupted : public CommandStatus {
+ static const CommandInterrupted* s_instance;
+public:
+ static const CommandInterrupted* instance() throw() { return s_instance; }
+ CommandStatus& clone() const { return const_cast<CommandInterrupted&>(*this); }
+};/* class CommandInterrupted */
+
class CVC4_PUBLIC CommandUnsupported : public CommandStatus {
public:
CommandStatus& clone() const { return *new CommandUnsupported(*this); }
@@ -240,6 +247,11 @@ public:
*/
bool fail() const throw();
+ /**
+ * The command was ran but was interrupted due to resource limiting.
+ */
+ bool interrupted() const throw();
+
/** Get the command status (it's NULL if we haven't run yet). */
const CommandStatus* getCommandStatus() const throw() { return d_commandStatus; }
diff --git a/src/expr/expr_manager_template.cpp b/src/expr/expr_manager_template.cpp
index fb9da3e37..c5249075b 100644
--- a/src/expr/expr_manager_template.cpp
+++ b/src/expr/expr_manager_template.cpp
@@ -130,6 +130,10 @@ const Options& ExprManager::getOptions() const {
return d_nodeManager->getOptions();
}
+ResourceManager* ExprManager::getResourceManager() throw() {
+ return d_nodeManager->getResourceManager();
+}
+
BooleanType ExprManager::booleanType() const {
NodeManagerScope nms(d_nodeManager);
return BooleanType(Type(d_nodeManager, new TypeNode(d_nodeManager->booleanType())));
diff --git a/src/expr/expr_manager_template.h b/src/expr/expr_manager_template.h
index deb2f6918..2fabea0ff 100644
--- a/src/expr/expr_manager_template.h
+++ b/src/expr/expr_manager_template.h
@@ -45,6 +45,7 @@ class Options;
class IntStat;
struct ExprManagerMapCollection;
class StatisticsRegistry;
+class ResourceManager;
namespace expr {
namespace pickle {
@@ -120,9 +121,12 @@ public:
*/
~ExprManager() throw();
- /** Get this node manager's options */
+ /** Get this expr manager's options */
const Options& getOptions() const;
+ /** Get this expr manager's resource manager */
+ ResourceManager* getResourceManager() throw();
+
/** Get the type for booleans */
BooleanType booleanType() const;
diff --git a/src/expr/node_manager.cpp b/src/expr/node_manager.cpp
index 31b17ccda..48aacddf2 100644
--- a/src/expr/node_manager.cpp
+++ b/src/expr/node_manager.cpp
@@ -22,7 +22,9 @@
#include "expr/attribute.h"
#include "util/cvc4_assert.h"
#include "options/options.h"
+#include "smt/options.h"
#include "util/statistics_registry.h"
+#include "util/resource_manager.h"
#include "util/tls.h"
#include "expr/type_checker.h"
@@ -83,6 +85,7 @@ struct NVReclaim {
NodeManager::NodeManager(ExprManager* exprManager) :
d_options(new Options()),
d_statisticsRegistry(new StatisticsRegistry()),
+ d_resourceManager(new ResourceManager()),
next_id(0),
d_attrManager(new expr::attr::AttributeManager()),
d_exprManager(exprManager),
@@ -97,6 +100,7 @@ NodeManager::NodeManager(ExprManager* exprManager,
const Options& options) :
d_options(new Options(options)),
d_statisticsRegistry(new StatisticsRegistry()),
+ d_resourceManager(new ResourceManager()),
next_id(0),
d_attrManager(new expr::attr::AttributeManager()),
d_exprManager(exprManager),
@@ -117,6 +121,22 @@ void NodeManager::init() {
d_operators[i] = mkConst(Kind(k));
}
}
+ d_resourceManager->setHardLimit((*d_options)[options::hardLimit]);
+ if((*d_options)[options::perCallResourceLimit] != 0) {
+ d_resourceManager->setResourceLimit((*d_options)[options::perCallResourceLimit], false);
+ }
+ if((*d_options)[options::cumulativeResourceLimit] != 0) {
+ d_resourceManager->setResourceLimit((*d_options)[options::cumulativeResourceLimit], true);
+ }
+ if((*d_options)[options::perCallMillisecondLimit] != 0) {
+ d_resourceManager->setTimeLimit((*d_options)[options::perCallMillisecondLimit], false);
+ }
+ if((*d_options)[options::cumulativeMillisecondLimit] != 0) {
+ d_resourceManager->setTimeLimit((*d_options)[options::cumulativeMillisecondLimit], true);
+ }
+ if((*d_options)[options::cpuTime]) {
+ d_resourceManager->useCPUTime(true);
+ }
}
NodeManager::~NodeManager() {
@@ -162,6 +182,8 @@ NodeManager::~NodeManager() {
// defensive coding, in case destruction-order issues pop up (they often do)
delete d_statisticsRegistry;
d_statisticsRegistry = NULL;
+ delete d_resourceManager;
+ d_resourceManager = NULL;
delete d_attrManager;
d_attrManager = NULL;
delete d_options;
@@ -202,10 +224,21 @@ void NodeManager::reclaimZombies() {
NodeValueReferenceCountNonZero());
d_zombies.clear();
+#ifdef _LIBCPP_VERSION
+ NodeValue* last = NULL;
+#endif
for(vector<NodeValue*>::iterator i = zombies.begin();
i != zombies.end();
++i) {
NodeValue* nv = *i;
+#ifdef _LIBCPP_VERSION
+ // Work around an apparent bug in libc++'s hash_set<> which can
+ // (very occasionally) have an element repeated.
+ if(nv == last) {
+ continue;
+ }
+ last = nv;
+#endif
// collect ONLY IF still zero
if(nv->d_rc == 0) {
diff --git a/src/expr/node_manager.h b/src/expr/node_manager.h
index d4d89109c..f4c3a1999 100644
--- a/src/expr/node_manager.h
+++ b/src/expr/node_manager.h
@@ -42,6 +42,7 @@
namespace CVC4 {
class StatisticsRegistry;
+class ResourceManager;
namespace expr {
namespace attr {
@@ -101,6 +102,7 @@ class NodeManager {
Options* d_options;
StatisticsRegistry* d_statisticsRegistry;
+ ResourceManager* d_resourceManager;
NodeValuePool d_nodeValuePool;
@@ -317,6 +319,8 @@ public:
/** The node manager in the current public-facing CVC4 library context */
static NodeManager* currentNM() { return s_current; }
+ /** The resource manager associated with the current node manager */
+ static ResourceManager* currentResourceManager() { return s_current->d_resourceManager; }
/** Get this node manager's options (const version) */
const Options& getOptions() const {
@@ -328,6 +332,9 @@ public:
return *d_options;
}
+ /** Get this node manager's resource manager */
+ ResourceManager* getResourceManager() throw() { return d_resourceManager; }
+
/** Get this node manager's statistics registry */
StatisticsRegistry* getStatisticsRegistry() const throw() {
return d_statisticsRegistry;
diff --git a/src/main/driver_unified.cpp b/src/main/driver_unified.cpp
index f9b222b2b..9035ed8b8 100644
--- a/src/main/driver_unified.cpp
+++ b/src/main/driver_unified.cpp
@@ -187,7 +187,7 @@ int runCvc4(int argc, char* argv[], Options& opts) {
} else {
unsigned len = strlen(filename);
if(len >= 5 && !strcmp(".smt2", filename + len - 5)) {
- opts.set(options::inputLanguage, language::input::LANG_SMTLIB_V2_5);
+ opts.set(options::inputLanguage, language::input::LANG_SMTLIB_V2_0);
} else if(len >= 4 && !strcmp(".smt", filename + len - 4)) {
opts.set(options::inputLanguage, language::input::LANG_SMTLIB_V1);
} else if(len >= 5 && !strcmp(".smt1", filename + len - 5)) {
@@ -298,8 +298,21 @@ int runCvc4(int argc, char* argv[], Options& opts) {
// have the replay parser use the declarations input interactively
replayParser->useDeclarationsFrom(shell.getParser());
}
- while((cmd = shell.readCommand())) {
+
+ while(true) {
+ try {
+ cmd = shell.readCommand();
+ } catch(UnsafeInterruptException& e) {
+ *opts[options::out] << CommandInterrupted();
+ break;
+ }
+ if (cmd == NULL)
+ break;
status = pExecutor->doCommand(cmd) && status;
+ if (cmd->interrupted()) {
+ delete cmd;
+ break;
+ }
delete cmd;
}
} else if(opts[options::tearDownIncremental]) {
@@ -332,15 +345,34 @@ int runCvc4(int argc, char* argv[], Options& opts) {
replayParser->useDeclarationsFrom(parser);
}
bool needReset = false;
- while((status || opts[options::continuedExecution]) && (cmd = parser->nextCommand())) {
+ // true if one of the commands was interrupted
+ bool interrupted = false;
+ while (status || opts[options::continuedExecution]) {
+ if (interrupted) {
+ *opts[options::out] << CommandInterrupted();
+ break;
+ }
+
+ try {
+ cmd = parser->nextCommand();
+ if (cmd == NULL) break;
+ } catch (UnsafeInterruptException& e) {
+ interrupted = true;
+ continue;
+ }
+
if(dynamic_cast<PushCommand*>(cmd) != NULL) {
if(needReset) {
pExecutor->reset();
- for(size_t i = 0; i < allCommands.size(); ++i) {
- for(size_t j = 0; j < allCommands[i].size(); ++j) {
+ for(size_t i = 0; i < allCommands.size() && !interrupted; ++i) {
+ if (interrupted) break;
+ for(size_t j = 0; j < allCommands[i].size() && !interrupted; ++j) {
Command* cmd = allCommands[i][j]->clone();
cmd->setMuted(true);
pExecutor->doCommand(cmd);
+ if(cmd->interrupted()) {
+ interrupted = true;
+ }
delete cmd;
}
}
@@ -351,29 +383,44 @@ int runCvc4(int argc, char* argv[], Options& opts) {
} else if(dynamic_cast<PopCommand*>(cmd) != NULL) {
allCommands.pop_back(); // fixme leaks cmds here
pExecutor->reset();
- for(size_t i = 0; i < allCommands.size(); ++i) {
- for(size_t j = 0; j < allCommands[i].size(); ++j) {
+ for(size_t i = 0; i < allCommands.size() && !interrupted; ++i) {
+ for(size_t j = 0; j < allCommands[i].size() && !interrupted; ++j) {
Command* cmd = allCommands[i][j]->clone();
cmd->setMuted(true);
pExecutor->doCommand(cmd);
+ if(cmd->interrupted()) {
+ interrupted = true;
+ }
delete cmd;
}
}
+ if (interrupted) continue;
*opts[options::out] << CommandSuccess();
} else if(dynamic_cast<CheckSatCommand*>(cmd) != NULL ||
dynamic_cast<QueryCommand*>(cmd) != NULL) {
if(needReset) {
pExecutor->reset();
- for(size_t i = 0; i < allCommands.size(); ++i) {
- for(size_t j = 0; j < allCommands[i].size(); ++j) {
+ for(size_t i = 0; i < allCommands.size() && !interrupted; ++i) {
+ for(size_t j = 0; j < allCommands[i].size() && !interrupted; ++j) {
Command* cmd = allCommands[i][j]->clone();
cmd->setMuted(true);
pExecutor->doCommand(cmd);
+ if(cmd->interrupted()) {
+ interrupted = true;
+ }
delete cmd;
}
}
}
+ if (interrupted) {
+ continue;
+ }
+
status = pExecutor->doCommand(cmd);
+ if(cmd->interrupted()) {
+ interrupted = true;
+ continue;
+ }
needReset = true;
} else if(dynamic_cast<ResetCommand*>(cmd) != NULL) {
pExecutor->doCommand(cmd);
@@ -396,6 +443,11 @@ int runCvc4(int argc, char* argv[], Options& opts) {
allCommands.back().push_back(copy);
}
status = pExecutor->doCommand(cmd);
+ if(cmd->interrupted()) {
+ interrupted = true;
+ continue;
+ }
+
if(dynamic_cast<QuitCommand*>(cmd) != NULL) {
delete cmd;
break;
@@ -428,8 +480,27 @@ int runCvc4(int argc, char* argv[], Options& opts) {
// have the replay parser use the file's declarations
replayParser->useDeclarationsFrom(parser);
}
- while((status || opts[options::continuedExecution]) && (cmd = parser->nextCommand())) {
+ bool interrupted = false;
+ while(status || opts[options::continuedExecution]) {
+ if (interrupted) {
+ *opts[options::out] << CommandInterrupted();
+ pExecutor->reset();
+ break;
+ }
+ try {
+ cmd = parser->nextCommand();
+ if (cmd == NULL) break;
+ } catch (UnsafeInterruptException& e) {
+ interrupted = true;
+ continue;
+ }
+
status = pExecutor->doCommand(cmd);
+ if (cmd->interrupted() && status == 0) {
+ interrupted = true;
+ break;
+ }
+
if(dynamic_cast<QuitCommand*>(cmd) != NULL) {
delete cmd;
break;
diff --git a/src/main/interactive_shell.cpp b/src/main/interactive_shell.cpp
index 0aee195e4..3b237f6a4 100644
--- a/src/main/interactive_shell.cpp
+++ b/src/main/interactive_shell.cpp
@@ -172,7 +172,7 @@ InteractiveShell::~InteractiveShell() {
#endif /* HAVE_LIBREADLINE */
}
-Command* InteractiveShell::readCommand() {
+Command* InteractiveShell::readCommand() throw (UnsafeInterruptException) {
char* lineBuf = NULL;
string line = "";
diff --git a/src/main/interactive_shell.h b/src/main/interactive_shell.h
index 43054f980..ef55919a1 100644
--- a/src/main/interactive_shell.h
+++ b/src/main/interactive_shell.h
@@ -19,6 +19,7 @@
#include <string>
#include "util/language.h"
+#include "util/unsafe_interrupt_exception.h"
#include "options/options.h"
namespace CVC4 {
@@ -56,7 +57,7 @@ public:
* Read a command from the interactive shell. This will read as
* many lines as necessary to parse a well-formed command.
*/
- Command* readCommand();
+ Command* readCommand() throw (UnsafeInterruptException);
/**
* Return the internal parser being used.
diff --git a/src/options/options_template.cpp b/src/options/options_template.cpp
index f6c6846e5..6d3a4cb00 100644
--- a/src/options/options_template.cpp
+++ b/src/options/options_template.cpp
@@ -238,18 +238,18 @@ options::OptionsHolder::OptionsHolder() : ${all_modules_defaults}
{
}
-#line 234 "${template}"
+#line 241 "${template}"
static const std::string mostCommonOptionsDescription = "\
Most commonly-used CVC4 options:${common_documentation}";
-#line 239 "${template}"
+#line 246 "${template}"
static const std::string optionsDescription = mostCommonOptionsDescription + "\n\
\n\
Additional CVC4 options:${remaining_documentation}";
-#line 245 "${template}"
+#line 252 "${template}"
static const std::string optionsFootnote = "\n\
[*] Each of these options has a --no-OPTIONNAME variant, which reverses the\n\
@@ -326,7 +326,7 @@ static struct option cmdlineOptions[] = {${all_modules_long_options}
{ NULL, no_argument, NULL, '\0' }
};/* cmdlineOptions */
-#line 322 "${template}"
+#line 329 "${template}"
static void preemptGetopt(int& argc, char**& argv, const char* opt) {
const size_t maxoptlen = 128;
@@ -519,7 +519,7 @@ std::vector<std::string> Options::parseOptions(int argc, char* main_argv[]) thro
switch(c) {
${all_modules_option_handlers}
-#line 515 "${template}"
+#line 522 "${template}"
case ':':
// This can be a long or short option, and the way to get at the
@@ -588,7 +588,7 @@ std::string Options::suggestCommandLineOptions(const std::string& optionName) th
static const char* smtOptions[] = {
${all_modules_smt_options},
-#line 584 "${template}"
+#line 591 "${template}"
NULL
};/* smtOptions[] */
@@ -610,7 +610,7 @@ SExpr Options::getOptions() const throw() {
${all_modules_get_options}
-#line 606 "${template}"
+#line 613 "${template}"
return SExpr(opts);
}
diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp
index 045cd4ae1..dc44ed5ba 100644
--- a/src/parser/parser.cpp
+++ b/src/parser/parser.cpp
@@ -26,9 +26,12 @@
#include "parser/parser_exception.h"
#include "expr/command.h"
#include "expr/expr.h"
+#include "expr/node.h"
#include "expr/kind.h"
#include "expr/type.h"
#include "util/output.h"
+#include "util/resource_manager.h"
+#include "options/options.h"
using namespace std;
using namespace CVC4::kind;
@@ -38,6 +41,7 @@ namespace parser {
Parser::Parser(ExprManager* exprManager, Input* input, bool strictMode, bool parseOnly) :
d_exprManager(exprManager),
+ d_resourceManager(d_exprManager->getResourceManager()),
d_input(input),
d_symtabAllocated(),
d_symtab(&d_symtabAllocated),
@@ -460,7 +464,7 @@ void Parser::preemptCommand(Command* cmd) {
d_commandQueue.push_back(cmd);
}
-Command* Parser::nextCommand() throw(ParserException) {
+Command* Parser::nextCommand() throw(ParserException, UnsafeInterruptException) {
Debug("parser") << "nextCommand()" << std::endl;
Command* cmd = NULL;
if(!d_commandQueue.empty()) {
@@ -483,11 +487,19 @@ Command* Parser::nextCommand() throw(ParserException) {
}
}
Debug("parser") << "nextCommand() => " << cmd << std::endl;
+ if (cmd != NULL &&
+ dynamic_cast<SetOptionCommand*>(cmd) == NULL &&
+ dynamic_cast<QuitCommand*>(cmd) == NULL) {
+ // don't count set-option commands as to not get stuck in an infinite
+ // loop of resourcing out
+ d_resourceManager->spendResource();
+ }
return cmd;
}
-Expr Parser::nextExpression() throw(ParserException) {
+Expr Parser::nextExpression() throw(ParserException, UnsafeInterruptException) {
Debug("parser") << "nextExpression()" << std::endl;
+ d_resourceManager->spendResource();
Expr result;
if(!done()) {
try {
diff --git a/src/parser/parser.h b/src/parser/parser.h
index ffe33a980..53241709d 100644
--- a/src/parser/parser.h
+++ b/src/parser/parser.h
@@ -30,6 +30,7 @@
#include "expr/symbol_table.h"
#include "expr/kind.h"
#include "expr/expr_stream.h"
+#include "util/unsafe_interrupt_exception.h"
namespace CVC4 {
@@ -39,6 +40,7 @@ class ExprManager;
class Command;
class FunctionType;
class Type;
+class ResourceManager;
namespace parser {
@@ -108,6 +110,8 @@ class CVC4_PUBLIC Parser {
/** The expression manager */
ExprManager *d_exprManager;
+ /** The resource manager associated with this expr manager */
+ ResourceManager *d_resourceManager;
/** The input that we're parsing. */
Input *d_input;
@@ -504,10 +508,10 @@ public:
bool isPredicate(const std::string& name);
/** Parse and return the next command. */
- Command* nextCommand() throw(ParserException);
+ Command* nextCommand() throw(ParserException, UnsafeInterruptException);
/** Parse and return the next expression. */
- Expr nextExpression() throw(ParserException);
+ Expr nextExpression() throw(ParserException, UnsafeInterruptException);
/** Issue a warning to the user. */
inline void warning(const std::string& msg) {
diff --git a/src/parser/smt2/Smt2.g b/src/parser/smt2/Smt2.g
index 0a3773d08..511b67997 100644
--- a/src/parser/smt2/Smt2.g
+++ b/src/parser/smt2/Smt2.g
@@ -1298,21 +1298,49 @@ attribute[CVC4::Expr& expr,CVC4::Expr& retExpr, std::string& attr]
PARSER_STATE->warning(ss.str());
}
// do nothing
- } else if(attr==":axiom" || attr==":conjecture" || attr==":sygus" || attr==":synthesis") {
+ } else if(attr==":axiom" || attr==":conjecture" || attr==":fun-def" || attr==":sygus" || attr==":synthesis") {
if(hasValue) {
std::stringstream ss;
ss << "warning: Attribute " << attr << " does not take a value (ignoring)";
PARSER_STATE->warning(ss.str());
}
- std::string attr_name = attr;
- attr_name.erase( attr_name.begin() );
- //will set the attribute on auxiliary var (preserves attribute on formula through rewriting)
- Type t = EXPR_MANAGER->booleanType();
- Expr avar = PARSER_STATE->mkVar(attr_name, t);
- retExpr = MK_EXPR(kind::INST_ATTRIBUTE, avar);
- Command* c = new SetUserAttributeCommand( attr_name, avar );
- c->setMuted(true);
- PARSER_STATE->preemptCommand(c);
+ bool success = true;
+ if( attr==":fun-def" ){
+ if( ( expr.getKind()!=kind::EQUAL && expr.getKind()!=kind::IFF ) || expr[0].getKind()!=kind::APPLY_UF ){
+ success = false;
+ }else{
+ FunctionType t = (FunctionType)expr[0].getOperator().getType();
+ for( unsigned i=0; i<expr[0].getNumChildren(); i++ ){
+ if( expr[0][i].getKind()!=kind::BOUND_VARIABLE || expr[0][i].getType()!=t.getArgTypes()[i] ){
+ success = false;
+ break;
+ }else{
+ for( unsigned j=0; j<i; j++ ){
+ if( expr[0][j]==expr[0][i] ){
+ success = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if( !success ){
+ std::stringstream ss;
+ ss << "warning: Function definition should be an equality whose LHS is an uninterpreted function applied to unique variables.";
+ PARSER_STATE->warning(ss.str());
+ }
+ }
+ if( success ){
+ std::string attr_name = attr;
+ attr_name.erase( attr_name.begin() );
+ //will set the attribute on auxiliary var (preserves attribute on formula through rewriting)
+ Type t = EXPR_MANAGER->booleanType();
+ Expr avar = PARSER_STATE->mkVar(attr_name, t);
+ retExpr = MK_EXPR(kind::INST_ATTRIBUTE, avar);
+ Command* c = new SetUserAttributeCommand( attr_name, avar );
+ c->setMuted(true);
+ PARSER_STATE->preemptCommand(c);
+ }
} else {
PARSER_STATE->attributeNotSupported(attr);
}
@@ -1592,6 +1620,8 @@ builtinOp[CVC4::Kind& kind]
| DTSIZE_TOK { $kind = CVC4::kind::DT_SIZE; }
| FMFCARD_TOK { $kind = CVC4::kind::CARDINALITY_CONSTRAINT; }
+
+ | INST_CLOSURE_TOK { $kind = CVC4::kind::INST_CLOSURE; }
// NOTE: Theory operators go here
;
@@ -1856,7 +1886,7 @@ GET_ASSERTIONS_TOK : 'get-assertions';
GET_PROOF_TOK : 'get-proof';
GET_UNSAT_CORE_TOK : 'get-unsat-core';
EXIT_TOK : 'exit';
-RESET_TOK : 'reset';
+RESET_TOK : { PARSER_STATE->v2_5() }? 'reset';
RESET_ASSERTIONS_TOK : 'reset-assertions';
ITE_TOK : 'ite';
LET_TOK : 'let';
@@ -1998,6 +2028,8 @@ DTSIZE_TOK : 'dt.size';
FMFCARD_TOK : 'fmf.card';
+INST_CLOSURE_TOK : 'inst-closure';
+
EMPTYSET_TOK: { PARSER_STATE->isTheoryEnabled(Smt2::THEORY_SETS) }? 'emptyset';
// Other set theory operators are not
// tokenized and handled directly when
diff --git a/src/printer/ast/ast_printer.cpp b/src/printer/ast/ast_printer.cpp
index 94ca46257..c24ed8372 100644
--- a/src/printer/ast/ast_printer.cpp
+++ b/src/printer/ast/ast_printer.cpp
@@ -179,7 +179,8 @@ void AstPrinter::toStream(std::ostream& out, const CommandStatus* s) const throw
if(tryToStream<CommandSuccess>(out, s) ||
tryToStream<CommandFailure>(out, s) ||
- tryToStream<CommandUnsupported>(out, s)) {
+ tryToStream<CommandUnsupported>(out, s) ||
+ tryToStream<CommandInterrupted>(out, s)) {
return;
}
@@ -373,6 +374,10 @@ static void toStream(std::ostream& out, const CommandSuccess* s) throw() {
}
}
+static void toStream(std::ostream& out, const CommandInterrupted* s) throw() {
+ out << "INTERRUPTED" << endl;
+}
+
static void toStream(std::ostream& out, const CommandUnsupported* s) throw() {
out << "UNSUPPORTED" << endl;
}
diff --git a/src/printer/cvc/cvc_printer.cpp b/src/printer/cvc/cvc_printer.cpp
index f8df9d906..2e1170666 100644
--- a/src/printer/cvc/cvc_printer.cpp
+++ b/src/printer/cvc/cvc_printer.cpp
@@ -905,7 +905,8 @@ void CvcPrinter::toStream(std::ostream& out, const CommandStatus* s) const throw
if(tryToStream<CommandSuccess>(out, s, d_cvc3Mode) ||
tryToStream<CommandFailure>(out, s, d_cvc3Mode) ||
- tryToStream<CommandUnsupported>(out, s, d_cvc3Mode)) {
+ tryToStream<CommandUnsupported>(out, s, d_cvc3Mode) ||
+ tryToStream<CommandInterrupted>(out, s, d_cvc3Mode)) {
return;
}
@@ -1267,6 +1268,10 @@ static void toStream(std::ostream& out, const CommandUnsupported* s, bool cvc3Mo
out << "UNSUPPORTED" << endl;
}
+static void toStream(std::ostream& out, const CommandInterrupted* s, bool cvc3Mode) throw() {
+ out << "INTERRUPTED" << endl;
+}
+
static void toStream(std::ostream& out, const CommandFailure* s, bool cvc3Mode) throw() {
out << s->getMessage() << endl;
}
diff --git a/src/printer/smt2/smt2_printer.cpp b/src/printer/smt2/smt2_printer.cpp
index 88bcce5ae..4f12ed012 100644
--- a/src/printer/smt2/smt2_printer.cpp
+++ b/src/printer/smt2/smt2_printer.cpp
@@ -794,7 +794,8 @@ void Smt2Printer::toStream(std::ostream& out, const CommandStatus* s) const thro
if(tryToStream<CommandSuccess>(out, s, d_variant) ||
tryToStream<CommandFailure>(out, s, d_variant) ||
- tryToStream<CommandUnsupported>(out, s, d_variant)) {
+ tryToStream<CommandUnsupported>(out, s, d_variant) ||
+ tryToStream<CommandInterrupted>(out, s, d_variant)) {
return;
}
@@ -1208,6 +1209,10 @@ static void toStream(std::ostream& out, const CommandSuccess* s, Variant v) thro
}
}
+static void toStream(std::ostream& out, const CommandInterrupted* s, Variant v) throw() {
+ out << "interrupted" << endl;
+}
+
static void toStream(std::ostream& out, const CommandUnsupported* s, Variant v) throw() {
#ifdef CVC4_COMPETITION_MODE
// if in competition mode, lie and say we're ok
diff --git a/src/prop/bvminisat/bvminisat.cpp b/src/prop/bvminisat/bvminisat.cpp
index 71b8eb69d..ab157844a 100644
--- a/src/prop/bvminisat/bvminisat.cpp
+++ b/src/prop/bvminisat/bvminisat.cpp
@@ -97,10 +97,6 @@ void BVMinisatSatSolver::markUnremovable(SatLiteral lit){
d_minisat->setFrozen(BVMinisat::var(toMinisatLit(lit)), true);
}
-bool BVMinisatSatSolver::spendResource(){
- // Do nothing for the BV solver.
- return false;
-}
void BVMinisatSatSolver::interrupt(){
d_minisat->interrupt();
@@ -186,11 +182,6 @@ SatLiteral BVMinisatSatSolver::toSatLiteral(BVMinisat::Lit lit) {
BVMinisat::sign(lit));
}
-SatValue BVMinisatSatSolver::toSatLiteralValue(bool res) {
- if(res) return SAT_VALUE_TRUE;
- else return SAT_VALUE_FALSE;
-}
-
SatValue BVMinisatSatSolver::toSatLiteralValue(BVMinisat::lbool res) {
if(res == (BVMinisat::lbool((uint8_t)0))) return SAT_VALUE_TRUE;
if(res == (BVMinisat::lbool((uint8_t)2))) return SAT_VALUE_UNKNOWN;
diff --git a/src/prop/bvminisat/bvminisat.h b/src/prop/bvminisat/bvminisat.h
index c7ee2e0b7..6246e6885 100644
--- a/src/prop/bvminisat/bvminisat.h
+++ b/src/prop/bvminisat/bvminisat.h
@@ -21,7 +21,6 @@
#pragma once
#include "prop/sat_solver.h"
-#include "prop/sat_solver_registry.h"
#include "prop/bvminisat/simp/SimpSolver.h"
#include "context/cdo.h"
@@ -47,8 +46,11 @@ private:
d_notify->notify(satClause);
}
+ void spendResource() {
+ d_notify->spendResource();
+ }
void safePoint() {
- d_notify->safePoint();
+ d_notify->safePoint();
}
};
@@ -87,8 +89,6 @@ public:
void markUnremovable(SatLiteral lit);
- bool spendResource();
-
void interrupt();
SatValue solve();
@@ -108,7 +108,6 @@ public:
static SatVariable toSatVariable(BVMinisat::Var var);
static BVMinisat::Lit toMinisatLit(SatLiteral lit);
static SatLiteral toSatLiteral(BVMinisat::Lit lit);
- static SatValue toSatLiteralValue(bool res);
static SatValue toSatLiteralValue(BVMinisat::lbool res);
static void toMinisatClause(SatClause& clause, BVMinisat::vec<BVMinisat::Lit>& minisat_clause);
diff --git a/src/prop/bvminisat/core/Solver.h b/src/prop/bvminisat/core/Solver.h
index 882f23ef7..3fcf34185 100644
--- a/src/prop/bvminisat/core/Solver.h
+++ b/src/prop/bvminisat/core/Solver.h
@@ -52,6 +52,7 @@ public:
*/
virtual void notify(vec<Lit>& learnt) = 0;
+ virtual void spendResource() = 0;
virtual void safePoint() = 0;
};
@@ -98,12 +99,12 @@ public:
// Solving:
//
bool simplify (); // Removes already satisfied clauses.
- bool solve (const vec<Lit>& assumps); // Search for a model that respects a given set of assumptions.
+ lbool solve (const vec<Lit>& assumps); // Search for a model that respects a given set of assumptions.
lbool solveLimited (const vec<Lit>& assumps); // Search for a model that respects a given set of assumptions (With resource constraints).
- bool solve (); // Search without assumptions.
- bool solve (Lit p); // Search for a model that respects a single assumption.
- bool solve (Lit p, Lit q); // Search for a model that respects two assumptions.
- bool solve (Lit p, Lit q, Lit r); // Search for a model that respects three assumptions.
+ lbool solve (); // Search without assumptions.
+ lbool solve (Lit p); // Search for a model that respects a single assumption.
+ lbool solve (Lit p, Lit q); // Search for a model that respects two assumptions.
+ lbool solve (Lit p, Lit q, Lit r); // Search for a model that respects three assumptions.
bool okay () const; // FALSE means solver is in a conflicting state
lbool assertAssumption(Lit p, bool propagate); // Assert a new assumption, start BCP if propagate = true
lbool propagateAssumptions(); // Do BCP over asserted assumptions
@@ -412,20 +413,19 @@ inline void Solver::interrupt(){ asynch_interrupt = true; }
inline void Solver::clearInterrupt(){ asynch_interrupt = false; }
inline void Solver::budgetOff(){ conflict_budget = propagation_budget = -1; }
inline bool Solver::withinBudget() const {
- Assert (notify);
- notify->safePoint();
+ Assert (notify);
+ notify->spendResource();
+ notify->safePoint();
+
return !asynch_interrupt &&
(conflict_budget < 0 || conflicts < (uint64_t)conflict_budget) &&
(propagation_budget < 0 || propagations < (uint64_t)propagation_budget); }
-// FIXME: after the introduction of asynchronous interrruptions the solve-versions that return a
-// pure bool do not give a safe interface. Either interrupts must be possible to turn off here, or
-// all calls to solve must return an 'lbool'. I'm not yet sure which I prefer.
-inline bool Solver::solve () { budgetOff(); return solve_() == l_True; }
-inline bool Solver::solve (Lit p) { budgetOff(); assumptions.push(p); return solve_() == l_True; }
-inline bool Solver::solve (Lit p, Lit q) { budgetOff(); assumptions.push(p); assumptions.push(q); return solve_() == l_True; }
-inline bool Solver::solve (Lit p, Lit q, Lit r) { budgetOff(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_() == l_True; }
-inline bool Solver::solve (const vec<Lit>& assumps){ budgetOff(); assumps.copyTo(assumptions); return solve_() == l_True; }
+inline lbool Solver::solve () { budgetOff(); return solve_(); }
+inline lbool Solver::solve (Lit p) { budgetOff(); assumptions.push(p); return solve_(); }
+inline lbool Solver::solve (Lit p, Lit q) { budgetOff(); assumptions.push(p); assumptions.push(q); return solve_(); }
+inline lbool Solver::solve (Lit p, Lit q, Lit r) { budgetOff(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_(); }
+inline lbool Solver::solve (const vec<Lit>& assumps){ budgetOff(); assumps.copyTo(assumptions); return solve_(); }
inline lbool Solver::solveLimited (const vec<Lit>& assumps){ assumps.copyTo(assumptions); return solve_(); }
inline bool Solver::okay () const { return ok; }
diff --git a/src/prop/bvminisat/simp/SimpSolver.h b/src/prop/bvminisat/simp/SimpSolver.h
index d808daa22..4ff17d3ab 100644
--- a/src/prop/bvminisat/simp/SimpSolver.h
+++ b/src/prop/bvminisat/simp/SimpSolver.h
@@ -56,13 +56,13 @@ class SimpSolver : public Solver {
// Solving:
//
- bool solve (const vec<Lit>& assumps, bool do_simp = true, bool turn_off_simp = false);
- lbool solveLimited(const vec<Lit>& assumps, bool do_simp = true, bool turn_off_simp = false);
- lbool solveLimited(bool do_simp = true, bool turn_off_simp = false);
- bool solve ( bool do_simp = true, bool turn_off_simp = false);
- bool solve (Lit p , bool do_simp = true, bool turn_off_simp = false);
- bool solve (Lit p, Lit q, bool do_simp = true, bool turn_off_simp = false);
- bool solve (Lit p, Lit q, Lit r, bool do_simp = true, bool turn_off_simp = false);
+ lbool solve (const vec<Lit>& assumps, bool do_simp = true, bool turn_off_simp = false);
+ lbool solveLimited(const vec<Lit>& assumps, bool do_simp = true, bool turn_off_simp = false);
+ lbool solveLimited(bool do_simp = true, bool turn_off_simp = false);
+ lbool solve ( bool do_simp = true, bool turn_off_simp = false);
+ lbool solve (Lit p , bool do_simp = true, bool turn_off_simp = false);
+ lbool solve (Lit p, Lit q, bool do_simp = true, bool turn_off_simp = false);
+ lbool solve (Lit p, Lit q, Lit r, bool do_simp = true, bool turn_off_simp = false);
bool eliminate (bool turn_off_elim = false); // Perform variable elimination based simplification.
// Memory managment:
@@ -184,13 +184,31 @@ inline bool SimpSolver::addClause (Lit p, Lit q) { add_tmp.clear();
inline bool SimpSolver::addClause (Lit p, Lit q, Lit r) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); }
inline void SimpSolver::setFrozen (Var v, bool b) { frozen[v] = (char)b; if (use_simplification && !b) { updateElimHeap(v); } }
-inline bool SimpSolver::solve ( bool do_simp, bool turn_off_simp) { budgetOff(); return solve_(do_simp, turn_off_simp) == l_True; }
-inline bool SimpSolver::solve (Lit p , bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.push(p); return solve_(do_simp, turn_off_simp) == l_True; }
-inline bool SimpSolver::solve (Lit p, Lit q, bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.push(p); assumptions.push(q); return solve_(do_simp, turn_off_simp) == l_True; }
-inline bool SimpSolver::solve (Lit p, Lit q, Lit r, bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_(do_simp, turn_off_simp) == l_True; }
-inline bool SimpSolver::solve (const vec<Lit>& assumps, bool do_simp, bool turn_off_simp){
+inline lbool SimpSolver::solve ( bool do_simp, bool turn_off_simp) {
+ budgetOff();
+ return solve_(do_simp, turn_off_simp);
+ }
+inline lbool SimpSolver::solve (Lit p , bool do_simp, bool turn_off_simp) {
+ budgetOff();
+ assumptions.push(p);
+ return solve_(do_simp, turn_off_simp);
+ }
+inline lbool SimpSolver::solve (Lit p, Lit q, bool do_simp, bool turn_off_simp) {
+ budgetOff();
+ assumptions.push(p);
+ assumptions.push(q);
+ return solve_(do_simp, turn_off_simp);
+ }
+inline lbool SimpSolver::solve (Lit p, Lit q, Lit r, bool do_simp, bool turn_off_simp) {
+ budgetOff();
+ assumptions.push(p);
+ assumptions.push(q);
+ assumptions.push(r);
+ return solve_(do_simp, turn_off_simp);
+ }
+inline lbool SimpSolver::solve (const vec<Lit>& assumps, bool do_simp, bool turn_off_simp){
budgetOff(); assumps.copyTo(assumptions);
- return solve_(do_simp, turn_off_simp) == l_True;
+ return solve_(do_simp, turn_off_simp);
}
inline lbool SimpSolver::solveLimited (const vec<Lit>& assumps, bool do_simp, bool turn_off_simp){
diff --git a/src/prop/cnf_stream.cpp b/src/prop/cnf_stream.cpp
index ad187aa46..8d7b014cc 100644
--- a/src/prop/cnf_stream.cpp
+++ b/src/prop/cnf_stream.cpp
@@ -30,6 +30,7 @@
#include "proof/proof_manager.h"
#include "proof/sat_proof.h"
#include "prop/minisat/minisat.h"
+#include "smt/smt_engine_scope.h"
#include <queue>
using namespace std;
@@ -665,6 +666,12 @@ void TseitinCnfStream::convertAndAssert(TNode node, bool removable, bool negated
void TseitinCnfStream::convertAndAssert(TNode node, bool negated) {
Debug("cnf") << "convertAndAssert(" << node << ", negated = " << (negated ? "true" : "false") << ")" << endl;
+ if (d_convertAndAssertCounter % ResourceManager::getFrequencyCount() == 0) {
+ NodeManager::currentResourceManager()->spendResource();
+ d_convertAndAssertCounter = 0;
+ }
+ ++d_convertAndAssertCounter;
+
switch(node.getKind()) {
case AND:
convertAndAssertAnd(node, negated);
diff --git a/src/prop/cnf_stream.h b/src/prop/cnf_stream.h
index b76051279..b22290ae4 100644
--- a/src/prop/cnf_stream.h
+++ b/src/prop/cnf_stream.h
@@ -74,6 +74,12 @@ protected:
*/
const bool d_fullLitToNodeMap;
+ /**
+ * Counter for resource limiting that is used to spend a resource
+ * every ResourceManager::resourceCounter calls to convertAndAssert.
+ */
+ unsigned long d_convertAndAssertCounter;
+
/** The "registrar" for pre-registration of terms */
Registrar* d_registrar;
diff --git a/src/prop/minisat/core/Solver.cc b/src/prop/minisat/core/Solver.cc
index e5e28bb0b..ea370ac08 100644
--- a/src/prop/minisat/core/Solver.cc
+++ b/src/prop/minisat/core/Solver.cc
@@ -1593,7 +1593,7 @@ CRef Solver::updateLemmas() {
Debug("minisat::lemmas") << "Solver::updateLemmas() begin" << std::endl;
// Avoid adding lemmas indefinitely without resource-out
- spendResource();
+ proxy->spendResource();
CRef conflict = CRef_Undef;
@@ -1710,3 +1710,15 @@ CRef Solver::updateLemmas() {
return conflict;
}
+
+inline bool Solver::withinBudget() const {
+ Assert (proxy);
+ // spendResource sets async_interrupt or throws UnsafeInterruptException
+ // depending on whether hard-limit is enabled
+ proxy->spendResource();
+
+ bool within_budget = !asynch_interrupt &&
+ (conflict_budget < 0 || conflicts < (uint64_t)conflict_budget) &&
+ (propagation_budget < 0 || propagations < (uint64_t)propagation_budget);
+ return within_budget;
+}
diff --git a/src/prop/minisat/core/Solver.h b/src/prop/minisat/core/Solver.h
index 6d9fd538f..ecebb086d 100644
--- a/src/prop/minisat/core/Solver.h
+++ b/src/prop/minisat/core/Solver.h
@@ -169,12 +169,12 @@ public:
// Solving:
//
bool simplify (); // Removes already satisfied clauses.
- bool solve (const vec<Lit>& assumps); // Search for a model that respects a given set of assumptions.
+ lbool solve (const vec<Lit>& assumps); // Search for a model that respects a given set of assumptions.
lbool solveLimited (const vec<Lit>& assumps); // Search for a model that respects a given set of assumptions (With resource constraints).
- bool solve (); // Search without assumptions.
- bool solve (Lit p); // Search for a model that respects a single assumption.
- bool solve (Lit p, Lit q); // Search for a model that respects two assumptions.
- bool solve (Lit p, Lit q, Lit r); // Search for a model that respects three assumptions.
+ lbool solve (); // Search without assumptions.
+ lbool solve (Lit p); // Search for a model that respects a single assumption.
+ lbool solve (Lit p, Lit q); // Search for a model that respects two assumptions.
+ lbool solve (Lit p, Lit q, Lit r); // Search for a model that respects three assumptions.
bool okay () const; // FALSE means solver is in a conflicting state
void toDimacs ();
@@ -219,7 +219,6 @@ public:
void budgetOff();
void interrupt(); // Trigger a (potentially asynchronous) interruption of the solver.
void clearInterrupt(); // Clear interrupt indicator flag.
- void spendResource();
// Memory managment:
//
@@ -535,20 +534,12 @@ inline void Solver::setPropBudget(int64_t x){ propagation_budget = propagati
inline void Solver::interrupt(){ asynch_interrupt = true; }
inline void Solver::clearInterrupt(){ asynch_interrupt = false; }
inline void Solver::budgetOff(){ conflict_budget = propagation_budget = -1; }
-inline bool Solver::withinBudget() const {
- return !asynch_interrupt &&
- (conflict_budget < 0 || conflicts + resources_consumed < (uint64_t)conflict_budget) &&
- (propagation_budget < 0 || propagations < (uint64_t)propagation_budget); }
-inline void Solver::spendResource() { ++resources_consumed; }
-
-// FIXME: after the introduction of asynchronous interrruptions the solve-versions that return a
-// pure bool do not give a safe interface. Either interrupts must be possible to turn off here, or
-// all calls to solve must return an 'lbool'. I'm not yet sure which I prefer.
-inline bool Solver::solve () { budgetOff(); assumptions.clear(); return solve_() == l_True; }
-inline bool Solver::solve (Lit p) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_() == l_True; }
-inline bool Solver::solve (Lit p, Lit q) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_() == l_True; }
-inline bool Solver::solve (Lit p, Lit q, Lit r) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_() == l_True; }
-inline bool Solver::solve (const vec<Lit>& assumps){ budgetOff(); assumps.copyTo(assumptions); return solve_() == l_True; }
+
+inline lbool Solver::solve () { budgetOff(); assumptions.clear(); return solve_(); }
+inline lbool Solver::solve (Lit p) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_(); }
+inline lbool Solver::solve (Lit p, Lit q) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_(); }
+inline lbool Solver::solve (Lit p, Lit q, Lit r) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_(); }
+inline lbool Solver::solve (const vec<Lit>& assumps){ budgetOff(); assumps.copyTo(assumptions); return solve_(); }
inline lbool Solver::solveLimited (const vec<Lit>& assumps){ assumps.copyTo(assumptions); return solve_(); }
inline bool Solver::okay () const { return ok; }
diff --git a/src/prop/minisat/minisat.cpp b/src/prop/minisat/minisat.cpp
index 99341455c..b896b03fb 100644
--- a/src/prop/minisat/minisat.cpp
+++ b/src/prop/minisat/minisat.cpp
@@ -59,11 +59,6 @@ SatLiteral MinisatSatSolver::toSatLiteral(Minisat::Lit lit) {
Minisat::sign(lit));
}
-SatValue MinisatSatSolver::toSatLiteralValue(bool res) {
- if(res) return SAT_VALUE_TRUE;
- else return SAT_VALUE_FALSE;
-}
-
SatValue MinisatSatSolver::toSatLiteralValue(Minisat::lbool res) {
if(res == (Minisat::lbool((uint8_t)0))) return SAT_VALUE_TRUE;
if(res == (Minisat::lbool((uint8_t)2))) return SAT_VALUE_UNKNOWN;
@@ -182,10 +177,6 @@ SatValue MinisatSatSolver::solve() {
return toSatLiteralValue(d_minisat->solve());
}
-bool MinisatSatSolver::spendResource() {
- d_minisat->spendResource();
- return !d_minisat->withinBudget();
-}
void MinisatSatSolver::interrupt() {
d_minisat->interrupt();
diff --git a/src/prop/minisat/minisat.h b/src/prop/minisat/minisat.h
index 3d3cea356..a355702bc 100644
--- a/src/prop/minisat/minisat.h
+++ b/src/prop/minisat/minisat.h
@@ -19,7 +19,6 @@
#pragma once
#include "prop/sat_solver.h"
-#include "prop/sat_solver_registry.h"
#include "prop/minisat/simp/SimpSolver.h"
namespace CVC4 {
@@ -43,7 +42,6 @@ public:
static SatVariable toSatVariable(Minisat::Var var);
static Minisat::Lit toMinisatLit(SatLiteral lit);
static SatLiteral toSatLiteral(Minisat::Lit lit);
- static SatValue toSatLiteralValue(bool res);
static SatValue toSatLiteralValue(Minisat::lbool res);
static Minisat::lbool toMinisatlbool(SatValue val);
//(Commented because not in use) static bool tobool(SatValue val);
@@ -62,7 +60,6 @@ public:
SatValue solve();
SatValue solve(long unsigned int&);
- bool spendResource();
void interrupt();
SatValue value(SatLiteral l);
diff --git a/src/prop/minisat/simp/SimpSolver.h b/src/prop/minisat/simp/SimpSolver.h
index 041309546..e1dfeb95e 100644
--- a/src/prop/minisat/simp/SimpSolver.h
+++ b/src/prop/minisat/simp/SimpSolver.h
@@ -62,12 +62,12 @@ class SimpSolver : public Solver {
// Solving:
//
- bool solve (const vec<Lit>& assumps, bool do_simp = true, bool turn_off_simp = false);
- lbool solveLimited(const vec<Lit>& assumps, bool do_simp = true, bool turn_off_simp = false);
- bool solve ( bool do_simp = true, bool turn_off_simp = false);
- bool solve (Lit p , bool do_simp = true, bool turn_off_simp = false);
- bool solve (Lit p, Lit q, bool do_simp = true, bool turn_off_simp = false);
- bool solve (Lit p, Lit q, Lit r, bool do_simp = true, bool turn_off_simp = false);
+ lbool solve (const vec<Lit>& assumps, bool do_simp = true, bool turn_off_simp = false);
+ lbool solveLimited(const vec<Lit>& assumps, bool do_simp = true, bool turn_off_simp = false);
+ lbool solve ( bool do_simp = true, bool turn_off_simp = false);
+ lbool solve (Lit p , bool do_simp = true, bool turn_off_simp = false);
+ lbool solve (Lit p, Lit q, bool do_simp = true, bool turn_off_simp = false);
+ lbool solve (Lit p, Lit q, Lit r, bool do_simp = true, bool turn_off_simp = false);
bool eliminate (bool turn_off_elim = false); // Perform variable elimination based simplification.
// Memory managment:
@@ -193,12 +193,42 @@ inline bool SimpSolver::addClause (Lit p, Lit q, Lit r, bool removable, uint6
{ add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp, removable, proof_id); }
inline void SimpSolver::setFrozen (Var v, bool b) { frozen[v] = (char)b; if (use_simplification && !b) { updateElimHeap(v); } }
-inline bool SimpSolver::solve ( bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); return solve_(do_simp, turn_off_simp) == l_True; }
-inline bool SimpSolver::solve (Lit p , bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_(do_simp, turn_off_simp) == l_True; }
-inline bool SimpSolver::solve (Lit p, Lit q, bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_(do_simp, turn_off_simp) == l_True; }
-inline bool SimpSolver::solve (Lit p, Lit q, Lit r, bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_(do_simp, turn_off_simp) == l_True; }
-inline bool SimpSolver::solve (const vec<Lit>& assumps, bool do_simp, bool turn_off_simp){
- budgetOff(); assumps.copyTo(assumptions); return solve_(do_simp, turn_off_simp) == l_True; }
+// the solver can always return unknown due to resource limiting
+inline lbool SimpSolver::solve ( bool do_simp, bool turn_off_simp) {
+ budgetOff();
+ assumptions.clear();
+ return solve_(do_simp, turn_off_simp);
+ }
+
+inline lbool SimpSolver::solve (Lit p , bool do_simp, bool turn_off_simp) {
+ budgetOff();
+ assumptions.clear();
+ assumptions.push(p);
+ return solve_(do_simp, turn_off_simp);
+ }
+
+inline lbool SimpSolver::solve (Lit p, Lit q, bool do_simp, bool turn_off_simp) {
+ budgetOff();
+ assumptions.clear();
+ assumptions.push(p);
+ assumptions.push(q);
+ return solve_(do_simp, turn_off_simp);
+ }
+
+inline lbool SimpSolver::solve (Lit p, Lit q, Lit r, bool do_simp, bool turn_off_simp) {
+ budgetOff();
+ assumptions.clear();
+ assumptions.push(p);
+ assumptions.push(q);
+ assumptions.push(r);
+ return solve_(do_simp, turn_off_simp);
+ }
+
+ inline lbool SimpSolver::solve (const vec<Lit>& assumps, bool do_simp, bool turn_off_simp){
+ budgetOff();
+ assumps.copyTo(assumptions);
+ return solve_(do_simp, turn_off_simp);
+ }
inline lbool SimpSolver::solveLimited (const vec<Lit>& assumps, bool do_simp, bool turn_off_simp){
assumps.copyTo(assumptions); return solve_(do_simp, turn_off_simp); }
diff --git a/src/prop/options b/src/prop/options
index 71091d2b5..8189d61f8 100644
--- a/src/prop/options
+++ b/src/prop/options
@@ -5,9 +5,6 @@
module PROP "prop/options.h" SAT layer
-option - --show-sat-solvers void :handler CVC4::prop::showSatSolvers :handler-include "prop/options_handlers.h"
- show all available SAT solvers
-
option satRandomFreq random-frequency --random-freq=P double :default 0.0 :predicate greater_equal(0.0) less_equal(1.0)
sets the frequency of random decisions in the sat solver (P=0.0 by default)
option satRandomSeed random-seed --random-seed=S uint32_t :default 0 :read-write
diff --git a/src/prop/options_handlers.h b/src/prop/options_handlers.h
deleted file mode 100644
index 8ed53a3f5..000000000
--- a/src/prop/options_handlers.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/********************* */
-/*! \file options_handlers.h
- ** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief [[ Add one-line brief description here ]]
- **
- ** [[ Add lengthier description here ]]
- ** \todo document this file
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__PROP__OPTIONS_HANDLERS_H
-#define __CVC4__PROP__OPTIONS_HANDLERS_H
-
-#include "prop/sat_solver_factory.h"
-#include <string>
-#include <vector>
-
-namespace CVC4 {
-namespace prop {
-
-inline void showSatSolvers(std::string option, SmtEngine* smt) {
- std::vector<std::string> solvers;
- SatSolverFactory::getSolverIds(solvers);
- printf("Available SAT solvers: ");
- for (unsigned i = 0; i < solvers.size(); ++ i) {
- if (i > 0) {
- printf(", ");
- }
- printf("%s", solvers[i].c_str());
- }
- printf("\n");
- exit(0);
-}
-
-}/* CVC4::prop namespace */
-}/* CVC4 namespace */
-
-#endif /* __CVC4__PROP__OPTIONS_HANDLERS_H */
diff --git a/src/prop/prop_engine.cpp b/src/prop/prop_engine.cpp
index a998d4240..c7dae533e 100644
--- a/src/prop/prop_engine.cpp
+++ b/src/prop/prop_engine.cpp
@@ -32,6 +32,7 @@
#include "main/options.h"
#include "util/output.h"
#include "util/result.h"
+#include "util/resource_manager.h"
#include "expr/expr.h"
#include "expr/command.h"
@@ -74,8 +75,8 @@ PropEngine::PropEngine(TheoryEngine* te, DecisionEngine *de, Context* satContext
d_satSolver(NULL),
d_registrar(NULL),
d_cnfStream(NULL),
- d_satTimer(*this),
- d_interrupted(false) {
+ d_interrupted(false),
+ d_resourceManager(NodeManager::currentResourceManager()) {
Debug("prop") << "Constructing the PropEngine" << endl;
@@ -159,7 +160,7 @@ void PropEngine::printSatisfyingAssignment(){
}
}
-Result PropEngine::checkSat(unsigned long& millis, unsigned long& resource) {
+Result PropEngine::checkSat() {
Assert(!d_inCheckSat, "Sat solver in solve()!");
Debug("prop") << "PropEngine::checkSat()" << endl;
@@ -171,25 +172,23 @@ Result PropEngine::checkSat(unsigned long& millis, unsigned long& resource) {
d_theoryEngine->presolve();
if(options::preprocessOnly()) {
- millis = resource = 0;
return Result(Result::SAT_UNKNOWN, Result::REQUIRES_FULL_CHECK);
}
- // Set the timer
- d_satTimer.set(millis);
-
// Reset the interrupted flag
d_interrupted = false;
// Check the problem
- SatValue result = d_satSolver->solve(resource);
-
- millis = d_satTimer.elapsed();
+ SatValue result = d_satSolver->solve();
if( result == SAT_VALUE_UNKNOWN ) {
- Result::UnknownExplanation why =
- d_satTimer.expired() ? Result::TIMEOUT :
- (d_interrupted ? Result::INTERRUPTED : Result::RESOURCEOUT);
+
+ Result::UnknownExplanation why = Result::INTERRUPTED;
+ if (d_resourceManager->outOfTime())
+ why = Result::TIMEOUT;
+ if (d_resourceManager->outOfResources())
+ why = Result::RESOURCEOUT;
+
return Result(Result::SAT_UNKNOWN, why);
}
@@ -279,16 +278,11 @@ void PropEngine::interrupt() throw(ModalException) {
d_interrupted = true;
d_satSolver->interrupt();
- d_theoryEngine->interrupt();
Debug("prop") << "interrupt()" << endl;
}
-void PropEngine::spendResource() throw() {
- if(d_satSolver->spendResource()) {
- d_satSolver->interrupt();
- d_theoryEngine->interrupt();
- }
- checkTime();
+void PropEngine::spendResource() throw (UnsafeInterruptException) {
+ d_resourceManager->spendResource();
}
bool PropEngine::properExplanation(TNode node, TNode expl) const {
diff --git a/src/prop/prop_engine.h b/src/prop/prop_engine.h
index ed022a64f..2750319e6 100644
--- a/src/prop/prop_engine.h
+++ b/src/prop/prop_engine.h
@@ -24,12 +24,14 @@
#include "expr/node.h"
#include "options/options.h"
#include "util/result.h"
+#include "util/unsafe_interrupt_exception.h"
#include "smt/modal_exception.h"
#include "proof/proof_manager.h"
#include <sys/time.h>
namespace CVC4 {
+class ResourceManager;
class DecisionEngine;
class TheoryEngine;
@@ -45,78 +47,6 @@ class DPLLSatSolverInterface;
class PropEngine;
/**
- * A helper class to keep track of a time budget and signal
- * the PropEngine when the budget expires.
- */
-class SatTimer {
-
- PropEngine& d_propEngine;
- unsigned long d_ms;
- timeval d_limit;
-
-public:
-
- /** Construct a SatTimer attached to the given PropEngine. */
- SatTimer(PropEngine& propEngine) :
- d_propEngine(propEngine),
- d_ms(0) {
- }
-
- /** Is the timer currently active? */
- bool on() const {
- return d_ms != 0;
- }
-
- /** Set a millisecond timer (0==off). */
- void set(unsigned long millis) {
- d_ms = millis;
- // keep track of when it was set, even if it's disabled (i.e. == 0)
- Trace("limit") << "SatTimer::set(" << d_ms << ")" << std::endl;
- gettimeofday(&d_limit, NULL);
- Trace("limit") << "SatTimer::set(): it's " << d_limit.tv_sec << "," << d_limit.tv_usec << std::endl;
- d_limit.tv_sec += millis / 1000;
- d_limit.tv_usec += (millis % 1000) * 1000;
- if(d_limit.tv_usec > 1000000) {
- ++d_limit.tv_sec;
- d_limit.tv_usec -= 1000000;
- }
- Trace("limit") << "SatTimer::set(): limit is at " << d_limit.tv_sec << "," << d_limit.tv_usec << std::endl;
- }
-
- /** Return the milliseconds elapsed since last set(). */
- unsigned long elapsed() {
- timeval tv;
- gettimeofday(&tv, NULL);
- Trace("limit") << "SatTimer::elapsed(): it's now " << tv.tv_sec << "," << tv.tv_usec << std::endl;
- tv.tv_sec -= d_limit.tv_sec - d_ms / 1000;
- tv.tv_usec -= d_limit.tv_usec - (d_ms % 1000) * 1000;
- Trace("limit") << "SatTimer::elapsed(): elapsed time is " << tv.tv_sec << "," << tv.tv_usec << std::endl;
- return tv.tv_sec * 1000 + tv.tv_usec / 1000;
- }
-
- bool expired() {
- if(on()) {
- timeval tv;
- gettimeofday(&tv, NULL);
- Trace("limit") << "SatTimer::expired(): current time is " << tv.tv_sec << "," << tv.tv_usec << std::endl;
- Trace("limit") << "SatTimer::expired(): limit time is " << d_limit.tv_sec << "," << d_limit.tv_usec << std::endl;
- if(d_limit.tv_sec < tv.tv_sec ||
- (d_limit.tv_sec == tv.tv_sec && d_limit.tv_usec <= tv.tv_usec)) {
- Trace("limit") << "SatTimer::expired(): OVER LIMIT!" << std::endl;
- return true;
- } else {
- Trace("limit") << "SatTimer::expired(): within limit" << std::endl;
- }
- }
- return false;
- }
-
- /** Check the current time and signal the PropEngine if over-time. */
- void check();
-
-};/* class SatTimer */
-
-/**
* PropEngine is the abstraction of a Sat Solver, providing methods for
* solving the SAT problem and conversion to CNF (via the CnfStream).
*/
@@ -152,11 +82,10 @@ class PropEngine {
/** The CNF converter in use */
CnfStream* d_cnfStream;
- /** A timer for SAT calls */
- SatTimer d_satTimer;
-
/** Whether we were just interrupted (or not) */
bool d_interrupted;
+ /** Pointer to resource manager for associated SmtEngine */
+ ResourceManager* d_resourceManager;
/** Dump out the satisfying assignment (after SAT result) */
void printSatisfyingAssignment();
@@ -236,12 +165,8 @@ public:
/**
* Checks the current context for satisfiability.
*
- * @param millis the time limit for this call in milliseconds
- * (0==off); on output, it is set to the milliseconds used
- * @param on input, resource the number of resource units permitted
- * for this call (0==off); on output, it is set to the resource used
*/
- Result checkSat(unsigned long& millis, unsigned long& resource);
+ Result checkSat();
/**
* Get the value of a boolean variable.
@@ -295,21 +220,15 @@ public:
bool isRunning() const;
/**
- * Check the current time budget.
- */
- void checkTime();
-
- /**
* Interrupt a running solver (cause a timeout).
*/
void interrupt() throw(ModalException);
/**
- * "Spend" a "resource." If the sum of these externally-counted
- * resources and SAT-internal resources exceed the current limit,
- * SAT should terminate.
+ * Informs the ResourceManager that a resource has been spent. If out of
+ * resources, can throw an UnsafeInterruptException exception.
*/
- void spendResource() throw();
+ void spendResource() throw (UnsafeInterruptException);
/**
* For debugging. Return true if "expl" is a well-formed
@@ -326,17 +245,6 @@ public:
};/* class PropEngine */
-inline void SatTimer::check() {
- if(d_propEngine.isRunning() && expired()) {
- Trace("limit") << "SatTimer::check(): interrupt!" << std::endl;
- d_propEngine.interrupt();
- }
-}
-
-inline void PropEngine::checkTime() {
- d_satTimer.check();
-}
-
}/* CVC4::prop namespace */
}/* CVC4 namespace */
diff --git a/src/prop/sat_solver.h b/src/prop/sat_solver.h
index adf6dfd07..b71844590 100644
--- a/src/prop/sat_solver.h
+++ b/src/prop/sat_solver.h
@@ -62,12 +62,6 @@ public:
/** Check the satisfiability of the added clauses */
virtual SatValue solve(long unsigned int&) = 0;
- /**
- * Instruct the solver that it should bump its consumed resource count.
- * Returns true if resources are exhausted.
- */
- virtual bool spendResource() = 0;
-
/** Interrupt the solver */
virtual void interrupt() = 0;
@@ -102,6 +96,7 @@ public:
* Notify about a learnt clause.
*/
virtual void notify(SatClause& clause) = 0;
+ virtual void spendResource() = 0;
virtual void safePoint() = 0;
};/* class BVSatSolverInterface::Notify */
diff --git a/src/prop/sat_solver_factory.cpp b/src/prop/sat_solver_factory.cpp
index 650c05dd4..98b8fce47 100644
--- a/src/prop/sat_solver_factory.cpp
+++ b/src/prop/sat_solver_factory.cpp
@@ -15,16 +15,12 @@
**/
#include "prop/sat_solver_factory.h"
-#include "prop/sat_solver_registry.h"
#include "prop/minisat/minisat.h"
#include "prop/bvminisat/bvminisat.h"
namespace CVC4 {
namespace prop {
-template class SatSolverConstructor<MinisatSatSolver>;
-template class SatSolverConstructor<BVMinisatSatSolver>;
-
BVSatSolverInterface* SatSolverFactory::createMinisat(context::Context* mainSatContext, const std::string& name) {
return new BVMinisatSatSolver(mainSatContext, name);
}
@@ -33,18 +29,5 @@ DPLLSatSolverInterface* SatSolverFactory::createDPLLMinisat() {
return new MinisatSatSolver();
}
-SatSolver* SatSolverFactory::create(const char* name) {
- SatSolverConstructorInterface* constructor = SatSolverRegistry::getConstructor(name);
- if (constructor) {
- return constructor->construct();
- } else {
- return NULL;
- }
-}
-
-void SatSolverFactory::getSolverIds(std::vector<std::string>& solvers) {
- SatSolverRegistry::getSolverIds(solvers);
-}
-
-} /* namespace CVC4::prop */
-} /* namespace CVC4 */
+} /* CVC4::prop namespace */
+} /* CVC4 namespace */
diff --git a/src/prop/sat_solver_factory.h b/src/prop/sat_solver_factory.h
index 0b419d545..34776c245 100644
--- a/src/prop/sat_solver_factory.h
+++ b/src/prop/sat_solver_factory.h
@@ -31,15 +31,7 @@ public:
static BVSatSolverInterface* createMinisat(context::Context* mainSatContext, const std::string& name = "");
static DPLLSatSolverInterface* createDPLLMinisat();
- static SatSolver* create(const char* id);
-
- /** Get the solver ids that are available */
- static void getSolverIds(std::vector<std::string>& solvers);
-
-};
-
-}
-}
-
-
+};/* class SatSolverFactory */
+}/* CVC4::prop namespace */
+}/* CVC4 namespace */
diff --git a/src/prop/sat_solver_registry.cpp b/src/prop/sat_solver_registry.cpp
deleted file mode 100644
index 7867c6cc3..000000000
--- a/src/prop/sat_solver_registry.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/********************* */
-/*! \file sat_solver_registry.cpp
- ** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief This class transforms a sequence of formulas into clauses.
- **
- ** This class takes a sequence of formulas.
- ** It outputs a stream of clauses that is propositionally
- ** equi-satisfiable with the conjunction of the formulas.
- ** This stream is maintained in an online fashion.
- **
- ** Compile time registration of SAT solvers with the SAT solver factory
- **/
-
-#include "prop/sat_solver_registry.h"
-#include "sstream"
-
-using namespace std;
-using namespace CVC4;
-using namespace prop;
-
-SatSolverConstructorInterface* SatSolverRegistry::getConstructor(string id) {
- SatSolverRegistry* registry = getInstance();
- registry_type::const_iterator find = registry->d_solvers.find(id);
- if (find == registry->d_solvers.end()) {
- return NULL;
- } else {
- return find->second;
- }
-}
-
-void SatSolverRegistry::getSolverIds(std::vector<std::string>& solvers) {
- SatSolverRegistry* registry = getInstance();
- registry_type::const_iterator it = registry->d_solvers.begin();
- registry_type::const_iterator it_end = registry->d_solvers.end();
- for (; it != it_end; ++ it) {
- solvers.push_back(it->first);
- }
-}
-
-SatSolverRegistry* SatSolverRegistry::getInstance() {
- static SatSolverRegistry registry;
- return &registry;
-}
-
-SatSolverRegistry::~SatSolverRegistry() {
- registry_type::const_iterator it = d_solvers.begin();
- registry_type::const_iterator it_end = d_solvers.begin();
- for (; it != it_end; ++ it) {
- delete it->second;
- }
-}
diff --git a/src/prop/sat_solver_registry.h b/src/prop/sat_solver_registry.h
deleted file mode 100644
index b8173866f..000000000
--- a/src/prop/sat_solver_registry.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/********************* */
-/*! \file sat_solver_registry.h
- ** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief This class transforms a sequence of formulas into clauses.
- **
- ** This class takes a sequence of formulas.
- ** It outputs a stream of clauses that is propositionally
- ** equi-satisfiable with the conjunction of the formulas.
- ** This stream is maintained in an online fashion.
- **
- ** Compile time registration of SAT solvers with the SAT solver factory
- **/
-
-#pragma once
-
-#include "cvc4_private.h"
-
-#include <map>
-#include <string>
-#include <cxxabi.h>
-#include "prop/sat_solver.h"
-#include "prop/sat_solver_factory.h"
-
-namespace CVC4 {
-namespace prop {
-
-/**
- * Interface for SAT solver constructors. Solvers should declare an instantiation of the
- * SatSolverConstructor interface below.
- */
-class SatSolverConstructorInterface {
-public:
- virtual ~SatSolverConstructorInterface() {}
- virtual SatSolver* construct() = 0;
-};
-
-/**
- * Registry containing all the registered SAT solvers.
- */
-class SatSolverRegistry {
-
- typedef std::map<std::string, SatSolverConstructorInterface*> registry_type;
-
- /** Map from ids to solver constructors */
- registry_type d_solvers;
-
- /** Nobody can create the registry, there can be only one! */
- SatSolverRegistry() {}
-
- /**
- * Register a SAT solver with the registry. The Constructor type should be a subclass
- * of the SatSolverConstructor.
- */
- template <typename Constructor>
- size_t registerSolver(const char* id) {
- int status;
- char* demangled = abi::__cxa_demangle(id, 0, 0, &status);
- d_solvers[demangled] = new Constructor();
- free(demangled);
- return d_solvers.size();
- }
-
- /** Get the instance of the registry */
- static SatSolverRegistry* getInstance();
-
-public:
-
- /** Destructor */
- ~SatSolverRegistry();
-
- /**
- * Returns the constructor for the given SAT solver.
- */
- static SatSolverConstructorInterface* getConstructor(std::string id);
-
- /** Get the ids of the available solvers */
- static void getSolverIds(std::vector<std::string>& solvers);
-
- /** The Constructors are friends, since they need to register */
- template<typename Solver>
- friend class SatSolverConstructor;
-
-};
-
-/**
- * Declare an instance of this class with the SAT solver in order to put it in the registry.
- */
-template<typename Solver>
-class SatSolverConstructor : public SatSolverConstructorInterface {
-
- /** Static solver id we use for initialization */
- static const size_t s_solverId;
-
-public:
-
- /** Constructs the solver */
- SatSolver* construct() {
- return new Solver();
- }
-
-};
-
-template<typename Solver>
-const size_t SatSolverConstructor<Solver>::s_solverId = SatSolverRegistry::getInstance()->registerSolver<SatSolverConstructor>(typeid(Solver).name());
-
-}
-}
-
diff --git a/src/prop/theory_proxy.cpp b/src/prop/theory_proxy.cpp
index 2bcd48099..59e87dd33 100644
--- a/src/prop/theory_proxy.cpp
+++ b/src/prop/theory_proxy.cpp
@@ -103,7 +103,7 @@ TNode TheoryProxy::getNode(SatLiteral lit) {
}
void TheoryProxy::notifyRestart() {
- d_propEngine->checkTime();
+ d_propEngine->spendResource();
d_theoryEngine->notifyRestart();
static uint32_t lemmaCount = 0;
@@ -179,8 +179,8 @@ void TheoryProxy::logDecision(SatLiteral lit) {
#endif /* CVC4_REPLAY */
}
-void TheoryProxy::checkTime() {
- d_propEngine->checkTime();
+void TheoryProxy::spendResource() {
+ d_theoryEngine->spendResource();
}
bool TheoryProxy::isDecisionRelevant(SatVariable var) {
diff --git a/src/prop/theory_proxy.h b/src/prop/theory_proxy.h
index a962f653a..3565aa501 100644
--- a/src/prop/theory_proxy.h
+++ b/src/prop/theory_proxy.h
@@ -111,7 +111,7 @@ public:
void logDecision(SatLiteral lit);
- void checkTime();
+ void spendResource();
bool isDecisionEngineDone();
diff --git a/src/smt/boolean_terms.cpp b/src/smt/boolean_terms.cpp
index 6ce8efef9..ba3845d7a 100644
--- a/src/smt/boolean_terms.cpp
+++ b/src/smt/boolean_terms.cpp
@@ -132,6 +132,38 @@ Node BooleanTermConverter::rewriteAs(TNode in, TypeNode as) throw() {
if(as.isBoolean() && in.getType().isBitVector() && in.getType().getBitVectorSize() == 1) {
return NodeManager::currentNM()->mkNode(kind::EQUAL, NodeManager::currentNM()->mkConst(BitVector(1u, 1u)), in);
}
+ if(in.getType().isRecord()) {
+ Assert(as.isRecord());
+ const Record& inRec = in.getType().getConst<Record>();
+ const Record& asRec = as.getConst<Record>();
+ Assert(inRec.getNumFields() == asRec.getNumFields());
+ NodeBuilder<> nb(kind::RECORD);
+ nb << NodeManager::currentNM()->mkConst(asRec);
+ for(size_t i = 0; i < asRec.getNumFields(); ++i) {
+ Assert(inRec[i].first == asRec[i].first);
+ Node arg = NodeManager::currentNM()->mkNode(NodeManager::currentNM()->mkConst(RecordSelect(inRec[i].first)), in);
+ if(inRec[i].second != asRec[i].second) {
+ arg = rewriteAs(arg, TypeNode::fromType(asRec[i].second));
+ }
+ nb << arg;
+ }
+ Node out = nb;
+ return out;
+ }
+ if(in.getType().isTuple()) {
+ Assert(as.isTuple());
+ Assert(in.getType().getNumChildren() == as.getNumChildren());
+ NodeBuilder<> nb(kind::TUPLE);
+ for(size_t i = 0; i < as.getNumChildren(); ++i) {
+ Node arg = NodeManager::currentNM()->mkNode(NodeManager::currentNM()->mkConst(TupleSelect(i)), in);
+ if(in.getType()[i] != as[i]) {
+ arg = rewriteAs(arg, as[i]);
+ }
+ nb << arg;
+ }
+ Node out = nb;
+ return out;
+ }
if(in.getType().isDatatype()) {
if(as.isBoolean() && in.getType().hasAttribute(BooleanTermAttr())) {
return NodeManager::currentNM()->mkNode(kind::EQUAL, d_ttDt, in);
@@ -282,11 +314,13 @@ const Datatype& BooleanTermConverter::convertDatatype(const Datatype& dt) throw(
const Datatype& newD = newDtt.getDatatype();
for(c = dt.begin(); c != dt.end(); ++c) {
Debug("boolean-terms") << "constructor " << (*c).getConstructor() << ":" << (*c).getConstructor().getType() << " made into " << newD[(*c).getName() + "'"].getConstructor() << ":" << newD[(*c).getName() + "'"].getConstructor().getType() << endl;
- Node::fromExpr(newD[(*c).getName() + "'"].getConstructor()).setAttribute(BooleanTermAttr(), Node::fromExpr((*c).getConstructor()));// other attr?
+ const DatatypeConstructor *newC;
+ Node::fromExpr((*(newC = &newD[(*c).getName() + "'"])).getConstructor()).setAttribute(BooleanTermAttr(), Node::fromExpr((*c).getConstructor()));// other attr?
Debug("boolean-terms") << "mapped " << newD[(*c).getName() + "'"].getConstructor() << " to " << (*c).getConstructor() << endl;
d_varCache[Node::fromExpr((*c).getConstructor())] = Node::fromExpr(newD[(*c).getName() + "'"].getConstructor());
d_varCache[Node::fromExpr((*c).getTester())] = Node::fromExpr(newD[(*c).getName() + "'"].getTester());
for(DatatypeConstructor::const_iterator a = (*c).begin(); a != (*c).end(); ++a) {
+ Node::fromExpr((*newC)[(*a).getName() + "'"].getSelector()).setAttribute(BooleanTermAttr(), Node::fromExpr((*a).getSelector()));// other attr?
d_varCache[Node::fromExpr((*a).getSelector())] = Node::fromExpr(newD[(*c).getName() + "'"].getSelector((*a).getName() + "'"));
}
}
diff --git a/src/smt/model_postprocessor.cpp b/src/smt/model_postprocessor.cpp
index dd9d0a78c..44b56fdd4 100644
--- a/src/smt/model_postprocessor.cpp
+++ b/src/smt/model_postprocessor.cpp
@@ -27,6 +27,15 @@ Node ModelPostprocessor::rewriteAs(TNode n, TypeNode asType) {
// good to go, we have the right type
return n;
}
+ if(n.getKind() == kind::LAMBDA) {
+ Assert(asType.isFunction());
+ Node rhs = rewriteAs(n[1], asType[1]);
+ Node out = NodeManager::currentNM()->mkNode(kind::LAMBDA, n[0], rhs);
+ Debug("boolean-terms") << "rewrote " << n << " as " << out << std::endl;
+ Debug("boolean-terms") << "need type " << asType << endl;
+ // Assert(out.getType() == asType);
+ return out;
+ }
if(!n.isConst()) {
// we don't handle non-const right now
return n;
@@ -235,6 +244,43 @@ void ModelPostprocessor::visit(TNode current, TNode parent) {
Debug("boolean-terms") << "model-post: " << current << endl
<< "- returning " << n << endl;
d_nodes[current] = n;
+ } else if(current.getKind() == kind::LAMBDA) {
+ // rewrite based on children
+ bool self = true;
+ for(size_t i = 0; i < current.getNumChildren(); ++i) {
+ Assert(d_nodes.find(current[i]) != d_nodes.end());
+ if(!d_nodes[current[i]].isNull()) {
+ self = false;
+ break;
+ }
+ }
+ if(self) {
+ Debug("tuprec") << "returning self for kind " << current.getKind() << endl;
+ // rewrite to self
+ d_nodes[current] = Node::null();
+ } else {
+ // rewrite based on children
+ NodeBuilder<> nb(current.getKind());
+ if(current.getMetaKind() == kind::metakind::PARAMETERIZED) {
+ TNode op = current.getOperator();
+ Node realOp;
+ if(op.getAttribute(BooleanTermAttr(), realOp)) {
+ nb << realOp;
+ } else {
+ nb << op;
+ }
+ }
+ for(size_t i = 0; i < current.getNumChildren(); ++i) {
+ Assert(d_nodes.find(current[i]) != d_nodes.end());
+ TNode rw = d_nodes[current[i]];
+ if(rw.isNull()) {
+ rw = current[i];
+ }
+ nb << rw;
+ }
+ d_nodes[current] = nb;
+ Debug("tuprec") << "rewrote children for kind " << current.getKind() << " got " << d_nodes[current] << endl;
+ }
} else {
Debug("tuprec") << "returning self for kind " << current.getKind() << endl;
// rewrite to self
diff --git a/src/smt/options b/src/smt/options
index 0dc416474..20dd5b7d5 100644
--- a/src/smt/options
+++ b/src/smt/options
@@ -87,14 +87,18 @@ option - regular-output-channel argument :handler CVC4::smt::setRegularOutputCha
option - diagnostic-output-channel argument :handler CVC4::smt::setDiagnosticOutputChannel :handler-include "smt/options_handlers.h"
set the diagnostic output channel of the solver
-common-option cumulativeMillisecondLimit tlimit --tlimit=MS "unsigned long"
+common-option cumulativeMillisecondLimit tlimit --tlimit=MS "unsigned long" :handler CVC4::smt::tlimitHandler :handler-include "smt/options_handlers.h"
enable time limiting (give milliseconds)
-common-option perCallMillisecondLimit tlimit-per --tlimit-per=MS "unsigned long"
+common-option perCallMillisecondLimit tlimit-per --tlimit-per=MS "unsigned long" :handler CVC4::smt::tlimitPerHandler :handler-include "smt/options_handlers.h"
enable time limiting per query (give milliseconds)
-common-option cumulativeResourceLimit rlimit --rlimit=N "unsigned long"
+common-option cumulativeResourceLimit rlimit --rlimit=N "unsigned long" :handler CVC4::smt::rlimitHandler :handler-include "smt/options_handlers.h"
enable resource limiting (currently, roughly the number of SAT conflicts)
-common-option perCallResourceLimit reproducible-resource-limit --rlimit-per=N "unsigned long"
+common-option perCallResourceLimit reproducible-resource-limit --rlimit-per=N "unsigned long" :handler CVC4::smt::rlimitPerHandler :handler-include "smt/options_handlers.h"
enable resource limiting per query
+common-option hardLimit hard-limit --hard-limit bool :default false
+ the resource limit is hard potentially leaving the smtEngine in an unsafe state (should be destroyed and rebuild after resourcing out)
+common-option cpuTime cpu-time --cpu-time bool :default false
+ measures CPU time if set to true and wall time if false (default false)
expert-option rewriteApplyToConst rewrite-apply-to-const --rewrite-apply-to-const bool :default false
eliminate function applications, rewriting e.g. f(5) to a new symbol f_5
diff --git a/src/smt/options_handlers.h b/src/smt/options_handlers.h
index d02b88fd2..fc2b796d3 100644
--- a/src/smt/options_handlers.h
+++ b/src/smt/options_handlers.h
@@ -21,6 +21,7 @@
#include "cvc4autoconfig.h"
#include "util/dump.h"
+#include "util/resource_manager.h"
#include "smt/modal_exception.h"
#include "smt/smt_engine.h"
#include "lib/strtok_r.h"
@@ -452,6 +453,63 @@ inline void statsEnabledBuild(std::string option, bool value, SmtEngine* smt) th
#endif /* CVC4_STATISTICS_ON */
}
+inline unsigned long tlimitHandler(std::string option, std::string optarg, SmtEngine* smt) throw(OptionException) {
+ unsigned long ms;
+ std::istringstream convert(optarg);
+ if (!(convert >> ms))
+ throw OptionException("option `"+option+"` requires a number as an argument");
+
+ // make sure the resource is set if the option is updated
+ // if the smt engine is null the resource will be set in the
+ if (smt != NULL) {
+ ResourceManager* rm = NodeManager::fromExprManager(smt->getExprManager())->getResourceManager();
+ rm->setTimeLimit(ms, true);
+ }
+ return ms;
+}
+
+inline unsigned long tlimitPerHandler(std::string option, std::string optarg, SmtEngine* smt) throw(OptionException) {
+ unsigned long ms;
+
+ std::istringstream convert(optarg);
+ if (!(convert >> ms))
+ throw OptionException("option `"+option+"` requires a number as an argument");
+
+ if (smt != NULL) {
+ ResourceManager* rm = NodeManager::fromExprManager(smt->getExprManager())->getResourceManager();
+ rm->setTimeLimit(ms, false);
+ }
+ return ms;
+}
+
+inline unsigned long rlimitHandler(std::string option, std::string optarg, SmtEngine* smt) throw(OptionException) {
+ unsigned long ms;
+
+ std::istringstream convert(optarg);
+ if (!(convert >> ms))
+ throw OptionException("option `"+option+"` requires a number as an argument");
+
+ if (smt != NULL) {
+ ResourceManager* rm = NodeManager::fromExprManager(smt->getExprManager())->getResourceManager();
+ rm->setResourceLimit(ms, true);
+ }
+ return ms;
+}
+
+inline unsigned long rlimitPerHandler(std::string option, std::string optarg, SmtEngine* smt) throw(OptionException) {
+ unsigned long ms;
+
+ std::istringstream convert(optarg);
+ if (!(convert >> ms))
+ throw OptionException("option `"+option+"` requires a number as an argument");
+
+ if (smt != NULL) {
+ ResourceManager* rm = NodeManager::fromExprManager(smt->getExprManager())->getResourceManager();
+ rm->setResourceLimit(ms, false);
+ }
+ return ms;
+}
+
}/* CVC4::smt namespace */
}/* CVC4 namespace */
diff --git a/src/smt/smt_engine.cpp b/src/smt/smt_engine.cpp
index d0a920653..8f5ba2024 100644
--- a/src/smt/smt_engine.cpp
+++ b/src/smt/smt_engine.cpp
@@ -51,6 +51,7 @@
#include "main/options.h"
#include "util/unsat_core.h"
#include "util/proof.h"
+#include "util/resource_manager.h"
#include "proof/proof.h"
#include "proof/proof_manager.h"
#include "util/boolean_simplification.h"
@@ -83,6 +84,7 @@
#include "util/sort_inference.h"
#include "theory/quantifiers/quant_conflict_find.h"
#include "theory/quantifiers/macros.h"
+#include "theory/quantifiers/fun_def_process.h"
#include "theory/quantifiers/first_order_reasoning.h"
#include "theory/quantifiers/quantifiers_rewriter.h"
#include "theory/quantifiers/options.h"
@@ -207,6 +209,8 @@ struct SmtEngineStatistics {
/** Has something simplified to false? */
IntStat d_simplifiedToFalse;
+ /** Number of resource units spent. */
+ ReferenceStat<uint64_t> d_resourceUnitsUsed;
SmtEngineStatistics() :
d_definitionExpansionTime("smt::SmtEngine::definitionExpansionTime"),
@@ -229,7 +233,8 @@ struct SmtEngineStatistics {
d_solveTime("smt::SmtEngine::solveTime"),
d_pushPopTime("smt::SmtEngine::pushPopTime"),
d_processAssertionsTime("smt::SmtEngine::processAssertionsTime"),
- d_simplifiedToFalse("smt::SmtEngine::simplifiedToFalse", 0)
+ d_simplifiedToFalse("smt::SmtEngine::simplifiedToFalse", 0),
+ d_resourceUnitsUsed("smt::SmtEngine::resourceUnitsUsed")
{
StatisticsRegistry::registerStat(&d_definitionExpansionTime);
@@ -253,6 +258,7 @@ struct SmtEngineStatistics {
StatisticsRegistry::registerStat(&d_pushPopTime);
StatisticsRegistry::registerStat(&d_processAssertionsTime);
StatisticsRegistry::registerStat(&d_simplifiedToFalse);
+ StatisticsRegistry::registerStat(&d_resourceUnitsUsed);
}
~SmtEngineStatistics() {
@@ -277,6 +283,7 @@ struct SmtEngineStatistics {
StatisticsRegistry::unregisterStat(&d_pushPopTime);
StatisticsRegistry::unregisterStat(&d_processAssertionsTime);
StatisticsRegistry::unregisterStat(&d_simplifiedToFalse);
+ StatisticsRegistry::unregisterStat(&d_resourceUnitsUsed);
}
};/* struct SmtEngineStatistics */
@@ -296,6 +303,10 @@ struct SmtEngineStatistics {
*/
class SmtEnginePrivate : public NodeManagerListener {
SmtEngine& d_smt;
+ /**
+ * Manager for limiting time and abstract resource usage.
+ */
+ ResourceManager* d_resourceManager;
/** Learned literals */
vector<Node> d_nonClausalLearnedLiterals;
@@ -434,12 +445,13 @@ private:
*
* Returns false if the formula simplifies to "false"
*/
- bool simplifyAssertions() throw(TypeCheckingException, LogicException);
+ bool simplifyAssertions() throw(TypeCheckingException, LogicException, UnsafeInterruptException);
public:
SmtEnginePrivate(SmtEngine& smt) :
d_smt(smt),
+ d_resourceManager(NULL),
d_nonClausalLearnedLiterals(),
d_realAssertionsEnd(0),
d_booleanTermConverter(NULL),
@@ -459,6 +471,7 @@ public:
{
d_smt.d_nodeManager->subscribeEvents(this);
d_true = NodeManager::currentNM()->mkConst(true);
+ d_resourceManager = NodeManager::currentResourceManager();
}
~SmtEnginePrivate() {
@@ -473,6 +486,11 @@ public:
d_smt.d_nodeManager->unsubscribeEvents(this);
}
+ ResourceManager* getResourceManager() { return d_resourceManager; }
+ void spendResource() throw(UnsafeInterruptException) {
+ d_resourceManager->spendResource();
+ }
+
void nmNotifyNewSort(TypeNode tn, uint32_t flags) {
DeclareTypeCommand c(tn.getAttribute(expr::VarNameAttr()),
0,
@@ -561,7 +579,7 @@ public:
* Expand definitions in n.
*/
Node expandDefinitions(TNode n, hash_map<Node, Node, NodeHashFunction>& cache, bool expandOnly = false)
- throw(TypeCheckingException, LogicException);
+ throw(TypeCheckingException, LogicException, UnsafeInterruptException);
/**
* Rewrite Boolean terms in a Node.
@@ -684,12 +702,6 @@ SmtEngine::SmtEngine(ExprManager* em) throw() :
d_queryMade(false),
d_needPostsolve(false),
d_earlyTheoryPP(true),
- d_timeBudgetCumulative(0),
- d_timeBudgetPerCall(0),
- d_resourceBudgetCumulative(0),
- d_resourceBudgetPerCall(0),
- d_cumulativeTimeUsed(0),
- d_cumulativeResourceUsed(0),
d_status(),
d_private(NULL),
d_smtAttributes(NULL),
@@ -701,7 +713,7 @@ SmtEngine::SmtEngine(ExprManager* em) throw() :
d_private = new smt::SmtEnginePrivate(*this);
d_statisticsRegistry = new StatisticsRegistry();
d_stats = new SmtEngineStatistics();
-
+ d_stats->d_resourceUnitsUsed.setData(d_private->getResourceManager()->d_cumulativeResourceUsed);
// We have mutual dependency here, so we add the prop engine to the theory
// engine later (it is non-essential there)
d_theoryEngine = new TheoryEngine(d_context, d_userContext, d_private->d_iteRemover, const_cast<const LogicInfo&>(d_logic));
@@ -763,19 +775,6 @@ void SmtEngine::finishInit() {
}
d_dumpCommands.clear();
- if(options::perCallResourceLimit() != 0) {
- setResourceLimit(options::perCallResourceLimit(), false);
- }
- if(options::cumulativeResourceLimit() != 0) {
- setResourceLimit(options::cumulativeResourceLimit(), true);
- }
- if(options::perCallMillisecondLimit() != 0) {
- setTimeLimit(options::perCallMillisecondLimit(), false);
- }
- if(options::cumulativeMillisecondLimit() != 0) {
- setTimeLimit(options::cumulativeMillisecondLimit(), true);
- }
-
PROOF( ProofManager::currentPM()->setLogic(d_logic.getLogicString()); );
}
@@ -1035,7 +1034,10 @@ void SmtEngine::setDefaults() {
// Set the options for the theoryOf
if(!options::theoryOfMode.wasSetByUser()) {
- if(d_logic.isSharingEnabled() && !d_logic.isTheoryEnabled(THEORY_BV) && !d_logic.isTheoryEnabled(THEORY_STRINGS)) {
+ if(d_logic.isSharingEnabled() &&
+ !d_logic.isTheoryEnabled(THEORY_BV) &&
+ !d_logic.isTheoryEnabled(THEORY_STRINGS) &&
+ !d_logic.isTheoryEnabled(THEORY_SETS) ) {
Trace("smt") << "setting theoryof-mode to term-based" << endl;
options::theoryOfMode.set(THEORY_OF_TERM_BASED);
}
@@ -1057,13 +1059,16 @@ void SmtEngine::setDefaults() {
}
// If in arrays, set the UF handler to arrays
- if(d_logic.isTheoryEnabled(THEORY_ARRAY) && ( !d_logic.isQuantified() ||
+ if(d_logic.isTheoryEnabled(THEORY_ARRAY) && ( !d_logic.isQuantified() ||
(d_logic.isQuantified() && !d_logic.isTheoryEnabled(THEORY_UF)))) {
Theory::setUninterpretedSortOwner(THEORY_ARRAY);
} else {
Theory::setUninterpretedSortOwner(THEORY_UF);
}
+
// Turn on ite simplification for QF_LIA and QF_AUFBV
+ // WARNING: These checks match much more than just QF_AUFBV and
+ // QF_LIA logics. --K [2014/10/15]
if(! options::doITESimp.wasSetByUser()) {
bool qf_aufbv = !d_logic.isQuantified() &&
d_logic.isTheoryEnabled(THEORY_ARRAY) &&
@@ -1274,25 +1279,22 @@ void SmtEngine::setDefaults() {
options::decisionMode.set(decMode);
options::decisionStopOnly.set(stoponly);
}
-
- //for finite model finding
- if( ! options::instWhenMode.wasSetByUser()){
- //instantiate only on last call
- if( options::fmfInstEngine() ){
- Trace("smt") << "setting inst when mode to LAST_CALL" << endl;
- options::instWhenMode.set( quantifiers::INST_WHEN_LAST_CALL );
+ //local theory extensions
+ if( options::localTheoryExt() ){
+ //no E-matching?
+ if( !options::instMaxLevel.wasSetByUser() ){
+ options::instMaxLevel.set( 0 );
}
}
if( d_logic.hasCardinalityConstraints() ){
//must have finite model finding on
options::finiteModelFind.set( true );
}
- if( options::recurseCbqi() ){
- options::cbqi.set( true );
- }
if(options::fmfBoundIntLazy.wasSetByUser() && options::fmfBoundIntLazy()) {
options::fmfBoundInt.set( true );
}
+ //now have determined whether fmfBoundInt is on/off
+ //apply fmfBoundInt options
if( options::fmfBoundInt() ){
//must have finite model finding on
options::finiteModelFind.set( true );
@@ -1304,13 +1306,45 @@ void SmtEngine::setDefaults() {
options::mbqiMode.set( quantifiers::MBQI_NONE );
}
}
- if( options::mbqiMode()==quantifiers::MBQI_INTERVAL ){
- //must do pre-skolemization
- options::preSkolemQuant.set( true );
- }
if( options::ufssSymBreak() ){
options::sortInference.set( true );
}
+ if( options::fmfFunWellDefined() ){
+ if( !options::finiteModelFind.wasSetByUser() ){
+ options::finiteModelFind.set( true );
+ }
+ }
+
+ //now, have determined whether finite model find is on/off
+ //apply finite model finding options
+ if( options::finiteModelFind() ){
+ if( !options::eMatching.wasSetByUser() ){
+ options::eMatching.set( options::fmfInstEngine() );
+ }
+ if( !options::quantConflictFind.wasSetByUser() ){
+ options::quantConflictFind.set( false );
+ }
+ if( ! options::instWhenMode.wasSetByUser()){
+ //instantiate only on last call
+ if( options::eMatching() ){
+ Trace("smt") << "setting inst when mode to LAST_CALL" << endl;
+ options::instWhenMode.set( quantifiers::INST_WHEN_LAST_CALL );
+ }
+ }
+ if( options::mbqiMode()==quantifiers::MBQI_ABS ){
+ if( !options::preSkolemQuant.wasSetByUser() ){
+ options::preSkolemQuant.set( true );
+ }
+ if( !options::fmfOneInstPerRound.wasSetByUser() ){
+ options::fmfOneInstPerRound.set( true );
+ }
+ }
+ }
+
+ //implied options...
+ if( options::recurseCbqi() ){
+ options::cbqi.set( true );
+ }
if( options::qcfMode.wasSetByUser() || options::qcfTConstraint() ){
options::quantConflictFind.set( true );
}
@@ -1633,7 +1667,7 @@ void SmtEngine::defineFunction(Expr func,
}
Node SmtEnginePrivate::expandDefinitions(TNode n, hash_map<Node, Node, NodeHashFunction>& cache, bool expandOnly)
- throw(TypeCheckingException, LogicException) {
+ throw(TypeCheckingException, LogicException, UnsafeInterruptException) {
stack< triple<Node, Node, bool> > worklist;
stack<Node> result;
@@ -1643,6 +1677,7 @@ Node SmtEnginePrivate::expandDefinitions(TNode n, hash_map<Node, Node, NodeHashF
// or upward pass).
do {
+ spendResource();
n = worklist.top().first; // n is the input / original
Node node = worklist.top().second; // node is the output / result
bool childrenPushed = worklist.top().third;
@@ -1779,7 +1814,7 @@ Node SmtEnginePrivate::expandDefinitions(TNode n, hash_map<Node, Node, NodeHashF
void SmtEnginePrivate::removeITEs() {
d_smt.finalOptionsAreSet();
-
+ spendResource();
Trace("simplify") << "SmtEnginePrivate::removeITEs()" << endl;
// Remove all of the ITE occurrences and normalize
@@ -1791,6 +1826,7 @@ void SmtEnginePrivate::removeITEs() {
void SmtEnginePrivate::staticLearning() {
d_smt.finalOptionsAreSet();
+ spendResource();
TimerStat::CodeTimer staticLearningTimer(d_smt.d_stats->d_staticLearningTime);
@@ -1823,6 +1859,7 @@ static void dumpAssertions(const char* key, const AssertionPipeline& assertionLi
// returns false if it learns a conflict
bool SmtEnginePrivate::nonClausalSimplify() {
+ spendResource();
d_smt.finalOptionsAreSet();
if(options::unsatCores()) {
@@ -2151,6 +2188,7 @@ void SmtEnginePrivate::bvAbstraction() {
void SmtEnginePrivate::bvToBool() {
Trace("bv-to-bool") << "SmtEnginePrivate::bvToBool()" << endl;
+ spendResource();
std::vector<Node> new_assertions;
d_smt.d_theoryEngine->ppBvToBool(d_assertions.ref(), new_assertions);
for (unsigned i = 0; i < d_assertions.size(); ++ i) {
@@ -2161,10 +2199,13 @@ void SmtEnginePrivate::bvToBool() {
bool SmtEnginePrivate::simpITE() {
TimerStat::CodeTimer simpITETimer(d_smt.d_stats->d_simpITETime);
+ spendResource();
+
Trace("simplify") << "SmtEnginePrivate::simpITE()" << endl;
unsigned numAssertionOnEntry = d_assertions.size();
for (unsigned i = 0; i < d_assertions.size(); ++i) {
+ spendResource();
Node result = d_smt.d_theoryEngine->ppSimpITE(d_assertions[i]);
d_assertions.replace(i, result);
if(result.isConst() && !result.getConst<bool>()){
@@ -2211,6 +2252,7 @@ void SmtEnginePrivate::compressBeforeRealAssertions(size_t before){
void SmtEnginePrivate::unconstrainedSimp() {
TimerStat::CodeTimer unconstrainedSimpTimer(d_smt.d_stats->d_unconstrainedSimpTime);
+ spendResource();
Trace("simplify") << "SmtEnginePrivate::unconstrainedSimp()" << endl;
d_smt.d_theoryEngine->ppUnconstrainedSimp(d_assertions.ref());
}
@@ -2658,7 +2700,8 @@ void SmtEnginePrivate::doMiplibTrick() {
// returns false if simplification led to "false"
bool SmtEnginePrivate::simplifyAssertions()
- throw(TypeCheckingException, LogicException) {
+ throw(TypeCheckingException, LogicException, UnsafeInterruptException) {
+ spendResource();
Assert(d_smt.d_pendingPops == 0);
try {
ScopeCounter depth(d_simplifyAssertionsDepth);
@@ -2785,6 +2828,18 @@ Result SmtEngine::check() {
Trace("smt") << "SmtEngine::check()" << endl;
+ ResourceManager* resourceManager = d_private->getResourceManager();
+
+ resourceManager->beginCall();
+
+ // Only way we can be out of resource is if cumulative budget is on
+ if (resourceManager->cumulativeLimitOn() &&
+ resourceManager->out()) {
+ Result::UnknownExplanation why = resourceManager->outOfResources() ?
+ Result::RESOURCEOUT : Result::TIMEOUT;
+ return Result(Result::VALIDITY_UNKNOWN, why, d_filename);
+ }
+
// Make sure the prop layer has all of the assertions
Trace("smt") << "SmtEngine::check(): processing assertions" << endl;
d_private->processAssertions();
@@ -2804,41 +2859,16 @@ Result SmtEngine::check() {
}
}
- unsigned long millis = 0;
- if(d_timeBudgetCumulative != 0) {
- millis = getTimeRemaining();
- if(millis == 0) {
- return Result(Result::VALIDITY_UNKNOWN, Result::TIMEOUT, d_filename);
- }
- }
- if(d_timeBudgetPerCall != 0 && (millis == 0 || d_timeBudgetPerCall < millis)) {
- millis = d_timeBudgetPerCall;
- }
-
- unsigned long resource = 0;
- if(d_resourceBudgetCumulative != 0) {
- resource = getResourceRemaining();
- if(resource == 0) {
- return Result(Result::VALIDITY_UNKNOWN, Result::RESOURCEOUT, d_filename);
- }
- }
- if(d_resourceBudgetPerCall != 0 && (resource == 0 || d_resourceBudgetPerCall < resource)) {
- resource = d_resourceBudgetPerCall;
- }
-
TimerStat::CodeTimer solveTimer(d_stats->d_solveTime);
Chat() << "solving..." << endl;
Trace("smt") << "SmtEngine::check(): running check" << endl;
- Result result = d_propEngine->checkSat(millis, resource);
+ Result result = d_propEngine->checkSat();
- // PropEngine::checkSat() returns the actual amount used in these
- // variables.
- d_cumulativeTimeUsed += millis;
- d_cumulativeResourceUsed += resource;
+ resourceManager->endCall();
+ Trace("limit") << "SmtEngine::check(): cumulative millis " << resourceManager->getTimeUsage()
+ << ", resources " << resourceManager->getResourceUsage() << endl;
- Trace("limit") << "SmtEngine::check(): cumulative millis " << d_cumulativeTimeUsed
- << ", conflicts " << d_cumulativeResourceUsed << endl;
return Result(result, d_filename);
}
@@ -2911,6 +2941,9 @@ bool SmtEnginePrivate::checkForBadSkolems(TNode n, TNode skolem, hash_map<Node,
Node SmtEnginePrivate::rewriteBooleanTerms(TNode n) {
TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_rewriteBooleanTermsTime);
+
+ spendResource();
+
if(d_booleanTermConverter == NULL) {
// This needs to be initialized _after_ the whole SMT framework is in place, subscribed
// to ExprManager notifications, etc. Otherwise we might miss the "BooleanTerm" datatype
@@ -2944,7 +2977,7 @@ Node SmtEnginePrivate::rewriteBooleanTerms(TNode n) {
void SmtEnginePrivate::processAssertions() {
TimerStat::CodeTimer paTimer(d_smt.d_stats->d_processAssertionsTime);
-
+ spendResource();
Assert(d_smt.d_fullyInited);
Assert(d_smt.d_pendingPops == 0);
@@ -3063,6 +3096,7 @@ void SmtEnginePrivate::processAssertions() {
<< "applying substitutions" << endl;
for (unsigned i = 0; i < d_assertions.size(); ++ i) {
Trace("simplify") << "applying to " << d_assertions[i] << endl;
+ spendResource();
d_assertions.replace(i, Rewriter::rewrite(d_topLevelSubstitutions.apply(d_assertions[i])));
Trace("simplify") << " got " << d_assertions[i] << endl;
}
@@ -3079,6 +3113,7 @@ void SmtEnginePrivate::processAssertions() {
Chat() << "...doing bvToBool..." << endl;
bvToBool();
dumpAssertions("post-bv-to-bool", d_assertions);
+ Trace("smt") << "POST bvToBool" << endl;
}
if( d_smt.d_logic.isTheoryEnabled(THEORY_STRINGS) ) {
@@ -3132,6 +3167,10 @@ void SmtEnginePrivate::processAssertions() {
success = qm.simplify( d_assertions.ref(), true );
}while( success );
}
+ if( options::fmfFunWellDefined() ){
+ quantifiers::FunDefFmf fdf;
+ fdf.simplify( d_assertions.ref() );
+ }
Trace("fo-rsn-enable") << std::endl;
if( options::foPropQuant() ){
@@ -3179,7 +3218,6 @@ void SmtEnginePrivate::processAssertions() {
}
dumpAssertions("post-static-learning", d_assertions);
- Trace("smt") << "POST bvToBool" << endl;
Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
@@ -3322,14 +3360,14 @@ void SmtEnginePrivate::processAssertions() {
// introducing new ones
dumpAssertions("post-everything", d_assertions);
-
+
//set instantiation level of everything to zero
if( options::instLevelInputOnly() && options::instMaxLevel()!=-1 ){
for( unsigned i=0; i < d_assertions.size(); i++ ) {
theory::QuantifiersEngine::setInstantiationLevelAttr( d_assertions[i], 0 );
}
}
-
+
// Push the formula to SAT
{
Chat() << "converting to CNF..." << endl;
@@ -3374,86 +3412,93 @@ void SmtEngine::ensureBoolean(const Expr& e) throw(TypeCheckingException) {
}
Result SmtEngine::checkSat(const Expr& ex, bool inUnsatCore) throw(TypeCheckingException, ModalException, LogicException) {
- Assert(ex.isNull() || ex.getExprManager() == d_exprManager);
- SmtScope smts(this);
- finalOptionsAreSet();
- doPendingPops();
+ try {
+ Assert(ex.isNull() || ex.getExprManager() == d_exprManager);
+ SmtScope smts(this);
+ finalOptionsAreSet();
+ doPendingPops();
- Trace("smt") << "SmtEngine::checkSat(" << ex << ")" << endl;
+ Trace("smt") << "SmtEngine::checkSat(" << ex << ")" << endl;
- if(d_queryMade && !options::incrementalSolving()) {
- throw ModalException("Cannot make multiple queries unless "
- "incremental solving is enabled "
- "(try --incremental)");
- }
+ if(d_queryMade && !options::incrementalSolving()) {
+ throw ModalException("Cannot make multiple queries unless "
+ "incremental solving is enabled "
+ "(try --incremental)");
+ }
- Expr e;
- if(!ex.isNull()) {
- // Substitute out any abstract values in ex.
- e = d_private->substituteAbstractValues(Node::fromExpr(ex)).toExpr();
- // Ensure expr is type-checked at this point.
- ensureBoolean(e);
- // Give it to proof manager
- PROOF( ProofManager::currentPM()->addAssertion(e, inUnsatCore); );
- }
+ Expr e;
+ if(!ex.isNull()) {
+ // Substitute out any abstract values in ex.
+ e = d_private->substituteAbstractValues(Node::fromExpr(ex)).toExpr();
+ // Ensure expr is type-checked at this point.
+ ensureBoolean(e);
+ // Give it to proof manager
+ PROOF( ProofManager::currentPM()->addAssertion(e, inUnsatCore); );
+ }
- // check to see if a postsolve() is pending
- if(d_needPostsolve) {
- d_theoryEngine->postsolve();
- d_needPostsolve = false;
- }
+ // check to see if a postsolve() is pending
+ if(d_needPostsolve) {
+ d_theoryEngine->postsolve();
+ d_needPostsolve = false;
+ }
- // Push the context
- internalPush();
+ // Push the context
+ internalPush();
- // Note that a query has been made
- d_queryMade = true;
+ // Note that a query has been made
+ d_queryMade = true;
- // Add the formula
- if(!e.isNull()) {
- d_problemExtended = true;
- if(d_assertionList != NULL) {
- d_assertionList->push_back(e);
+ // Add the formula
+ if(!e.isNull()) {
+ d_problemExtended = true;
+ if(d_assertionList != NULL) {
+ d_assertionList->push_back(e);
+ }
+ d_private->addFormula(e.getNode());
}
- d_private->addFormula(e.getNode());
- }
- // Run the check
- Result r = check().asSatisfiabilityResult();
- d_needPostsolve = true;
+ Result r(Result::SAT_UNKNOWN, Result::UNKNOWN_REASON);
+ r = check().asSatisfiabilityResult();
+ d_needPostsolve = true;
- // Dump the query if requested
- if(Dump.isOn("benchmark")) {
- // the expr already got dumped out if assertion-dumping is on
- Dump("benchmark") << CheckSatCommand();
- }
+ // Dump the query if requested
+ if(Dump.isOn("benchmark")) {
+ // the expr already got dumped out if assertion-dumping is on
+ Dump("benchmark") << CheckSatCommand();
+ }
- // Pop the context
- internalPop();
+ // Pop the context
+ internalPop();
- // Remember the status
- d_status = r;
+ // Remember the status
+ d_status = r;
- d_problemExtended = false;
+ d_problemExtended = false;
- Trace("smt") << "SmtEngine::checkSat(" << e << ") => " << r << endl;
+ Trace("smt") << "SmtEngine::checkSat(" << e << ") => " << r << endl;
- // Check that SAT results generate a model correctly.
- if(options::checkModels()) {
- if(r.asSatisfiabilityResult().isSat() == Result::SAT ||
- (r.isUnknown() && r.whyUnknown() == Result::INCOMPLETE) ){
- checkModel(/* hard failure iff */ ! r.isUnknown());
+ // Check that SAT results generate a model correctly.
+ if(options::checkModels()) {
+ if(r.asSatisfiabilityResult().isSat() == Result::SAT ||
+ (r.isUnknown() && r.whyUnknown() == Result::INCOMPLETE) ){
+ checkModel(/* hard failure iff */ ! r.isUnknown());
+ }
}
- }
- // Check that UNSAT results generate a proof correctly.
- if(options::checkProofs()) {
- if(r.asSatisfiabilityResult().isSat() == Result::UNSAT) {
- TimerStat::CodeTimer checkProofTimer(d_stats->d_checkProofTime);
- checkProof();
+ // Check that UNSAT results generate a proof correctly.
+ if(options::checkProofs()) {
+ if(r.asSatisfiabilityResult().isSat() == Result::UNSAT) {
+ TimerStat::CodeTimer checkProofTimer(d_stats->d_checkProofTime);
+ checkProof();
+ }
}
- }
- return r;
+ return r;
+ } catch (UnsafeInterruptException& e) {
+ AlwaysAssert(d_private->getResourceManager()->out());
+ Result::UnknownExplanation why = d_private->getResourceManager()->outOfResources() ?
+ Result::RESOURCEOUT : Result::TIMEOUT;
+ return Result(Result::SAT_UNKNOWN, why, d_filename);
+ }
}/* SmtEngine::checkSat() */
Result SmtEngine::query(const Expr& ex, bool inUnsatCore) throw(TypeCheckingException, ModalException, LogicException) {
@@ -3464,6 +3509,7 @@ Result SmtEngine::query(const Expr& ex, bool inUnsatCore) throw(TypeCheckingExce
doPendingPops();
Trace("smt") << "SMT query(" << ex << ")" << endl;
+ try {
if(d_queryMade && !options::incrementalSolving()) {
throw ModalException("Cannot make multiple queries unless "
"incremental solving is enabled "
@@ -3497,7 +3543,8 @@ Result SmtEngine::query(const Expr& ex, bool inUnsatCore) throw(TypeCheckingExce
d_private->addFormula(e.getNode().notNode());
// Run the check
- Result r = check().asValidityResult();
+ Result r(Result::SAT_UNKNOWN, Result::UNKNOWN_REASON);
+ r = check().asValidityResult();
d_needPostsolve = true;
// Dump the query if requested
@@ -3532,9 +3579,15 @@ Result SmtEngine::query(const Expr& ex, bool inUnsatCore) throw(TypeCheckingExce
}
return r;
+ } catch (UnsafeInterruptException& e) {
+ AlwaysAssert(d_private->getResourceManager()->out());
+ Result::UnknownExplanation why = d_private->getResourceManager()->outOfResources() ?
+ Result::RESOURCEOUT : Result::TIMEOUT;
+ return Result(Result::VALIDITY_UNKNOWN, why, d_filename);
+ }
}/* SmtEngine::query() */
-Result SmtEngine::assertFormula(const Expr& ex, bool inUnsatCore) throw(TypeCheckingException, LogicException) {
+Result SmtEngine::assertFormula(const Expr& ex, bool inUnsatCore) throw(TypeCheckingException, LogicException, UnsafeInterruptException) {
Assert(ex.getExprManager() == d_exprManager);
SmtScope smts(this);
finalOptionsAreSet();
@@ -3565,7 +3618,7 @@ Node SmtEngine::postprocess(TNode node, TypeNode expectedType) const {
return realValue;
}
-Expr SmtEngine::simplify(const Expr& ex) throw(TypeCheckingException, LogicException) {
+Expr SmtEngine::simplify(const Expr& ex) throw(TypeCheckingException, LogicException, UnsafeInterruptException) {
Assert(ex.getExprManager() == d_exprManager);
SmtScope smts(this);
finalOptionsAreSet();
@@ -3588,7 +3641,9 @@ Expr SmtEngine::simplify(const Expr& ex) throw(TypeCheckingException, LogicExcep
return n.toExpr();
}
-Expr SmtEngine::expandDefinitions(const Expr& ex) throw(TypeCheckingException, LogicException) {
+Expr SmtEngine::expandDefinitions(const Expr& ex) throw(TypeCheckingException, LogicException, UnsafeInterruptException) {
+ d_private->spendResource();
+
Assert(ex.getExprManager() == d_exprManager);
SmtScope smts(this);
finalOptionsAreSet();
@@ -3611,7 +3666,7 @@ Expr SmtEngine::expandDefinitions(const Expr& ex) throw(TypeCheckingException, L
return n.toExpr();
}
-Expr SmtEngine::getValue(const Expr& ex) const throw(ModalException, TypeCheckingException, LogicException) {
+Expr SmtEngine::getValue(const Expr& ex) const throw(ModalException, TypeCheckingException, LogicException, UnsafeInterruptException) {
Assert(ex.getExprManager() == d_exprManager);
SmtScope smts(this);
@@ -3717,7 +3772,7 @@ bool SmtEngine::addToAssignment(const Expr& ex) throw() {
return true;
}
-CVC4::SExpr SmtEngine::getAssignment() throw(ModalException) {
+CVC4::SExpr SmtEngine::getAssignment() throw(ModalException, UnsafeInterruptException) {
Trace("smt") << "SMT getAssignment()" << endl;
SmtScope smts(this);
finalOptionsAreSet();
@@ -3746,8 +3801,8 @@ CVC4::SExpr SmtEngine::getAssignment() throw(ModalException) {
vector<SExpr> sexprs;
TypeNode boolType = d_nodeManager->booleanType();
TheoryModel* m = d_theoryEngine->getModel();
- for(AssignmentSet::const_iterator i = d_assignments->begin(),
- iend = d_assignments->end();
+ for(AssignmentSet::key_iterator i = d_assignments->key_begin(),
+ iend = d_assignments->key_end();
i != iend;
++i) {
Assert((*i).getType() == boolType);
@@ -3816,7 +3871,7 @@ void SmtEngine::addToModelCommandAndDump(const Command& c, uint32_t flags, bool
}
}
-Model* SmtEngine::getModel() throw(ModalException) {
+Model* SmtEngine::getModel() throw(ModalException, UnsafeInterruptException) {
Trace("smt") << "SMT getModel()" << endl;
SmtScope smts(this);
@@ -4024,7 +4079,7 @@ void SmtEngine::checkModel(bool hardFailure) {
Notice() << "SmtEngine::checkModel(): all assertions checked out OK !" << endl;
}
-UnsatCore SmtEngine::getUnsatCore() throw(ModalException) {
+UnsatCore SmtEngine::getUnsatCore() throw(ModalException, UnsafeInterruptException) {
Trace("smt") << "SMT getUnsatCore()" << endl;
SmtScope smts(this);
finalOptionsAreSet();
@@ -4048,7 +4103,7 @@ UnsatCore SmtEngine::getUnsatCore() throw(ModalException) {
#endif /* CVC4_PROOF */
}
-Proof* SmtEngine::getProof() throw(ModalException) {
+Proof* SmtEngine::getProof() throw(ModalException, UnsafeInterruptException) {
Trace("smt") << "SMT getProof()" << endl;
SmtScope smts(this);
finalOptionsAreSet();
@@ -4101,7 +4156,7 @@ vector<Expr> SmtEngine::getAssertions() throw(ModalException) {
return vector<Expr>(d_assertionList->begin(), d_assertionList->end());
}
-void SmtEngine::push() throw(ModalException, LogicException) {
+void SmtEngine::push() throw(ModalException, LogicException, UnsafeInterruptException) {
SmtScope smts(this);
finalOptionsAreSet();
doPendingPops();
@@ -4131,7 +4186,7 @@ void SmtEngine::push() throw(ModalException, LogicException) {
<< d_userContext->getLevel() << endl;
}
-void SmtEngine::pop() throw(ModalException) {
+void SmtEngine::pop() throw(ModalException, UnsafeInterruptException) {
SmtScope smts(this);
finalOptionsAreSet();
Trace("smt") << "SMT pop()" << endl;
@@ -4253,49 +4308,26 @@ void SmtEngine::interrupt() throw(ModalException) {
}
void SmtEngine::setResourceLimit(unsigned long units, bool cumulative) {
- if(cumulative) {
- Trace("limit") << "SmtEngine: setting cumulative resource limit to " << units << endl;
- d_resourceBudgetCumulative = (units == 0) ? 0 : (d_cumulativeResourceUsed + units);
- } else {
- Trace("limit") << "SmtEngine: setting per-call resource limit to " << units << endl;
- d_resourceBudgetPerCall = units;
- }
+ d_private->getResourceManager()->setResourceLimit(units, cumulative);
}
-
-void SmtEngine::setTimeLimit(unsigned long millis, bool cumulative) {
- if(cumulative) {
- Trace("limit") << "SmtEngine: setting cumulative time limit to " << millis << " ms" << endl;
- d_timeBudgetCumulative = (millis == 0) ? 0 : (d_cumulativeTimeUsed + millis);
- } else {
- Trace("limit") << "SmtEngine: setting per-call time limit to " << millis << " ms" << endl;
- d_timeBudgetPerCall = millis;
- }
+void SmtEngine::setTimeLimit(unsigned long milis, bool cumulative) {
+ d_private->getResourceManager()->setTimeLimit(milis, cumulative);
}
unsigned long SmtEngine::getResourceUsage() const {
- return d_cumulativeResourceUsed;
+ return d_private->getResourceManager()->getResourceUsage();
}
unsigned long SmtEngine::getTimeUsage() const {
- return d_cumulativeTimeUsed;
+ return d_private->getResourceManager()->getTimeUsage();
}
unsigned long SmtEngine::getResourceRemaining() const throw(ModalException) {
- if(d_resourceBudgetCumulative == 0) {
- throw ModalException("No cumulative resource limit is currently set");
- }
-
- return d_resourceBudgetCumulative <= d_cumulativeResourceUsed ? 0 :
- d_resourceBudgetCumulative - d_cumulativeResourceUsed;
+ return d_private->getResourceManager()->getResourceRemaining();
}
unsigned long SmtEngine::getTimeRemaining() const throw(ModalException) {
- if(d_timeBudgetCumulative == 0) {
- throw ModalException("No cumulative time limit is currently set");
- }
-
- return d_timeBudgetCumulative <= d_cumulativeTimeUsed ? 0 :
- d_timeBudgetCumulative - d_cumulativeTimeUsed;
+ return d_private->getResourceManager()->getTimeRemaining();
}
Statistics SmtEngine::getStatistics() const throw() {
diff --git a/src/smt/smt_engine.h b/src/smt/smt_engine.h
index 489d34d79..a39d2a7b5 100644
--- a/src/smt/smt_engine.h
+++ b/src/smt/smt_engine.h
@@ -35,6 +35,7 @@
#include "util/result.h"
#include "util/sexpr.h"
#include "util/hash.h"
+#include "util/unsafe_interrupt_exception.h"
#include "util/statistics.h"
#include "theory/logic_info.h"
@@ -233,19 +234,6 @@ class CVC4_PUBLIC SmtEngine {
*/
bool d_earlyTheoryPP;
- /** A user-imposed cumulative time budget, in milliseconds. 0 = no limit. */
- unsigned long d_timeBudgetCumulative;
- /** A user-imposed per-call time budget, in milliseconds. 0 = no limit. */
- unsigned long d_timeBudgetPerCall;
- /** A user-imposed cumulative resource budget. 0 = no limit. */
- unsigned long d_resourceBudgetCumulative;
- /** A user-imposed per-call resource budget. 0 = no limit. */
- unsigned long d_resourceBudgetPerCall;
-
- /** The number of milliseconds used by this SmtEngine since its inception. */
- unsigned long d_cumulativeTimeUsed;
- /** The amount of resource used by this SmtEngine since its inception. */
- unsigned long d_cumulativeResourceUsed;
/**
* Most recent result of last checkSat/query or (set-info :status).
@@ -383,7 +371,7 @@ class CVC4_PUBLIC SmtEngine {
* or INVALID query). Only permitted if CVC4 was built with model
* support and produce-models is on.
*/
- Model* getModel() throw(ModalException);
+ Model* getModel() throw(ModalException, UnsafeInterruptException);
// disallow copy/assignment
SmtEngine(const SmtEngine&) CVC4_UNDEFINED;
@@ -463,7 +451,7 @@ public:
* takes a Boolean flag to determine whether to include this asserted
* formula in an unsat core (if one is later requested).
*/
- Result assertFormula(const Expr& e, bool inUnsatCore = true) throw(TypeCheckingException, LogicException);
+ Result assertFormula(const Expr& e, bool inUnsatCore = true) throw(TypeCheckingException, LogicException, UnsafeInterruptException);
/**
* Check validity of an expression with respect to the current set
@@ -487,20 +475,20 @@ public:
* @todo (design) is this meant to give an equivalent or an
* equisatisfiable formula?
*/
- Expr simplify(const Expr& e) throw(TypeCheckingException, LogicException);
+ Expr simplify(const Expr& e) throw(TypeCheckingException, LogicException, UnsafeInterruptException);
/**
* Expand the definitions in a term or formula. No other
* simplification or normalization is done.
*/
- Expr expandDefinitions(const Expr& e) throw(TypeCheckingException, LogicException);
+ Expr expandDefinitions(const Expr& e) throw(TypeCheckingException, LogicException, UnsafeInterruptException);
/**
* Get the assigned value of an expr (only if immediately preceded
* by a SAT or INVALID query). Only permitted if the SmtEngine is
* set to operate interactively and produce-models is on.
*/
- Expr getValue(const Expr& e) const throw(ModalException, TypeCheckingException, LogicException);
+ Expr getValue(const Expr& e) const throw(ModalException, TypeCheckingException, LogicException, UnsafeInterruptException);
/**
* Add a function to the set of expressions whose value is to be
@@ -518,14 +506,14 @@ public:
* INVALID query). Only permitted if the SmtEngine is set to
* operate interactively and produce-assignments is on.
*/
- CVC4::SExpr getAssignment() throw(ModalException);
+ CVC4::SExpr getAssignment() throw(ModalException, UnsafeInterruptException);
/**
* Get the last proof (only if immediately preceded by an UNSAT
* or VALID query). Only permitted if CVC4 was built with proof
* support and produce-proofs is on.
*/
- Proof* getProof() throw(ModalException);
+ Proof* getProof() throw(ModalException, UnsafeInterruptException);
/**
* Print all instantiations made by the quantifiers module.
@@ -537,7 +525,7 @@ public:
* UNSAT or VALID query). Only permitted if CVC4 was built with
* unsat-core support and produce-unsat-cores is on.
*/
- UnsatCore getUnsatCore() throw(ModalException);
+ UnsatCore getUnsatCore() throw(ModalException, UnsafeInterruptException);
/**
* Get the current set of assertions. Only permitted if the
@@ -548,12 +536,12 @@ public:
/**
* Push a user-level context.
*/
- void push() throw(ModalException, LogicException);
+ void push() throw(ModalException, LogicException, UnsafeInterruptException);
/**
* Pop a user-level context. Throws an exception if nothing to pop.
*/
- void pop() throw(ModalException);
+ void pop() throw(ModalException, UnsafeInterruptException);
/**
* Completely reset the state of the solver, as though destroyed and
diff --git a/src/smt/smt_engine_scope.h b/src/smt/smt_engine_scope.h
index fb5810fd5..701775c9c 100644
--- a/src/smt/smt_engine_scope.h
+++ b/src/smt/smt_engine_scope.h
@@ -38,6 +38,9 @@ inline SmtEngine* currentSmtEngine() {
Assert(s_smtEngine_current != NULL);
return s_smtEngine_current;
}
+inline bool smtEngineInScope() {
+ return s_smtEngine_current != NULL;
+}
inline ProofManager* currentProofManager() {
#ifdef CVC4_PROOF
diff --git a/src/theory/arith/theory_arith_private.cpp b/src/theory/arith/theory_arith_private.cpp
index c657796ee..c8e7991a5 100644
--- a/src/theory/arith/theory_arith_private.cpp
+++ b/src/theory/arith/theory_arith_private.cpp
@@ -3346,6 +3346,12 @@ bool TheoryArithPrivate::hasFreshArithLiteral(Node n) const{
void TheoryArithPrivate::check(Theory::Effort effortLevel){
Assert(d_currentPropagationList.empty());
+
+ if(done() && !Theory::fullEffort(effortLevel) && ( d_qflraStatus == Result::SAT) ){
+ return;
+ }
+
+ TimerStat::CodeTimer checkTimer(d_containing.d_checkTime);
//cout << "TheoryArithPrivate::check " << effortLevel << std::endl;
Debug("effortlevel") << "TheoryArithPrivate::check " << effortLevel << std::endl;
Debug("arith") << "TheoryArithPrivate::check begun " << effortLevel << std::endl;
diff --git a/src/theory/arrays/theory_arrays.cpp b/src/theory/arrays/theory_arrays.cpp
index 13314b46e..8b313e124 100644
--- a/src/theory/arrays/theory_arrays.cpp
+++ b/src/theory/arrays/theory_arrays.cpp
@@ -61,7 +61,6 @@ TheoryArrays::TheoryArrays(context::Context* c, context::UserContext* u, OutputC
d_numGetModelValConflicts("theory::arrays::number of getModelVal conflicts", 0),
d_numSetModelValSplits("theory::arrays::number of setModelVal splits", 0),
d_numSetModelValConflicts("theory::arrays::number of setModelVal conflicts", 0),
- d_checkTimer("theory::arrays::checkTime"),
d_ppEqualityEngine(u, "theory::arrays::TheoryArraysPP"),
d_ppFacts(u),
// d_ppCache(u),
@@ -82,6 +81,9 @@ TheoryArrays::TheoryArrays(context::Context* c, context::UserContext* u, OutputC
d_sharedOther(c),
d_sharedTerms(c, false),
d_reads(c),
+ d_constReadsList(c),
+ d_constReadsContext(new context::Context()),
+ d_contextPopper(c, d_constReadsContext),
d_skolemIndex(c, 0),
d_decisionRequests(c),
d_permRef(c),
@@ -100,7 +102,6 @@ TheoryArrays::TheoryArrays(context::Context* c, context::UserContext* u, OutputC
StatisticsRegistry::registerStat(&d_numGetModelValConflicts);
StatisticsRegistry::registerStat(&d_numSetModelValSplits);
StatisticsRegistry::registerStat(&d_numSetModelValConflicts);
- StatisticsRegistry::registerStat(&d_checkTimer);
d_true = NodeManager::currentNM()->mkConst<bool>(true);
d_false = NodeManager::currentNM()->mkConst<bool>(false);
@@ -124,7 +125,11 @@ TheoryArrays::TheoryArrays(context::Context* c, context::UserContext* u, OutputC
}
TheoryArrays::~TheoryArrays() {
-
+ CNodeNListMap::iterator it = d_constReads.begin();
+ for( ; it != d_constReads.end(); ++it ) {
+ (*it).second->deleteSelf();
+ }
+ delete d_constReadsContext;
StatisticsRegistry::unregisterStat(&d_numRow);
StatisticsRegistry::unregisterStat(&d_numExt);
StatisticsRegistry::unregisterStat(&d_numProp);
@@ -135,8 +140,6 @@ TheoryArrays::~TheoryArrays() {
StatisticsRegistry::unregisterStat(&d_numGetModelValConflicts);
StatisticsRegistry::unregisterStat(&d_numSetModelValSplits);
StatisticsRegistry::unregisterStat(&d_numSetModelValConflicts);
- StatisticsRegistry::unregisterStat(&d_checkTimer);
-
}
void TheoryArrays::setMasterEqualityEngine(eq::EqualityEngine* eq) {
@@ -449,8 +452,8 @@ void TheoryArrays::preRegisterTermInternal(TNode node)
}
if (node.getType().isArray()) {
- d_equalityEngine.addTriggerTerm(node, THEORY_ARRAY);
d_mayEqualEqualityEngine.addTerm(node);
+ d_equalityEngine.addTriggerTerm(node, THEORY_ARRAY);
}
else {
d_equalityEngine.addTerm(node);
@@ -464,7 +467,32 @@ void TheoryArrays::preRegisterTermInternal(TNode node)
Assert(d_equalityEngine.getRepresentative(store) == store);
d_infoMap.addIndex(store, node[1]);
- d_reads.push_back(node);
+
+ // Synchronize d_constReadsContext with SAT context
+ Assert(d_constReadsContext->getLevel() <= getSatContext()->getLevel());
+ while (d_constReadsContext->getLevel() < getSatContext()->getLevel()) {
+ d_constReadsContext->push();
+ }
+
+ // Record read in sharing data structure
+ TNode index = d_equalityEngine.getRepresentative(node[1]);
+ if (index.isConst()) {
+ CTNodeList* temp;
+ CNodeNListMap::iterator it = d_constReads.find(index);
+ if (it == d_constReads.end()) {
+ temp = new(true) CTNodeList(d_constReadsContext);
+ d_constReads[index] = temp;
+ }
+ else {
+ temp = (*it).second;
+ }
+ temp->push_back(node);
+ d_constReadsList.push_back(node);
+ }
+ else {
+ d_reads.push_back(node);
+ }
+
Assert((d_isPreRegistered.insert(node), true));
checkRowForIndex(node[1], store);
break;
@@ -523,19 +551,19 @@ void TheoryArrays::preRegisterTermInternal(TNode node)
throw LogicException("Array theory solver does not yet support non-constant default values for arrays");
}
d_infoMap.setConstArr(node, node);
- d_equalityEngine.addTriggerTerm(node, THEORY_ARRAY);
d_mayEqualEqualityEngine.addTerm(node);
Assert(d_mayEqualEqualityEngine.getRepresentative(node) == node);
+ d_equalityEngine.addTriggerTerm(node, THEORY_ARRAY);
d_defValues[node] = defaultValue;
break;
}
default:
// Variables etc
if (node.getType().isArray()) {
- d_equalityEngine.addTriggerTerm(node, THEORY_ARRAY);
- Assert(d_equalityEngine.getSize(node) == 1);
// The may equal needs the node
d_mayEqualEqualityEngine.addTerm(node);
+ d_equalityEngine.addTriggerTerm(node, THEORY_ARRAY);
+ Assert(d_equalityEngine.getSize(node) == 1);
}
else {
d_equalityEngine.addTerm(node);
@@ -604,6 +632,76 @@ EqualityStatus TheoryArrays::getEqualityStatus(TNode a, TNode b) {
}
+void TheoryArrays::checkPair(TNode r1, TNode r2)
+{
+ Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): checking reads " << r1 << " and " << r2 << std::endl;
+
+ TNode x = r1[1];
+ TNode y = r2[1];
+ Assert(d_equalityEngine.isTriggerTerm(x, THEORY_ARRAY));
+
+ if (d_equalityEngine.hasTerm(x) && d_equalityEngine.hasTerm(y) &&
+ (d_equalityEngine.areEqual(x,y) || d_equalityEngine.areDisequal(x,y,false))) {
+ Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): equality known, skipping" << std::endl;
+ return;
+ }
+
+ // If the terms are already known to be equal, we are also in good shape
+ if (d_equalityEngine.areEqual(r1, r2)) {
+ Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): equal, skipping" << std::endl;
+ return;
+ }
+
+ if (r1[0] != r2[0]) {
+ // If arrays are known to be disequal, or cannot become equal, we can continue
+ Assert(d_mayEqualEqualityEngine.hasTerm(r1[0]) && d_mayEqualEqualityEngine.hasTerm(r2[0]));
+ if (r1[0].getType() != r2[0].getType() ||
+ d_equalityEngine.areDisequal(r1[0], r2[0], false)) {
+ Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): arrays can't be equal, skipping" << std::endl;
+ return;
+ }
+ else if (!d_mayEqualEqualityEngine.areEqual(r1[0], r2[0])) {
+ return;
+ }
+ }
+
+ if (!d_equalityEngine.isTriggerTerm(y, THEORY_ARRAY)) {
+ Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): not connected to shared terms, skipping" << std::endl;
+ return;
+ }
+
+ // Get representative trigger terms
+ TNode x_shared = d_equalityEngine.getTriggerTermRepresentative(x, THEORY_ARRAY);
+ TNode y_shared = d_equalityEngine.getTriggerTermRepresentative(y, THEORY_ARRAY);
+ EqualityStatus eqStatusDomain = d_valuation.getEqualityStatus(x_shared, y_shared);
+ switch (eqStatusDomain) {
+ case EQUALITY_TRUE_AND_PROPAGATED:
+ // Should have been propagated to us
+ Assert(false);
+ break;
+ case EQUALITY_TRUE:
+ // Missed propagation - need to add the pair so that theory engine can force propagation
+ Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): missed propagation" << std::endl;
+ break;
+ case EQUALITY_FALSE_AND_PROPAGATED:
+ // Should have been propagated to us
+ Assert(false);
+ case EQUALITY_FALSE:
+ case EQUALITY_FALSE_IN_MODEL:
+ // This is unlikely, but I think it could happen
+ Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): checkPair called when false in model" << std::endl;
+ return;
+ default:
+ // Covers EQUALITY_TRUE_IN_MODEL (common case) and EQUALITY_UNKNOWN
+ break;
+ }
+
+ // Add this pair
+ Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): adding to care-graph" << std::endl;
+ addCarePair(x_shared, y_shared);
+}
+
+
void TheoryArrays::computeCareGraph()
{
if (d_sharedArrays.size() > 0) {
@@ -630,93 +728,69 @@ void TheoryArrays::computeCareGraph()
}
if (d_sharedTerms) {
- vector< pair<TNode, TNode> > currentPairs;
+ // Synchronize d_constReadsContext with SAT context
+ Assert(d_constReadsContext->getLevel() <= getSatContext()->getLevel());
+ while (d_constReadsContext->getLevel() < getSatContext()->getLevel()) {
+ d_constReadsContext->push();
+ }
// Go through the read terms and see if there are any to split on
+
+ // Give constReadsContext a push so that all the work it does here is erased - models can change if context changes at all
+ // The context is popped at the end. If this loop is interrupted for some reason, we have to make sure the context still
+ // gets popped or the solver will be in an inconsistent state
+ d_constReadsContext->push();
unsigned size = d_reads.size();
for (unsigned i = 0; i < size; ++ i) {
TNode r1 = d_reads[i];
- // Make sure shared terms were identified correctly
- // Assert(theoryOf(r1[0]) == THEORY_ARRAY || isShared(r1[0]));
- // Assert(theoryOf(r1[1]) == THEORY_ARRAY ||
- // d_sharedOther.find(r1[1]) != d_sharedOther.end());
+ Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): checking read " << r1 << std::endl;
+ Assert(d_equalityEngine.hasTerm(r1));
+ TNode x = r1[1];
- for (unsigned j = i + 1; j < size; ++ j) {
- TNode r2 = d_reads[j];
-
- Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): checking reads " << r1 << " and " << r2 << std::endl;
+ if (!d_equalityEngine.isTriggerTerm(x, THEORY_ARRAY)) {
+ Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): not connected to shared terms, skipping" << std::endl;
+ continue;
+ }
+ Node x_shared = d_equalityEngine.getTriggerTermRepresentative(x, THEORY_ARRAY);
- // If the terms are already known to be equal, we are also in good shape
- if (d_equalityEngine.hasTerm(r1) && d_equalityEngine.hasTerm(r2) && d_equalityEngine.areEqual(r1, r2)) {
- Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): equal, skipping" << std::endl;
- continue;
+ // Get the model value of index and find all reads that read from that same model value: these are the pairs we have to check
+ // Also, insert this read in the list at the proper index
+
+ if (!x_shared.isConst()) {
+ x_shared = d_valuation.getModelValue(x_shared);
+ }
+ if (!x_shared.isNull()) {
+ CTNodeList* temp;
+ CNodeNListMap::iterator it = d_constReads.find(x_shared);
+ if (it == d_constReads.end()) {
+ // This is the only x_shared with this model value - no need to create any splits
+ temp = new(true) CTNodeList(d_constReadsContext);
+ d_constReads[x_shared] = temp;
}
-
- if (r1[0] != r2[0]) {
- // If arrays are known to be disequal, or cannot become equal, we can continue
- Assert(d_mayEqualEqualityEngine.hasTerm(r1[0]) && d_mayEqualEqualityEngine.hasTerm(r2[0]));
- if (r1[0].getType() != r2[0].getType() ||
- d_equalityEngine.areDisequal(r1[0], r2[0], false)) {
- Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): arrays can't be equal, skipping" << std::endl;
- continue;
- }
- else if (!d_mayEqualEqualityEngine.areEqual(r1[0], r2[0])) {
- if (r2.getType().getCardinality().isInfinite()) {
- continue;
- }
- // TODO: add a disequality split for these two arrays
- continue;
+ else {
+ temp = (*it).second;
+ for (size_t j = 0; j < temp->size(); ++j) {
+ checkPair(r1, (*temp)[j]);
}
}
-
- TNode x = r1[1];
- TNode y = r2[1];
-
- if (!d_equalityEngine.isTriggerTerm(x, THEORY_ARRAY) || !d_equalityEngine.isTriggerTerm(y, THEORY_ARRAY)) {
- Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): not connected to shared terms, skipping" << std::endl;
- continue;
- }
-
- EqualityStatus eqStatus = getEqualityStatus(x, y);
-
- if (eqStatus != EQUALITY_UNKNOWN) {
- Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): equality status known, skipping" << std::endl;
- continue;
+ temp->push_back(r1);
+ }
+ else {
+ // We don't know the model value for x. Just do brute force examination of all pairs of reads
+ for (unsigned j = 0; j < size; ++j) {
+ TNode r2 = d_reads[j];
+ Assert(d_equalityEngine.hasTerm(r2));
+ checkPair(r1,r2);
}
-
- // Get representative trigger terms
- TNode x_shared = d_equalityEngine.getTriggerTermRepresentative(x, THEORY_ARRAY);
- TNode y_shared = d_equalityEngine.getTriggerTermRepresentative(y, THEORY_ARRAY);
- EqualityStatus eqStatusDomain = d_valuation.getEqualityStatus(x_shared, y_shared);
- switch (eqStatusDomain) {
- case EQUALITY_TRUE_AND_PROPAGATED:
- // Should have been propagated to us
- Assert(false);
- break;
- case EQUALITY_TRUE:
- // Missed propagation - need to add the pair so that theory engine can force propagation
- Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): missed propagation" << std::endl;
- break;
- case EQUALITY_FALSE_AND_PROPAGATED:
- // Should have been propagated to us
- Assert(false);
- case EQUALITY_FALSE:
- case EQUALITY_FALSE_IN_MODEL:
- // Don't need to include this pair
- if (options::arraysReduceSharing()) {
- continue;
- }
- default:
- break;
+ for (unsigned j = 0; j < d_constReadsList.size(); ++j) {
+ TNode r2 = d_constReadsList[j];
+ Assert(d_equalityEngine.hasTerm(r2));
+ checkPair(r1,r2);
}
-
-
- // Otherwise, add this pair
- Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): adding to care-graph" << std::endl;
- addCarePair(x_shared, y_shared);
}
}
+ d_constReadsContext->pop();
}
}
@@ -957,7 +1031,7 @@ void TheoryArrays::check(Effort e) {
if (done() && !fullEffort(e)) {
return;
}
- TimerStat::CodeTimer codeTimer(d_checkTimer);
+ TimerStat::CodeTimer checkTimer(d_checkTime);
while (!done() && !d_conflict)
{
@@ -1036,7 +1110,9 @@ void TheoryArrays::check(Effort e) {
// generate the lemmas on the worklist
Trace("arrays-lem")<<"Arrays::discharging lemmas: "<<d_RowQueue.size()<<"\n";
while (d_RowQueue.size() > 0 && !d_conflict) {
- dischargeLemmas();
+ if (dischargeLemmas()) {
+ break;
+ }
}
}
@@ -2498,8 +2574,9 @@ Node TheoryArrays::getNextDecisionRequest() {
}
-void TheoryArrays::dischargeLemmas()
+bool TheoryArrays::dischargeLemmas()
{
+ bool lemmasAdded = false;
size_t sz = d_RowQueue.size();
for (unsigned count = 0; count < sz; ++count) {
RowLemmaType l = d_RowQueue.front();
@@ -2580,7 +2657,12 @@ void TheoryArrays::dischargeLemmas()
d_RowAlreadyAdded.insert(l);
d_out->lemma(lem);
++d_numRow;
+ lemmasAdded = true;
+ if (options::arraysReduceSharing()) {
+ return true;
+ }
}
+ return lemmasAdded;
}
void TheoryArrays::conflict(TNode a, TNode b) {
diff --git a/src/theory/arrays/theory_arrays.h b/src/theory/arrays/theory_arrays.h
index 649232dae..b2e039912 100644
--- a/src/theory/arrays/theory_arrays.h
+++ b/src/theory/arrays/theory_arrays.h
@@ -123,8 +123,6 @@ class TheoryArrays : public Theory {
IntStat d_numSetModelValSplits;
/** conflicts in setModelVal */
IntStat d_numSetModelValConflicts;
- /** time spent in check() */
- TimerStat d_checkTimer;
public:
@@ -215,6 +213,9 @@ class TheoryArrays : public Theory {
/** Equaltity engine for determining if two arrays might be equal */
eq::EqualityEngine d_mayEqualEqualityEngine;
+ // Helper for computeCareGraph
+ void checkPair(TNode r1, TNode r2);
+
public:
void addSharedTerm(TNode t);
@@ -347,7 +348,35 @@ class TheoryArrays : public Theory {
CDNodeSet d_sharedArrays;
CDNodeSet d_sharedOther;
context::CDO<bool> d_sharedTerms;
+
+ // Map from constant values to read terms that read from that values equal to that constant value in the current model
+ // When a new read term is created, we check the index to see if we know the model value. If so, we add it to d_constReads (and d_constReadsList)
+ // If not, we push it onto d_reads and figure out where it goes at computeCareGraph time.
+ // d_constReadsList is used as a backup in case we can't compute the model at computeCareGraph time.
+ typedef std::hash_map<Node, CTNodeList*, NodeHashFunction> CNodeNListMap;
+ CNodeNListMap d_constReads;
context::CDList<TNode> d_reads;
+ context::CDList<TNode> d_constReadsList;
+ context::Context* d_constReadsContext;
+ /** Helper class to keep d_constReadsContext in sync with satContext */
+ class ContextPopper : public context::ContextNotifyObj {
+ context::Context* d_satContext;
+ context::Context* d_contextToPop;
+ protected:
+ void contextNotifyPop() {
+ if (d_contextToPop->getLevel() > d_satContext->getLevel()) {
+ d_contextToPop->pop();
+ }
+ }
+ public:
+ ContextPopper(context::Context* context, context::Context* contextToPop)
+ :context::ContextNotifyObj(context), d_satContext(context),
+ d_contextToPop(contextToPop)
+ {}
+
+ };/* class ContextPopper */
+ ContextPopper d_contextPopper;
+
std::hash_map<Node, Node, NodeHashFunction> d_skolemCache;
context::CDO<unsigned> d_skolemIndex;
std::vector<Node> d_skolemAssertions;
@@ -376,7 +405,7 @@ class TheoryArrays : public Theory {
void checkRowForIndex(TNode i, TNode a);
void checkRowLemmas(TNode a, TNode b);
void queueRowLemma(RowLemmaType lem);
- void dischargeLemmas();
+ bool dischargeLemmas();
std::vector<Node> d_decisions;
bool d_inCheckModel;
diff --git a/src/theory/bv/bitblaster_template.h b/src/theory/bv/bitblaster_template.h
index ea31e3821..79434102e 100644
--- a/src/theory/bv/bitblaster_template.h
+++ b/src/theory/bv/bitblaster_template.h
@@ -28,6 +28,7 @@
#include "prop/sat_solver.h"
#include "theory/valuation.h"
#include "theory/theory_registrar.h"
+#include "util/resource_manager.h"
class Abc_Obj_t_;
typedef Abc_Obj_t_ Abc_Obj_t;
@@ -134,6 +135,7 @@ class TLazyBitblaster : public TBitblaster<Node> {
{}
bool notify(prop::SatLiteral lit);
void notify(prop::SatClause& clause);
+ void spendResource();
void safePoint();
};
@@ -143,8 +145,9 @@ class TLazyBitblaster : public TBitblaster<Node> {
prop::NullRegistrar* d_nullRegistrar;
context::Context* d_nullContext;
// sat solver used for bitblasting and associated CnfStream
- prop::BVSatSolverInterface* d_satSolver;
- prop::CnfStream* d_cnfStream;
+ prop::BVSatSolverInterface* d_satSolver;
+ prop::BVSatSolverInterface::Notify* d_satSolverNotify;
+ prop::CnfStream* d_cnfStream;
AssertionList* d_assertedAtoms; /**< context dependent list storing the atoms
currently asserted by the DPLL SAT solver. */
@@ -227,7 +230,8 @@ private:
Statistics(const std::string& name);
~Statistics();
};
- std::string d_name;
+ std::string d_name;
+public:
Statistics d_statistics;
};
@@ -236,6 +240,9 @@ public:
MinisatEmptyNotify() {}
bool notify(prop::SatLiteral lit) { return true; }
void notify(prop::SatClause& clause) { }
+ void spendResource() {
+ NodeManager::currentResourceManager()->spendResource();
+ }
void safePoint() {}
};
@@ -440,8 +447,10 @@ Node TBitblaster<T>::getTermModel(TNode node, bool fullModel) {
// if it is a leaf may ask for fullModel
value = getModelFromSatSolver(node, fullModel);
Debug("bv-equality-status")<< "TLazyBitblaster::getTermModel from VarValue" << node <<" => " << value <<"\n";
- Assert (!value.isNull());
- d_modelCache[node] = value;
+ Assert ((fullModel && !value.isNull() && value.isConst()) || !fullModel);
+ if (!value.isNull()) {
+ d_modelCache[node] = value;
+ }
return value;
}
Assert (node.getType().isBitVector());
diff --git a/src/theory/bv/bv_eager_solver.cpp b/src/theory/bv/bv_eager_solver.cpp
index f9f8ff581..57a635c20 100644
--- a/src/theory/bv/bv_eager_solver.cpp
+++ b/src/theory/bv/bv_eager_solver.cpp
@@ -67,6 +67,7 @@ bool EagerBitblastSolver::isInitialized() {
}
void EagerBitblastSolver::assertFormula(TNode formula) {
+ d_bv->spendResource();
Assert (isInitialized());
Debug("bitvector-eager") << "EagerBitblastSolver::assertFormula "<< formula <<"\n";
d_assertionSet.insert(formula);
diff --git a/src/theory/bv/bv_inequality_graph.cpp b/src/theory/bv/bv_inequality_graph.cpp
index f29b8d467..dca679194 100644
--- a/src/theory/bv/bv_inequality_graph.cpp
+++ b/src/theory/bv/bv_inequality_graph.cpp
@@ -263,6 +263,7 @@ ReasonId InequalityGraph::registerReason(TNode reason) {
if (d_reasonToIdMap.find(reason) != d_reasonToIdMap.end()) {
return d_reasonToIdMap[reason];
}
+ d_reasonSet.insert(reason);
ReasonId id = d_reasonNodes.size();
d_reasonNodes.push_back(reason);
d_reasonToIdMap[reason] = id;
diff --git a/src/theory/bv/bv_quick_check.cpp b/src/theory/bv/bv_quick_check.cpp
index cc294306a..6231b8e46 100644
--- a/src/theory/bv/bv_quick_check.cpp
+++ b/src/theory/bv/bv_quick_check.cpp
@@ -25,10 +25,10 @@ using namespace CVC4::theory::bv;
using namespace CVC4::prop;
BVQuickCheck::BVQuickCheck(const std::string& name, theory::bv::TheoryBV* bv)
- : d_ctx(new context::Context())
- , d_bitblaster(new TLazyBitblaster(d_ctx, bv, name, true))
+ : d_ctx()
+ , d_bitblaster(new TLazyBitblaster(&d_ctx, bv, name, true))
, d_conflict()
- , d_inConflict(d_ctx, false)
+ , d_inConflict(&d_ctx, false)
{}
@@ -100,11 +100,11 @@ bool BVQuickCheck::addAssertion(TNode assertion) {
void BVQuickCheck::push() {
- d_ctx->push();
+ d_ctx.push();
}
void BVQuickCheck::pop() {
- d_ctx->pop();
+ d_ctx.pop();
}
BVQuickCheck::vars_iterator BVQuickCheck::beginVars() {
@@ -114,8 +114,8 @@ BVQuickCheck::vars_iterator BVQuickCheck::endVars() {
return d_bitblaster->endVars();
}
-Node BVQuickCheck::getVarValue(TNode var) {
- return d_bitblaster->getTermModel(var, true);
+Node BVQuickCheck::getVarValue(TNode var, bool fullModel) {
+ return d_bitblaster->getTermModel(var, fullModel);
}
@@ -130,8 +130,8 @@ void BVQuickCheck::clearSolver() {
}
void BVQuickCheck::popToZero() {
- while (d_ctx->getLevel() > 0) {
- d_ctx->pop();
+ while (d_ctx.getLevel() > 0) {
+ d_ctx.pop();
}
}
@@ -140,8 +140,8 @@ void BVQuickCheck::collectModelInfo(theory::TheoryModel* model, bool fullModel)
}
BVQuickCheck::~BVQuickCheck() {
+ clearSolver();
delete d_bitblaster;
- delete d_ctx;
}
QuickXPlain::QuickXPlain(const std::string& name, BVQuickCheck* solver, unsigned long budget)
@@ -150,9 +150,9 @@ QuickXPlain::QuickXPlain(const std::string& name, BVQuickCheck* solver, unsigned
, d_numCalled(0)
, d_minRatioSum(0)
, d_numConflicts(0)
- , d_period(20)
- , d_thresh(0.7)
- , d_hardThresh(0.9)
+ // , d_period(20)
+ // , d_thresh(0.7)
+ // , d_hardThresh(0.9)
, d_statistics(name)
{}
QuickXPlain::~QuickXPlain() {}
diff --git a/src/theory/bv/bv_quick_check.h b/src/theory/bv/bv_quick_check.h
index 6c32fbb4d..01d772cb9 100644
--- a/src/theory/bv/bv_quick_check.h
+++ b/src/theory/bv/bv_quick_check.h
@@ -39,7 +39,7 @@ class TLazyBitblaster;
class TheoryBV;
class BVQuickCheck {
- context::Context* d_ctx;
+ context::Context d_ctx;
TLazyBitblaster* d_bitblaster;
Node d_conflict;
context::CDO<bool> d_inConflict;
@@ -103,7 +103,7 @@ public:
vars_iterator beginVars();
vars_iterator endVars();
- Node getVarValue(TNode var);
+ Node getVarValue(TNode var, bool fullModel);
};
@@ -127,10 +127,10 @@ class QuickXPlain {
unsigned d_numCalled; // number of times called
double d_minRatioSum; // sum of minimization ratio for computing average min ratio
unsigned d_numConflicts; // number of conflicts (including when minimization not applied)
- unsigned d_period; // after how many conflicts to try minimizing again
+ // unsigned d_period; // after how many conflicts to try minimizing again
- double d_thresh; // if minimization ratio is less, increase period
- double d_hardThresh; // decrease period if minimization ratio is greater than this
+ // double d_thresh; // if minimization ratio is less, increase period
+ // double d_hardThresh; // decrease period if minimization ratio is greater than this
Statistics d_statistics;
diff --git a/src/theory/bv/bv_subtheory_algebraic.cpp b/src/theory/bv/bv_subtheory_algebraic.cpp
index e8acf268f..154f3d7f3 100644
--- a/src/theory/bv/bv_subtheory_algebraic.cpp
+++ b/src/theory/bv/bv_subtheory_algebraic.cpp
@@ -557,6 +557,7 @@ bool AlgebraicSolver::isSubstitutableIn(TNode node, TNode in) {
void AlgebraicSolver::processAssertions(std::vector<WorklistElement>& worklist, SubstitutionEx& subst) {
bool changed = true;
while(changed) {
+ // d_bv->spendResource();
changed = false;
for (unsigned i = 0; i < worklist.size(); ++i) {
// apply current substitutions
@@ -694,17 +695,22 @@ void AlgebraicSolver::collectModelInfo(TheoryModel* model, bool fullModel) {
Debug("bitvector-model") << "Model:\n";
for (BVQuickCheck::vars_iterator it = d_quickSolver->beginVars(); it != d_quickSolver->endVars(); ++it) {
TNode var = *it;
- Node value = d_quickSolver->getVarValue(var);
- Debug("bitvector-model") << " " << var << " => " << value << "\n";
- Assert (value.getKind() == kind::CONST_BITVECTOR);
- d_modelMap->addSubstitution(var, value);
+ Node value = d_quickSolver->getVarValue(var, true);
+ Assert (!value.isNull() || !fullModel);
+
+ // may be a shared term that did not appear in the current assertions
+ if (!value.isNull()) {
+ Debug("bitvector-model") << " " << var << " => " << value << "\n";
+ Assert (value.getKind() == kind::CONST_BITVECTOR);
+ d_modelMap->addSubstitution(var, value);
+ }
}
Debug("bitvector-model") << "Final Model:\n";
for (unsigned i = 0; i < variables.size(); ++i) {
TNode current = values[i];
TNode subst = Rewriter::rewrite(d_modelMap->apply(current));
- Debug("bitvector-model") << " " << variables[i] << " => " << subst << "\n";
+ Debug("bitvector-model") << "AlgebraicSolver: " << variables[i] << " => " << subst << "\n";
// Doesn't have to be constant as it may be irrelevant
// Assert (subst.getKind() == kind::CONST_BITVECTOR);
model->assertEquality(variables[i], subst, true);
diff --git a/src/theory/bv/bv_subtheory_bitblast.cpp b/src/theory/bv/bv_subtheory_bitblast.cpp
index 35542fc68..c86572ead 100644
--- a/src/theory/bv/bv_subtheory_bitblast.cpp
+++ b/src/theory/bv/bv_subtheory_bitblast.cpp
@@ -103,8 +103,11 @@ void BitblastSolver::bitblastQueue() {
// don't bit-blast lemma atoms
continue;
}
- Debug("bitblast-queue") << "Bitblasting atom " << atom <<"\n";
- d_bitblaster->bbAtom(atom);
+ Debug("bitblast-queue") << "Bitblasting atom " << atom <<"\n";
+ {
+ TimerStat::CodeTimer codeTimer(d_bitblaster->d_statistics.d_bitblastTimer);
+ d_bitblaster->bbAtom(atom);
+ }
}
}
@@ -149,6 +152,7 @@ bool BitblastSolver::check(Theory::Effort e) {
// We need to ensure we are fully propagated, so propagate now
if (d_useSatPropagation) {
+ d_bv->spendResource();
bool ok = d_bitblaster->propagate();
if (!ok) {
std::vector<TNode> conflictAtoms;
@@ -219,7 +223,11 @@ void BitblastSolver::collectModelInfo(TheoryModel* m, bool fullModel) {
Node BitblastSolver::getModelValue(TNode node)
{
- Node val = d_bitblaster->getTermModel(node, false);
+ if (d_bv->d_invalidateModelCache.get()) {
+ d_bitblaster->invalidateModelCache();
+ }
+ d_bv->d_invalidateModelCache.set(false);
+ Node val = d_bitblaster->getTermModel(node, true);
return val;
}
diff --git a/src/theory/bv/bv_subtheory_core.cpp b/src/theory/bv/bv_subtheory_core.cpp
index d2c79fec2..938a93b85 100644
--- a/src/theory/bv/bv_subtheory_core.cpp
+++ b/src/theory/bv/bv_subtheory_core.cpp
@@ -166,6 +166,9 @@ bool CoreSolver::decomposeFact(TNode fact) {
bool CoreSolver::check(Theory::Effort e) {
Trace("bitvector::core") << "CoreSolver::check \n";
+
+ d_bv->spendResource();
+
d_checkCalled = true;
Assert (!d_bv->inConflict());
++(d_statistics.d_numCallstoCheck);
diff --git a/src/theory/bv/bv_subtheory_inequality.cpp b/src/theory/bv/bv_subtheory_inequality.cpp
index 4f9eb0823..660551fe2 100644
--- a/src/theory/bv/bv_subtheory_inequality.cpp
+++ b/src/theory/bv/bv_subtheory_inequality.cpp
@@ -29,6 +29,7 @@ using namespace CVC4::theory::bv::utils;
bool InequalitySolver::check(Theory::Effort e) {
Debug("bv-subtheory-inequality") << "InequalitySolveR::check("<< e <<")\n";
++(d_statistics.d_numCallstoCheck);
+ d_bv->spendResource();
bool ok = true;
while (!done() && ok) {
@@ -137,14 +138,14 @@ void InequalitySolver::assertFact(TNode fact) {
}
bool InequalitySolver::isInequalityOnly(TNode node) {
- if (d_ineqOnlyCache.find(node) != d_ineqOnlyCache.end()) {
- return d_ineqOnlyCache[node];
- }
-
if (node.getKind() == kind::NOT) {
node = node[0];
}
+ if (node.getAttribute(IneqOnlyComputedAttribute())) {
+ return node.getAttribute(IneqOnlyAttribute());
+ }
+
if (node.getKind() != kind::EQUAL &&
node.getKind() != kind::BITVECTOR_ULT &&
node.getKind() != kind::BITVECTOR_ULE &&
@@ -152,13 +153,15 @@ bool InequalitySolver::isInequalityOnly(TNode node) {
node.getKind() != kind::SELECT &&
node.getKind() != kind::STORE &&
node.getMetaKind() != kind::metakind::VARIABLE) {
+ // not worth caching
return false;
}
bool res = true;
- for (unsigned i = 0; i < node.getNumChildren(); ++i) {
+ for (unsigned i = 0; res && i < node.getNumChildren(); ++i) {
res = res && isInequalityOnly(node[i]);
}
- d_ineqOnlyCache[node] = res;
+ node.setAttribute(IneqOnlyComputedAttribute(), true);
+ node.setAttribute(IneqOnlyAttribute(), res);
return res;
}
diff --git a/src/theory/bv/bv_subtheory_inequality.h b/src/theory/bv/bv_subtheory_inequality.h
index b9195c7d1..c9d9dabd3 100644
--- a/src/theory/bv/bv_subtheory_inequality.h
+++ b/src/theory/bv/bv_subtheory_inequality.h
@@ -22,11 +22,20 @@
#include "theory/bv/bv_subtheory.h"
#include "theory/bv/bv_inequality_graph.h"
#include "context/cdhashset.h"
+#include "expr/attribute.h"
namespace CVC4 {
namespace theory {
namespace bv {
+/** Cache for InequalitySolver::isInequalityOnly() */
+struct IneqOnlyAttributeId {};
+typedef expr::Attribute<IneqOnlyAttributeId, bool> IneqOnlyAttribute;
+
+/** Whether the above has been computed yet or not for an expr */
+struct IneqOnlyComputedAttributeId {};
+typedef expr::Attribute<IneqOnlyComputedAttributeId, bool> IneqOnlyComputedAttribute;
+
class InequalitySolver: public SubtheorySolver {
struct Statistics {
IntStat d_numCallstoCheck;
@@ -38,7 +47,6 @@ class InequalitySolver: public SubtheorySolver {
InequalityGraph d_inequalityGraph;
context::CDHashMap<Node, TNode, NodeHashFunction> d_explanations;
context::CDO<bool> d_isComplete;
- __gnu_cxx::hash_map<TNode, bool, TNodeHashFunction> d_ineqOnlyCache;
typedef __gnu_cxx::hash_set<TNode, TNodeHashFunction> TNodeSet;
TNodeSet d_ineqTerms;
bool isInequalityOnly(TNode node);
@@ -51,7 +59,6 @@ public:
d_inequalityGraph(c),
d_explanations(c),
d_isComplete(c, true),
- d_ineqOnlyCache(),
d_ineqTerms(),
d_statistics()
{}
diff --git a/src/theory/bv/eager_bitblaster.cpp b/src/theory/bv/eager_bitblaster.cpp
index 877baec4e..065d5d5ef 100644
--- a/src/theory/bv/eager_bitblaster.cpp
+++ b/src/theory/bv/eager_bitblaster.cpp
@@ -103,6 +103,7 @@ void EagerBitblaster::bbTerm(TNode node, Bits& bits) {
return;
}
+ d_bv->spendResource();
Debug("bitvector-bitblast") << "Bitblasting node " << node <<"\n";
d_termBBStrategies[node.getKind()] (node, bits, this);
diff --git a/src/theory/bv/lazy_bitblaster.cpp b/src/theory/bv/lazy_bitblaster.cpp
index f8927284f..fbebcd952 100644
--- a/src/theory/bv/lazy_bitblaster.cpp
+++ b/src/theory/bv/lazy_bitblaster.cpp
@@ -51,11 +51,11 @@ TLazyBitblaster::TLazyBitblaster(context::Context* c, bv::TheoryBV* bv, const st
d_nullRegistrar,
d_nullContext);
- prop::BVSatSolverInterface::Notify* notify = d_emptyNotify ?
+ d_satSolverNotify = d_emptyNotify ?
(prop::BVSatSolverInterface::Notify*) new MinisatEmptyNotify() :
(prop::BVSatSolverInterface::Notify*) new MinisatNotify(d_cnfStream, bv, this);
- d_satSolver->setNotify(notify);
+ d_satSolver->setNotify(d_satSolverNotify);
}
void TLazyBitblaster::setAbstraction(AbstractionModule* abs) {
@@ -67,6 +67,9 @@ TLazyBitblaster::~TLazyBitblaster() {
delete d_nullRegistrar;
delete d_nullContext;
delete d_satSolver;
+ delete d_satSolverNotify;
+ d_assertedAtoms->deleteSelf();
+ d_explanations->deleteSelf();
}
@@ -167,6 +170,7 @@ void TLazyBitblaster::bbTerm(TNode node, Bits& bits) {
return;
}
+ d_bv->spendResource();
Debug("bitvector-bitblast") << "Bitblasting node " << node <<"\n";
++d_statistics.d_numTerms;
@@ -352,6 +356,10 @@ void TLazyBitblaster::MinisatNotify::notify(prop::SatClause& clause) {
}
}
+void TLazyBitblaster::MinisatNotify::spendResource() {
+ d_bv->spendResource();
+}
+
void TLazyBitblaster::MinisatNotify::safePoint() {
d_bv->d_out->safePoint();
}
@@ -475,6 +483,7 @@ void TLazyBitblaster::collectModelInfo(TheoryModel* m, bool fullModel) {
void TLazyBitblaster::clearSolver() {
Assert (d_ctx->getLevel() == 0);
delete d_satSolver;
+ delete d_satSolverNotify;
delete d_cnfStream;
d_assertedAtoms->deleteSelf();
d_assertedAtoms = new(true) context::CDList<prop::SatLiteral>(d_ctx);
@@ -482,16 +491,17 @@ void TLazyBitblaster::clearSolver() {
d_explanations = new(true) ExplanationMap(d_ctx);
d_bbAtoms.clear();
d_variables.clear();
- d_termCache.clear();
+ d_termCache.clear();
+ invalidateModelCache();
// recreate sat solver
d_satSolver = prop::SatSolverFactory::createMinisat(d_ctx);
d_cnfStream = new prop::TseitinCnfStream(d_satSolver,
- new prop::NullRegistrar(),
- new context::Context());
+ d_nullRegistrar,
+ d_nullContext);
- prop::BVSatSolverInterface::Notify* notify = d_emptyNotify ?
+ d_satSolverNotify = d_emptyNotify ?
(prop::BVSatSolverInterface::Notify*) new MinisatEmptyNotify() :
(prop::BVSatSolverInterface::Notify*) new MinisatNotify(d_cnfStream, d_bv, this);
- d_satSolver->setNotify(notify);
+ d_satSolver->setNotify(d_satSolverNotify);
}
diff --git a/src/theory/bv/options b/src/theory/bv/options
index 775a46088..801dec0db 100644
--- a/src/theory/bv/options
+++ b/src/theory/bv/options
@@ -45,6 +45,9 @@ option bitvectorToBool --bv-to-bool bool :default false :read-write
option bitvectorDivByZeroConst --bv-div-zero-const bool :default false
always return -1 on division by zero
+expert-option bvExtractArithRewrite --bv-extract-arith bool :default false :read-write
+ enable rewrite pushing extract [i:0] over arithmetic operations (can blow up)
+
expert-option bvAbstraction --bv-abstraction bool :default false :read-write
mcm benchmark abstraction
diff --git a/src/theory/bv/theory_bv.cpp b/src/theory/bv/theory_bv.cpp
index 91150f663..08fe5f2e9 100644
--- a/src/theory/bv/theory_bv.cpp
+++ b/src/theory/bv/theory_bv.cpp
@@ -95,6 +95,7 @@ TheoryBV::~TheoryBV() {
for (unsigned i = 0; i < d_subtheories.size(); ++i) {
delete d_subtheories[i];
}
+ delete d_abstractionModule;
}
void TheoryBV::setMasterEqualityEngine(eq::EqualityEngine* eq) {
@@ -106,6 +107,10 @@ void TheoryBV::setMasterEqualityEngine(eq::EqualityEngine* eq) {
}
}
+void TheoryBV::spendResource() throw(UnsafeInterruptException) {
+ getOutputChannel().spendResource();
+}
+
TheoryBV::Statistics::Statistics():
d_avgConflictSize("theory::bv::AvgBVConflictSize"),
d_solveSubstitutions("theory::bv::NumberOfSolveSubstitutions", 0),
@@ -360,7 +365,9 @@ void TheoryBV::check(Effort e)
if (done() && !fullEffort(e)) {
return;
}
+ TimerStat::CodeTimer checkTimer(d_checkTime);
Debug("bitvector") << "TheoryBV::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
d_invalidateModelCache.set(true);
// if we are using the eager solver
diff --git a/src/theory/bv/theory_bv.h b/src/theory/bv/theory_bv.h
index a37a4019e..11d8cb895 100644
--- a/src/theory/bv/theory_bv.h
+++ b/src/theory/bv/theory_bv.h
@@ -103,6 +103,7 @@ private:
Statistics d_statistics;
+ void spendResource() throw(UnsafeInterruptException);
/**
* Return the uninterpreted function symbol corresponding to division-by-zero
@@ -218,6 +219,7 @@ private:
friend class CoreSolver;
friend class InequalitySolver;
friend class AlgebraicSolver;
+ friend class EagerBitblastSolver;
};/* class TheoryBV */
}/* CVC4::theory::bv namespace */
diff --git a/src/theory/bv/theory_bv_rewriter.cpp b/src/theory/bv/theory_bv_rewriter.cpp
index dc91c338b..86f2c6760 100644
--- a/src/theory/bv/theory_bv_rewriter.cpp
+++ b/src/theory/bv/theory_bv_rewriter.cpp
@@ -16,6 +16,7 @@
**/
#include "theory/theory.h"
+#include "theory/bv/options.h"
#include "theory/bv/theory_bv_rewriter.h"
#include "theory/bv/theory_bv_rewrite_rules.h"
#include "theory/bv/theory_bv_rewrite_rules_core.h"
@@ -178,10 +179,12 @@ RewriteResponse TheoryBVRewriter::RewriteExtract(TNode node, bool prerewrite) {
return RewriteResponse(REWRITE_AGAIN_FULL, resultNode);
}
- // if (RewriteRule<ExtractArith>::applies(node)) {
- // resultNode = RewriteRule<ExtractArith>::run<false>(node);
- // return RewriteResponse(REWRITE_AGAIN_FULL, resultNode);
- // }
+ if (options::bvExtractArithRewrite()) {
+ if (RewriteRule<ExtractArith>::applies(node)) {
+ resultNode = RewriteRule<ExtractArith>::run<false>(node);
+ return RewriteResponse(REWRITE_AGAIN_FULL, resultNode);
+ }
+ }
resultNode = LinearRewriteStrategy
diff --git a/src/theory/datatypes/theory_datatypes.cpp b/src/theory/datatypes/theory_datatypes.cpp
index 62f5ad3ff..a70343702 100644
--- a/src/theory/datatypes/theory_datatypes.cpp
+++ b/src/theory/datatypes/theory_datatypes.cpp
@@ -49,7 +49,7 @@ TheoryDatatypes::TheoryDatatypes(Context* c, UserContext* u, OutputChannel& out,
d_equalityEngine(d_notify, c, "theory::datatypes::TheoryDatatypes"),
d_labels( c ),
d_selector_apps( c ),
- d_consEqc( c ),
+ //d_consEqc( c ),
d_conflict( c, false ),
d_collectTermsCache( c ),
d_consTerms( c ),
@@ -60,7 +60,7 @@ TheoryDatatypes::TheoryDatatypes(Context* c, UserContext* u, OutputChannel& out,
d_equalityEngine.addFunctionKind(kind::APPLY_SELECTOR_TOTAL);
d_equalityEngine.addFunctionKind(kind::DT_SIZE);
d_equalityEngine.addFunctionKind(kind::APPLY_TESTER);
- d_equalityEngine.addFunctionKind(kind::APPLY_UF);
+ //d_equalityEngine.addFunctionKind(kind::APPLY_UF);
d_true = NodeManager::currentNM()->mkConst( true );
d_dtfCounter = 0;
@@ -123,6 +123,9 @@ void TheoryDatatypes::check(Effort e) {
if (done() && !fullEffort(e)) {
return;
}
+ d_addedLemma = false;
+
+ TimerStat::CodeTimer checkTimer(d_checkTime);
Trace("datatypes-debug") << "Check effort " << e << std::endl;
while(!done() && !d_conflict) {
@@ -148,14 +151,15 @@ void TheoryDatatypes::check(Effort e) {
flushPendingFacts();
}
- if( e == EFFORT_FULL && !d_conflict && !d_valuation.needCheck() ) {
+ if( e == EFFORT_FULL && !d_conflict && !d_addedLemma && !d_valuation.needCheck() ) {
//check for cycles
+ Assert( d_pending.empty() && d_pending_merge.empty() );
bool addedFact;
do {
checkCycles();
addedFact = !d_pending.empty() || !d_pending_merge.empty();
flushPendingFacts();
- if( d_conflict ){
+ if( d_conflict || d_addedLemma ){
return;
}
}while( addedFact );
@@ -170,9 +174,9 @@ void TheoryDatatypes::check(Effort e) {
TypeNode tn = n.getType();
if( DatatypesRewriter::isTypeDatatype( tn ) ){
Trace("datatypes-debug") << "Process equivalence class " << n << std::endl;
- EqcInfo* eqc = getOrMakeEqcInfo( n, true );
+ EqcInfo* eqc = getOrMakeEqcInfo( n );
//if there are more than 1 possible constructors for eqc
- if( eqc->d_constructor.get().isNull() && !hasLabel( eqc, n ) ) {
+ if( !hasLabel( eqc, n ) ){
Trace("datatypes-debug") << "No constructor..." << std::endl;
const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
@@ -191,7 +195,7 @@ void TheoryDatatypes::check(Effort e) {
if( consIndex==-1 ){
consIndex = j;
}
- if( !dt[ j ].isFinite() && !eqc->d_selectors ) {
+ if( !dt[ j ].isFinite() && ( !eqc || !eqc->d_selectors ) ) {
needSplit = false;
}
}
@@ -303,6 +307,7 @@ void TheoryDatatypes::flushPendingFacts(){
}
Trace("dt-lemma") << "Datatypes lemma : " << lem << std::endl;
d_out->lemma( lem );
+ d_addedLemma = true;
}else{
assertFact( fact, exp );
}
@@ -363,6 +368,7 @@ void TheoryDatatypes::preRegisterTerm(TNode n) {
} else {
// Function applications/predicates
d_equalityEngine.addTerm(n);
+ //d_equalityEngine.addTriggerTerm(n, THEORY_DATATYPES);
}
break;
}
@@ -532,11 +538,11 @@ Node TheoryDatatypes::ppRewrite(TNode in) {
void TheoryDatatypes::addSharedTerm(TNode t) {
Debug("datatypes") << "TheoryDatatypes::addSharedTerm(): "
<< t << " " << t.getType().isBoolean() << endl;
- if( t.getType().isBoolean() ){
+ //if( t.getType().isBoolean() ){
//d_equalityEngine.addTriggerPredicate(t, THEORY_DATATYPES);
- }else{
- d_equalityEngine.addTriggerTerm(t, THEORY_DATATYPES);
- }
+ //}else{
+ d_equalityEngine.addTriggerTerm(t, THEORY_DATATYPES);
+ //}
Debug("datatypes") << "TheoryDatatypes::addSharedTerm() finished" << std::endl;
}
@@ -649,7 +655,7 @@ void TheoryDatatypes::eqNotifyNewClass(TNode t){
}
}
*/
- d_consEqc[t] = true;
+ //d_consEqc[t] = true;
}
}
@@ -749,9 +755,9 @@ void TheoryDatatypes::merge( Node t1, Node t2 ){
if( d_conflict ){
return;
}
- d_consEqc[t1] = true;
+ //d_consEqc[t1] = true;
}
- d_consEqc[t2] = false;
+ //d_consEqc[t2] = false;
}
}else{
Debug("datatypes-debug") << "No eqc info for " << t1 << ", must create" << std::endl;
@@ -832,7 +838,7 @@ d_inst( c, false ), d_constructor( c, Node::null() ), d_selectors( c, false ){
}
bool TheoryDatatypes::hasLabel( EqcInfo* eqc, Node n ){
- return !eqc->d_constructor.get().isNull() || !getLabel( n ).isNull();
+ return ( eqc && !eqc->d_constructor.get().isNull() ) || !getLabel( n ).isNull();
}
Node TheoryDatatypes::getLabel( Node n ) {
@@ -847,13 +853,22 @@ Node TheoryDatatypes::getLabel( Node n ) {
}
int TheoryDatatypes::getLabelIndex( EqcInfo* eqc, Node n ){
- if( !eqc->d_constructor.get().isNull() ){
+ if( eqc && !eqc->d_constructor.get().isNull() ){
return Datatype::indexOf( eqc->d_constructor.get().getOperator().toExpr() );
}else{
return Datatype::indexOf( getLabel( n ).getOperator().toExpr() );
}
}
+bool TheoryDatatypes::hasTester( Node n ) {
+ NodeListMap::iterator lbl_i = d_labels.find( n );
+ if( lbl_i != d_labels.end() ){
+ return !(*(*lbl_i).second).empty();
+ }else{
+ return false;
+ }
+}
+
void TheoryDatatypes::getPossibleCons( EqcInfo* eqc, Node n, std::vector< bool >& pcons ){
const Datatype& dt = ((DatatypeType)(n.getType()).toType()).getDatatype();
pcons.resize( dt.getNumConstructors(), !hasLabel( eqc, n ) );
@@ -1059,15 +1074,14 @@ void TheoryDatatypes::collapseSelector( Node s, Node c ) {
}
EqualityStatus TheoryDatatypes::getEqualityStatus(TNode a, TNode b){
- if( d_equalityEngine.hasTerm(a) && d_equalityEngine.hasTerm(b) ){
- if (d_equalityEngine.areEqual(a, b)) {
- // The terms are implied to be equal
- return EQUALITY_TRUE;
- }
- if (d_equalityEngine.areDisequal(a, b, false)) {
- // The terms are implied to be dis-equal
- return EQUALITY_FALSE;
- }
+ Assert(d_equalityEngine.hasTerm(a) && d_equalityEngine.hasTerm(b));
+ if (d_equalityEngine.areEqual(a, b)) {
+ // The terms are implied to be equal
+ return EQUALITY_TRUE;
+ }
+ if (d_equalityEngine.areDisequal(a, b, false)) {
+ // The terms are implied to be dis-equal
+ return EQUALITY_FALSE;
}
return EQUALITY_FALSE_IN_MODEL;
}
@@ -1081,6 +1095,7 @@ void TheoryDatatypes::computeCareGraph(){
TNode f1 = r==0 ? d_consTerms[i] : d_selTerms[i];
for( unsigned j=i+1; j<functionTerms; j++ ){
TNode f2 = r==0 ? d_consTerms[j] : d_selTerms[j];
+ Trace("dt-cg-debug") << "dt-cg: " << f1 << " and " << f2 << " " << (f1.getOperator()==f2.getOperator()) << " " << areEqual( f1, f2 ) << std::endl;
if( f1.getOperator()==f2.getOperator() && !areEqual( f1, f2 ) ){
Trace("dt-cg") << "Check " << f1 << " and " << f2 << std::endl;
bool somePairIsDisequal = false;
@@ -1088,17 +1103,23 @@ void TheoryDatatypes::computeCareGraph(){
for (unsigned k = 0; k < f1.getNumChildren(); ++ k) {
TNode x = f1[k];
TNode y = f2[k];
+ Assert(d_equalityEngine.hasTerm(x));
+ Assert(d_equalityEngine.hasTerm(y));
if( areDisequal(x, y) ){
somePairIsDisequal = true;
break;
- }else if( !areEqual( x, y ) ){
+ }else if( !d_equalityEngine.areEqual( x, y ) ){
Trace("dt-cg") << "Arg #" << k << " is " << x << " " << y << std::endl;
- if( d_equalityEngine.isTriggerTerm(x, THEORY_UF) && d_equalityEngine.isTriggerTerm(y, THEORY_UF) ){
- EqualityStatus eqStatus = d_valuation.getEqualityStatus(x, y);
- if( eqStatus!=EQUALITY_UNKNOWN ){
- TNode x_shared = d_equalityEngine.getTriggerTermRepresentative(x, THEORY_DATATYPES);
- TNode y_shared = d_equalityEngine.getTriggerTermRepresentative(y, THEORY_DATATYPES);
- Trace("dt-cg") << "Arg #" << k << " shared term is " << x_shared << " " << y_shared << std::endl;
+ if( d_equalityEngine.isTriggerTerm(x, THEORY_DATATYPES) && d_equalityEngine.isTriggerTerm(y, THEORY_DATATYPES) ){
+ TNode x_shared = d_equalityEngine.getTriggerTermRepresentative(x, THEORY_DATATYPES);
+ TNode y_shared = d_equalityEngine.getTriggerTermRepresentative(y, THEORY_DATATYPES);
+ Trace("dt-cg") << "Arg #" << k << " shared term is " << x_shared << " " << y_shared << std::endl;
+ EqualityStatus eqStatus = d_valuation.getEqualityStatus(x_shared, y_shared);
+ Trace("dt-cg") << "...eq status is " << eqStatus << std::endl;
+ if( eqStatus==EQUALITY_FALSE_AND_PROPAGATED || eqStatus==EQUALITY_FALSE || eqStatus==EQUALITY_FALSE_IN_MODEL ){
+ somePairIsDisequal = true;
+ break;
+ }else{
currentPairs.push_back(make_pair(x_shared, y_shared));
}
}
@@ -1123,43 +1144,9 @@ void TheoryDatatypes::collectModelInfo( TheoryModel* m, bool fullModel ){
printModelDebug( "dt-model" );
Trace("dt-model") << std::endl;
- /*
- bool eq_merged = false;
- std::vector< Node > all_eqc;
- eq::EqClassesIterator eqcs1_i = eq::EqClassesIterator( &d_equalityEngine );
- while( !eqcs1_i.isFinished() ){
- Node eqc = (*eqcs1_i);
- all_eqc.push_back( eqc );
- ++eqcs1_i;
- }
- //check if equivalence classes have merged
- for( unsigned i=0; i<all_eqc.size(); i++ ){
- for( unsigned j=(i+1); j<all_eqc.size(); j++ ){
- if( m->areEqual( all_eqc[i], all_eqc[j] ) ){
- Trace("dt-cmi") << "Pre-already forced equal : " << all_eqc[i] << " = " << all_eqc[j] << std::endl;
- eq_merged = true;
- }
- }
- }
- Assert( !eq_merged );
- */
-
//combine the equality engine
m->assertEqualityEngine( &d_equalityEngine );
- /*
- //check again if equivalence classes have merged
- for( unsigned i=0; i<all_eqc.size(); i++ ){
- for( unsigned j=(i+1); j<all_eqc.size(); j++ ){
- if( m->areEqual( all_eqc[i], all_eqc[j] ) ){
- Trace("dt-cmi") << "Already forced equal : " << all_eqc[i] << " = " << all_eqc[j] << std::endl;
- eq_merged = true;
- }
- }
- }
- Assert( !eq_merged );
- */
-
//get all constructors
eq::EqClassesIterator eqccs_i = eq::EqClassesIterator( &d_equalityEngine );
std::vector< Node > cons;
@@ -1170,11 +1157,33 @@ void TheoryDatatypes::collectModelInfo( TheoryModel* m, bool fullModel ){
//for all equivalence classes that are datatypes
if( DatatypesRewriter::isTermDatatype( eqc ) ){
EqcInfo* ei = getOrMakeEqcInfo( eqc );
- if( !ei->d_constructor.get().isNull() ){
- cons.push_back( ei->d_constructor.get() );
- eqc_cons[ eqc ] = ei->d_constructor.get();
+ if( ei && !ei->d_constructor.get().isNull() ){
+ Node c = ei->d_constructor.get();
+ cons.push_back( c );
+ eqc_cons[ eqc ] = c;
+ Trace("dt-cmi") << "Datatypes : assert representative " << c << " for " << eqc << std::endl;
+ m->assertRepresentative( c );
}else{
- nodes.push_back( eqc );
+ //if eqc contains a symbol known to datatypes (a selector), then we must assign
+#if 0
+ bool shouldConsider = false;
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &d_equalityEngine );
+ while( !eqc_i.isFinished() ){
+ Node n = *eqc_i;
+ Trace("dt-cmi-debug") << n << " has kind " << n.getKind() << ", isVar = " << n.isVar() << std::endl;
+ if( n.isVar() || n.getKind()==APPLY_SELECTOR_TOTAL ){
+ shouldConsider = true;
+ break;
+ }
+ ++eqc_i;
+ }
+#else
+ //should assign constructors to EQC if they have a selector or a tester
+ bool shouldConsider = ( ei && ei->d_selectors ) || hasTester( eqc );
+#endif
+ if( shouldConsider ){
+ nodes.push_back( eqc );
+ }
}
}
++eqccs_i;
@@ -1190,11 +1199,14 @@ void TheoryDatatypes::collectModelInfo( TheoryModel* m, bool fullModel ){
bool addCons = false;
const Datatype& dt = ((DatatypeType)(eqc.getType()).toType()).getDatatype();
if( !d_equalityEngine.hasTerm( eqc ) ){
+ Assert( false );
+ /*
if( !dt.isCodatatype() ){
Trace("dt-cmi") << "NOTICE : Datatypes: need to assign constructor for " << eqc << std::endl;
Trace("dt-cmi") << " Type : " << eqc.getType() << std::endl;
TypeNode tn = eqc.getType();
//if it is infinite, make sure it is fresh
+ // this ensures that the term that this is an argument of is distinct.
if( eqc.getType().getCardinality().isInfinite() ){
std::map< TypeNode, int >::iterator it = typ_enum_map.find( tn );
int teIndex;
@@ -1235,6 +1247,7 @@ void TheoryDatatypes::collectModelInfo( TheoryModel* m, bool fullModel ){
neqc = *te;
}
}
+ */
}else{
Trace("dt-cmi") << "NOTICE : Datatypes: no constructor in equivalence class " << eqc << std::endl;
Trace("dt-cmi") << " Type : " << eqc.getType() << std::endl;
@@ -1246,34 +1259,18 @@ void TheoryDatatypes::collectModelInfo( TheoryModel* m, bool fullModel ){
Trace("dt-cmi") << pcons[i] << " ";
}
Trace("dt-cmi") << std::endl;
- /*
- std::map< int, std::map< int, bool > > sels;
- Trace("dt-cmi") << "Existing selectors : ";
- NodeListMap::iterator sel_i = d_selector_apps.find( eqc );
- if( sel_i != d_selector_apps.end() ){
- NodeList* sel = (*sel_i).second;
- for( NodeList::const_iterator j = sel->begin(); j != sel->end(); j++ ){
- Expr selectorExpr = (*j).getOperator().toExpr();
- unsigned cindex = Datatype::cindexOf( selectorExpr );
- unsigned index = Datatype::indexOf( selectorExpr );
- sels[cindex][index] = true;
- Trace("dt-cmi") << (*j) << " (" << cindex << ", " << index << ") ";
- }
- }
- Trace("dt-cmi") << std::endl;
- */
for( unsigned r=0; r<2; r++ ){
if( neqc.isNull() ){
for( unsigned i=0; i<pcons.size(); i++ ){
//must try the infinite ones first
if( pcons[i] && (r==1)==dt[ i ].isFinite() ){
- neqc = getInstantiateCons( eqc, dt, i, false );
- for( unsigned j=0; j<neqc.getNumChildren(); j++ ){
- //if( sels[i].find( j )==sels[i].end() && DatatypesRewriter::isTermDatatype( neqc[j] ) ){
- if( !d_equalityEngine.hasTerm( neqc[j] ) && DatatypesRewriter::isTermDatatype( neqc[j] ) ){
- nodes.push_back( neqc[j] );
- }
- }
+ neqc = DatatypesRewriter::getInstCons( eqc, dt, i );
+ //for( unsigned j=0; j<neqc.getNumChildren(); j++ ){
+ // //if( sels[i].find( j )==sels[i].end() && DatatypesRewriter::isTermDatatype( neqc[j] ) ){
+ // if( !d_equalityEngine.hasTerm( neqc[j] ) && DatatypesRewriter::isTermDatatype( neqc[j] ) ){
+ // nodes.push_back( neqc[j] );
+ // }
+ //}
break;
}
}
@@ -1285,25 +1282,9 @@ void TheoryDatatypes::collectModelInfo( TheoryModel* m, bool fullModel ){
Trace("dt-cmi") << "Assign : " << neqc << std::endl;
m->assertEquality( eqc, neqc, true );
eqc_cons[ eqc ] = neqc;
+ Trace("dt-cmi") << "Datatypes : assert representative " << neqc << " for " << eqc << std::endl;
+ m->assertRepresentative( neqc );
}
- /*
- for( unsigned kk=0; kk<all_eqc.size(); kk++ ){
- for( unsigned ll=(kk+1); ll<all_eqc.size(); ll++ ){
- if( m->areEqual( all_eqc[kk], all_eqc[ll] ) ){
- Trace("dt-cmi") << "Forced equal : " << kk << " " << ll << " : " << all_eqc[kk] << " = " << all_eqc[ll] << std::endl;
- Node r = m->getRepresentative( all_eqc[kk] );
- Trace("dt-cmi") << " { ";
- eq::EqClassIterator eqc_i = eq::EqClassIterator( r, m->d_equalityEngine );
- while( !eqc_i.isFinished() ){
- Trace("dt-cmi") << (*eqc_i) << " ";
- ++eqc_i;
- }
- Trace("dt-cmi") << "} " << std::endl;
- }
- Assert( !m->areEqual( all_eqc[kk], all_eqc[ll] ) );
- }
- }
- */
//m->assertRepresentative( neqc );
if( addCons ){
cons.push_back( neqc );
@@ -1368,16 +1349,17 @@ void TheoryDatatypes::collectTerms( Node n ) {
collectTerms( n[i] );
}
if( n.getKind() == APPLY_CONSTRUCTOR ){
+ Debug("datatypes") << " Found constructor " << n << endl;
d_consTerms.push_back( n );
}else if( n.getKind() == APPLY_SELECTOR_TOTAL || n.getKind() == DT_SIZE ){
d_selTerms.push_back( n );
//we must also record which selectors exist
Debug("datatypes") << " Found selector " << n << endl;
- if (n.getType().isBoolean()) {
- d_equalityEngine.addTriggerPredicate( n );
- }else{
- d_equalityEngine.addTerm( n );
- }
+ //if (n.getType().isBoolean()) {
+ // d_equalityEngine.addTriggerPredicate( n );
+ //}else{
+ // d_equalityEngine.addTerm( n );
+ //}
Node rep = getRepresentative( n[0] );
//record it in the selectors
EqcInfo* eqc = getOrMakeEqcInfo( rep, true );
@@ -1426,20 +1408,24 @@ void TheoryDatatypes::processNewTerm( Node n ){
}
}
-Node TheoryDatatypes::getInstantiateCons( Node n, const Datatype& dt, int index, bool isActive ){
+Node TheoryDatatypes::getInstantiateCons( Node n, const Datatype& dt, int index ){
std::map< int, Node >::iterator it = d_inst_map[n].find( index );
if( it!=d_inst_map[n].end() ){
return it->second;
}else{
//add constructor to equivalence class
- Node n_ic = DatatypesRewriter::getInstCons( n, dt, index );
- if( isActive ){
- for( unsigned i = 0; i<n_ic.getNumChildren(); i++ ){
- processNewTerm( n_ic[i] );
- }
- collectTerms( n_ic );
+ Node k = n;
+ if( n.getKind()==APPLY_CONSTRUCTOR ){
+ //must construct variable to refer to n, add lemma immediately
+ k = NodeManager::currentNM()->mkSkolem( "k", n.getType(), "for dt instantiation" );
+ Node eq = k.eqNode( n );
+ Trace("datatypes-infer") << "DtInfer : instantiation ref : " << eq << std::endl;
+ d_out->lemma( eq );
}
+ Node n_ic = DatatypesRewriter::getInstCons( k, dt, index );
+ //Assert( n_ic==Rewriter::rewrite( n_ic ) );
n_ic = Rewriter::rewrite( n_ic );
+ collectTerms( n_ic );
Debug("dt-enum") << "Made instantiate cons " << n_ic << std::endl;
d_inst_map[n][index] = n_ic;
return n_ic;
@@ -1464,7 +1450,7 @@ void TheoryDatatypes::instantiate( EqcInfo* eqc, Node n ){
//if( eqc->d_selectors || dt[ index ].isFinite() ){ // || mustSpecifyAssignment()
//instantiate this equivalence class
eqc->d_inst = true;
- Node tt_cons = getInstantiateCons( tt, dt, index, true );
+ Node tt_cons = getInstantiateCons( tt, dt, index );
Node eq;
if( tt!=tt_cons ){
eq = tt.eqNode( tt_cons );
@@ -1523,6 +1509,7 @@ void TheoryDatatypes::checkCycles() {
}
//process codatatypes
if( cdt_eqc.size()>1 && options::cdtBisimilar() ){
+ printModelDebug("dt-cdt-debug");
Trace("dt-cdt-debug") << "Process " << cdt_eqc.size() << " co-datatypes" << std::endl;
std::vector< std::vector< Node > > part_out;
std::vector< TNode > exp;
@@ -1740,27 +1727,37 @@ bool TheoryDatatypes::mustSpecifyAssignment(){
}
bool TheoryDatatypes::mustCommunicateFact( Node n, Node exp ){
- //the datatypes decision procedure makes 5 "internal" inferences apart from the equality engine :
+ //the datatypes decision procedure makes "internal" inferences apart from the equality engine :
// (1) Unification : C( t1...tn ) = C( s1...sn ) => ti = si
// (2) Label : ~is_C1( t ) ... ~is_C{i-1}( t ) ~is_C{i+1}( t ) ... ~is_Cn( t ) => is_Ci( t )
// (3) Instantiate : is_C( t ) => t = C( sel_1( t ) ... sel_n( t ) )
// (4) collapse selector : S( C( t1...tn ) ) = t'
// (5) collapse term size : size( C( t1...tn ) ) = 1 + size( t1 ) + ... + size( tn )
// (6) non-negative size : 0 <= size( t )
- //We may need to communicate (3) outwards if the conclusions involve other theories. Also communicate (5), (6), and OR conclusions.
+ //We may need to communicate outwards if the conclusions involve other theories. Also communicate (6) and OR conclusions.
Trace("dt-lemma-debug") << "Compute for " << exp << " => " << n << std::endl;
bool addLemma = false;
- if( ( n.getKind()==EQUAL || n.getKind()==IFF) && n[1].getKind()==APPLY_CONSTRUCTOR && exp.getKind()!=EQUAL ){
- const Datatype& dt = ((DatatypeType)(n[1].getType()).toType()).getDatatype();
- addLemma = dt.involvesExternalType();
+ if( n.getKind()==EQUAL || n.getKind()==IFF ){
+ /*
+ for( unsigned i=0; i<2; i++ ){
+ if( !n[i].isVar() && n[i].getKind()!=APPLY_SELECTOR_TOTAL && n[i].getKind()!=APPLY_CONSTRUCTOR ){
+ addLemma = true;
+ }
+ }
+ */
+ TypeNode tn = n[0].getType();
+ if( !DatatypesRewriter::isTypeDatatype( tn ) ){
+ addLemma = true;
+ }else{
+ const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ addLemma = dt.involvesExternalType();
+ }
//for( int j=0; j<(int)n[1].getNumChildren(); j++ ){
// if( !DatatypesRewriter::isTermDatatype( n[1][j] ) ){
// addLemma = true;
// break;
// }
//}
- }else if( n.getKind()==EQUAL && ( n[0].getKind()==DT_SIZE || n[1].getKind()==DT_SIZE ) ){
- addLemma = true;
}else if( n.getKind()==LEQ ){
addLemma = true;
}else if( n.getKind()==OR ){
@@ -1768,14 +1765,14 @@ bool TheoryDatatypes::mustCommunicateFact( Node n, Node exp ){
}
if( addLemma ){
//check if we have already added this lemma
- if( std::find( d_inst_lemmas[ n[0] ].begin(), d_inst_lemmas[ n[0] ].end(), n[1] )==d_inst_lemmas[ n[0] ].end() ){
- d_inst_lemmas[ n[0] ].push_back( n[1] );
- Trace("dt-lemma-debug") << "Communicate " << n << std::endl;
- return true;
- }else{
- Trace("dt-lemma-debug") << "Already communicated " << n << std::endl;
- return false;
- }
+ //if( std::find( d_inst_lemmas[ n[0] ].begin(), d_inst_lemmas[ n[0] ].end(), n[1] )==d_inst_lemmas[ n[0] ].end() ){
+ // d_inst_lemmas[ n[0] ].push_back( n[1] );
+ Trace("dt-lemma-debug") << "Communicate " << n << std::endl;
+ return true;
+ //}else{
+ // Trace("dt-lemma-debug") << "Already communicated " << n << std::endl;
+ // return false;
+ //}
}
//else if( exp.getKind()==APPLY_TESTER ){
//if( n.getKind()==EQUAL && !DatatypesRewriter::isTermDatatype( n[0] ) ){
@@ -1837,7 +1834,9 @@ void TheoryDatatypes::printModelDebug( const char* c ){
//add terms to model
eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &d_equalityEngine );
while( !eqc_i.isFinished() ){
- Trace( c ) << (*eqc_i) << " ";
+ if( (*eqc_i)!=eqc ){
+ Trace( c ) << (*eqc_i) << " ";
+ }
++eqc_i;
}
Trace( c ) << "}" << std::endl;
diff --git a/src/theory/datatypes/theory_datatypes.h b/src/theory/datatypes/theory_datatypes.h
index 81cbe7523..30b0140a9 100644
--- a/src/theory/datatypes/theory_datatypes.h
+++ b/src/theory/datatypes/theory_datatypes.h
@@ -123,12 +123,14 @@ private:
//all selectors whose argument is this eqc
context::CDO< bool > d_selectors;
};
- /** does eqc of n have a label? */
+ /** does eqc of n have a label (do we know its constructor)? */
bool hasLabel( EqcInfo* eqc, Node n );
/** get the label associated to n */
Node getLabel( Node n );
/** get the index of the label associated to n */
int getLabelIndex( EqcInfo* eqc, Node n );
+ /** does eqc of n have any testers? */
+ bool hasTester( Node n );
/** get the possible constructors for n */
void getPossibleCons( EqcInfo* eqc, Node n, std::vector< bool >& cons );
private:
@@ -141,7 +143,7 @@ private:
/** map from nodes to their instantiated equivalent for each constructor type */
std::map< Node, std::map< int, Node > > d_inst_map;
/** which instantiation lemmas we have sent */
- std::map< Node, std::vector< Node > > d_inst_lemmas;
+ //std::map< Node, std::vector< Node > > d_inst_lemmas;
/** labels for each equivalence class
* for each eqc n, d_labels[n] is testers that hold for this equivalence class, either:
* a list of equations of the form
@@ -155,9 +157,11 @@ private:
/** selector apps for eqch equivalence class */
NodeListMap d_selector_apps;
/** constructor terms */
- BoolMap d_consEqc;
+ //BoolMap d_consEqc;
/** Are we in conflict */
context::CDO<bool> d_conflict;
+ /** Added lemma ? */
+ bool d_addedLemma;
/** The conflict node */
Node d_conflictNode;
/** cache for which terms we have called collectTerms(...) on */
@@ -166,14 +170,14 @@ private:
std::vector< Node > d_pending;
std::map< Node, Node > d_pending_exp;
std::vector< Node > d_pending_merge;
- /** expand definition skolem functions */
- std::map< Node, Node > d_exp_def_skolem;
/** All the constructor terms that the theory has seen */
context::CDList<TNode> d_consTerms;
/** All the selector terms that the theory has seen */
context::CDList<TNode> d_selTerms;
/** counter for forcing assignments (ensures fairness) */
unsigned d_dtfCounter;
+ /** expand definition skolem functions */
+ std::map< Node, Node > d_exp_def_skolem;
private:
/** assert fact */
void assertFact( Node fact, Node exp );
@@ -258,7 +262,7 @@ private:
/** collect terms */
void collectTerms( Node n );
/** get instantiate cons */
- Node getInstantiateCons( Node n, const Datatype& dt, int index, bool isActive );
+ Node getInstantiateCons( Node n, const Datatype& dt, int index );
/** process new term that was created internally */
void processNewTerm( Node n );
/** check instantiate */
diff --git a/src/theory/example/theory_uf_tim.cpp b/src/theory/example/theory_uf_tim.cpp
index 6963251b8..139a811b8 100644
--- a/src/theory/example/theory_uf_tim.cpp
+++ b/src/theory/example/theory_uf_tim.cpp
@@ -271,6 +271,11 @@ Node TheoryUFTim::constructConflict(TNode diseq) {
}
void TheoryUFTim::check(Effort level) {
+ if (done() && !fullEffort(level)) {
+ return;
+ }
+
+ TimerStat::CodeTimer checkTimer(d_checkTime);
Debug("uf") << "uf: begin check(" << level << ")" << std::endl;
diff --git a/src/theory/idl/theory_idl.cpp b/src/theory/idl/theory_idl.cpp
index 9e402f430..55dec35e9 100644
--- a/src/theory/idl/theory_idl.cpp
+++ b/src/theory/idl/theory_idl.cpp
@@ -49,10 +49,11 @@ Node TheoryIdl::ppRewrite(TNode atom) {
}
void TheoryIdl::check(Effort level) {
- //// Not needed for now, as no code outside while() loop below.
- // if (done() && !fullEffort(e)) {
- // return;
- // }
+ if (done() && !fullEffort(level)) {
+ return;
+ }
+
+ TimerStat::CodeTimer checkTimer(d_checkTime);
while(!done()) {
diff --git a/src/theory/output_channel.h b/src/theory/output_channel.h
index 40eba6ff5..fdf253d3f 100644
--- a/src/theory/output_channel.h
+++ b/src/theory/output_channel.h
@@ -21,6 +21,7 @@
#include "util/cvc4_assert.h"
#include "theory/interrupted.h"
+#include "util/resource_manager.h"
namespace CVC4 {
namespace theory {
@@ -84,7 +85,7 @@ public:
* With safePoint(), the theory signals that it is at a safe point
* and can be interrupted.
*/
- virtual void safePoint() throw(Interrupted, AssertionException) {
+ virtual void safePoint() throw(Interrupted, UnsafeInterruptException, AssertionException) {
}
/**
@@ -97,7 +98,7 @@ public:
* unit conflict) which is assigned TRUE (and T-conflicting) in the
* current assignment.
*/
- virtual void conflict(TNode n) throw(AssertionException) = 0;
+ virtual void conflict(TNode n) throw(AssertionException, UnsafeInterruptException) = 0;
/**
* Propagate a theory literal.
@@ -105,7 +106,7 @@ public:
* @param n - a theory consequence at the current decision level
* @return false if an immediate conflict was encountered
*/
- virtual bool propagate(TNode n) throw(AssertionException) = 0;
+ virtual bool propagate(TNode n) throw(AssertionException, UnsafeInterruptException) = 0;
/**
* Tell the core that a valid theory lemma at decision level 0 has
@@ -119,7 +120,7 @@ public:
*/
virtual LemmaStatus lemma(TNode n, bool removable = false,
bool preprocess = false)
- throw(TypeCheckingExceptionPrivate, AssertionException) = 0;
+ throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) = 0;
/**
* Request a split on a new theory atom. This is equivalent to
@@ -128,12 +129,12 @@ public:
* @param n - a theory atom; must be of Boolean type
*/
LemmaStatus split(TNode n)
- throw(TypeCheckingExceptionPrivate, AssertionException) {
+ throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
return splitLemma(n.orNode(n.notNode()));
}
virtual LemmaStatus splitLemma(TNode n, bool removable = false)
- throw(TypeCheckingExceptionPrivate, AssertionException) = 0;
+ throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) = 0;
/**
* If a decision is made on n, it must be in the phase specified.
@@ -148,7 +149,7 @@ public:
* @param phase - the phase to decide on n
*/
virtual void requirePhase(TNode n, bool phase)
- throw(Interrupted, TypeCheckingExceptionPrivate, AssertionException) = 0;
+ throw(Interrupted, TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) = 0;
/**
* Flips the most recent unflipped decision to the other phase and
@@ -191,14 +192,14 @@ public:
* could be flipped, or if the root decision was re-flipped
*/
virtual bool flipDecision()
- throw(Interrupted, TypeCheckingExceptionPrivate, AssertionException) = 0;
+ throw(Interrupted, TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) = 0;
/**
* Notification from a theory that it realizes it is incomplete at
* this context level. If SAT is later determined by the
* TheoryEngine, it should actually return an UNKNOWN result.
*/
- virtual void setIncomplete() throw(AssertionException) = 0;
+ virtual void setIncomplete() throw(AssertionException, UnsafeInterruptException) = 0;
/**
* "Spend" a "resource." The meaning is specific to the context in
@@ -211,7 +212,7 @@ public:
* long-running operations, they cannot rely on resource() to break
* out of infinite or intractable computations.
*/
- virtual void spendResource() throw() {}
+ virtual void spendResource() throw(UnsafeInterruptException) {}
/**
* Handle user attribute.
@@ -226,7 +227,7 @@ public:
* Using this leads to non-termination issues.
* It is appropriate for prototyping for theories.
*/
- virtual void demandRestart() throw(TypeCheckingExceptionPrivate, AssertionException) {}
+ virtual void demandRestart() throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {}
};/* class OutputChannel */
diff --git a/src/theory/quantifiers/candidate_generator.cpp b/src/theory/quantifiers/candidate_generator.cpp
index 0f2adf3b4..9e3fed20a 100644
--- a/src/theory/quantifiers/candidate_generator.cpp
+++ b/src/theory/quantifiers/candidate_generator.cpp
@@ -103,7 +103,9 @@ Node CandidateGeneratorQE::getNextCandidate(){
Node n = d_qe->getTermDatabase()->d_op_map[d_op][d_term_iter];
d_term_iter++;
if( isLegalCandidate( n ) ){
- return n;
+ if( d_qe->getTermDatabase()->hasTermCurrent( n ) ){
+ return n;
+ }
}
}
}else if( d_mode==cand_term_eqc ){
@@ -126,41 +128,6 @@ Node CandidateGeneratorQE::getNextCandidate(){
return Node::null();
}
-//CandidateGeneratorQEDisequal::CandidateGeneratorQEDisequal( QuantifiersEngine* qe, Node eqc ) :
-// d_qe( qe ), d_eq_class( eqc ){
-// d_eci = NULL;
-//}
-//void CandidateGeneratorQEDisequal::resetInstantiationRound(){
-//
-//}
-////we will iterate over all terms that are disequal from eqc
-//void CandidateGeneratorQEDisequal::reset( Node eqc ){
-// //Assert( !eqc.isNull() );
-// ////begin iterating over equivalence classes that are disequal from eqc
-// //d_eci = d_ith->getEquivalenceClassInfo( eqc );
-// //if( d_eci ){
-// // d_eqci_iter = d_eci->d_disequal.begin();
-// //}
-//}
-//Node CandidateGeneratorQEDisequal::getNextCandidate(){
-// //if( d_eci ){
-// // while( d_eqci_iter != d_eci->d_disequal.end() ){
-// // if( (*d_eqci_iter).second ){
-// // //we have an equivalence class that is disequal from eqc
-// // d_cg->reset( (*d_eqci_iter).first );
-// // Node n = d_cg->getNextCandidate();
-// // //if there is a candidate in this equivalence class, return it
-// // if( !n.isNull() ){
-// // return n;
-// // }
-// // }
-// // ++d_eqci_iter;
-// // }
-// //}
-// return Node::null();
-//}
-
-
CandidateGeneratorQELitEq::CandidateGeneratorQELitEq( QuantifiersEngine* qe, Node mpat ) :
d_match_pattern( mpat ), d_qe( qe ){
@@ -225,19 +192,30 @@ void CandidateGeneratorQEAll::resetInstantiationRound() {
void CandidateGeneratorQEAll::reset( Node eqc ) {
d_eq = eq::EqClassesIterator( d_qe->getEqualityQuery()->getEngine() );
+ d_firstTime = true;
}
Node CandidateGeneratorQEAll::getNextCandidate() {
while( !d_eq.isFinished() ){
- Node n = (*d_eq);
- if( options::instMaxLevel()!=-1 ){
- n = d_qe->getEqualityQuery()->getInternalRepresentative( n, d_f, d_index );
- }
+ TNode n = (*d_eq);
++d_eq;
- if( n.getType().isSubtypeOf( d_match_pattern.getType() ) ){
- //an equivalence class with the same type as the pattern, return it
- return n;
+ if( n.getType().isSubtypeOf( d_match_pattern_type ) ){
+ TNode nh = d_qe->getTermDatabase()->getHasTermEqc( n );
+ if( !nh.isNull() ){
+ if( options::instMaxLevel()!=-1 ){
+ nh = d_qe->getEqualityQuery()->getInternalRepresentative( nh, d_f, d_index );
+ }
+ d_firstTime = false;
+ //an equivalence class with the same type as the pattern, return it
+ return nh;
+ }
}
}
+ if( d_firstTime ){
+ Assert( d_qe->getTermDatabase()->d_type_map[d_match_pattern_type].empty() );
+ //must return something
+ d_firstTime = false;
+ return d_qe->getTermDatabase()->getFreeVariableForType( d_match_pattern_type );
+ }
return Node::null();
}
diff --git a/src/theory/quantifiers/candidate_generator.h b/src/theory/quantifiers/candidate_generator.h
index 011e2924d..7a959a70d 100644
--- a/src/theory/quantifiers/candidate_generator.h
+++ b/src/theory/quantifiers/candidate_generator.h
@@ -150,6 +150,8 @@ private:
// quantifier/index for the variable we are matching
Node d_f;
unsigned d_index;
+ //first time
+ bool d_firstTime;
public:
CandidateGeneratorQEAll( QuantifiersEngine* qe, Node mpat );
~CandidateGeneratorQEAll(){}
diff --git a/src/theory/quantifiers/ce_guided_instantiation.cpp b/src/theory/quantifiers/ce_guided_instantiation.cpp
index 2ec15f538..bf9409f06 100644
--- a/src/theory/quantifiers/ce_guided_instantiation.cpp
+++ b/src/theory/quantifiers/ce_guided_instantiation.cpp
@@ -47,6 +47,12 @@ void CegInstantiation::CegConjecture::initializeGuard( QuantifiersEngine * qe ){
d_guard = qe->getValuation().ensureLiteral( d_guard );
AlwaysAssert( !d_guard.isNull() );
qe->getOutputChannel().requirePhase( d_guard, true );
+ if( !d_syntax_guided ){
+ //add immediate lemma
+ Node lem = NodeManager::currentNM()->mkNode( OR, d_guard.negate(), d_base_inst.negate() );
+ Trace("cegqi") << "Add candidate lemma : " << lem << std::endl;
+ qe->getOutputChannel().lemma( lem );
+ }
}
}
@@ -82,6 +88,9 @@ bool CegInstantiation::needsCheck( Theory::Effort e ) {
bool CegInstantiation::needsModel( Theory::Effort e ) {
return true;
}
+bool CegInstantiation::needsFullModel( Theory::Effort e ) {
+ return false;
+}
void CegInstantiation::check( Theory::Effort e, unsigned quant_e ) {
if( quant_e==QuantifiersEngine::QEFFORT_MODEL ){
@@ -109,10 +118,11 @@ void CegInstantiation::registerQuantifier( Node q ) {
for( unsigned j=0; j<d_conj->d_base_inst[0][0].getNumChildren(); j++ ){
d_conj->d_inner_vars.push_back( d_conj->d_base_inst[0][0][j] );
}
+ d_conj->d_syntax_guided = true;
}else if( getTermDatabase()->isQAttrSynthesis( q ) ){
- //add immediate lemma
- Node lem = NodeManager::currentNM()->mkNode( OR, d_conj->d_guard.negate(), d_conj->d_base_inst );
- d_quantEngine->getOutputChannel().lemma( lem );
+ d_conj->d_syntax_guided = false;
+ }else{
+ Assert( false );
}
//fairness
if( options::ceGuidedInstFair()!=CEGQI_FAIR_NONE ){
@@ -233,11 +243,14 @@ void CegInstantiation::checkCegConjecture( CegConjecture * conj ) {
}
}else if( getTermDatabase()->isQAttrSynthesis( q ) ){
+ Trace("cegqi-engine") << " * Value is : ";
std::vector< Node > model_terms;
for( unsigned i=0; i<conj->d_candidates.size(); i++ ){
Node t = getModelTerm( conj->d_candidates[i] );
model_terms.push_back( t );
+ Trace("cegqi-engine") << conj->d_candidates[i] << " -> " << t << " ";
}
+ Trace("cegqi-engine") << std::endl;
d_quantEngine->addInstantiation( q, model_terms, false );
}
}else{
@@ -266,7 +279,7 @@ bool CegInstantiation::getModelValues( std::vector< Node >& n, std::vector< Node
for( unsigned i=0; i<n.size(); i++ ){
Node nv = getModelValue( n[i] );
v.push_back( nv );
- Trace("cegqi-engine") << nv << " ";
+ Trace("cegqi-engine") << n[i] << " -> " << nv << " ";
if( nv.isNull() ){
success = false;
}
diff --git a/src/theory/quantifiers/ce_guided_instantiation.h b/src/theory/quantifiers/ce_guided_instantiation.h
index 2502416bd..235f2b01c 100644
--- a/src/theory/quantifiers/ce_guided_instantiation.h
+++ b/src/theory/quantifiers/ce_guided_instantiation.h
@@ -44,6 +44,8 @@ private:
Node d_base_inst;
/** guard split */
Node d_guard_split;
+ /** is syntax-guided */
+ bool d_syntax_guided;
/** list of constants for quantified formula */
std::vector< Node > d_candidates;
/** list of variables on inner quantification */
@@ -97,6 +99,7 @@ public:
public:
bool needsCheck( Theory::Effort e );
bool needsModel( Theory::Effort e );
+ bool needsFullModel( Theory::Effort e );
/* Call during quantifier engine's check */
void check( Theory::Effort e, unsigned quant_e );
/* Called for new quantifiers */
diff --git a/src/theory/quantifiers/conjecture_generator.cpp b/src/theory/quantifiers/conjecture_generator.cpp
index f491adc7c..06552196d 100755
--- a/src/theory/quantifiers/conjecture_generator.cpp
+++ b/src/theory/quantifiers/conjecture_generator.cpp
@@ -390,6 +390,7 @@ void ConjectureGenerator::check( Theory::Effort e, unsigned quant_e ) {
Trace("sg-engine") << "---Conjecture Engine Round, effort = " << e << "---" << std::endl;
}
eq::EqualityEngine * ee = getEqualityEngine();
+ d_conj_count = 0;
Trace("sg-proc") << "Get eq classes..." << std::endl;
d_op_arg_index.clear();
@@ -415,8 +416,10 @@ void ConjectureGenerator::check( Theory::Effort e, unsigned quant_e ) {
eq::EqClassIterator ieqc_i = eq::EqClassIterator( r, ee );
while( !ieqc_i.isFinished() ){
TNode n = (*ieqc_i);
- if( isHandledTerm( n ) ){
- d_op_arg_index[r].addTerm( this, n );
+ if( getTermDatabase()->hasTermCurrent( n ) ){
+ if( isHandledTerm( n ) ){
+ d_op_arg_index[r].addTerm( this, n );
+ }
}
++ieqc_i;
}
@@ -471,7 +474,7 @@ void ConjectureGenerator::check( Theory::Effort e, unsigned quant_e ) {
eq::EqClassIterator eqc_i = eq::EqClassIterator( r, ee );
while( !eqc_i.isFinished() ){
TNode n = (*eqc_i);
- if( !n.getAttribute(NoMatchAttribute()) && ( n.getKind()!=EQUAL || isFalse ) ){
+ if( getTermDatabase()->hasTermCurrent( n ) && !n.getAttribute(NoMatchAttribute()) && ( n.getKind()!=EQUAL || isFalse ) ){
if( firstTime ){
Trace("sg-gen-eqc") << "e" << d_em[r] << " : { " << std::endl;
firstTime = false;
@@ -826,7 +829,7 @@ void ConjectureGenerator::check( Theory::Effort e, unsigned quant_e ) {
break;
}
}
-
+ Trace("sg-stats") << "Total conjectures considered : " << d_conj_count << std::endl;
if( Trace.isOn("thm-ee") ){
Trace("thm-ee") << "Universal equality engine is : " << std::endl;
eq::EqClassesIterator ueqcs_i = eq::EqClassesIterator( &d_uequalityEngine );
@@ -865,7 +868,8 @@ void ConjectureGenerator::check( Theory::Effort e, unsigned quant_e ) {
unsigned ConjectureGenerator::flushWaitingConjectures( unsigned& addedLemmas, int ldepth, int rdepth ) {
if( !d_waiting_conjectures_lhs.empty() ){
Trace("sg-proc") << "Generated " << d_waiting_conjectures_lhs.size() << " conjectures at depth " << ldepth << "/" << rdepth << "." << std::endl;
- if( !optStatsOnly() && (int)addedLemmas<options::conjectureGenPerRound() ){
+ if( (int)addedLemmas<options::conjectureGenPerRound() ){
+ /*
std::vector< unsigned > indices;
for( unsigned i=0; i<d_waiting_conjectures_lhs.size(); i++ ){
indices.push_back( i );
@@ -877,21 +881,22 @@ unsigned ConjectureGenerator::flushWaitingConjectures( unsigned& addedLemmas, in
scs.d_scores.insert( scs.d_scores.begin(), d_waiting_conjectures_score.begin(), d_waiting_conjectures_score.end() );
std::sort( indices.begin(), indices.end(), scs );
}
- if( doSort && d_waiting_conjectures_score[indices[0]]<optFilterScoreThreshold() ){
- //do splitting on demand (TODO)
-
- }else{
- for( unsigned i=0; i<indices.size(); i++ ){
- //if( d_waiting_conjectures_score[indices[i]]<optFilterScoreThreshold() ){
- if( d_waiting_conjectures_score[indices[i]]>=optFilterScoreThreshold() ){
- //we have determined a relevant subgoal
- Node lhs = d_waiting_conjectures_lhs[indices[i]];
- Node rhs = d_waiting_conjectures_rhs[indices[i]];
- if( options::conjectureFilterCanonical() && ( getUniversalRepresentative( lhs )!=lhs || getUniversalRepresentative( rhs )!=rhs ) ){
- //skip
+ //if( doSort && d_waiting_conjectures_score[indices[0]]<optFilterScoreThreshold() ){
+ */
+ unsigned prevCount = d_conj_count;
+ for( unsigned i=0; i<d_waiting_conjectures_lhs.size(); i++ ){
+ if( d_waiting_conjectures_score[i]>=optFilterScoreThreshold() ){
+ //we have determined a relevant subgoal
+ Node lhs = d_waiting_conjectures_lhs[i];
+ Node rhs = d_waiting_conjectures_rhs[i];
+ if( options::conjectureFilterCanonical() && ( getUniversalRepresentative( lhs )!=lhs || getUniversalRepresentative( rhs )!=rhs ) ){
+ //skip
+ }else{
+ Trace("sg-engine") << "*** Consider conjecture : " << lhs << " == " << rhs << std::endl;
+ Trace("sg-engine-debug") << " score : " << d_waiting_conjectures_score[i] << std::endl;
+ if( optStatsOnly() ){
+ d_conj_count++;
}else{
- Trace("sg-engine") << "*** Consider conjecture : " << lhs << " == " << rhs << std::endl;
- Trace("sg-engine-debug") << " score : " << d_waiting_conjectures_score[indices[i]] << std::endl;
std::vector< Node > bvs;
for( std::map< TypeNode, unsigned >::iterator it = d_pattern_var_id[lhs].begin(); it != d_pattern_var_id[lhs].end(); ++it ){
for( unsigned i=0; i<=it->second; i++ ){
@@ -918,14 +923,13 @@ unsigned ConjectureGenerator::flushWaitingConjectures( unsigned& addedLemmas, in
break;
}
}
- }else{
- if( doSort ){
- break;
- }
}
}
}
Trace("sg-proc") << "...have now added " << addedLemmas << " conjecture lemmas." << std::endl;
+ if( optStatsOnly() ){
+ Trace("sg-stats") << "Generated " << (d_conj_count-prevCount) << " conjectures at depth " << ldepth << "/" << rdepth << "." << std::endl;
+ }
}
d_waiting_conjectures_lhs.clear();
d_waiting_conjectures_rhs.clear();
@@ -1286,7 +1290,7 @@ int ConjectureGenerator::considerCandidateConjecture( TNode lhs, TNode rhs ) {
Trace("sg-cconj") << " #witnesses for " << it->first << " : " << it->second.size() << std::endl;
}
}else{
- score = 0;
+ score = 1;
}
Trace("sg-cconj") << " -> SUCCESS." << std::endl;
diff --git a/src/theory/quantifiers/conjecture_generator.h b/src/theory/quantifiers/conjecture_generator.h
index 59d908fec..462fadfce 100755
--- a/src/theory/quantifiers/conjecture_generator.h
+++ b/src/theory/quantifiers/conjecture_generator.h
@@ -342,6 +342,7 @@ private: //information regarding the terms
void registerPattern( Node pat, TypeNode tpat );
private: //for debugging
std::map< TNode, unsigned > d_em;
+ unsigned d_conj_count;
public:
//term generation environment
TermGenEnv d_tge;
diff --git a/src/theory/quantifiers/first_order_model.cpp b/src/theory/quantifiers/first_order_model.cpp
index 07fea3cca..d4f32becc 100644
--- a/src/theory/quantifiers/first_order_model.cpp
+++ b/src/theory/quantifiers/first_order_model.cpp
@@ -17,7 +17,6 @@
#include "theory/quantifiers/term_database.h"
#include "theory/quantifiers/quantifiers_attributes.h"
#include "theory/quantifiers/full_model_check.h"
-#include "theory/quantifiers/qinterval_builder.h"
#include "theory/quantifiers/ambqi_builder.h"
#include "theory/quantifiers/options.h"
@@ -677,18 +676,24 @@ Node FirstOrderModelFmc::getFunctionValue(Node op, const char* argPrefix ) {
Node curr;
for( int i=(d_models[op]->d_cond.size()-1); i>=0; i--) {
Node v = d_models[op]->d_value[i];
+ Trace("fmc-model-func") << "Value is : " << v << std::endl;
if( !hasTerm( v ) ){
//can happen when the model basis term does not exist in ground assignment
TypeNode tn = v.getType();
- if( d_rep_set.d_type_reps.find( tn )!=d_rep_set.d_type_reps.end() && !d_rep_set.d_type_reps[ tn ].empty() ){
- //see full_model_check.cpp line 366
- v = d_rep_set.d_type_reps[tn][ d_rep_set.d_type_reps[tn].size()-1 ];
- }else{
- Assert( false );
+ //check if it is a constant introduced as a representative not existing in the model's equality engine
+ if( !d_rep_set.hasRep( tn, v ) ){
+ if( d_rep_set.d_type_reps.find( tn )!=d_rep_set.d_type_reps.end() && !d_rep_set.d_type_reps[ tn ].empty() ){
+ //see full_model_check.cpp line 366
+ v = d_rep_set.d_type_reps[tn][ d_rep_set.d_type_reps[tn].size()-1 ];
+ }else{
+ Assert( false );
+ }
+ Trace("fmc-model-func") << "No term, assign " << v << std::endl;
}
}
v = getRepresentative( v );
if( curr.isNull() ){
+ Trace("fmc-model-func") << "base : " << v << std::endl;
curr = v;
}else{
//make the condition
@@ -711,6 +716,8 @@ Node FirstOrderModelFmc::getFunctionValue(Node op, const char* argPrefix ) {
}
Assert( !children.empty() );
Node cc = children.size()==1 ? children[0] : NodeManager::currentNM()->mkNode( AND, children );
+
+ Trace("fmc-model-func") << "condition : " << cc << ", value : " << v << std::endl;
curr = NodeManager::currentNM()->mkNode( ITE, cc, v, curr );
}
}
@@ -746,167 +753,6 @@ bool FirstOrderModelFmc::isInRange( Node v, Node i ) {
}
-FirstOrderModelQInt::FirstOrderModelQInt(QuantifiersEngine * qe, context::Context* c, std::string name) :
-FirstOrderModel(qe, c, name) {
-
-}
-
-void FirstOrderModelQInt::processInitialize( bool ispre ) {
- if( !ispre ){
- Trace("qint-debug") << "Process initialize" << std::endl;
- for( std::map<Node, QIntDef * >::iterator it = d_models.begin(); it != d_models.end(); ++it ) {
- Node op = it->first;
- TypeNode tno = op.getType();
- Trace("qint-debug") << " Init " << op << " " << tno << std::endl;
- for( unsigned i=0; i<tno.getNumChildren(); i++) {
- //make sure a representative of the type exists
- if( !d_rep_set.hasType( tno[i] ) ){
- Node e = getSomeDomainElement( tno[i] );
- Trace("qint-debug") << " * Initialize type " << tno[i] << ", add ";
- Trace("qint-debug") << e << " " << e.getType() << std::endl;
- //d_rep_set.add( e );
- }
- }
- }
- }
-}
-
-Node FirstOrderModelQInt::getFunctionValue(Node op, const char* argPrefix ) {
- Trace("qint-debug") << "Get function value for " << op << std::endl;
- TypeNode type = op.getType();
- std::vector< Node > vars;
- for( size_t i=0; i<type.getNumChildren()-1; i++ ){
- std::stringstream ss;
- ss << argPrefix << (i+1);
- Node b = NodeManager::currentNM()->mkBoundVar( ss.str(), type[i] );
- vars.push_back( b );
- }
- Node boundVarList = NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, vars);
- Node curr = d_models[op]->getFunctionValue( this, vars );
- Node fv = NodeManager::currentNM()->mkNode(kind::LAMBDA, boundVarList, curr);
- Trace("qint-debug") << "Return " << fv << std::endl;
- return fv;
-}
-
-Node FirstOrderModelQInt::getCurrentUfModelValue( Node n, std::vector< Node > & args, bool partial ) {
- Debug("qint-debug") << "get curr uf value " << n << std::endl;
- return d_models[n]->evaluate( this, args );
-}
-
-void FirstOrderModelQInt::processInitializeModelForTerm(Node n) {
- Debug("qint-debug") << "process init " << n << " " << n.getKind() << std::endl;
-
- if( n.getKind()==APPLY_UF || n.getKind()==VARIABLE || n.getKind()==SKOLEM ){
- Node op = n.getKind()==APPLY_UF ? n.getOperator() : n;
- if( d_models.find(op)==d_models.end()) {
- Debug("qint-debug") << "init model for " << op << std::endl;
- d_models[op] = new QIntDef;
- }
- }
-}
-
-Node FirstOrderModelQInt::getUsedRepresentative( Node n ) {
- if( hasTerm( n ) ){
- if( n.getType().isBoolean() ){
- return areEqual(n, d_true) ? d_true : d_false;
- }else{
- return getRepresentative( n );
- }
- }else{
- Trace("qint-debug") << "Get rep " << n << " " << n.getType() << std::endl;
- Assert( d_rep_set.hasType( n.getType() ) && !d_rep_set.d_type_reps[n.getType()].empty() );
- return d_rep_set.d_type_reps[n.getType()][0];
- }
-}
-
-void FirstOrderModelQInt::processInitializeQuantifier( Node q ) {
- if( d_var_order.find( q )==d_var_order.end() ){
- d_var_order[q] = new QuantVarOrder( q );
- d_var_order[q]->debugPrint("qint-var-order");
- Trace("qint-var-order") << std::endl;
- }
-}
-unsigned FirstOrderModelQInt::getOrderedNumVars( Node q ) {
- //return q[0].getNumChildren();
- return d_var_order[q]->getNumVars();
-}
-
-TypeNode FirstOrderModelQInt::getOrderedVarType( Node q, int i ) {
- //return q[0][i].getType();
- return d_var_order[q]->getVar( i ).getType();
-}
-
-int FirstOrderModelQInt::getOrderedVarNumToVarNum( Node q, int i ) {
- return getVariableId( q, d_var_order[q]->getVar( i ) );
-}
-
-bool FirstOrderModelQInt::isLessThan( Node v1, Node v2 ) {
- Assert( !v1.isNull() );
- Assert( !v2.isNull() );
- if( v1.getType().isSort() ){
- Assert( getRepId( v1 )!=-1 );
- Assert( getRepId( v2 )!=-1 );
- int rid1 = d_rep_id[v1];
- int rid2 = d_rep_id[v2];
- return rid1<rid2;
- }else{
- return false;
- }
-}
-
-Node FirstOrderModelQInt::getMin( Node v1, Node v2 ) {
- return isLessThan( v1, v2 ) ? v1 : v2;
-}
-
-Node FirstOrderModelQInt::getMax( Node v1, Node v2 ) {
- return isLessThan( v1, v2 ) ? v2 : v1;
-}
-
-Node FirstOrderModelQInt::getMaximum( TypeNode tn ) {
- return d_max[tn];
-}
-
-Node FirstOrderModelQInt::getNext( TypeNode tn, Node v ) {
- if( v.isNull() ){
- return d_min[tn];
- }else{
- Assert( getRepId( v )!=-1 );
- int rid = d_rep_id[v];
- if( rid==(int)(d_rep_set.d_type_reps[tn].size()-1) ){
- Assert( false );
- return Node::null();
- }else{
- return d_rep_set.d_type_reps[tn][ rid+1 ];
- }
- }
-}
-Node FirstOrderModelQInt::getPrev( TypeNode tn, Node v ) {
- if( v.isNull() ){
- Assert( false );
- return Node::null();
- }else{
- Assert( getRepId( v )!=-1 );
- int rid = d_rep_id[v];
- if( rid==0 ){
- return Node::null();
- }else{
- return d_rep_set.d_type_reps[tn][ rid-1 ];
- }
- }
-}
-
-bool FirstOrderModelQInt::doMeet( Node l1, Node u1, Node l2, Node u2, Node& lr, Node& ur ) {
- Trace("qint-debug2") << "doMeet " << l1 << "..." << u1 << " with " << l2 << "..." << u2 << std::endl;
- Assert( !u1.isNull() );
- Assert( !u2.isNull() );
- lr = l1.isNull() ? l2 : ( l2.isNull() ? l1 : getMax( l1, l2 ) );
- ur = getMin( u1, u2 );
- //return lr==ur || lr.isNull() || isLessThan( lr, ur );
- return lr.isNull() || isLessThan( lr, ur );
-}
-
-
-
FirstOrderModelAbs::FirstOrderModelAbs(QuantifiersEngine * qe, context::Context* c, std::string name) :
FirstOrderModel(qe, c, name) {
diff --git a/src/theory/quantifiers/first_order_model.h b/src/theory/quantifiers/first_order_model.h
index 0b282d5a5..77ccad247 100644
--- a/src/theory/quantifiers/first_order_model.h
+++ b/src/theory/quantifiers/first_order_model.h
@@ -191,50 +191,6 @@ public:
}/* CVC4::theory::quantifiers::fmcheck namespace */
-
-class QIntDef;
-class QuantVarOrder;
-class FirstOrderModelQInt : public FirstOrderModel
-{
- friend class QIntervalBuilder;
-private:
- /** uf op to some representation */
- std::map<Node, QIntDef * > d_models;
- /** representatives to ids */
- std::map< Node, int > d_rep_id;
- std::map< TypeNode, Node > d_min;
- std::map< TypeNode, Node > d_max;
- /** quantifiers to information regarding variable ordering */
- std::map<Node, QuantVarOrder * > d_var_order;
- /** get current model value */
- Node getCurrentUfModelValue( Node n, std::vector< Node > & args, bool partial );
- void processInitializeModelForTerm(Node n);
-public:
- FirstOrderModelQInt(QuantifiersEngine * qe, context::Context* c, std::string name);
- FirstOrderModelQInt * asFirstOrderModelQInt() { return this; }
- void processInitialize( bool ispre );
- Node getFunctionValue(Node op, const char* argPrefix );
-
- Node getUsedRepresentative( Node n );
- int getRepId( Node n ) { return d_rep_id.find( n )==d_rep_id.end() ? -1 : d_rep_id[n]; }
- bool isLessThan( Node v1, Node v2 );
- Node getMin( Node v1, Node v2 );
- Node getMax( Node v1, Node v2 );
- Node getMinimum( TypeNode tn ) { return getNext( tn, Node::null() ); }
- Node getMaximum( TypeNode tn );
- bool isMinimum( Node n ) { return n==getMinimum( n.getType() ); }
- bool isMaximum( Node n ) { return n==getMaximum( n.getType() ); }
- Node getNext( TypeNode tn, Node v );
- Node getPrev( TypeNode tn, Node v );
- bool doMeet( Node l1, Node u1, Node l2, Node u2, Node& lr, Node& ur );
- QuantVarOrder * getVarOrder( Node q ) { return d_var_order[q]; }
-
- void processInitializeQuantifier( Node q ) ;
- unsigned getOrderedNumVars( Node q );
- TypeNode getOrderedVarType( Node q, int i );
- int getOrderedVarNumToVarNum( Node q, int i );
-};/* class FirstOrderModelQInt */
-
class AbsDef;
class FirstOrderModelAbs : public FirstOrderModel
diff --git a/src/theory/quantifiers/fun_def_process.cpp b/src/theory/quantifiers/fun_def_process.cpp
new file mode 100644
index 000000000..cb772a31f
--- /dev/null
+++ b/src/theory/quantifiers/fun_def_process.cpp
@@ -0,0 +1,197 @@
+/********************* */
+/*! \file fun_def_process.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds
+ ** Major contributors: Morgan Deters
+ ** Minor contributors (to current version): Kshitij Bansal
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Sort inference module
+ **
+ ** This class implements pre-process steps for well-defined functions
+ **/
+
+#include <vector>
+
+#include "theory/quantifiers/fun_def_process.h"
+#include "theory/rewriter.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/quant_util.h"
+
+using namespace CVC4;
+using namespace std;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+using namespace CVC4::kind;
+
+
+void FunDefFmf::simplify( std::vector< Node >& assertions, bool doRewrite ) {
+ std::vector< int > fd_assertions;
+ //first pass : find defined functions, transform quantifiers
+ for( unsigned i=0; i<assertions.size(); i++ ){
+ if( assertions[i].getKind()==FORALL ){
+ if( quantifiers::TermDb::isFunDef( assertions[i] ) ){
+ Assert( assertions[i][1].getKind()==EQUAL || assertions[i][1].getKind()==IFF );
+ Node n = assertions[i][1][0];
+ Assert( n.getKind()==APPLY_UF );
+ Node f = n.getOperator();
+
+ //check if already defined, if so, throw error
+ if( d_sorts.find( f )!=d_sorts.end() ){
+ Message() << "Cannot define function " << f << " more than once." << std::endl;
+ exit( 0 );
+ }
+
+ //create a sort S that represents the inputs of the function
+ std::stringstream ss;
+ ss << "I_" << f;
+ TypeNode iType = NodeManager::currentNM()->mkSort( ss.str() );
+ d_sorts[f] = iType;
+
+ //create functions f1...fn mapping from this sort to concrete elements
+ for( unsigned j=0; j<n.getNumChildren(); j++ ){
+ TypeNode typ = NodeManager::currentNM()->mkFunctionType( iType, n[j].getType() );
+ std::stringstream ss;
+ ss << f << "_arg_" << j;
+ d_input_arg_inj[f].push_back( NodeManager::currentNM()->mkSkolem( ss.str(), typ, "op created during fun def fmf" ) );
+ }
+
+ //construct new quantifier forall S. F[f1(S)/x1....fn(S)/xn]
+ std::vector< Node > children;
+ Node bv = NodeManager::currentNM()->mkBoundVar("?i", iType );
+ Node bvl = NodeManager::currentNM()->mkNode( kind::BOUND_VAR_LIST, bv );
+ std::vector< Node > subs;
+ std::vector< Node > vars;
+ for( unsigned j=0; j<n.getNumChildren(); j++ ){
+ vars.push_back( n[j] );
+ subs.push_back( NodeManager::currentNM()->mkNode( APPLY_UF, d_input_arg_inj[f][j], bv ) );
+ }
+ Node bd = assertions[i][1].substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+
+ Trace("fmf-fun-def") << "FMF fun def: rewrite " << assertions[i] << std::endl;
+ Trace("fmf-fun-def") << " to " << std::endl;
+ assertions[i] = NodeManager::currentNM()->mkNode( FORALL, bvl, bd );
+ Trace("fmf-fun-def") << " " << assertions[i] << std::endl;
+ fd_assertions.push_back( i );
+ }
+ }
+ }
+ //second pass : rewrite assertions
+ for( unsigned i=0; i<assertions.size(); i++ ){
+ bool is_fd = std::find( fd_assertions.begin(), fd_assertions.end(), i )!=fd_assertions.end();
+ std::vector< Node > constraints;
+ Node n = simplify( assertions[i], true, true, constraints, is_fd );
+ Assert( constraints.empty() );
+ if( n!=assertions[i] ){
+ n = Rewriter::rewrite( n );
+ Trace("fmf-fun-def-rewrite") << "FMF fun def : rewrite " << assertions[i] << std::endl;
+ Trace("fmf-fun-def-rewrite") << " to " << std::endl;
+ Trace("fmf-fun-def-rewrite") << " " << n << std::endl;
+ assertions[i] = n;
+ }
+ }
+}
+
+Node FunDefFmf::simplify( Node n, bool pol, bool hasPol, std::vector< Node >& constraints, bool is_fun_def ) {
+ Trace("fmf-fun-def-debug") << "Simplify " << n << " " << pol << " " << hasPol << " " << is_fun_def << std::endl;
+ if( n.getKind()==FORALL ){
+ Node c = simplify( n[1], pol, hasPol, constraints, is_fun_def );
+ if( c!=n[1] ){
+ return NodeManager::currentNM()->mkNode( FORALL, n[0], c );
+ }else{
+ return n;
+ }
+ }else if( n.getType().isBoolean() && n.getKind()!=APPLY_UF ){
+ std::vector< Node > children;
+ bool childChanged = false;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ Node c = n[i];
+ //do not process LHS of definition
+ if( !is_fun_def || i!=0 ){
+ bool newHasPol;
+ bool newPol;
+ QuantPhaseReq::getPolarity( n, i, hasPol, pol, newHasPol, newPol );
+ //get child constraints
+ std::vector< Node > cconstraints;
+ c = simplify( n[i], newPol, newHasPol, cconstraints );
+ constraints.insert( constraints.end(), cconstraints.begin(), cconstraints.end() );
+ }
+ children.push_back( c );
+ childChanged = c!=n[i] || childChanged;
+ }
+ if( !constraints.empty() || childChanged ){
+ std::vector< Node > c;
+ if( childChanged ){
+ c.push_back( NodeManager::currentNM()->mkNode( n.getKind(), children ) );
+ }else{
+ c.push_back( n );
+ }
+ if( hasPol ){
+ //conjoin with current
+ for( unsigned i=0; i<constraints.size(); i++ ){
+ if( pol ){
+ c.push_back( constraints[i] );
+ }else{
+ c.push_back( constraints[i].negate() );
+ }
+ }
+ constraints.clear();
+ }else{
+ //must add at higher level
+ }
+ return c.size()==1 ? c[0] : NodeManager::currentNM()->mkNode( pol ? AND : OR, c );
+ }
+ }else{
+ //simplify term
+ simplifyTerm( n, constraints );
+ }
+ return n;
+}
+
+void FunDefFmf::simplifyTerm( Node n, std::vector< Node >& constraints ) {
+ Trace("fmf-fun-def-debug") << "Simplify term " << n << std::endl;
+ if( n.getKind()==ITE ){
+ simplifyTerm( n[0], constraints );
+ std::vector< Node > ccons1;
+ std::vector< Node > ccons2;
+ simplifyTerm( n[1], ccons1 );
+ simplifyTerm( n[2], ccons2 );
+ if( !ccons1.empty() || !ccons2.empty() ){
+ Node n1 = ccons1.empty() ? NodeManager::currentNM()->mkConst( true ) : ( ccons1.size()==1 ? ccons1[0] : NodeManager::currentNM()->mkNode( AND, ccons1 ) );
+ Node n2 = ccons2.empty() ? NodeManager::currentNM()->mkConst( true ) : ( ccons2.size()==1 ? ccons2[0] : NodeManager::currentNM()->mkNode( AND, ccons2 ) );
+ constraints.push_back( NodeManager::currentNM()->mkNode( ITE, n[0], n1, n2 ) );
+ }
+ }else{
+ if( n.getKind()==APPLY_UF ){
+ //check if f is defined, if so, we must enforce domain constraints for this f-application
+ Node f = n.getOperator();
+ std::map< Node, TypeNode >::iterator it = d_sorts.find( f );
+ if( it!=d_sorts.end() ){
+ //create existential
+ Node z = NodeManager::currentNM()->mkBoundVar("?z", it->second );
+ Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, z );
+ std::vector< Node > children;
+ for( unsigned j=0; j<n.getNumChildren(); j++ ){
+ Node uz = NodeManager::currentNM()->mkNode( APPLY_UF, d_input_arg_inj[f][j], z );
+ if( !n[j].getType().isBoolean() ){
+ children.push_back( uz.eqNode( n[j] ) );
+ }else{
+ children.push_back( uz.iffNode( n[j] ) );
+ }
+ }
+ Node bd = children.size()==1 ? children[0] : NodeManager::currentNM()->mkNode( AND, children );
+ bd = bd.negate();
+ Node ex = NodeManager::currentNM()->mkNode( FORALL, bvl, bd );
+ ex = ex.negate();
+ constraints.push_back( ex );
+ Trace("fmf-fun-def-debug") << "---> add constraint " << ex << std::endl;
+ }
+ }
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ simplifyTerm( n[i], constraints );
+ }
+ }
+}
diff --git a/src/theory/quantifiers/fun_def_process.h b/src/theory/quantifiers/fun_def_process.h
new file mode 100644
index 000000000..40364eeb7
--- /dev/null
+++ b/src/theory/quantifiers/fun_def_process.h
@@ -0,0 +1,54 @@
+/********************* */
+/*! \file fun_def_process.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds
+ ** Major contributors: Morgan Deters
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Pre-process steps for well-defined functions
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__QUANTIFIERS_FUN_DEF_PROCESS_H
+#define __CVC4__QUANTIFIERS_FUN_DEF_PROCESS_H
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <map>
+#include "expr/node.h"
+#include "expr/type_node.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+//find finite models for well-defined functions
+class FunDefFmf {
+private:
+ //defined functions to input sort
+ std::map< Node, TypeNode > d_sorts;
+ //defined functions to injections input -> argument elements
+ std::map< Node, std::vector< Node > > d_input_arg_inj;
+ //simplify
+ Node simplify( Node n, bool pol, bool hasPol, std::vector< Node >& constraints, bool is_fun_def = false );
+ //simplify term
+ void simplifyTerm( Node n, std::vector< Node >& constraints );
+public:
+ FunDefFmf(){}
+ ~FunDefFmf(){}
+
+ void simplify( std::vector< Node >& assertions, bool doRewrite = false );
+};
+
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/inst_gen.cpp b/src/theory/quantifiers/inst_gen.cpp
deleted file mode 100644
index 33fcaa27a..000000000
--- a/src/theory/quantifiers/inst_gen.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-/********************* */
-/*! \file inst_gen.cpp
- ** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Implementation of inst gen classes
- **/
-
-#include "theory/quantifiers/inst_gen.h"
-#include "theory/quantifiers/model_engine.h"
-#include "theory/quantifiers/model_builder.h"
-#include "theory/quantifiers/first_order_model.h"
-#include "theory/quantifiers/term_database.h"
-
-//#define CHILD_USE_CONSIDER
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::quantifiers;
-
-
-
-InstGenProcess::InstGenProcess( Node n ) : d_node( n ){
- Assert( TermDb::hasInstConstAttr(n) );
- int count = 0;
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- if( n[i].getKind()!=INST_CONSTANT && TermDb::hasInstConstAttr(n[i]) ){
- d_children.push_back( InstGenProcess( n[i] ) );
- d_children_index.push_back( i );
- d_children_map[ i ] = count;
- count++;
- }
- if( n[i].getKind()==INST_CONSTANT ){
- d_var_num[i] = n[i].getAttribute(InstVarNumAttribute());
- }
- }
-}
-
-void InstGenProcess::addMatchValue( QuantifiersEngine* qe, Node f, Node val, InstMatch& m ){
- if( !qe->existsInstantiation( f, m, true ) ){
- //make sure no duplicates are produced
- if( d_inst_trie[val].addInstMatch( qe, f, m, true ) ){
- d_match_values.push_back( val );
- d_matches.push_back( InstMatch( &m ) );
- ((QModelBuilderIG*)qe->getModelBuilder())->d_instGenMatches++;
- }
- }
-}
-
-void InstGenProcess::calculateMatches( QuantifiersEngine* qe, Node f, std::vector< Node >& considerVal, bool useConsider ){
- Trace("inst-gen-cm") << "* Calculate matches " << d_node << std::endl;
- //whether we are doing a product or sum or matches
- bool doProduct = true;
- //get the model
- FirstOrderModel* fm = qe->getModel();
-
- //calculate terms we will consider
- std::vector< Node > considerTerms;
- std::vector< std::vector< Node > > newConsiderVal;
- std::vector< bool > newUseConsider;
- std::map< Node, InstMatch > considerTermsMatch[2];
- std::map< Node, bool > considerTermsSuccess[2];
- newConsiderVal.resize( d_children.size() );
- newUseConsider.resize( d_children.size(), useConsider );
- if( d_node.getKind()==APPLY_UF ){
- Node op = d_node.getOperator();
- if( useConsider ){
-#ifndef CHILD_USE_CONSIDER
- for( size_t i=0; i<newUseConsider.size(); i++ ){
- newUseConsider[i] = false;
- }
-#endif
- for( size_t i=0; i<considerVal.size(); i++ ){
- eq::EqClassIterator eqc( qe->getEqualityQuery()->getEngine()->getRepresentative( considerVal[i] ),
- qe->getEqualityQuery()->getEngine() );
- while( !eqc.isFinished() ){
- Node en = (*eqc);
- if( en.getKind()==APPLY_UF && en.getOperator()==op ){
- considerTerms.push_back( en );
- }
- ++eqc;
- }
- }
- }else{
- considerTerms.insert( considerTerms.begin(), fm->d_uf_terms[op].begin(), fm->d_uf_terms[op].end() );
- }
- //for each term we consider, calculate a current match
- for( size_t i=0; i<considerTerms.size(); i++ ){
- Node n = considerTerms[i];
- bool isSelected = ((QModelBuilderIG*)qe->getModelBuilder())->isTermSelected( n );
- bool hadSuccess CVC4_UNUSED = false;
- for( int t=(isSelected ? 0 : 1); t<2; t++ ){
- if( t==0 || !n.getAttribute(NoMatchAttribute()) ){
- considerTermsMatch[t][n] = InstMatch( f );
- considerTermsSuccess[t][n] = true;
- for( size_t j=0; j<d_node.getNumChildren(); j++ ){
- if( d_children_map.find( j )==d_children_map.end() ){
- if( t!=0 || !n[j].getAttribute(ModelBasisAttribute()) ){
- if( d_node[j].getKind()==INST_CONSTANT ){
- if( !considerTermsMatch[t][n].set( qe, d_var_num[j], n[j] ) ){
- Trace("inst-gen-cm") << "fail match: " << n[j] << " is not equal to ";
- Trace("inst-gen-cm") << considerTermsMatch[t][n].get( d_var_num[j] ) << std::endl;
- considerTermsSuccess[t][n] = false;
- break;
- }
- }else if( !qe->getEqualityQuery()->areEqual( d_node[j], n[j] ) ){
- Trace("inst-gen-cm") << "fail arg: " << n[j] << " is not equal to " << d_node[j] << std::endl;
- considerTermsSuccess[t][n] = false;
- break;
- }
- }
- }
- }
- //if successful, store it
- if( considerTermsSuccess[t][n] ){
-#ifdef CHILD_USE_CONSIDER
- if( !hadSuccess ){
- hadSuccess = true;
- for( size_t k=0; k<d_children.size(); k++ ){
- if( newUseConsider[k] ){
- int childIndex = d_children_index[k];
- //determine if we are restricted or not
- if( t!=0 || !n[childIndex].getAttribute(ModelBasisAttribute()) ){
- Node r = qe->getModel()->getRepresentative( n[childIndex] );
- if( std::find( newConsiderVal[k].begin(), newConsiderVal[k].end(), r )==newConsiderVal[k].end() ){
- newConsiderVal[k].push_back( r );
- //check if we now need to consider the entire domain
- TypeNode tn = r.getType();
- if( qe->getModel()->d_rep_set.hasType( tn ) ){
- if( (int)newConsiderVal[k].size()>=qe->getModel()->d_rep_set.getNumRepresentatives( tn ) ){
- newConsiderVal[k].clear();
- newUseConsider[k] = false;
- }
- }
- }
- }else{
- //matching against selected term, will need to consider all values
- newConsiderVal[k].clear();
- newUseConsider[k] = false;
- }
- }
- }
- }
-#endif
- }
- }
- }
- }
- }else{
- //the interpretted case
- if( d_node.getType().isBoolean() ){
- if( useConsider ){
- //if( considerVal.size()!=1 ) { std::cout << "consider val = " << considerVal.size() << std::endl; }
- Assert( considerVal.size()==1 );
- bool reqPol = considerVal[0]==fm->d_true;
- Node ncv = considerVal[0];
- if( d_node.getKind()==NOT ){
- ncv = reqPol ? fm->d_false : fm->d_true;
- }
- if( d_node.getKind()==NOT || d_node.getKind()==AND || d_node.getKind()==OR ){
- for( size_t i=0; i<newConsiderVal.size(); i++ ){
- newConsiderVal[i].push_back( ncv );
- }
- //instead we will do a sum
- if( ( d_node.getKind()==AND && !reqPol ) || ( d_node.getKind()==OR && reqPol ) ){
- doProduct = false;
- }
- }else{
- //do not use consider
- for( size_t i=0; i<newUseConsider.size(); i++ ){
- newUseConsider[i] = false;
- }
- }
- }
- }
- }
-
- //calculate all matches for children
- for( int i=0; i<(int)d_children.size(); i++ ){
- d_children[i].calculateMatches( qe, f, newConsiderVal[i], newUseConsider[i] );
- if( doProduct && d_children[i].getNumMatches()==0 ){
- return;
- }
- }
- if( d_node.getKind()==APPLY_UF ){
- //if this is an uninterpreted function
- Node op = d_node.getOperator();
- //process all values
- for( size_t i=0; i<considerTerms.size(); i++ ){
- Node n = considerTerms[i];
- bool isSelected = ((QModelBuilderIG*)qe->getModelBuilder())->isTermSelected( n );
- for( int t=(isSelected ? 0 : 1); t<2; t++ ){
- //do not consider ground case if it is already congruent to another ground term
- if( t==0 || !n.getAttribute(NoMatchAttribute()) ){
- Trace("inst-gen-cm") << "calculate for " << n << ", selected = " << (t==0) << std::endl;
- if( considerTermsSuccess[t][n] ){
- //try to find unifier for d_node = n
- calculateMatchesUninterpreted( qe, f, considerTermsMatch[t][n], n, 0, t==0 );
- }
- }
- }
- }
- }else{
- //if this is an interpreted function
- if( doProduct ){
- //combining children matches
- InstMatch curr( f );
- std::vector< Node > terms;
- calculateMatchesInterpreted( qe, f, curr, terms, 0 );
- }else{
- //summing children matches
- Assert( considerVal.size()==1 );
- for( int i=0; i<(int)d_children.size(); i++ ){
- for( int j=0; j<(int)d_children[ i ].getNumMatches(); j++ ){
- InstMatch m( f );
- if( d_children[ i ].getMatch( qe->getEqualityQuery(), j, m ) ){
- addMatchValue( qe, f, considerVal[0], m );
- }
- }
- }
- }
- }
- Trace("inst-gen-cm") << "done calculate matches" << std::endl;
- //can clear information used for finding duplicates
- d_inst_trie.clear();
-}
-
-bool InstGenProcess::getMatch( EqualityQuery* q, int i, InstMatch& m ){
- //FIXME: is this correct? (query may not be accurate)
- return m.merge( q, d_matches[i] );
-}
-
-void InstGenProcess::calculateMatchesUninterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, Node n, int childIndex, bool isSelected ){
- if( childIndex==(int)d_children.size() ){
- Node val = qe->getModel()->getRepresentative( n ); //FIXME: is this correct?
- Trace("inst-gen-cm") << " - u-match : " << val << std::endl;
- Trace("inst-gen-cm") << " : " << curr << std::endl;
- addMatchValue( qe, f, val, curr );
- }else{
- Trace("inst-gen-cm") << "Consider child index = " << childIndex << ", against ground term argument " << d_children_index[childIndex] << " ... " << n[d_children_index[childIndex]] << std::endl;
- bool sel = ( isSelected && n[d_children_index[childIndex]].getAttribute(ModelBasisAttribute()) );
- for( int i=0; i<(int)d_children[ childIndex ].getNumMatches(); i++ ){
- //FIXME: is this correct?
- if( sel || qe->getEqualityQuery()->areEqual( d_children[ childIndex ].getMatchValue( i ), n[d_children_index[childIndex]] ) ){
- InstMatch next( &curr );
- if( d_children[ childIndex ].getMatch( qe->getEqualityQuery(), i, next ) ){
- calculateMatchesUninterpreted( qe, f, next, n, childIndex+1, isSelected );
- }else{
- Trace("inst-gen-cm") << curr << " not equal to " << d_children[ childIndex ].d_matches[i] << std::endl;
- Trace("inst-gen-cm") << childIndex << " match " << i << " not equal subs." << std::endl;
- }
- }else{
- Trace("inst-gen-cm") << childIndex << " match " << i << " not equal value." << std::endl;
- }
- }
- }
-}
-
-void InstGenProcess::calculateMatchesInterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, std::vector< Node >& terms, int argIndex ){
- FirstOrderModel* fm = qe->getModel();
- if( argIndex==(int)d_node.getNumChildren() ){
- Node val;
- if( d_node.getNumChildren()==0 ){
- val = d_node;
- }else if( d_node.getKind()==EQUAL ){
- val = qe->getEqualityQuery()->areEqual( terms[0], terms[1] ) ? fm->d_true : fm->d_false;
- }else{
- val = NodeManager::currentNM()->mkNode( d_node.getKind(), terms );
- val = Rewriter::rewrite( val );
- }
- Trace("inst-gen-cm") << " - i-match : " << d_node << std::endl;
- Trace("inst-gen-cm") << " : " << val << std::endl;
- Trace("inst-gen-cm") << " : " << curr << std::endl;
- addMatchValue( qe, f, val, curr );
- }else{
- if( d_children_map.find( argIndex )==d_children_map.end() ){
- terms.push_back( fm->getRepresentative( d_node[argIndex] ) );
- calculateMatchesInterpreted( qe, f, curr, terms, argIndex+1 );
- terms.pop_back();
- }else{
- for( int i=0; i<(int)d_children[ d_children_map[argIndex] ].getNumMatches(); i++ ){
- InstMatch next( &curr );
- if( d_children[ d_children_map[argIndex] ].getMatch( qe->getEqualityQuery(), i, next ) ){
- terms.push_back( d_children[ d_children_map[argIndex] ].getMatchValue( i ) );
- calculateMatchesInterpreted( qe, f, next, terms, argIndex+1 );
- terms.pop_back();
- }
- }
- }
- }
-}
diff --git a/src/theory/quantifiers/inst_gen.h b/src/theory/quantifiers/inst_gen.h
deleted file mode 100644
index 6567994f2..000000000
--- a/src/theory/quantifiers/inst_gen.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/********************* */
-/*! \file inst_gen.h
- ** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Inst Gen classes
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__THEORY__QUANTIFIERS__INST_GEN_H
-#define __CVC4__THEORY__QUANTIFIERS__INST_GEN_H
-
-#include "theory/quantifiers_engine.h"
-#include "theory/quantifiers/inst_match.h"
-
-namespace CVC4 {
-namespace theory {
-namespace quantifiers {
-
-class InstGenProcess
-{
-private:
- //the node we are processing
- Node d_node;
- std::map< int, int > d_var_num;
- //the sub children for this node
- std::vector< InstGenProcess > d_children;
- std::vector< int > d_children_index;
- std::map< int, int > d_children_map;
- //the matches we have produced
- std::vector< InstMatch > d_matches;
- std::vector< Node > d_match_values;
- //add match value
- std::map< Node, inst::InstMatchTrie > d_inst_trie;
- void addMatchValue( QuantifiersEngine* qe, Node f, Node val, InstMatch& m );
-private:
- void calculateMatchesUninterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, Node n, int childIndex, bool isSelected );
- void calculateMatchesInterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, std::vector< Node >& terms, int argIndex );
-public:
- InstGenProcess( Node n );
- virtual ~InstGenProcess(){}
-
- void calculateMatches( QuantifiersEngine* qe, Node f, std::vector< Node >& considerVal, bool useConsider );
- int getNumMatches() { return d_matches.size(); }
- bool getMatch( EqualityQuery* q, int i, InstMatch& m );
- Node getMatchValue( int i ) { return d_match_values[i]; }
-};/* class InstGenProcess */
-
-}/* CVC4::theory::quantifiers namespace */
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
-
-#endif /* __CVC4__THEORY__QUANTIFIERS__INST_GEN_H */
diff --git a/src/theory/quantifiers/inst_match_generator.cpp b/src/theory/quantifiers/inst_match_generator.cpp
index c78ea7b01..cd24f9ac2 100644
--- a/src/theory/quantifiers/inst_match_generator.cpp
+++ b/src/theory/quantifiers/inst_match_generator.cpp
@@ -36,6 +36,7 @@ InstMatchGenerator::InstMatchGenerator( Node pat ){
Assert( quantifiers::TermDb::hasInstConstAttr(pat) );
d_pattern = pat;
d_match_pattern = pat;
+ d_match_pattern_type = pat.getType();
d_next = NULL;
d_matchPolicy = MATCH_GEN_DEFAULT;
}
@@ -92,6 +93,7 @@ void InstMatchGenerator::initialize( QuantifiersEngine* qe, std::vector< InstMat
}
}
}
+ d_match_pattern_type = d_match_pattern.getType();
Trace("inst-match-gen") << "Pattern is " << d_pattern << ", match pattern is " << d_match_pattern << std::endl;
d_match_pattern_op = qe->getTermDatabase()->getOperator( d_match_pattern );
@@ -315,7 +317,7 @@ bool InstMatchGenerator::getNextMatch( Node f, InstMatch& m, QuantifiersEngine*
t = d_cg->getNextCandidate();
Trace("matching-debug2") << "Matching candidate : " << t << std::endl;
//if t not null, try to fit it into match m
- if( !t.isNull() && t.getType().isSubtypeOf( d_match_pattern.getType() ) ){
+ if( !t.isNull() && t.getType().isSubtypeOf( d_match_pattern_type ) ){
success = getMatch( f, t, m, qe );
}
}while( !success && !t.isNull() );
@@ -454,7 +456,7 @@ bool VarMatchGeneratorTermSubs::getNextMatch( Node f, InstMatch& m, QuantifiersE
}
/** constructors */
-InstMatchGeneratorMulti::InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption ) :
+InstMatchGeneratorMulti::InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe ) :
d_f( f ){
Debug("smart-multi-trigger") << "Making smart multi-trigger for " << f << std::endl;
std::map< Node, std::vector< Node > > var_contains;
@@ -675,6 +677,7 @@ InstMatchGeneratorSimple::InstMatchGeneratorSimple( Node f, Node pat ) : d_f( f
if( d_match_pattern[i].getKind()==INST_CONSTANT ){
d_var_num[i] = d_match_pattern[i].getAttribute(InstVarNumAttribute());
}
+ d_match_pattern_arg_types.push_back( d_match_pattern[i].getType() );
}
}
@@ -713,7 +716,7 @@ void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngin
Node t = it->first;
Node prev = m.get( v );
//using representatives, just check if equal
- if( ( prev.isNull() || prev==t ) && t.getType().isSubtypeOf( d_match_pattern[argIndex].getType() ) ){
+ if( ( prev.isNull() || prev==t ) && t.getType().isSubtypeOf( d_match_pattern_arg_types[argIndex] ) ){
m.setValue( v, t);
addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
m.setValue( v, prev);
diff --git a/src/theory/quantifiers/inst_match_generator.h b/src/theory/quantifiers/inst_match_generator.h
index aa5d37713..1be67caed 100644
--- a/src/theory/quantifiers/inst_match_generator.h
+++ b/src/theory/quantifiers/inst_match_generator.h
@@ -96,6 +96,8 @@ public:
Node d_pattern;
/** match pattern */
Node d_match_pattern;
+ /** match pattern type */
+ TypeNode d_match_pattern_type;
/** match pattern op */
Node d_match_pattern_op;
public:
@@ -182,7 +184,7 @@ private:
void calculateMatches( QuantifiersEngine* qe );
public:
/** constructors */
- InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption = 0 );
+ InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe );
/** destructor */
~InstMatchGeneratorMulti(){}
/** reset instantiation round (call this whenever equivalence classes have changed) */
@@ -204,6 +206,8 @@ private:
Node d_f;
/** match term */
Node d_match_pattern;
+ /** match pattern arg types */
+ std::vector< TypeNode > d_match_pattern_arg_types;
/** operator */
Node d_op;
/** to indicies */
diff --git a/src/theory/quantifiers/inst_strategy_e_matching.cpp b/src/theory/quantifiers/inst_strategy_e_matching.cpp
index 4284c8145..8918a6dac 100644
--- a/src/theory/quantifiers/inst_strategy_e_matching.cpp
+++ b/src/theory/quantifiers/inst_strategy_e_matching.cpp
@@ -28,6 +28,14 @@ using namespace CVC4::theory;
using namespace CVC4::theory::inst;
using namespace CVC4::theory::quantifiers;
+//priority levels :
+//1 : user patterns (when user-pat!={resort,ignore}), auto-gen patterns (for non-user pattern quantifiers)
+//2 : user patterns (when user-pat=resort ), auto gen patterns (for user pattern quantifiers, when user-pat=use)
+//3 : local theory extensions
+//4 :
+//5 : full saturate quantifiers
+
+
//#define MULTI_TRIGGER_FULL_EFFORT_HALF
#define MULTI_MULTI_TRIGGERS
@@ -173,7 +181,7 @@ int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e )
if( gen ){
generateTriggers( f, effort, e, status );
if( d_auto_gen_trigger[f].empty() && f.getNumChildren()==2 ){
- Trace("no-trigger") << "Could not find trigger for " << f << std::endl;
+ Trace("trigger-warn") << "Could not find trigger for " << f << std::endl;
}
}
@@ -220,8 +228,16 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f, Theory::Effort effor
d_patTerms[0][f].clear();
d_patTerms[1][f].clear();
std::vector< Node > patTermsF;
- Trigger::collectPatTerms( d_quantEngine, f, d_quantEngine->getTermDatabase()->getInstConstantBody( f ), patTermsF, d_tr_strategy, d_user_no_gen[f], true );
- Trace("auto-gen-trigger") << "Collected pat terms for " << d_quantEngine->getTermDatabase()->getInstConstantBody( f ) << ", no-patterns : " << d_user_no_gen[f].size() << std::endl;
+ //well-defined function: can assume LHS is only trigger
+ Node bd = d_quantEngine->getTermDatabase()->getInstConstantBody( f );
+ if( d_quantEngine->getTermDatabase()->isQAttrFunDef( f ) && options::quantFunWellDefined() ){
+ Assert( bd.getKind()==EQUAL || bd.getKind()==IFF );
+ Assert( bd[0].getKind()==APPLY_UF );
+ patTermsF.push_back( bd[0] );
+ }else{
+ Trigger::collectPatTerms( d_quantEngine, f, bd, patTermsF, d_tr_strategy, d_user_no_gen[f], true );
+ }
+ Trace("auto-gen-trigger") << "Collected pat terms for " << bd << ", no-patterns : " << d_user_no_gen[f].size() << std::endl;
Trace("auto-gen-trigger") << " ";
for( int i=0; i<(int)patTermsF.size(); i++ ){
Trace("auto-gen-trigger") << patTermsF[i] << " ";
@@ -314,8 +330,7 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f, Theory::Effort effor
d_made_multi_trigger[f] = true;
}
//will possibly want to get an old trigger
- tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, false, Trigger::TR_GET_OLD,
- options::smartTriggers() );
+ tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, false, Trigger::TR_GET_OLD, options::smartTriggers() );
}
if( tr ){
if( tr->isMultiTrigger() ){
@@ -349,8 +364,7 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f, Theory::Effort effor
if( !options::relevantTriggers() ||
d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[index].getOperator() )<=nqfs_curr ){
d_single_trigger_gen[ patTerms[index] ] = true;
- Trigger* tr2 = Trigger::mkTrigger( d_quantEngine, f, patTerms[index], matchOption, false, Trigger::TR_RETURN_NULL,
- options::smartTriggers() );
+ Trigger* tr2 = Trigger::mkTrigger( d_quantEngine, f, patTerms[index], matchOption, false, Trigger::TR_RETURN_NULL, options::smartTriggers() );
if( tr2 ){
//Notice() << "Add additional trigger " << patTerms[index] << std::endl;
tr2->resetInstantiationRound();
@@ -397,7 +411,75 @@ void InstStrategyAutoGenTriggers::addUserNoPattern( Node f, Node pat ) {
}
}
+
+void InstStrategyLocalTheoryExt::processResetInstantiationRound( Theory::Effort effort ){
+ //reset triggers
+ for( std::map< Node, Trigger* >::iterator it = d_lte_trigger.begin(); it != d_lte_trigger.end(); ++it ){
+ it->second->resetInstantiationRound();
+ it->second->reset( Node::null() );
+ }
+}
+
+int InstStrategyLocalTheoryExt::process( Node f, Theory::Effort effort, int e ) {
+ if( e<3 ){
+ return STATUS_UNFINISHED;
+ }else if( e==3 ){
+ if( isLocalTheoryExt( f ) ){
+ std::map< Node, Trigger* >::iterator it = d_lte_trigger.find( f );
+ if( it!=d_lte_trigger.end() ){
+ Trigger * tr = it->second;
+ //process the trigger
+ Trace("process-trigger") << " LTE process ";
+ tr->debugPrint("process-trigger");
+ Trace("process-trigger") << "..." << std::endl;
+ InstMatch baseMatch( f );
+ int numInst = tr->addInstantiations( baseMatch );
+ Trace("process-trigger") << " Done, numInst = " << numInst << "." << std::endl;
+ d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_lte += numInst;
+ }
+ }
+ }
+ return STATUS_UNKNOWN;
+}
+
+bool InstStrategyLocalTheoryExt::isLocalTheoryExt( Node f ) {
+ std::map< Node, bool >::iterator itq = d_quant.find( f );
+ if( itq==d_quant.end() ){
+ //generate triggers
+ Node bd = d_quantEngine->getTermDatabase()->getInstConstantBody( f );
+ std::vector< Node > vars;
+ std::vector< Node > patTerms;
+ bool ret = Trigger::isLocalTheoryExt( bd, vars, patTerms );
+ if( ret ){
+ d_quant[f] = ret;
+ //add all variables to trigger that don't already occur
+ for( unsigned i=0; i<f[0].getNumChildren(); i++ ){
+ Node x = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i );
+ if( std::find( vars.begin(), vars.end(), x )==vars.end() ){
+ patTerms.push_back( x );
+ }
+ }
+ Trace("local-t-ext") << "Local theory extensions trigger for " << f << " : " << std::endl;
+ for( unsigned i=0; i<patTerms.size(); i++ ){
+ Trace("local-t-ext") << " " << patTerms[i] << std::endl;
+ }
+ Trace("local-t-ext") << std::endl;
+ int matchOption = 0;
+ Trigger * tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, true, Trigger::TR_GET_OLD, options::smartTriggers() );
+ d_lte_trigger[f] = tr;
+ }else{
+ Trace("local-t-ext") << "No local theory extensions trigger for " << f << "." << std::endl;
+ Trace("local-t-ext-warn") << "WARNING: not local theory extensions : " << f << std::endl;
+ }
+ d_quant[f] = ret;
+ return ret;
+ }else{
+ return itq->second;
+ }
+}
+
void InstStrategyFreeVariable::processResetInstantiationRound( Theory::Effort effort ){
+
}
int InstStrategyFreeVariable::process( Node f, Theory::Effort effort, int e ){
@@ -496,6 +578,6 @@ int InstStrategyFreeVariable::process( Node f, Theory::Effort effort, int e ){
}
}
}
- return STATUS_UNKNOWN;
}
+ return STATUS_UNKNOWN;
}
diff --git a/src/theory/quantifiers/inst_strategy_e_matching.h b/src/theory/quantifiers/inst_strategy_e_matching.h
index dd4486803..d2c611d34 100644
--- a/src/theory/quantifiers/inst_strategy_e_matching.h
+++ b/src/theory/quantifiers/inst_strategy_e_matching.h
@@ -58,7 +58,7 @@ public:
std::string identify() const { return std::string("UserPatterns"); }
};/* class InstStrategyUserPatterns */
-class InstStrategyAutoGenTriggers : public InstStrategy{
+class InstStrategyAutoGenTriggers : public InstStrategy {
public:
enum {
RELEVANCE_NONE,
@@ -98,7 +98,7 @@ public:
/** tstrt is the type of triggers to use (maximum depth, minimum depth, or all)
rstrt is the relevance setting for trigger (use only relevant triggers vs. use all)
rgfr is the frequency at which triggers are generated */
- InstStrategyAutoGenTriggers( QuantifiersEngine* qe, int tstrt, int rgfr = -1 );
+ InstStrategyAutoGenTriggers( QuantifiersEngine* qe, int tstrt, int rgfr = -1 );
~InstStrategyAutoGenTriggers(){}
public:
/** get auto-generated trigger */
@@ -109,6 +109,26 @@ public:
void addUserNoPattern( Node f, Node pat );
};/* class InstStrategyAutoGenTriggers */
+
+class InstStrategyLocalTheoryExt : public InstStrategy {
+private:
+ /** have we registered quantifier, value is whether it is an LTE term */
+ std::map< Node, bool > d_quant;
+ /** triggers for each quantifier */
+ std::map< Node, inst::Trigger* > d_lte_trigger;
+private:
+ /** process functions */
+ void processResetInstantiationRound( Theory::Effort effort );
+ int process( Node f, Theory::Effort effort, int e );
+public:
+ InstStrategyLocalTheoryExt( QuantifiersEngine* qe ) : InstStrategy( qe ){}
+ /** identify */
+ std::string identify() const { return std::string("LocalTheoryExt"); }
+ /** is local theory quantifier? */
+ bool isLocalTheoryExt( Node f );
+};
+
+
class InstStrategyFreeVariable : public InstStrategy{
private:
/** guessed instantiations */
@@ -124,6 +144,7 @@ public:
std::string identify() const { return std::string("FreeVariable"); }
};/* class InstStrategyFreeVariable */
+
}
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/quantifiers/instantiation_engine.cpp b/src/theory/quantifiers/instantiation_engine.cpp
index 1cb86e32f..ade6d4313 100644
--- a/src/theory/quantifiers/instantiation_engine.cpp
+++ b/src/theory/quantifiers/instantiation_engine.cpp
@@ -31,26 +31,26 @@ using namespace CVC4::theory::quantifiers;
using namespace CVC4::theory::inst;
InstantiationEngine::InstantiationEngine( QuantifiersEngine* qe, bool setIncomplete ) :
-QuantifiersModule( qe ), d_isup(NULL), d_i_ag(NULL), d_setIncomplete( setIncomplete ), d_ierCounter( 0 ){
+QuantifiersModule( qe ), d_isup(NULL), d_i_ag(NULL), d_i_lte(NULL), d_i_fs(NULL), d_i_splx(NULL), d_setIncomplete( setIncomplete ), d_ierCounter( 0 ){
}
InstantiationEngine::~InstantiationEngine() {
delete d_i_ag;
delete d_isup;
+ delete d_i_lte;
+ delete d_i_fs;
+ delete d_i_splx;
}
void InstantiationEngine::finishInit(){
- if( !options::finiteModelFind() || options::fmfInstEngine() ){
-
+ if( options::eMatching() ){
//these are the instantiation strategies for E-matching
//user-provided patterns
if( options::userPatternsQuant()!=USER_PAT_MODE_IGNORE ){
d_isup = new InstStrategyUserPatterns( d_quantEngine );
- addInstStrategy( d_isup );
- }else{
- d_isup = NULL;
+ d_instStrategies.push_back( d_isup );
}
//auto-generated patterns
@@ -61,18 +61,25 @@ void InstantiationEngine::finishInit(){
tstrt = Trigger::TS_MAX_TRIGGER;
}
d_i_ag = new InstStrategyAutoGenTriggers( d_quantEngine, tstrt, 3 );
- addInstStrategy( d_i_ag );
-
- //full saturation : instantiate from relevant domain, then arbitrary terms
- if( !options::finiteModelFind() && options::fullSaturateQuant() ){
- addInstStrategy( new InstStrategyFreeVariable( d_quantEngine ) );
- }
+ d_instStrategies.push_back( d_i_ag );
+ }
+
+ //local theory extensions
+ if( options::localTheoryExt() ){
+ d_i_lte = new InstStrategyLocalTheoryExt( d_quantEngine );
+ d_instStrategies.push_back( d_i_lte );
+ }
+
+ //full saturation : instantiate from relevant domain, then arbitrary terms
+ if( options::fullSaturateQuant() ){
+ d_i_fs = new InstStrategyFreeVariable( d_quantEngine );
+ d_instStrategies.push_back( d_i_fs );
}
//counterexample-based quantifier instantiation
if( options::cbqi() ){
- addInstStrategy( new InstStrategySimplex( (arith::TheoryArith*)d_quantEngine->getTheoryEngine()->theoryOf( THEORY_ARITH ), d_quantEngine ) );
- // addInstStrategy( new InstStrategyDatatypesValue( d_quantEngine ) );
+ d_i_splx = new InstStrategySimplex( (arith::TheoryArith*)d_quantEngine->getTheoryEngine()->theoryOf( THEORY_ARITH ), d_quantEngine );
+ d_instStrategies.push_back( d_i_splx );
}
}
@@ -117,18 +124,16 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
//reset the instantiators
for( size_t i=0; i<d_instStrategies.size(); ++i ){
InstStrategy* is = d_instStrategies[i];
- if( isActiveStrategy( is ) ){
- is->processResetInstantiationRound( effort );
- }
+ is->processResetInstantiationRound( effort );
}
//iterate over an internal effort level e
int e = 0;
int eLimit = effort==Theory::EFFORT_LAST_CALL ? 10 : 2;
- d_inst_round_status = InstStrategy::STATUS_UNFINISHED;
+ bool finished = false;
//while unfinished, try effort level=0,1,2....
- while( d_inst_round_status==InstStrategy::STATUS_UNFINISHED && e<=eLimit ){
+ while( !finished && e<=eLimit ){
Debug("inst-engine") << "IE: Prepare instantiation (" << e << ")." << std::endl;
- d_inst_round_status = InstStrategy::STATUS_SAT;
+ finished = true;
//instantiate each quantifier
for( int q=0; q<d_quantEngine->getModel()->getNumAssertedQuantifiers(); q++ ){
Node f = d_quantEngine->getModel()->getAssertedQuantifier( q );
@@ -141,11 +146,13 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
//check each instantiation strategy
for( size_t i=0; i<d_instStrategies.size(); ++i ){
InstStrategy* is = d_instStrategies[i];
- if( isActiveStrategy( is ) && is->shouldProcess( f ) ){
+ if( is->shouldProcess( f ) ){
Debug("inst-engine-debug") << "Do " << is->identify() << " " << e_use << std::endl;
int quantStatus = is->process( f, effort, e_use );
Debug("inst-engine-debug") << " -> status is " << quantStatus << std::endl;
- InstStrategy::updateStatus( d_inst_round_status, quantStatus );
+ if( quantStatus==InstStrategy::STATUS_UNFINISHED ){
+ finished = false;
+ }
}
}
}
@@ -153,7 +160,7 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
}
//do not consider another level if already added lemma at this level
if( d_quantEngine->d_lemmas_waiting.size()>lastWaiting ){
- d_inst_round_status = InstStrategy::STATUS_UNKNOWN;
+ finished = true;
}
e++;
}
@@ -266,28 +273,27 @@ void InstantiationEngine::check( Theory::Effort e, unsigned quant_e ){
}
if( quantActive ){
bool addedLemmas = doInstantiationRound( e );
- //Debug("quantifiers-dec") << "Do instantiation, level = " << d_quantEngine->getValuation().getDecisionLevel() << std::endl;
- //for( int i=1; i<=(int)d_valuation.getDecisionLevel(); i++ ){
- // Debug("quantifiers-dec") << " " << d_valuation.getDecision( i ) << std::endl;
- //}
- if( e==Theory::EFFORT_LAST_CALL ){
- if( !addedLemmas ){
- if( d_inst_round_status==InstStrategy::STATUS_SAT ){
- Debug("inst-engine") << "No instantiation given, returning SAT..." << std::endl;
- debugSat( SAT_INST_STRATEGY );
- }else if( d_setIncomplete ){
+ if( !addedLemmas && e==Theory::EFFORT_LAST_CALL ){
+ //check if we need to set the incomplete flag
+ if( d_setIncomplete ){
+ //check if we are complete for all active quantifiers
+ bool inc = false;
+ for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
+ if( isIncomplete( f ) ){
+ inc = true;
+ break;
+ }
+ }
+ if( inc ){
Debug("inst-engine") << "No instantiation given, returning unknown..." << std::endl;
d_quantEngine->getOutputChannel().setIncomplete();
}else{
- Assert( options::finiteModelFind() );
- Debug("inst-engine") << "No instantiation given, defer to another engine..." << std::endl;
+ Debug("inst-engine") << "Instantiation strategies were complete..." << std::endl;
}
- }
- }
- }else{
- if( e==Theory::EFFORT_LAST_CALL ){
- if( options::cbqi() ){
- debugSat( SAT_CBQI );
+ }else{
+ Assert( options::finiteModelFind() );
+ Debug("inst-engine") << "No instantiation given, defer to another engine..." << std::endl;
}
}
}
@@ -365,6 +371,15 @@ bool InstantiationEngine::doCbqi( Node f ){
}
}
+bool InstantiationEngine::isIncomplete( Node f ) {
+ if( d_i_lte ){
+ //TODO : ensure completeness for local theory extensions
+ //return !d_i_lte->isLocalTheoryExt( f );
+ return true;
+ }else{
+ return true;
+ }
+}
@@ -449,6 +464,7 @@ InstantiationEngine::Statistics::Statistics():
d_instantiations_cbqi_arith("InstantiationEngine::Instantiations_Cbqi_Arith", 0),
d_instantiations_cbqi_arith_minus("InstantiationEngine::Instantiations_Cbqi_Arith_Minus", 0),
d_instantiations_cbqi_datatypes("InstantiationEngine::Instantiations_Cbqi_Datatypes", 0),
+ d_instantiations_lte("InstantiationEngine::Instantiations_Local_T_Ext", 0),
d_instantiation_rounds("InstantiationEngine::Rounds", 0 )
{
StatisticsRegistry::registerStat(&d_instantiations_user_patterns);
@@ -458,6 +474,7 @@ InstantiationEngine::Statistics::Statistics():
StatisticsRegistry::registerStat(&d_instantiations_cbqi_arith);
StatisticsRegistry::registerStat(&d_instantiations_cbqi_arith_minus);
StatisticsRegistry::registerStat(&d_instantiations_cbqi_datatypes);
+ StatisticsRegistry::registerStat(&d_instantiations_lte);
StatisticsRegistry::registerStat(&d_instantiation_rounds);
}
@@ -469,5 +486,6 @@ InstantiationEngine::Statistics::~Statistics(){
StatisticsRegistry::unregisterStat(&d_instantiations_cbqi_arith);
StatisticsRegistry::unregisterStat(&d_instantiations_cbqi_arith_minus);
StatisticsRegistry::unregisterStat(&d_instantiations_cbqi_datatypes);
+ StatisticsRegistry::unregisterStat(&d_instantiations_lte);
StatisticsRegistry::unregisterStat(&d_instantiation_rounds);
}
diff --git a/src/theory/quantifiers/instantiation_engine.h b/src/theory/quantifiers/instantiation_engine.h
index bf0bb03e1..2fa37ac35 100644
--- a/src/theory/quantifiers/instantiation_engine.h
+++ b/src/theory/quantifiers/instantiation_engine.h
@@ -26,6 +26,9 @@ namespace quantifiers {
class InstStrategyUserPatterns;
class InstStrategyAutoGenTriggers;
+class InstStrategyLocalTheoryExt;
+class InstStrategyFreeVariable;
+class InstStrategySimplex;
/** instantiation strategy class */
class InstStrategy {
@@ -33,7 +36,6 @@ public:
enum Status {
STATUS_UNFINISHED,
STATUS_UNKNOWN,
- STATUS_SAT,
};/* enum Status */
protected:
/** reference to the instantiation engine */
@@ -57,16 +59,6 @@ public:
virtual void processResetInstantiationRound( Theory::Effort effort ) = 0;
/** process method, returns a status */
virtual int process( Node f, Theory::Effort effort, int e ) = 0;
- /** update status */
- static void updateStatus( int& currStatus, int addStatus ){
- if( addStatus==STATUS_UNFINISHED ){
- currStatus = STATUS_UNFINISHED;
- }else if( addStatus==STATUS_UNKNOWN ){
- if( currStatus==STATUS_SAT ){
- currStatus = STATUS_UNKNOWN;
- }
- }
- }
/** identify */
virtual std::string identify() const { return std::string("Unknown"); }
};/* class InstStrategy */
@@ -77,24 +69,19 @@ private:
/** instantiation strategies */
std::vector< InstStrategy* > d_instStrategies;
/** instantiation strategies active */
- std::map< InstStrategy*, bool > d_instStrategyActive;
+ //std::map< InstStrategy*, bool > d_instStrategyActive;
/** user-pattern instantiation strategy */
InstStrategyUserPatterns* d_isup;
/** auto gen triggers; only kept for destructor cleanup */
InstStrategyAutoGenTriggers* d_i_ag;
- /** is instantiation strategy active */
- bool isActiveStrategy( InstStrategy* is ) {
- return d_instStrategyActive.find( is )!=d_instStrategyActive.end() && d_instStrategyActive[is];
- }
- /** add inst strategy */
- void addInstStrategy( InstStrategy* is ){
- d_instStrategies.push_back( is );
- d_instStrategyActive[is] = true;
- }
+ /** local theory extensions */
+ InstStrategyLocalTheoryExt * d_i_lte;
+ /** full saturate */
+ InstStrategyFreeVariable * d_i_fs;
+ /** simplex (cbqi) */
+ InstStrategySimplex * d_i_splx;
private:
typedef context::CDHashMap< Node, bool, NodeHashFunction > BoolMap;
- /** status of instantiation round (one of InstStrategy::STATUS_*) */
- int d_inst_round_status;
/** whether the instantiation engine should set incomplete if it cannot answer SAT */
bool d_setIncomplete;
/** inst round counter */
@@ -111,6 +98,8 @@ private:
bool hasApplyUf( Node f );
/** whether to do CBQI for quantifier f */
bool doCbqi( Node f );
+ /** is the engine incomplete for this quantifier */
+ bool isIncomplete( Node f );
private:
/** do instantiation round */
bool doInstantiationRound( Theory::Effort effort );
@@ -149,6 +138,7 @@ public:
IntStat d_instantiations_cbqi_arith;
IntStat d_instantiations_cbqi_arith_minus;
IntStat d_instantiations_cbqi_datatypes;
+ IntStat d_instantiations_lte;
IntStat d_instantiation_rounds;
Statistics();
~Statistics();
diff --git a/src/theory/quantifiers/kinds b/src/theory/quantifiers/kinds
index a8774440e..793e4a611 100644
--- a/src/theory/quantifiers/kinds
+++ b/src/theory/quantifiers/kinds
@@ -44,6 +44,8 @@ sort INST_PATTERN_LIST_TYPE \
# a list of instantiation patterns
operator INST_PATTERN_LIST 1: "a list of instantiation patterns"
+operator INST_CLOSURE 1 "predicate for specifying term in instantiation closure."
+
typerule FORALL ::CVC4::theory::quantifiers::QuantifierForallTypeRule
typerule EXISTS ::CVC4::theory::quantifiers::QuantifierExistsTypeRule
typerule BOUND_VAR_LIST ::CVC4::theory::quantifiers::QuantifierBoundVarListTypeRule
@@ -51,6 +53,7 @@ typerule INST_PATTERN ::CVC4::theory::quantifiers::QuantifierInstPatternTypeRule
typerule INST_NO_PATTERN ::CVC4::theory::quantifiers::QuantifierInstNoPatternTypeRule
typerule INST_ATTRIBUTE ::CVC4::theory::quantifiers::QuantifierInstAttributeTypeRule
typerule INST_PATTERN_LIST ::CVC4::theory::quantifiers::QuantifierInstPatternListTypeRule
+typerule INST_CLOSURE ::CVC4::theory::quantifiers::QuantifierInstClosureTypeRule
# for rewrite rules
# types...
diff --git a/src/theory/quantifiers/model_builder.cpp b/src/theory/quantifiers/model_builder.cpp
index f6392a0b2..53f55e70b 100644
--- a/src/theory/quantifiers/model_builder.cpp
+++ b/src/theory/quantifiers/model_builder.cpp
@@ -22,7 +22,6 @@
#include "theory/quantifiers/term_database.h"
#include "theory/quantifiers/model_builder.h"
#include "theory/quantifiers/quantifiers_attributes.h"
-#include "theory/quantifiers/inst_gen.h"
#include "theory/quantifiers/trigger.h"
#include "theory/quantifiers/options.h"
@@ -754,389 +753,3 @@ void QModelBuilderDefault::constructModelUf( FirstOrderModel* fm, Node op ){
}
-
-
-////////////////////// Inst-Gen style Model Builder ///////////
-
-void QModelBuilderInstGen::reset( FirstOrderModel* fm ){
- //for new inst gen
- d_quant_selection_formula.clear();
- d_term_selected.clear();
-
- //d_sub_quant_inst_trie.clear();//*
-}
-
-int QModelBuilderInstGen::initializeQuantifier( Node f, Node fp ){
- int addedLemmas = QModelBuilderIG::initializeQuantifier( f, fp );
- for( size_t i=0; i<d_sub_quants[f].size(); i++ ){
- addedLemmas += initializeQuantifier( d_sub_quants[f][i], fp );
- }
- return addedLemmas;
-}
-
-void QModelBuilderInstGen::analyzeQuantifier( FirstOrderModel* fm, Node f ){
- //Node fp = getParentQuantifier( f );//*
- //bool quantRedundant = ( f!=fp && d_sub_quant_inst_trie[fp].addInstMatch( d_qe, fp, d_sub_quant_inst[ f ], true ) );
- //if( f==fp || d_sub_quant_inst_trie[fp].addInstMatch( d_qe, fp, d_sub_quant_inst[ f ], true ) ){//*
- Trace("sel-form-debug") << "* Analyze " << f << std::endl;
- //determine selection formula, set terms in selection formula as being selected
- Node s = getSelectionFormula( d_qe->getTermDatabase()->getInstConstantBody( f ),
- d_qe->getTermDatabase()->getModelBasisBody( f ), true, 0 );
- //if( !s.isNull() ){
- // s = Rewriter::rewrite( s );
- //}
- Trace("sel-form-debug") << "Selection formula " << f << std::endl;
- Trace("sel-form-debug") << " " << s << std::endl;
- if( !s.isNull() ){
- d_quant_selection_formula[f] = s;
- Node gs = d_qe->getTermDatabase()->getModelBasis( f, s );
- setSelectedTerms( gs );
- //quick check if it is constant sat
- if( hasConstantDefinition( s ) ){
- d_quant_sat[f] = true;
- }
- }else{
- Trace("sel-form-null") << "*** No selection formula for " << f << std::endl;
- }
- //analyze sub quantifiers
- if( d_quant_sat.find( f )==d_quant_sat.end() ){
- for( size_t i=0; i<d_sub_quants[f].size(); i++ ){
- analyzeQuantifier( fm, d_sub_quants[f][i] );
- }
- }
-}
-
-
-int QModelBuilderInstGen::doInstGen( FirstOrderModel* fm, Node f ){
- int addedLemmas = 0;
- if( d_quant_sat.find( f )==d_quant_sat.end() ){
- Node fp = d_sub_quant_parent.find( f )==d_sub_quant_parent.end() ? f : d_sub_quant_parent[f];
- if( fp!=f ) Trace("inst-gen") << " ";
- Trace("inst-gen") << "Do Inst-Gen for " << f << std::endl;
- if( fp!=f ) Trace("inst-gen") << " ";
- Trace("inst-gen") << "Sel Form : " << d_quant_selection_formula[f] << std::endl;
- //we wish to add all known exceptions to our selection formula for f. this will help to refine our current model.
- if( !d_quant_selection_formula[f].isNull() ){
- //first, try on sub quantifiers
- bool subQuantSat = true;
- for( size_t i=0; i<d_sub_quants[f].size(); i++ ){
- addedLemmas += doInstGen( fm, d_sub_quants[f][i] );
- if( d_quant_sat.find( d_sub_quants[f][i] )==d_quant_sat.end() ){
- subQuantSat = false;
- }
- }
- if( addedLemmas>0 || !subQuantSat ){
- Trace("inst-gen") << " -> children added lemmas or non-satisfied" << std::endl;
- return addedLemmas;
- }else{
- Trace("inst-gen-debug") << "Calculate inst-gen instantiations..." << std::endl;
- //get all possible values of selection formula
- InstGenProcess igp( d_quant_selection_formula[f] );
- std::vector< Node > considered;
- considered.push_back( fm->d_false );
- igp.calculateMatches( d_qe, f, considered, true );
- //igp.calculateMatches( d_qe, f);
- Trace("inst-gen-debug") << "Add inst-gen instantiations (" << igp.getNumMatches() << ")..." << std::endl;
- for( int i=0; i<igp.getNumMatches(); i++ ){
- //if the match is not already true in the model
- if( igp.getMatchValue( i )!=fm->d_true ){
- InstMatch m( f );
- igp.getMatch( d_qe->getEqualityQuery(), i, m );
- //Trace("inst-gen-debug") << "Inst Gen : " << m << std::endl;
- //we only consider matches that are non-empty
- // matches that are empty should trigger other instances that are non-empty
- if( !m.empty() ){
- Trace("inst-gen-debug") << "Get in terms of parent..." << std::endl;
- //translate to be in terms match in terms of fp
- InstMatch mp(f);
- getParentQuantifierMatch( mp, fp, m, f );
- //if this is a partial instantion
- if( !m.isComplete() ){
- //need to make it internal here
- //Trace("mkInternal") << "Make internal representative " << mp << std::endl;
- //mp.makeInternalRepresentative( d_qe );
- //Trace("mkInternal") << "Got " << mp << std::endl;
- //if the instantiation does not yet exist
- if( d_sub_quant_inst_trie[fp].addInstMatch( d_qe, fp, mp, true ) ){
- //also add it to children
- d_child_sub_quant_inst_trie[f].addInstMatch( d_qe, f, m );
- //get the partial instantiation pf
- Node pf = d_qe->getInstantiation( fp, mp );
- Trace("inst-gen-pi") << "Partial instantiation of " << f << std::endl;
- Trace("inst-gen-pi") << " " << pf << std::endl;
- d_sub_quants[ f ].push_back( pf );
- d_sub_quant_inst[ pf ] = InstMatch( &mp );
- d_sub_quant_parent[ pf ] = fp;
- //now make mp a complete match
- mp.add( d_quant_basis_match[ fp ] );
- d_quant_basis_match[ pf ] = InstMatch( &mp );
- ++(d_statistics.d_num_quants_init);
- ++(d_statistics.d_num_partial_quants_init);
- addedLemmas += initializeQuantifier( pf, fp );
- Trace("inst-gen-pi") << "Done adding partial instantiation" << std::endl;
- subQuantSat = false;
- }
- }else{
- if( d_qe->addInstantiation( fp, mp ) ){
- addedLemmas++;
- }
- }
- }
- }
- }
- if( addedLemmas==0 ){
- //all sub quantifiers must be satisfied as well
- if( subQuantSat ){
- d_quant_sat[ f ] = true;
- }
- }
- if( fp!=f ) Trace("inst-gen") << " ";
- Trace("inst-gen") << " -> added lemmas = " << addedLemmas << std::endl;
- if( d_quant_sat.find( f )!=d_quant_sat.end() ){
- if( fp!=f ) Trace("inst-gen") << " ";
- Trace("inst-gen") << " -> *** it is satisfied" << std::endl;
- }
- }
- }
- }
- return addedLemmas;
-}
-
-Node mkAndSelectionFormula( std::vector< Node >& children ){
- std::vector< Node > ch;
- for( size_t i=0; i<children.size(); i++ ){
- if( children[i].getKind()==AND ){
- for( size_t j=0; j<children[i].getNumChildren(); j++ ){
- ch.push_back( children[i][j] );
- }
- }else{
- ch.push_back( children[i] );
- }
- }
- return NodeManager::currentNM()->mkNode( AND, ch );
-}
-Node mkAndSelectionFormula( Node n1, Node n2 ){
- std::vector< Node > children;
- children.push_back( n1 );
- children.push_back( n2 );
- return mkAndSelectionFormula( children );
-}
-
-//if possible, returns a formula n' such that n' => ( n <=> polarity ), and n' is true in the current context,
-// and NULL otherwise
-Node QModelBuilderInstGen::getSelectionFormula( Node fn, Node n, bool polarity, int useOption ){
- Trace("sel-form-debug") << "Looking for selection formula " << n << " " << polarity << std::endl;
- Node ret;
- if( n.getKind()==NOT ){
- ret = getSelectionFormula( fn[0], n[0], !polarity, useOption );
- }else if( n.getKind()==OR || n.getKind()==AND ){
- //whether we only need to find one or all
- bool favorPol = ( n.getKind()!=AND && polarity ) || ( n.getKind()==AND && !polarity );
- std::vector< Node > children;
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- Node fnc = fn[i];
- Node nc = n[i];
- Node nn = getSelectionFormula( fnc, nc, polarity, useOption );
- if( nn.isNull() && !favorPol ){
- //cannot make selection formula
- children.clear();
- break;
- }
- if( !nn.isNull() ){
- //if( favorPol ){ //temporary
- // return nn; //
- //} //
- if( std::find( children.begin(), children.end(), nn )==children.end() ){
- children.push_back( nn );
- }
- }
- }
- if( !children.empty() ){
- if( favorPol ){
- //filter which formulas we wish to keep, make disjunction
- Node min_lit;
- int min_score = -1;
- for( size_t i=0; i<children.size(); i++ ){
- //if it is constant apply uf application, return it for sure
- if( hasConstantDefinition( children[i] ) ){
- min_lit = children[i];
- break;
- }else{
- int score = getSelectionFormulaScore( children[i] );
- if( min_score<0 || score<min_score ){
- min_score = score;
- min_lit = children[i];
- }
- }
- }
- //currently just return the best single literal
- ret = min_lit;
- }else{
- //selection formula must be conjunction of children
- ret = mkAndSelectionFormula( children );
- }
- }else{
- ret = Node::null();
- }
- }else if( n.getKind()==ITE ){
- Node nn;
- Node nc[2];
- //get selection formula for the
- for( int i=0; i<2; i++ ){
- nn = getSelectionFormula( fn[0], n[0], i==0, useOption );
- nc[i] = getSelectionFormula( fn[i+1], n[i+1], polarity, useOption );
- if( !nn.isNull() && !nc[i].isNull() ){
- ret = mkAndSelectionFormula( nn, nc[i] );
- break;
- }
- }
- if( ret.isNull() && !nc[0].isNull() && !nc[1].isNull() ){
- ret = mkAndSelectionFormula( nc[0], nc[1] );
- }
- }else if( n.getKind()==IFF ){
- bool opPol = !polarity;
- for( int p=0; p<2; p++ ){
- Node nn[2];
- for( int i=0; i<2; i++ ){
- bool pol = i==0 ? p==0 : ( opPol ? p!=0 : p==0 );
- nn[i] = getSelectionFormula( fn[i], n[i], pol, useOption );
- if( nn[i].isNull() ){
- break;
- }
- }
- if( !nn[0].isNull() && !nn[1].isNull() ){
- ret = mkAndSelectionFormula( nn[0], nn[1] );
- }
- }
- }else{
- //literal case
- //first, check if it is a usable selection literal
- if( isUsableSelectionLiteral( n, useOption ) ){
- bool value;
- if( d_qe->getValuation().hasSatValue( n, value ) ){
- if( value==polarity ){
- ret = fn;
- if( !polarity ){
- ret = ret.negate();
- }
- }else{
- Trace("sel-form-debug") << " (wrong polarity)" << std::endl;
- }
- }else{
- Trace("sel-form-debug") << " (does not have sat value)" << std::endl;
- }
- }else{
- Trace("sel-form-debug") << " (is not usable literal)" << std::endl;
- }
- }
- Trace("sel-form-debug") << " return " << ret << std::endl;
- return ret;
-}
-
-int QModelBuilderInstGen::getSelectionFormulaScore( Node fn ){
- if( fn.getType().isBoolean() ){
- if( fn.getKind()==APPLY_UF ){
- Node op = fn.getOperator();
- //return total number of terms
- return d_qe->getTermDatabase()->d_op_nonred_count[op];
- }else{
- int score = 0;
- for( size_t i=0; i<fn.getNumChildren(); i++ ){
- score += getSelectionFormulaScore( fn[i] );
- }
- return score;
- }
- }else{
- return 0;
- }
-}
-
-void QModelBuilderInstGen::setSelectedTerms( Node s ){
-
- //if it is apply uf and has model basis arguments, then mark term as being "selected"
- if( s.getKind()==APPLY_UF ){
- Assert( s.hasAttribute(ModelBasisArgAttribute()) );
- if( !s.hasAttribute(ModelBasisArgAttribute()) ) std::cout << "no mba!! " << s << std::endl;
- if( s.getAttribute(ModelBasisArgAttribute())!=0 ){
- d_term_selected[ s ] = true;
- Trace("sel-form-term") << " " << s << " is a selected term." << std::endl;
- }
- }
- for( int i=0; i<(int)s.getNumChildren(); i++ ){
- setSelectedTerms( s[i] );
- }
-}
-
-bool QModelBuilderInstGen::isUsableSelectionLiteral( Node n, int useOption ){
- if( n.getKind()==FORALL ){
- return false;
- }else if( n.getKind()!=APPLY_UF ){
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- //if it is a variable, then return false
- if( n[i].getAttribute(ModelBasisAttribute()) ){
- return false;
- }
- }
- }
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( !isUsableSelectionLiteral( n[i], useOption ) ){
- return false;
- }
- }
- return true;
-}
-
-void QModelBuilderInstGen::getParentQuantifierMatch( InstMatch& mp, Node fp, InstMatch& m, Node f ){
- if( f!=fp ){
- //std::cout << "gpqm " << fp << " " << f << " " << m << std::endl;
- //std::cout << " " << fp[0].getNumChildren() << " " << f[0].getNumChildren() << std::endl;
- int counter = 0;
- for( size_t i=0; i<fp[0].getNumChildren(); i++ ){
- if( (int)counter< (int)f[0].getNumChildren() ){
- if( fp[0][i]==f[0][counter] ){
- Node n = m.get( counter );
- if( !n.isNull() ){
- mp.set( d_qe, i, n );
- }
- counter++;
- }
- }
- }
- mp.add( d_sub_quant_inst[f] );
- }else{
- mp.add( m );
- }
-}
-
-void QModelBuilderInstGen::constructModelUf( FirstOrderModel* fm, Node op ){
- FirstOrderModelIG* fmig = fm->asFirstOrderModelIG();
- bool setDefaultVal = true;
- Node defaultTerm = d_qe->getTermDatabase()->getModelBasisOpTerm( op );
- //set the values in the model
- for( size_t i=0; i<fmig->d_uf_terms[op].size(); i++ ){
- Node n = fmig->d_uf_terms[op][i];
- if( isTermActive( n ) ){
- Node v = fmig->getRepresentative( n );
- fmig->d_uf_model_gen[op].setValue( fm, n, v );
- }
- //also possible set as default
- if( d_term_selected.find( n )!=d_term_selected.end() || n==defaultTerm ){
- Node v = fmig->getRepresentative( n );
- fmig->d_uf_model_gen[op].setValue( fm, n, v, false );
- if( n==defaultTerm ){
- setDefaultVal = false;
- }
- }
- }
- //set the overall default value if not set already (is this necessary??)
- if( setDefaultVal ){
- Node defaultVal = d_uf_prefs[op].getBestDefaultValue( defaultTerm, fm );
- fmig->d_uf_model_gen[op].setValue( fm, defaultTerm, defaultVal, false );
- }
- fmig->d_uf_model_gen[op].makeModel( fm, fmig->d_uf_model_tree[op] );
- d_uf_model_constructed[op] = true;
-}
-
-bool QModelBuilderInstGen::existsInstantiation( Node f, InstMatch& m, bool modEq, bool modInst ){
- return d_child_sub_quant_inst_trie[f].existsInstMatch( d_qe, f, m, modEq, true );
-}
diff --git a/src/theory/quantifiers/model_builder.h b/src/theory/quantifiers/model_builder.h
index 3e4471fa4..7679cf93f 100644
--- a/src/theory/quantifiers/model_builder.h
+++ b/src/theory/quantifiers/model_builder.h
@@ -199,58 +199,6 @@ public:
bool hasInstGen( Node f ) { return !d_quant_selection_lit[f].isNull(); }
};
-class QModelBuilderInstGen : public QModelBuilderIG
-{
-private: ///information for (new) InstGen
- //map from quantifiers to their selection formulas
- std::map< Node, Node > d_quant_selection_formula;
- //map of terms that are selected
- std::map< Node, bool > d_term_selected;
- //a collection of (complete) InstMatch structures produced for each root quantifier
- std::map< Node, inst::InstMatchTrie > d_sub_quant_inst_trie;
- //for each quantifier, a collection of InstMatch structures, representing the children
- std::map< Node, inst::InstMatchTrie > d_child_sub_quant_inst_trie;
- //children quantifiers for each quantifier, each is an instance
- std::map< Node, std::vector< Node > > d_sub_quants;
- //instances of each partial instantiation with respect to the root
- std::map< Node, InstMatch > d_sub_quant_inst;
- //*root* parent of each partial instantiation
- std::map< Node, Node > d_sub_quant_parent;
-protected:
- //reset
- void reset( FirstOrderModel* fm );
- //initialize quantifiers, return number of lemmas produced, fp is the parent of quantifier f
- int initializeQuantifier( Node f, Node fp );
- //analyze quantifier
- void analyzeQuantifier( FirstOrderModel* fm, Node f );
- //do InstGen techniques for quantifier, return number of lemmas produced
- int doInstGen( FirstOrderModel* fm, Node f );
- //theory-specific build models
- void constructModelUf( FirstOrderModel* fm, Node op );
-private:
- //get selection formula for quantifier body
- Node getSelectionFormula( Node fn, Node n, bool polarity, int useOption );
- //get a heuristic score for a selection formula
- int getSelectionFormulaScore( Node fn );
- //set selected terms in term
- void setSelectedTerms( Node s );
- //is usable selection literal
- bool isUsableSelectionLiteral( Node n, int useOption );
- //get parent quantifier match
- void getParentQuantifierMatch( InstMatch& mp, Node fp, InstMatch& m, Node f );
- //get parent quantifier
- Node getParentQuantifier( Node f ) { return d_sub_quant_parent.find( f )==d_sub_quant_parent.end() ? f : d_sub_quant_parent[f]; }
-public:
- QModelBuilderInstGen( context::Context* c, QuantifiersEngine* qe ) : QModelBuilderIG( c, qe ){}
- ~QModelBuilderInstGen(){}
- // is term selected
- bool isTermSelected( Node n ) { return d_term_selected.find( n )!=d_term_selected.end(); }
- /** exist instantiation ? */
- bool existsInstantiation( Node f, InstMatch& m, bool modEq = true, bool modInst = false );
- //has inst gen
- bool hasInstGen( Node f ) { return !d_quant_selection_formula[f].isNull(); }
-};
-
}/* CVC4::theory::quantifiers namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/quantifiers/model_engine.cpp b/src/theory/quantifiers/model_engine.cpp
index eede5c3a8..591034ffc 100644
--- a/src/theory/quantifiers/model_engine.cpp
+++ b/src/theory/quantifiers/model_engine.cpp
@@ -22,7 +22,6 @@
#include "theory/quantifiers/term_database.h"
#include "theory/quantifiers/quantifiers_attributes.h"
#include "theory/quantifiers/full_model_check.h"
-#include "theory/quantifiers/qinterval_builder.h"
#include "theory/quantifiers/ambqi_builder.h"
using namespace std;
@@ -96,6 +95,10 @@ void ModelEngine::check( Theory::Effort e, unsigned quant_e ){
//CVC4 will answer SAT or unknown
Trace("fmf-consistent") << std::endl;
debugPrint("fmf-consistent");
+ //if the check was incomplete, we must set incomplete flag
+ if( d_incomplete_check ){
+ d_quantEngine->getOutputChannel().setIncomplete();
+ }
}else{
//otherwise, the search will continue
}
diff --git a/src/theory/quantifiers/modes.cpp b/src/theory/quantifiers/modes.cpp
index 9e4cab9fa..ebc1088a8 100644
--- a/src/theory/quantifiers/modes.cpp
+++ b/src/theory/quantifiers/modes.cpp
@@ -85,15 +85,9 @@ std::ostream& operator<<(std::ostream& out, theory::quantifiers::MbqiMode mode)
case theory::quantifiers::MBQI_NONE:
out << "MBQI_NONE";
break;
- case theory::quantifiers::MBQI_INST_GEN:
- out << "MBQI_INST_GEN";
- break;
case theory::quantifiers::MBQI_FMC:
out << "MBQI_FMC";
break;
- case theory::quantifiers::MBQI_INTERVAL:
- out << "MBQI_INTERVAL";
- break;
case theory::quantifiers::MBQI_ABS:
out << "MBQI_ABS";
break;
diff --git a/src/theory/quantifiers/modes.h b/src/theory/quantifiers/modes.h
index acc883f2a..5e692ace1 100644
--- a/src/theory/quantifiers/modes.h
+++ b/src/theory/quantifiers/modes.h
@@ -62,14 +62,10 @@ typedef enum {
MBQI_GEN_EVAL,
/** no mbqi */
MBQI_NONE,
- /** implementation that mimics inst-gen */
- MBQI_INST_GEN,
/** default, mbqi from Section 5.4.2 of AJR thesis */
MBQI_FMC,
/** mbqi with integer intervals */
MBQI_FMC_INTERVAL,
- /** mbqi with interval abstraction of uninterpreted sorts */
- MBQI_INTERVAL,
/** abstract mbqi algorithm */
MBQI_ABS,
/** mbqi trust (produce no instantiations) */
@@ -136,6 +132,13 @@ typedef enum {
CEGQI_FAIR_NONE,
} CegqiFairMode;
+typedef enum {
+ /** consider all terms in master equality engine */
+ TERM_DB_ALL,
+ /** consider only relevant terms */
+ TERM_DB_RELEVANT,
+} TermDbMode;
+
}/* CVC4::theory::quantifiers namespace */
}/* CVC4::theory namespace */
diff --git a/src/theory/quantifiers/options b/src/theory/quantifiers/options
index dc2102ffa..cac78af46 100644
--- a/src/theory/quantifiers/options
+++ b/src/theory/quantifiers/options
@@ -5,6 +5,9 @@
module QUANTIFIERS "theory/quantifiers/options.h" Quantifiers
+option eMatching --e-matching bool :read-write :default true
+ whether to do heuristic E-matching
+
# Whether to mini-scope quantifiers.
# For example, forall x. ( P( x ) ^ Q( x ) ) will be rewritten to
# ( forall x. P( x ) ) ^ ( forall x. Q( x ) )
@@ -29,6 +32,8 @@ option varElimQuant /--disable-var-elim-quant bool :default true
option dtVarExpandQuant --dt-var-exp-quant bool :default true
expand datatype variables bound to one constructor in quantifiers
+option iteCondVarSplitQuant --ite-cond-var-split-quant bool :default true
+ split variables occurring as conditions of ITE in quantifiers
option simpleIteLiftQuant /--disable-ite-lift-quant bool :default true
disable simple ite lifting for quantified formulas
@@ -36,7 +41,7 @@ option simpleIteLiftQuant /--disable-ite-lift-quant bool :default true
option cnfQuant --cnf-quant bool :default false
apply CNF conversion to quantified formulas
# Whether to NNF quantifier bodies
-option nnfQuant --nnf-quant bool :default false
+option nnfQuant --nnf-quant bool :default true
apply NNF conversion to quantified formulas
option clauseSplit --clause-split bool :default false
@@ -57,6 +62,8 @@ option macrosQuant --macros-quant bool :default false
option foPropQuant --fo-prop-quant bool :default false
perform first-order propagation on quantifiers
+option termDbMode --term-db-mode CVC4::theory::quantifiers::TermDbMode :default CVC4::theory::quantifiers::TERM_DB_ALL :read-write :include "theory/quantifiers/modes.h" :handler CVC4::theory::quantifiers::stringToTermDbMode :handler-include "theory/quantifiers/options_handlers.h"
+ which ground terms to consider for instantiation
# Whether to use smart triggers
option smartTriggers /--disable-smart-triggers bool :default true
disable smart triggers
@@ -72,13 +79,18 @@ option multiTriggerWhenSingle --multi-trigger-when-single bool :default true
option triggerSelMode --trigger-sel CVC4::theory::quantifiers::TriggerSelMode :default CVC4::theory::quantifiers::TRIGGER_SEL_DEFAULT :read-write :include "theory/quantifiers/modes.h" :handler CVC4::theory::quantifiers::stringToTriggerSelMode :handler-include "theory/quantifiers/options_handlers.h"
selection mode for triggers
+option quantFunWellDefined --quant-fun-wd bool :default false
+ assume that function defined by quantifiers are well defined
+option fmfFunWellDefined --fmf-fun bool :default false
+ find models for finite runs of defined functions, assumes functions are well-defined
+
# Whether to consider terms in the bodies of quantifiers for matching
option registerQuantBodyTerms --register-quant-body-terms bool :default false
consider ground terms within bodies of quantified formulas for matching
-option instWhenMode --inst-when=MODE CVC4::theory::quantifiers::InstWhenMode :default CVC4::theory::quantifiers::INST_WHEN_FULL :read-write :include "theory/quantifiers/modes.h" :handler CVC4::theory::quantifiers::stringToInstWhenMode :handler-include "theory/quantifiers/options_handlers.h" :predicate CVC4::theory::quantifiers::checkInstWhenMode :predicate-include "theory/quantifiers/options_handlers.h"
+option instWhenMode --inst-when=MODE CVC4::theory::quantifiers::InstWhenMode :default CVC4::theory::quantifiers::INST_WHEN_FULL_LAST_CALL :read-write :include "theory/quantifiers/modes.h" :handler CVC4::theory::quantifiers::stringToInstWhenMode :handler-include "theory/quantifiers/options_handlers.h" :predicate CVC4::theory::quantifiers::checkInstWhenMode :predicate-include "theory/quantifiers/options_handlers.h"
when to apply instantiation
-option instMaxLevel --inst-max-level=N int :default -1
+option instMaxLevel --inst-max-level=N int :read-write :default -1
maximum inst level of terms used to instantiate quantified formulas with (-1 == no limit, default)
option instLevelInputOnly --inst-level-input-only bool :default true
only input terms are assigned instantiation level zero
@@ -115,7 +127,7 @@ option finiteModelFind finite-model-find --finite-model-find bool :default false
option mbqiMode --mbqi=MODE CVC4::theory::quantifiers::MbqiMode :read-write :default CVC4::theory::quantifiers::MBQI_FMC :include "theory/quantifiers/modes.h" :handler CVC4::theory::quantifiers::stringToMbqiMode :handler-include "theory/quantifiers/options_handlers.h" :predicate CVC4::theory::quantifiers::checkMbqiMode :predicate-include "theory/quantifiers/options_handlers.h"
choose mode for model-based quantifier instantiation
-option fmfOneInstPerRound --mbqi-one-inst-per-round bool :default false
+option fmfOneInstPerRound --mbqi-one-inst-per-round bool :read-write :default false
only add one instantiation per quantifier per round for mbqi
option fmfOneQuantPerRound --mbqi-one-quant-per-round bool :default false
only add instantiations for one quantifier per round for mbqi
@@ -138,7 +150,7 @@ option fmfBoundIntLazy --fmf-bound-int-lazy bool :default false :read-write
option axiomInstMode --axiom-inst=MODE CVC4::theory::quantifiers::AxiomInstMode :default CVC4::theory::quantifiers::AXIOM_INST_MODE_DEFAULT :include "theory/quantifiers/modes.h" :handler CVC4::theory::quantifiers::stringToAxiomInstMode :handler-include "theory/quantifiers/options_handlers.h"
policy for instantiating axioms
-option quantConflictFind --quant-cf bool :read-write :default false
+option quantConflictFind --quant-cf bool :read-write :default true
enable conflict find mechanism for quantifiers
option qcfMode --quant-cf-mode=MODE CVC4::theory::quantifiers::QcfMode :default CVC4::theory::quantifiers::QCF_PROP_EQ :include "theory/quantifiers/modes.h" :handler CVC4::theory::quantifiers::stringToQcfMode :handler-include "theory/quantifiers/options_handlers.h"
what effort to apply conflict find mechanism
@@ -181,4 +193,10 @@ option ceGuidedInst --cegqi bool :default false
option ceGuidedInstFair --cegqi-fair=MODE CVC4::theory::quantifiers::CegqiFairMode :default CVC4::theory::quantifiers::CEGQI_FAIR_DT_SIZE :include "theory/quantifiers/modes.h" :handler CVC4::theory::quantifiers::stringToCegqiFairMode :handler-include "theory/quantifiers/options_handlers.h"
if and how to apply fairness for cegqi
+
+option localTheoryExt --local-t-ext bool :default false
+ do instantiation based on local theory extensions
+option termDbInstClosure --term-db-inst-closure bool :default false
+ only consider inst closure terms for E-matching
+
endmodule
diff --git a/src/theory/quantifiers/options_handlers.h b/src/theory/quantifiers/options_handlers.h
index c2afbbd3e..e9f85d454 100644
--- a/src/theory/quantifiers/options_handlers.h
+++ b/src/theory/quantifiers/options_handlers.h
@@ -29,17 +29,17 @@ namespace quantifiers {
static const std::string instWhenHelp = "\
Modes currently supported by the --inst-when option:\n\
\n\
-full (default)\n\
+full-last-call (default)\n\
++ Alternate running instantiation rounds at full effort and last\n\
+ call. In other words, interleave instantiation and theory combination.\n\
+\n\
+full\n\
+ Run instantiation round at full effort, before theory combination.\n\
\n\
full-delay \n\
+ Run instantiation round at full effort, before theory combination, after\n\
all other theories have finished.\n\
\n\
-full-last-call\n\
-+ Alternate running instantiation rounds at full effort and last\n\
- call. In other words, interleave instantiation and theory combination.\n\
-\n\
last-call\n\
+ Run instantiation at last call effort, after theory combination and\n\
and theories report sat.\n\
@@ -88,9 +88,6 @@ default \n\
none \n\
+ Disable model-based quantifier instantiation.\n\
\n\
-instgen \n\
-+ Use instantiation algorithm that mimics Inst-Gen calculus. \n\
-\n\
gen-ev \n\
+ Use model-based quantifier instantiation algorithm from CADE 24 finite\n\
model finding paper based on generalizing evaluations.\n\
@@ -98,9 +95,6 @@ gen-ev \n\
fmc-interval \n\
+ Same as default, but with intervals for models of integer functions.\n\
\n\
-interval \n\
-+ Use algorithm that abstracts domain elements as intervals. \n\
-\n\
abs \n\
+ Use abstract MBQI algorithm (uses disjoint sets). \n\
\n\
@@ -194,6 +188,16 @@ none \n\
+ Do not enforce fairness. \n\
\n\
";
+static const std::string termDbModeHelp = "\
+Modes for term database, supported by --term-db-mode:\n\
+\n\
+all \n\
++ Consider all terms in the system.\n\
+\n\
+relevant \n\
++ Consider only terms connected to current assertions. \n\
+\n\
+";
inline InstWhenMode stringToInstWhenMode(std::string option, std::string optarg, SmtEngine* smt) throw(OptionException) {
if(optarg == "pre-full") {
@@ -264,14 +268,10 @@ inline MbqiMode stringToMbqiMode(std::string option, std::string optarg, SmtEngi
return MBQI_GEN_EVAL;
} else if(optarg == "none") {
return MBQI_NONE;
- } else if(optarg == "instgen") {
- return MBQI_INST_GEN;
} else if(optarg == "default" || optarg == "fmc") {
return MBQI_FMC;
} else if(optarg == "fmc-interval") {
return MBQI_FMC_INTERVAL;
- } else if(optarg == "interval") {
- return MBQI_INTERVAL;
} else if(optarg == "abs") {
return MBQI_ABS;
} else if(optarg == "trust") {
@@ -390,6 +390,20 @@ inline CegqiFairMode stringToCegqiFairMode(std::string option, std::string optar
}
}
+inline TermDbMode stringToTermDbMode(std::string option, std::string optarg, SmtEngine* smt) throw(OptionException) {
+ if(optarg == "all" ) {
+ return TERM_DB_ALL;
+ } else if(optarg == "relevant") {
+ return TERM_DB_RELEVANT;
+ } else if(optarg == "help") {
+ puts(termDbModeHelp.c_str());
+ exit(1);
+ } else {
+ throw OptionException(std::string("unknown option for --term-db-mode: `") +
+ optarg + "'. Try --term-db-mode help.");
+ }
+}
+
}/* CVC4::theory::quantifiers namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/quantifiers/qinterval_builder.cpp b/src/theory/quantifiers/qinterval_builder.cpp
deleted file mode 100644
index 5dd6316b3..000000000
--- a/src/theory/quantifiers/qinterval_builder.cpp
+++ /dev/null
@@ -1,1111 +0,0 @@
-/********************* */
-/*! \file qinterval_builder.cpp
- ** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Implementation of qinterval builder
- **/
-
-
-#include "theory/quantifiers/qinterval_builder.h"
-#include "theory/quantifiers/term_database.h"
-
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::quantifiers;
-
-//lower bound is exclusive
-//upper bound is inclusive
-
-struct QIntSort
-{
- FirstOrderModelQInt * m;
- bool operator() (Node i, Node j) {
- return m->isLessThan( i, j );
- }
-};
-
-void QIntDef::init_vec( FirstOrderModelQInt * m, Node q, std::vector< Node >& l, std::vector< Node >& u ) {
- for( unsigned i=0; i<m->getOrderedNumVars( q ); i++ ){
- l.push_back( Node::null() );
- u.push_back( m->getMaximum( m->getOrderedVarType( q, i ) ) );
- }
-}
-
-void QIntDef::debugPrint( const char * c, FirstOrderModelQInt * m, Node q, std::vector< Node >& l, std::vector< Node >& u )
-{
- Trace(c) << "( ";
- for( unsigned i=0; i<l.size(); i++ ){
- if( i>0 ) Trace(c) << ", ";
- //Trace(c) << l[i] << "..." << u[i];
- int lindex = l[i].isNull() ? 0 : m->getRepId( l[i] ) + 1;
- int uindex = m->getRepId( u[i] );
- Trace(c) << lindex << "..." << uindex;
- }
- Trace(c) << " )";
-}
-
-
-int QIntDef::getEvIndex( FirstOrderModelQInt * m, Node n, bool exc ) {
- if( n.isNull() ){
- Assert( exc );
- return 0;
- }else{
- int min = 0;
- int max = (int)(d_def_order.size()-1);
- while( min!=max ){
- int index = (min+max)/2;
- Assert( index>=0 && index<(int)d_def_order.size() );
- if( n==d_def_order[index] ){
- max = index;
- min = index;
- }else if( m->isLessThan( n, d_def_order[index] ) ){
- max = index;
- }else{
- min = index+1;
- }
- }
- if( n==d_def_order[min] && exc ){
- min++;
- }
- Assert( min>=0 && min<(int)d_def_order.size() );
- if( ( min!=0 && !m->isLessThan( d_def_order[min-1], n ) && ( !exc || d_def_order[min-1]!=n ) ) ||
- ( ( exc || d_def_order[min]!=n ) && !m->isLessThan( n, d_def_order[min] ) ) ){
- Debug("qint-error") << "ERR size : " << d_def_order.size() << ", exc : " << exc << std::endl;
- for( unsigned i=0; i<d_def_order.size(); i++ ){
- Debug("qint-error") << "ERR ch #" << i << " : " << d_def_order[i];
- Debug("qint-error") << " " << m->getRepId( d_def_order[i] ) << std::endl;
- }
- Debug("qint-error") << " : " << n << " " << min << " " << m->getRepId( n ) << std::endl;
- }
-
- Assert( min==0 || m->isLessThan( d_def_order[min-1], n ) || ( exc && d_def_order[min-1]==n ) );
- Assert( ( !exc && n==d_def_order[min] ) || m->isLessThan( n, d_def_order[min] ) );
- return min;
- }
-}
-
-void QIntDef::addEntry( FirstOrderModelQInt * m, Node q, std::vector< Node >& l, std::vector< Node >& u,
- Node v, unsigned depth ) {
- if( depth==0 ){
- Trace("qint-compose-debug") << "Add entry ";
- debugPrint( "qint-compose-debug", m, q, l, u );
- Trace("qint-compose-debug") << " -> " << v << "..." << std::endl;
- }
- //Assert( false );
- if( depth==u.size() ){
- Assert( d_def_order.empty() );
- Assert( v.isNull() || v.isConst() || ( v.getType().isSort() && m->getRepId( v )!=-1 ) );
- d_def_order.push_back( v );
- }else{
- /*
- if( !d_def_order.empty() &&
- ( l[depth].isNull() || m->isLessThan( l[depth], d_def_order[d_def_order.size()-1] ) ) ){
- int startEvIndex = getEvIndex( m, l[depth], true );
- int endEvIndex;
- if( m->isLessThan( u[depth], d_def_order[d_def_order.size()-1] ) ){
- endEvIndex = getEvIndex( m, u[depth] );
- }else{
- endEvIndex = d_def_order.size()-1;
- }
- Trace("qint-compose-debug2") << this << " adding for bounds " << l[depth] << "..." << u[depth] << std::endl;
- for( int i=startEvIndex; i<=endEvIndex; i++ ){
- Trace("qint-compose-debug2") << this << " add entry " << d_def_order[i] << std::endl;
- d_def[d_def_order[i]].addEntry( m, q, l, u, v, depth+1 );
- }
- }
- if( !d_def_order.empty() &&
- d_def.find(u[depth])==d_def.end() &&
- !m->isLessThan( d_def_order[d_def_order.size()-1], u[depth] ) ){
- Trace("qint-compose-debug2") << "Bad : depth : " << depth << std::endl;
- }
- Assert( d_def_order.empty() ||
- d_def.find(u[depth])!=d_def.end() ||
- m->isLessThan( d_def_order[d_def_order.size()-1], u[depth] ) );
-
- if( d_def_order.empty() || m->isLessThan( d_def_order[d_def_order.size()-1], u[depth] ) ){
- Trace("qint-compose-debug2") << this << " add entry new : " << u[depth] << std::endl;
- d_def_order.push_back( u[depth] );
- d_def[u[depth]].addEntry( m, q, l, u, v, depth+1 );
- }
- */
- //%%%%%%
- bool success = true;
- int nnum = m->getVarOrder( q )->getNextNum( depth );
- Node pl;
- Node pu;
- if( nnum!=-1 ){
- Trace("qint-compose-debug2") << "...adding entry #" << depth << " is #" << nnum << std::endl;
- //Assert( l[nnum].isNull() || l[nnum]==l[depth] || m->isLessThan( l[nnum], l[depth] ) );
- //Assert( u[nnum]==u[depth] || m->isLessThan( u[depth], u[nnum] ) );
- pl = l[nnum];
- pu = u[nnum];
- if( !m->doMeet( l[nnum], u[nnum], l[depth], u[depth], l[nnum], u[nnum] ) ){
- success = false;
- }
- }
- //%%%%%%
- if( success ){
- Node r = u[depth];
- if( d_def.find( r )!=d_def.end() ){
- d_def[r].addEntry( m, q, l, u, v, depth+1 );
- }else{
- if( !d_def_order.empty() &&
- !m->isLessThan( d_def_order[d_def_order.size()-1], u[depth] ) ){
- Trace("qint-compose-debug2") << "Bad : depth : " << depth << " ";
- Trace("qint-compose-debug2") << d_def_order[d_def_order.size()-1] << " " << u[depth] << std::endl;
- }
- Assert( d_def_order.empty() || m->isLessThan( d_def_order[d_def_order.size()-1], r ) );
- d_def_order.push_back( r );
- d_def[r].addEntry( m, q, l, u, v, depth+1 );
- }
- }
- if( nnum!=-1 ){
- l[nnum] = pl;
- u[nnum] = pu;
- }
- }
-}
-
-Node QIntDef::simplify_r( FirstOrderModelQInt * m, Node q, std::vector< Node >& il, std::vector< Node >& iu,
- unsigned depth ) {
- if( d_def.empty() ){
- if( d_def_order.size()!=0 ){
- Debug("qint-error") << "Simplify, size = " << d_def_order.size() << std::endl;
- }
- Assert( d_def_order.size()==1 );
- return d_def_order[0];
- }else{
- Assert( !d_def_order.empty() );
- std::vector< Node > newDefs;
- Node curr;
- for( unsigned i=0; i<d_def_order.size(); i++ ){
- Node n = d_def[d_def_order[i]].simplify_r( m, q, il, iu, depth+1 );
- if( i>0 ){
- if( n==curr && !n.isNull() ){
- d_def.erase( d_def_order[i-1] );
- }else{
- newDefs.push_back( d_def_order[i-1] );
- }
- }
- curr = n;
- }
- newDefs.push_back( d_def_order[d_def_order.size()-1] );
- d_def_order.clear();
- d_def_order.insert( d_def_order.end(), newDefs.begin(), newDefs.end() );
- return d_def_order.size()==1 ? curr : Node::null();
- }
-}
-
-Node QIntDef::simplify( FirstOrderModelQInt * m, Node q ) {
- std::vector< Node > l;
- std::vector< Node > u;
- if( !q.isNull() ){
- //init_vec( m, q, l, u );
- }
- return simplify_r( m, q, l, u, 0 );
-}
-
-bool QIntDef::isTotal_r( FirstOrderModelQInt * m, Node q, std::vector< Node >& l, std::vector< Node >& u,
- unsigned depth ) {
- if( d_def_order.empty() ){
- return false;
- }else if( d_def.empty() ){
- return true;
- }else{
- //get the current maximum
- Node mx;
- if( !q.isNull() ){
- int pnum = m->getVarOrder( q )->getPrevNum( depth );
- if( pnum!=-1 ){
- mx = u[pnum];
- }
- }
- if( mx.isNull() ){
- mx = m->getMaximum( d_def_order[d_def_order.size()-1].getType() );
- }
- //if not current maximum
- if( d_def_order[d_def_order.size()-1]!=mx ){
- return false;
- }else{
- Node pu = u[depth];
- for( unsigned i=0; i<d_def_order.size(); i++ ){
- u[depth] = d_def_order[i];
- if( !d_def[d_def_order[i]].isTotal_r( m, q, l, u, depth+1 ) ){
- return false;
- }
- }
- u[depth] = pu;
- return true;
- }
- }
-}
-
-bool QIntDef::isTotal( FirstOrderModelQInt * m, Node q ) {
- std::vector< Node > l;
- std::vector< Node > u;
- if( !q.isNull() ){
- init_vec( m, q, l, u );
- }
- return isTotal_r( m, q, l, u, 0 );
-}
-
-void QIntDef::construct_compose_r( FirstOrderModelQInt * m, Node q,
- std::vector< Node >& l, std::vector< Node >& u,
- Node n, QIntDef * f,
- std::vector< Node >& args,
- std::map< unsigned, QIntDef >& children,
- std::map< unsigned, Node >& bchildren,
- QIntVarNumIndex& vindex, unsigned depth ) {
- //check for short circuit
- if( !f ){
- if( !args.empty() ){
- if( ( n.getKind()==OR && args[args.size()-1]==m->d_true ) ||
- ( n.getKind()==AND && args[args.size()-1]==m->d_false ) ){
- addEntry( m, q, l, u, args[args.size()-1] );
- return;
- }
- }
- }
-
- for( unsigned i=0; i<depth; i++ ) { Trace("qint-compose") << " "; }
- Trace("qint-compose") << (f ? "U" : "I" ) << "C( ";
- for( unsigned i=0; i<l.size(); i++ ){
- if( i>0 ) Trace("qint-compose") << ", ";
- //Trace("qint-compose") << l[i] << "..." << u[i];
- int lindex = l[i].isNull() ? 0 : m->getRepId( l[i] ) + 1;
- int uindex = m->getRepId( u[i] );
- Trace( "qint-compose" ) << lindex << "..." << uindex;
- }
- Trace("qint-compose") << " )...";
-
- //finished?
- if( ( f && f->d_def.empty() ) || args.size()==n.getNumChildren() ){
- if( f ){
- Assert( f->d_def_order.size()==1 );
- Trace("qint-compose") << "UVALUE(" << f->d_def_order[0] << ")" << std::endl;
- addEntry( m, q, l, u, f->d_def_order[0] );
- }else{
- Node nn;
- bool nnSet = false;
- for( unsigned i=0; i<args.size(); i++ ){
- if( args[i].isNull() ){
- nnSet = true;
- break;
- }
- }
- if( !nnSet ){
- if( n.getKind()==EQUAL ){
- nn = NodeManager::currentNM()->mkConst( args[0]==args[1] );
- }else{
- //apply the operator to args
- nn = NodeManager::currentNM()->mkNode( n.getKind(), args );
- nn = Rewriter::rewrite( nn );
- }
- }
- Trace("qint-compose") << "IVALUE(" << nn << ")" << std::endl;
- addEntry( m, q, l, u, nn );
- Trace("qint-compose-debug2") << "...added entry." << std::endl;
- }
- }else{
- //if a non-simple child
- if( children.find( depth )!=children.end() ){
- //***************************
- Trace("qint-compose") << "compound child, recurse" << std::endl;
- std::vector< int > currIndex;
- std::vector< int > endIndex;
- std::vector< Node > prevL;
- std::vector< Node > prevU;
- std::vector< QIntDef * > visited;
- do{
- Assert( currIndex.size()==visited.size() );
-
- //populate the vectors
- while( visited.size()<m->getOrderedNumVars( q ) ){
- unsigned i = visited.size();
- QIntDef * qq = visited.empty() ? &children[depth] : visited[i-1]->getChild( currIndex[i-1] );
- visited.push_back( qq );
- Node qq_mx = qq->getMaximum();
- Trace("qint-compose-debug2") << "...Get ev indices " << i << " " << l[i] << " " << u[i] << std::endl;
- currIndex.push_back( qq->getEvIndex( m, l[i], true ) );
- Trace("qint-compose-debug2") << "...Done get curr index " << currIndex[currIndex.size()-1] << std::endl;
- if( m->isLessThan( qq_mx, u[i] ) ){
- endIndex.push_back( qq->getNumChildren()-1 );
- }else{
- endIndex.push_back( qq->getEvIndex( m, u[i] ) );
- }
- Trace("qint-compose-debug2") << "...Done get end index " << endIndex[endIndex.size()-1] << std::endl;
- prevL.push_back( l[i] );
- prevU.push_back( u[i] );
- if( !m->doMeet( prevL[i], prevU[i],
- qq->getLower( currIndex[i] ), qq->getUpper( currIndex[i] ), l[i], u[i] ) ){
- Assert( false );
- }
- }
- for( unsigned i=0; i<depth; i++ ) { Trace("qint-compose") << " "; }
- for( unsigned i=0; i<currIndex.size(); i++ ){
- Trace("qint-compose") << "[" << currIndex[i] << "/" << endIndex[i] << "]";
- }
- Trace("qint-compose") << std::endl;
- //consider the current
- int activeIndex = visited.size()-1;
- QIntDef * qa = visited.empty() ? &children[depth] : visited[activeIndex]->getChild( currIndex[activeIndex] );
- if( f ){
- int fIndex = f->getEvIndex( m, qa->getValue() );
- construct_compose_r( m, q, l, u, n, f->getChild( fIndex ), args, children, bchildren, vindex, depth+1 );
- }else{
- args.push_back( qa->getValue() );
- construct_compose_r( m, q, l, u, n, f, args, children, bchildren, vindex, depth+1 );
- args.pop_back();
- }
-
- //increment the index (if possible)
- while( activeIndex>=0 && currIndex[activeIndex]==endIndex[activeIndex] ){
- currIndex.pop_back();
- endIndex.pop_back();
- l[activeIndex] = prevL[activeIndex];
- u[activeIndex] = prevU[activeIndex];
- prevL.pop_back();
- prevU.pop_back();
- visited.pop_back();
- activeIndex--;
- }
- if( activeIndex>=0 ){
- for( unsigned i=0; i<depth; i++ ) { Trace("qint-compose") << " "; }
- Trace("qint-compose-debug") << "Increment at " << activeIndex << std::endl;
- currIndex[activeIndex]++;
- if( !m->doMeet( prevL[activeIndex], prevU[activeIndex],
- visited[activeIndex]->getLower( currIndex[activeIndex] ),
- visited[activeIndex]->getUpper( currIndex[activeIndex] ),
- l[activeIndex], u[activeIndex] ) ){
- Assert( false );
- }
- }
- }while( !visited.empty() );
- //***************************
- }else{
- Assert( bchildren.find( depth )!=bchildren.end() );
- Node v = bchildren[depth];
- if( f ){
- if( v.getKind()==BOUND_VARIABLE ){
- int vn = vindex.d_var_num[depth];
- Trace("qint-compose") << "variable #" << vn << ", recurse" << std::endl;
- //int vn = m->getOrderedVarOccurId( q, n, depth );
- Trace("qint-compose-debug") << "-process " << v << ", which is var #" << vn << std::endl;
- Node lprev = l[vn];
- Node uprev = u[vn];
- //restrict to last variable in order
- int pnum = m->getVarOrder( q )->getPrevNum( vn );
- if( pnum!=-1 ){
- Trace("qint-compose-debug") << "-restrict to var #" << pnum << " " << l[pnum] << " " << u[pnum] << std::endl;
- l[vn] = l[pnum];
- u[vn] = u[pnum];
- }
- int startIndex = f->getEvIndex( m, l[vn], true );
- int endIndex = f->getEvIndex( m, u[vn] );
- Trace("qint-compose-debug") << "--will process " << startIndex << " " << endIndex << std::endl;
- for( int i=startIndex; i<=endIndex; i++ ){
- if( m->doMeet( lprev, uprev, f->getLower( i ), f->getUpper( i ), l[vn], u[vn] ) ){
- construct_compose_r( m, q, l, u, n, f->getChild( i ), args, children, bchildren, vindex, depth+1 );
- }else{
- Assert( false );
- }
- }
- l[vn] = lprev;
- u[vn] = uprev;
- }else{
- Trace("qint-compose") << "value, recurse" << std::endl;
- //simple
- int ei = f->getEvIndex( m, v );
- construct_compose_r( m, q, l, u, n, f->getChild( ei ), args, children, bchildren, vindex, depth+1 );
- }
- }else{
- Trace("qint-compose") << "value, recurse" << std::endl;
- args.push_back( v );
- construct_compose_r( m, q, l, u, n, f, args, children, bchildren, vindex, depth+1 );
- args.pop_back();
- }
- }
- }
-}
-
-
-void QIntDef::construct_enum_r( FirstOrderModelQInt * m, Node q, unsigned vn, unsigned depth, Node v ) {
- if( depth==m->getOrderedNumVars( q ) ){
- Assert( !v.isNull() );
- d_def_order.push_back( v );
- }else{
- TypeNode tn = m->getOrderedVarType( q, depth );
- //int vnum = m->getVarOrder( q )->getVar( depth )==
- if( depth==vn ){
- for( unsigned i=0; i<m->d_rep_set.d_type_reps[tn].size(); i++ ){
- Node vv = m->d_rep_set.d_type_reps[tn][i];
- d_def_order.push_back( vv );
- d_def[vv].construct_enum_r( m, q, vn, depth+1, vv );
- }
- }else if( m->getVarOrder( q )->getVar( depth )==m->getVarOrder( q )->getVar( vn ) && depth>vn ){
- d_def_order.push_back( v );
- d_def[v].construct_enum_r( m, q, vn, depth+1, v );
- }else{
- Node mx = m->getMaximum( tn );
- d_def_order.push_back( mx );
- d_def[mx].construct_enum_r( m, q, vn, depth+1, v );
- }
- }
-}
-
-bool QIntDef::construct_enum( FirstOrderModelQInt * m, Node q, unsigned vn ) {
- TypeNode tn = m->getOrderedVarType( q, vn );
- if( tn.isSort() ){
- construct_enum_r( m, q, vn, 0, Node::null() );
- return true;
- }else{
- return false;
- }
-}
-
-bool QIntDef::construct_compose( FirstOrderModelQInt * m, Node q, Node n, QIntDef * f,
- std::map< unsigned, QIntDef >& children,
- std::map< unsigned, Node >& bchildren, int varChCount,
- QIntVarNumIndex& vindex ) {
- Trace("qint-compose") << "Do " << (f ? "uninterpreted" : "interpreted");
- Trace("qint-compose") << " compose, var count = " << varChCount << "..." << std::endl;
- std::vector< Node > l;
- std::vector< Node > u;
- init_vec( m, q, l, u );
- if( varChCount==0 || f ){
- //standard (no variable child) interpreted compose, or uninterpreted compose
- std::vector< Node > args;
- construct_compose_r( m, q, l, u, n, f, args, children, bchildren, vindex, 0 );
- }else{
- //special cases
- bool success = false;
- int varIndex = ( bchildren.find( 0 )!=bchildren.end() && bchildren[0].getKind()==BOUND_VARIABLE ) ? 0 : 1;
- if( varChCount>1 ){
- if( n.getKind()==EQUAL ){
- //make it an enumeration
- unsigned vn = vindex.d_var_num[0];
- if( children[0].construct_enum( m, q, vn ) ){
- bchildren.erase( 0 );
- varIndex = 1;
- success = true;
- }
- }
- }else{
- success = n.getKind()==EQUAL;
- }
- if( success ){
- int oIndex = varIndex==0 ? 1 : 0;
- Node v = bchildren[varIndex];
- unsigned vn = vindex.d_var_num[varIndex];
- if( children.find( oIndex )==children.end() ){
- Assert( bchildren.find( oIndex )!=bchildren.end() );
- Node at = bchildren[oIndex];
- Trace("qint-icompose") << "Basic child, " << at << " with var " << v << std::endl;
- Node prev = m->getPrev( bchildren[oIndex].getType(), bchildren[oIndex] );
- Node above = u[vn];
- if( !prev.isNull() ){
- u[vn] = prev;
- addEntry( m, q, l, u, NodeManager::currentNM()->mkConst( false ) );
- }
- l[vn] = prev;
- u[vn] = at;
- addEntry( m, q, l, u, NodeManager::currentNM()->mkConst( true ) );
- if( at!=above ){
- l[vn] = at;
- u[vn] = above;
- addEntry( m, q, l, u, NodeManager::currentNM()->mkConst( false ) );
- }
- }else{
- QIntDef * qid = &children[oIndex];
- qid->debugPrint("qint-icompose", m, q );
- Trace("qint-icompose") << " against variable..." << v << ", which is var #" << vn << std::endl;
-
- TypeNode tn = v.getType();
- QIntDefIter qdi( m, q, qid );
- while( !qdi.isFinished() ){
- std::vector< Node > us;
- qdi.getUppers( us );
- std::vector< Node > ls;
- qdi.getLowers( ls );
- qdi.debugPrint( "qint-icompose" );
-
- Node n_below = ls[vn];
- Node n_prev = m->getPrev( tn, qdi.getValue() );
- Node n_at = qdi.getValue();
- Node n_above = us[vn];
- Trace("qint-icompose") << n_below << " < " << n_prev << " < " << n_at << " < " << n_above << std::endl;
- if( n.getKind()==EQUAL ){
- bool atLtAbove = m->isLessThan( n_at, n_above );
- Node currL = n_below;
- if( n_at==n_above || atLtAbove ){
- //add for value (at-1)
- if( !n_prev.isNull() && ( n_below.isNull() || m->isLessThan( n_below, n_prev ) ) ){
- ls[vn] = currL;
- us[vn] = n_prev;
- currL = n_prev;
- Trace("qint-icompose") << "-add entry(-) at " << ls[vn] << "..." << us[vn] << std::endl;
- addEntry( m, q, ls, us, NodeManager::currentNM()->mkConst( false ) );
- }
- //add for value (at)
- if( ( n_below.isNull() || m->isLessThan( n_below, n_at ) ) && atLtAbove ){
- ls[vn] = currL;
- us[vn] = n_at;
- currL = n_at;
- Trace("qint-icompose") << "-add entry(=) at " << ls[vn] << "..." << us[vn] << std::endl;
- addEntry( m, q, ls, us, NodeManager::currentNM()->mkConst( true ) );
- }
- }
- ls[vn] = currL;
- us[vn] = n_above;
- Trace("qint-icompose") << "-add entry(+) at " << ls[vn] << "..." << us[vn] << std::endl;
- addEntry( m, q, ls, us, NodeManager::currentNM()->mkConst( n_at==n_above ) );
- }else{
- return false;
- }
- qdi.increment();
-
- Trace("qint-icompose-debug") << "Now : " << std::endl;
- debugPrint("qint-icompose-debug", m, q );
- Trace("qint-icompose-debug") << std::endl;
- }
- }
-
- Trace("qint-icompose") << "Result : " << std::endl;
- debugPrint("qint-icompose", m, q );
- Trace("qint-icompose") << std::endl;
-
- }else{
- return false;
- }
- }
- Trace("qint-compose") << "Done i-compose" << std::endl;
- return true;
-}
-
-
-void QIntDef::construct( FirstOrderModelQInt * m, std::vector< Node >& fapps, unsigned depth ) {
- d_def.clear();
- d_def_order.clear();
- Assert( !fapps.empty() );
- if( depth==fapps[0].getNumChildren() ){
- //get representative in model for this term
- Assert( fapps.size()>=1 );
- Node r = m->getUsedRepresentative( fapps[0] );
- d_def_order.push_back( r );
- }else{
- std::map< Node, std::vector< Node > > fapp_child;
- //partition based on evaluations of fapps[1][depth]....fapps[n][depth]
- for( unsigned i=0; i<fapps.size(); i++ ){
- Node r = m->getUsedRepresentative( fapps[i][depth] );
- fapp_child[r].push_back( fapps[i] );
- }
- //sort by QIntSort
- for( std::map< Node, std::vector< Node > >::iterator it = fapp_child.begin(); it != fapp_child.end(); ++it ){
- d_def_order.push_back( it->first );
- }
- QIntSort qis;
- qis.m = m;
- std::sort( d_def_order.begin(), d_def_order.end(), qis );
- //construct children
- for( unsigned i=0; i<d_def_order.size(); i++ ){
- Node n = d_def_order[i];
- if( i==d_def_order.size()-1 ){
- d_def_order[i] = m->getMaximum( d_def_order[i].getType() );
- }
- Debug("qint-model-debug2") << "Construct for " << n << ", terms = " << fapp_child[n].size() << std::endl;
- d_def[d_def_order[i]].construct( m, fapp_child[n], depth+1 );
- }
- }
-}
-
-Node QIntDef::getFunctionValue( FirstOrderModelQInt * m, std::vector< Node >& vars, unsigned depth ) {
- if( d_def.empty() ){
- Assert( d_def_order.size()==1 );
- //must convert to actual domain constant
- if( d_def_order[0].getType().isSort() ){
- return m->d_rep_set.d_type_reps[ d_def_order[0].getType() ][ m->getRepId( d_def_order[0] ) ];
- }else{
- return m->getUsedRepresentative( d_def_order[0] );
- }
- }else{
- TypeNode tn = vars[depth].getType();
- Node curr;
- int rep_id = m->d_rep_set.getNumRepresentatives( tn );
- for( int i=(int)(d_def_order.size()-1); i>=0; i-- ){
- int curr_rep_id = i==0 ? 0 : m->getRepId( d_def_order[i-1] )+1;
- Node ccurr = d_def[d_def_order[i]].getFunctionValue( m, vars, depth+1 );
- if( curr.isNull() ){
- curr = ccurr;
- }else{
- std::vector< Node > c;
- Assert( curr_rep_id<rep_id );
- for( int j=curr_rep_id; j<rep_id; j++ ){
- c.push_back( vars[depth].eqNode( m->d_rep_set.d_type_reps[tn][j] ) );
- }
- Node cond = c.size()==1 ? c[0] : NodeManager::currentNM()->mkNode( OR, c );
- curr = NodeManager::currentNM()->mkNode( ITE, cond, ccurr, curr );
- }
- rep_id = curr_rep_id;
- }
- return curr;
- }
-}
-
-Node QIntDef::evaluate_r( FirstOrderModelQInt * m, std::vector< Node >& reps, unsigned depth ) {
- if( depth==reps.size() ){
- Assert( d_def_order.size()==1 );
- return d_def_order[0];
- }else{
- if( d_def.find( reps[depth] )!=d_def.end() ){
- return d_def[reps[depth]].evaluate_r( m, reps, depth+1 );
- }else{
- int ei = getEvIndex( m, reps[depth] );
- return d_def[d_def_order[ei]].evaluate_r( m, reps, depth+1 );
- }
- }
-}
-Node QIntDef::evaluate_n_r( FirstOrderModelQInt * m, Node n, unsigned depth ) {
- if( depth==n.getNumChildren() ){
- Assert( d_def_order.size()==1 );
- return d_def_order[0];
- }else{
- Node r = m->getUsedRepresentative( n[depth] );
- if( d_def.find( r )!=d_def.end() ){
- return d_def[r].evaluate_n_r( m, n, depth+1 );
- }else{
- int ei = getEvIndex( m, r );
- return d_def[d_def_order[ei]].evaluate_n_r( m, n, depth+1 );
- }
- }
-}
-
-
-
-QIntDef * QIntDef::getChild( unsigned i ) {
- Assert( i<d_def_order.size() );
- Assert( d_def.find( d_def_order[i] )!=d_def.end() );
- return &d_def[ d_def_order[i] ];
-}
-
-void QIntDef::debugPrint( const char * c, FirstOrderModelQInt * m, Node q, int t ) {
- /*
- for( unsigned i=0; i<d_def_order.size(); i++ ){
- for( int j=0; j<t; j++ ) { Trace(c) << " "; }
- //Trace(c) << this << " ";
- Trace(c) << d_def_order[i] << " : " << std::endl;
- if( d_def.find( d_def_order[i] )!=d_def.end() ){
- d_def[d_def_order[i]].debugPrint( c, m, t+1 );
- }
- }
- */
- //if( t==0 ){
- QIntDefIter qdi( m, q, this );
- while( !qdi.isFinished() ){
- qdi.debugPrint( c, t );
- qdi.increment();
- }
- //}
-}
-
-
-QIntDefIter::QIntDefIter( FirstOrderModelQInt * m, Node q, QIntDef * qid ) : d_fm( m ), d_q( q ){
- resetIndex( qid );
-}
-
-void QIntDefIter::debugPrint( const char * c, int t ) {
- //Trace( c ) << getSize() << " " << d_index_visited.size() << " ";
- for( int j=0; j<t; j++ ) { Trace(c) << " "; }
- std::vector< Node > l;
- std::vector< Node > u;
- getLowers( l );
- getUppers( u );
- QIntDef::debugPrint( c, d_fm, d_q, l, u );
- Trace( c ) << " -> " << getValue() << std::endl;
-}
-
-void QIntDefIter::resetIndex( QIntDef * qid ){
- //std::cout << "check : " << qid << " " << qid->d_def_order.size() << " " << qid->d_def.size() << std::endl;
- if( !qid->d_def.empty() ){
- //std::cout << "add to visited " << qid << std::endl;
- d_index.push_back( 0 );
- d_index_visited.push_back( qid );
- resetIndex( qid->getChild( 0 ) );
- }
-}
-
-bool QIntDefIter::increment( int index ) {
- if( !isFinished() ){
- index = index==-1 ? (int)(d_index.size()-1) : index;
- while( (int)(d_index.size()-1)>index ){
- //std::cout << "remove from visit 1 " << std::endl;
- d_index.pop_back();
- d_index_visited.pop_back();
- }
- while( index>=0 && d_index[index]>=(int)(d_index_visited[index]->d_def_order.size()-1) ){
- //std::cout << "remove from visit " << d_index_visited[ d_index_visited.size()-1 ] << std::endl;
- d_index.pop_back();
- d_index_visited.pop_back();
- index--;
- }
- if( index>=0 ){
- //std::cout << "increment at index = " << index << std::endl;
- d_index[index]++;
- resetIndex( d_index_visited[index]->getChild( d_index[index] ) );
- return true;
- }else{
- d_index.clear();
- return false;
- }
- }else{
- return false;
- }
-}
-
-Node QIntDefIter::getLower( int index ) {
- if( d_index[index]==0 && !d_q.isNull() ){
- int pnum = d_fm->getVarOrder( d_q )->getPrevNum( index );
- if( pnum!=-1 ){
- return getLower( pnum );
- }
- }
- return d_index_visited[index]->getLower( d_index[index] );
-}
-
-Node QIntDefIter::getUpper( int index ) {
- return d_index_visited[index]->getUpper( d_index[index] );
-}
-
-void QIntDefIter::getLowers( std::vector< Node >& reps ) {
- for( unsigned i=0; i<getSize(); i++ ){
- bool added = false;
- if( d_index[i]==0 && !d_q.isNull() ){
- int pnum = d_fm->getVarOrder( d_q )->getPrevNum( i );
- if( pnum!=-1 ){
- added = true;
- reps.push_back( reps[pnum] );
- }
- }
- if( !added ){
- reps.push_back( getLower( i ) );
- }
- }
-}
-
-void QIntDefIter::getUppers( std::vector< Node >& reps ) {
- for( unsigned i=0; i<getSize(); i++ ){
- reps.push_back( getUpper( i ) );
- }
-}
-
-Node QIntDefIter::getValue() {
- return d_index_visited[ d_index_visited.size()-1 ]->getChild( d_index[d_index.size()-1] )->getValue();
-}
-
-
-//------------------------variable ordering----------------------------
-
-QuantVarOrder::QuantVarOrder( Node q ) : d_q( q ) {
- d_var_count = 0;
- initialize( q[1], 0, d_var_occur );
-}
-
-int QuantVarOrder::initialize( Node n, int minVarIndex, QIntVarNumIndex& vindex ) {
- if( n.getKind()!=FORALL ){
- //std::vector< Node > vars;
- //std::vector< int > args;
- int procVarOn = n.getKind()==APPLY_UF ? 0 : 1;
- for( int r=0; r<=procVarOn; r++ ){
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- if( n[i].getKind()==BOUND_VARIABLE && r==procVarOn ){
- int occ_index = -1;
- for( unsigned j=0; j<d_var_to_num[n[i]].size(); j++ ){
- if( d_var_to_num[n[i]][j]>=minVarIndex ){
- occ_index = d_var_to_num[n[i]][j];
- }
- }
- if( occ_index==-1 ){
- //need to assign new
- d_num_to_var[d_var_count] = n[i];
- if( !d_var_to_num[n[i]].empty() ){
- int v = d_var_to_num[n[i]][ d_var_to_num[n[i]].size()-1 ];
- d_num_to_prev_num[ d_var_count ] = v;
- d_num_to_next_num[ v ] = d_var_count;
- }
- d_var_num_index[ d_var_count ] = d_var_to_num[n[i]].size();
- d_var_to_num[n[i]].push_back( d_var_count );
- occ_index = d_var_count;
- d_var_count++;
- }
- vindex.d_var_num[i] = occ_index;
- minVarIndex = occ_index;
- }else if( r==0 ){
- minVarIndex = initialize( n[i], minVarIndex, vindex.d_var_index[i] );
- }
- }
- }
- }
- return minVarIndex;
-}
-
-bool QuantVarOrder::getInstantiation( FirstOrderModelQInt * m, std::vector< Node >& l, std::vector< Node >& u,
- std::vector< Node >& inst ) {
- Debug("qint-var-order-debug2") << "Get for " << d_q << " " << l.size() << " " << u.size() << std::endl;
- for( unsigned i=0; i<d_q[0].getNumChildren(); i++ ){
- Debug("qint-var-order-debug2") << "Get for " << d_q[0][i] << " " << d_var_to_num[d_q[0][i]].size() << std::endl;
- Node ll = Node::null();
- Node uu = m->getMaximum( d_q[0][i].getType() );
- for( unsigned j=0; j<d_var_to_num[d_q[0][i]].size(); j++ ){
- Debug("qint-var-order-debug2") << "Go " << j << std::endl;
- Node cl = ll;
- Node cu = uu;
- int index = d_var_to_num[d_q[0][i]][j];
- Debug("qint-var-order-debug2") << "Do meet for " << index << "..." << std::endl;
- Debug("qint-var-order-debug2") << l[index] << " " << u[index] << " " << cl << " " << cu << std::endl;
- if( !m->doMeet( l[index], u[index], cl, cu, ll, uu ) ){
- Debug("qint-var-order-debug2") << "FAILED" << std::endl;
- return false;
- }
- Debug("qint-var-order-debug2") << "Result : " << ll << " " << uu << std::endl;
- }
- Debug("qint-var-order-debug2") << "Got " << uu << std::endl;
- inst.push_back( uu );
- }
- return true;
-}
-
-void QuantVarOrder::debugPrint( const char * c ) {
- Trace( c ) << "Variable order for " << d_q << " is : " << std::endl;
- debugPrint( c, d_q[1], d_var_occur );
- Trace( c ) << std::endl;
- for( unsigned i=0; i<d_q[0].getNumChildren(); i++ ){
- Trace( c ) << d_q[0][i] << " : ";
- for( unsigned j=0; j<d_var_to_num[d_q[0][i]].size(); j++ ){
- Trace( c ) << d_var_to_num[d_q[0][i]][j] << " ";
- }
- Trace( c ) << std::endl;
- }
-}
-
-void QuantVarOrder::debugPrint( const char * c, Node n, QIntVarNumIndex& vindex ) {
- if( n.getKind()==FORALL ){
- Trace(c) << "NESTED_QUANT";
- }else{
- Trace(c) << n.getKind() << "(";
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- if( i>0 ) Trace( c ) << ",";
- Trace( c ) << " ";
- if( n[i].getKind()==BOUND_VARIABLE ){
- Trace(c) << "VAR[" << vindex.d_var_num[i] << "]";
- }else{
- debugPrint( c, n[i], vindex.d_var_index[i] );
- }
- if( i==n.getNumChildren()-1 ) Trace( c ) << " ";
- }
- Trace(c) << ")";
- }
-}
-
-QIntervalBuilder::QIntervalBuilder( context::Context* c, QuantifiersEngine* qe ) :
-QModelBuilder( c, qe ){
- d_true = NodeManager::currentNM()->mkConst( true );
-}
-
-
-//------------------------model construction----------------------------
-
-void QIntervalBuilder::processBuildModel(TheoryModel* m, bool fullModel) {
- Trace("fmf-qint-debug") << "process build model " << fullModel << std::endl;
- FirstOrderModel* f = (FirstOrderModel*)m;
- FirstOrderModelQInt* fm = f->asFirstOrderModelQInt();
- if( fullModel ){
- Trace("qint-model") << "Construct model representation..." << std::endl;
- //make function values
- for( std::map<Node, QIntDef * >::iterator it = fm->d_models.begin(); it != fm->d_models.end(); ++it ) {
- if( it->first.getType().getNumChildren()>1 ){
- Trace("qint-model") << "Construct for " << it->first << "..." << std::endl;
- m->d_uf_models[ it->first ] = fm->getFunctionValue( it->first, "$x" );
- }
- }
- TheoryEngineModelBuilder::processBuildModel( m, fullModel );
- //mark that the model has been set
- fm->markModelSet();
- //debug the model
- debugModel( fm );
- }else{
- fm->initialize();
- //process representatives
- fm->d_rep_id.clear();
- fm->d_max.clear();
- fm->d_min.clear();
- Trace("qint-model") << std::endl << "Making representatives..." << std::endl;
- for( std::map< TypeNode, std::vector< Node > >::iterator it = fm->d_rep_set.d_type_reps.begin();
- it != fm->d_rep_set.d_type_reps.end(); ++it ){
- if( it->first.isSort() ){
- if( it->second.empty() ){
- std::cout << "Empty rep for " << it->first << std::endl;
- exit(0);
- }
- Trace("qint-model") << "Representatives for " << it->first << " : " << std::endl;
- for( unsigned i=0; i<it->second.size(); i++ ){
- Trace("qint-model") << i << " : " << it->second[i] << std::endl;
- fm->d_rep_id[it->second[i]] = i;
- }
- fm->d_min[it->first] = it->second[0];
- fm->d_max[it->first] = it->second[it->second.size()-1];
- }else{
- //TODO: enumerate?
- }
- }
- Trace("qint-model") << std::endl << "Making function definitions..." << std::endl;
- //construct the models for functions
- for( std::map<Node, QIntDef * >::iterator it = fm->d_models.begin(); it != fm->d_models.end(); ++it ) {
- Node f = it->first;
- Trace("qint-model-debug") << "Building Model for " << f << std::endl;
- //reset the model
- //get all (non-redundant) f-applications
- std::vector< Node > fapps;
- Trace("qint-model-debug") << "Initial terms: " << std::endl;
- for( size_t i=0; i<fm->d_uf_terms[f].size(); i++ ){
- Node n = fm->d_uf_terms[f][i];
- if( !n.getAttribute(NoMatchAttribute()) ){
- Trace("qint-model-debug") << " " << n << std::endl;
- fapps.push_back( n );
- }
- }
- if( fapps.empty() ){
- //choose arbitrary value
- Node mbt = d_qe->getTermDatabase()->getModelBasisOpTerm(f);
- Trace("qint-model-debug") << "Initial terms empty, add " << mbt << std::endl;
- fapps.push_back( mbt );
- }
- //construct the interval model
- it->second->construct( fm, fapps );
- Trace("qint-model-debug") << "Definition for " << f << " : " << std::endl;
- it->second->debugPrint("qint-model-debug", fm, Node::null() );
-
- it->second->simplify( fm, Node::null() );
- Trace("qint-model") << "(Simplified) definition for " << f << " : " << std::endl;
- it->second->debugPrint("qint-model", fm, Node::null() );
-
- if( Debug.isOn("qint-model-debug") ){
- for( size_t i=0; i<fm->d_uf_terms[f].size(); i++ ){
- Node e = it->second->evaluate_n( fm, fm->d_uf_terms[f][i] );
- Debug("qint-model-debug") << fm->d_uf_terms[f][i] << " evaluates to " << e << std::endl;
- Assert( fm->areEqual( e, fm->d_uf_terms[f][i] ) );
- }
- }
- }
- }
-}
-
-
-//--------------------model checking---------------------------------------
-
-//do exhaustive instantiation
-bool QIntervalBuilder::doExhaustiveInstantiation( FirstOrderModel * fm, Node q, int effort ) {
- Trace("qint-check") << "exhaustive instantiation " << q << " " << effort << std::endl;
- if (effort==0) {
-
- FirstOrderModelQInt * fmqint = fm->asFirstOrderModelQInt();
- QIntDef qid;
- doCheck( fmqint, q, qid, q[1], fmqint->d_var_order[q]->d_var_occur );
- //now process entries
- Trace("qint-inst") << "Interpretation for " << q << " is : " << std::endl;
- qid.debugPrint( "qint-inst", fmqint, q );
- Trace("qint-inst") << std::endl;
- Debug("qint-check-debug2") << "Make iterator..." << std::endl;
- QIntDefIter qdi( fmqint, q, &qid );
- while( !qdi.isFinished() ){
- if( qdi.getValue()!=d_true ){
- Debug("qint-check-debug2") << "Set up vectors..." << std::endl;
- std::vector< Node > l;
- std::vector< Node > u;
- std::vector< Node > inst;
- qdi.getLowers( l );
- qdi.getUppers( u );
- Debug("qint-check-debug2") << "Get instantiation..." << std::endl;
- if( fmqint->d_var_order[q]->getInstantiation( fmqint, l, u, inst ) ){
- Trace("qint-inst") << "** Instantiate with ";
- //just add the instance
- for( unsigned j=0; j<inst.size(); j++) {
- Trace("qint-inst") << inst[j] << " ";
- }
- Trace("qint-inst") << std::endl;
- d_triedLemmas++;
- if( d_qe->addInstantiation( q, inst ) ){
- Trace("qint-inst") << " ...added instantiation." << std::endl;
- d_addedLemmas++;
- }else{
- Trace("qint-inst") << " ...duplicate instantiation" << std::endl;
- //verify that instantiation is witness for current entry
- if( Debug.isOn("qint-check-debug2") ){
- Debug("qint-check-debug2") << "Check if : ";
- std::vector< Node > exp_inst;
- for( unsigned i=0; i<fmqint->getOrderedNumVars( q ); i++ ){
- int index = fmqint->getOrderedVarNumToVarNum( q, i );
- exp_inst.push_back( inst[ index ] );
- Debug("qint-check-debug2") << inst[index] << " ";
- }
- Debug("qint-check-debug2") << " evaluates to " << qdi.getValue() << std::endl;
- Assert( qid.evaluate( fmqint, exp_inst )==qdi.getValue() );
- }
- }
- }else{
- Trace("qint-inst") << "** Spurious instantiation." << std::endl;
- }
- }
- qdi.increment();
- }
- }
- return true;
-}
-
-bool QIntervalBuilder::doCheck( FirstOrderModelQInt * m, Node q, QIntDef & qid, Node n,
- QIntVarNumIndex& vindex ) {
- Assert( n.getKind()!=FORALL );
- std::map< unsigned, QIntDef > children;
- std::map< unsigned, Node > bchildren;
- int varChCount = 0;
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- if( n[i].getKind()==FORALL ){
- bchildren[i] = Node::null();
- }else if( n[i].getKind() == BOUND_VARIABLE ){
- varChCount++;
- bchildren[i] = n[i];
- }else if( m->hasTerm( n[i] ) ){
- bchildren[i] = m->getUsedRepresentative( n[i] );
- }else{
- if( !doCheck( m, q, children[i], n[i], vindex.d_var_index[i] ) ){
- bchildren[i] = Node::null();
- }
- }
- }
- Trace("qint-check-debug") << "Compute Interpretation of " << n << " " << n.getKind() << std::endl;
- if( n.getKind() == APPLY_UF || n.getKind() == VARIABLE || n.getKind() == SKOLEM ){
- Node op = n.getKind() == APPLY_UF ? n.getOperator() : n;
- //uninterpreted compose
- qid.construct_compose( m, q, n, m->d_models[op], children, bchildren, varChCount, vindex );
- }else if( !qid.construct_compose( m, q, n, NULL, children, bchildren, varChCount, vindex ) ){
- Trace("qint-check-debug") << "** Cannot produce definition for " << n << std::endl;
- return false;
- }
- Trace("qint-check-debug2") << "Definition for " << n << " is : " << std::endl;
- qid.debugPrint("qint-check-debug2", m, q);
- qid.simplify( m, q );
- Trace("qint-check-debug") << "(Simplified) Definition for " << n << " is : " << std::endl;
- qid.debugPrint("qint-check-debug", m, q);
- Trace("qint-check-debug") << std::endl;
- Assert( qid.isTotal( m, q ) );
- return true;
-}
diff --git a/src/theory/quantifiers/qinterval_builder.h b/src/theory/quantifiers/qinterval_builder.h
deleted file mode 100644
index 7515f13c6..000000000
--- a/src/theory/quantifiers/qinterval_builder.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/********************* */
-/*! \file qinterval_builder.h
- ** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief qinterval model class
- **/
-
-#include "cvc4_private.h"
-
-#ifndef QINTERVAL_BUILDER
-#define QINTERVAL_BUILDER
-
-#include "theory/quantifiers/model_builder.h"
-#include "theory/quantifiers/first_order_model.h"
-
-namespace CVC4 {
-namespace theory {
-namespace quantifiers {
-
-class FirstOrderModelQInt;
-
-class QIntVarNumIndex
-{
-public:
- std::map< int, int > d_var_num;
- std::map< int, QIntVarNumIndex > d_var_index;
-};
-
-class QIntDef
-{
-private:
- Node evaluate_r( FirstOrderModelQInt * m, std::vector< Node >& reps, unsigned depth );
- Node evaluate_n_r( FirstOrderModelQInt * m, Node n, unsigned depth );
- void construct_compose_r( FirstOrderModelQInt * m, Node q,
- std::vector< Node >& l, std::vector< Node >& u, Node n, QIntDef * f,
- std::vector< Node >& args,
- std::map< unsigned, QIntDef >& children,
- std::map< unsigned, Node >& bchildren,
- QIntVarNumIndex& vindex,
- unsigned depth );
-
- void construct_enum_r( FirstOrderModelQInt * m, Node q, unsigned vn, unsigned depth, Node v );
- int getEvIndex( FirstOrderModelQInt * m, Node n, bool exc = false );
- void addEntry( FirstOrderModelQInt * m, Node q, std::vector< Node >& l, std::vector< Node >& u,
- Node v, unsigned depth = 0 );
- Node simplify_r( FirstOrderModelQInt * m, Node q, std::vector< Node >& il, std::vector< Node >& iu,
- unsigned depth );
- bool isTotal_r( FirstOrderModelQInt * m, Node q, std::vector< Node >& il, std::vector< Node >& iu,
- unsigned depth );
-public:
- QIntDef(){}
- std::map< Node, QIntDef > d_def;
- std::vector< Node > d_def_order;
-
- void construct( FirstOrderModelQInt * m, std::vector< Node >& fapps, unsigned depth = 0 );
- bool construct_compose( FirstOrderModelQInt * m, Node q, Node n, QIntDef * f,
- std::map< unsigned, QIntDef >& children,
- std::map< unsigned, Node >& bchildren, int varChCount,
- QIntVarNumIndex& vindex );
- bool construct_enum( FirstOrderModelQInt * m, Node q, unsigned vn );
-
- Node evaluate( FirstOrderModelQInt * m, std::vector< Node >& reps ) { return evaluate_r( m, reps, 0 ); }
- Node evaluate_n( FirstOrderModelQInt * m, Node n ) { return evaluate_n_r( m, n, 0 ); }
-
- void debugPrint( const char * c, FirstOrderModelQInt * m, Node q, int t = 0 );
- QIntDef * getChild( unsigned i );
- Node getValue() { return d_def_order[0]; }
- Node getLower( unsigned i ) { return i==0 ? Node::null() : d_def_order[i-1]; }
- Node getUpper( unsigned i ) { return d_def_order[i]; }
- Node getMaximum() { return d_def_order.empty() ? Node::null() : getUpper( d_def_order.size()-1 ); }
- int getNumChildren() { return d_def_order.size(); }
- bool isTotal( FirstOrderModelQInt * m, Node q );
-
- Node simplify( FirstOrderModelQInt * m, Node q );
- Node getFunctionValue( FirstOrderModelQInt * m, std::vector< Node >& vars, unsigned depth = 0 );
-
- static void init_vec( FirstOrderModelQInt * m, Node q, std::vector< Node >& l, std::vector< Node >& u );
- static void debugPrint( const char * c, FirstOrderModelQInt * m, Node q, std::vector< Node >& l, std::vector< Node >& u );
-};
-
-class QIntDefIter {
-private:
- FirstOrderModelQInt * d_fm;
- Node d_q;
- void resetIndex( QIntDef * qid );
-public:
- QIntDefIter( FirstOrderModelQInt * m, Node q, QIntDef * qid );
- void debugPrint( const char * c, int t = 0 );
- std::vector< QIntDef * > d_index_visited;
- std::vector< int > d_index;
- bool isFinished() { return d_index.empty(); }
- bool increment( int index = -1 );
- unsigned getSize() { return d_index.size(); }
- Node getLower( int index );
- Node getUpper( int index );
- void getLowers( std::vector< Node >& reps );
- void getUppers( std::vector< Node >& reps );
- Node getValue();
-};
-
-
-class QuantVarOrder
-{
-private:
- int initialize( Node n, int minVarIndex, QIntVarNumIndex& vindex );
- int d_var_count;
- Node d_q;
- void debugPrint( const char * c, Node n, QIntVarNumIndex& vindex );
-public:
- QuantVarOrder( Node q );
- std::map< int, Node > d_num_to_var;
- std::map< int, int > d_num_to_prev_num;
- std::map< int, int > d_num_to_next_num;
- std::map< Node, std::vector< int > > d_var_to_num;
- std::map< int, int > d_var_num_index;
- //std::map< Node, std::map< int, int > > d_var_occur;
- //int getVarNum( Node n, int arg ) { return d_var_occur[n][arg]; }
- unsigned getNumVars() { return d_var_count; }
- Node getVar( int i ) { return d_num_to_var[i]; }
- int getPrevNum( int i ) { return d_num_to_prev_num.find( i )!=d_num_to_prev_num.end() ? d_num_to_prev_num[i] : -1; }
- int getNextNum( int i ) { return d_num_to_next_num.find( i )!=d_num_to_next_num.end() ? d_num_to_next_num[i] : -1; }
- int getVarNumIndex( int i ) { return d_var_num_index[i]; }
- bool getInstantiation( FirstOrderModelQInt * m, std::vector< Node >& l, std::vector< Node >& u,
- std::vector< Node >& inst );
- void debugPrint( const char * c );
- QIntVarNumIndex d_var_occur;
-};
-
-class QIntervalBuilder : public QModelBuilder
-{
-private:
- Node d_true;
- bool doCheck( FirstOrderModelQInt * m, Node q, QIntDef & qid, Node n,
- QIntVarNumIndex& vindex );
-public:
- QIntervalBuilder( context::Context* c, QuantifiersEngine* qe );
- //process build model
- void processBuildModel(TheoryModel* m, bool fullModel);
- //do exhaustive instantiation
- bool doExhaustiveInstantiation( FirstOrderModel * fm, Node q, int effort );
-};
-
-
-}
-}
-}
-
-#endif \ No newline at end of file
diff --git a/src/theory/quantifiers/quant_conflict_find.cpp b/src/theory/quantifiers/quant_conflict_find.cpp
index f976a0dbf..d465df4c0 100755
--- a/src/theory/quantifiers/quant_conflict_find.cpp
+++ b/src/theory/quantifiers/quant_conflict_find.cpp
@@ -43,6 +43,7 @@ void QuantInfo::initialize( Node q, Node qn ) {
for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
d_var_num[q[0][i]] = i;
d_vars.push_back( q[0][i] );
+ d_var_types.push_back( q[0][i].getType() );
}
registerNode( qn, true, true );
@@ -145,6 +146,7 @@ void QuantInfo::flatten( Node n, bool beneathQuant ) {
Trace("qcf-qregister-debug2") << "Add FLATTEN VAR : " << n << std::endl;
d_var_num[n] = d_vars.size();
d_vars.push_back( n );
+ d_var_types.push_back( n.getType() );
d_match.push_back( TNode::null() );
d_match_term.push_back( TNode::null() );
if( n.getKind()==ITE ){
@@ -456,8 +458,8 @@ bool QuantInfo::isTConstraintSpurious( QuantConflictFind * p, std::vector< Node
//check constraints
for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){
//apply substitution to the tconstraint
- Node cons = it->first.substitute( p->getQuantifiersEngine()->getTermDatabase()->d_vars[d_q].begin(),
- p->getQuantifiersEngine()->getTermDatabase()->d_vars[d_q].end(),
+ Node cons = it->first.substitute( p->getTermDatabase()->d_vars[d_q].begin(),
+ p->getTermDatabase()->d_vars[d_q].end(),
terms.begin(), terms.end() );
cons = it->second ? cons : cons.negate();
if( !entailmentTest( p, cons, p->d_effort==QuantConflictFind::effort_conflict ) ){
@@ -1298,7 +1300,7 @@ bool MatchGen::getNextMatch( QuantConflictFind * p, QuantInfo * qi ) {
if( d_type==typ_var && p->d_effort==QuantConflictFind::effort_mc && !d_matched_basis ){
d_matched_basis = true;
Node f = getOperator( d_n );
- TNode mbo = p->getQuantifiersEngine()->getTermDatabase()->getModelBasisOpTerm( f );
+ TNode mbo = p->getTermDatabase()->getModelBasisOpTerm( f );
if( qi->setMatch( p, d_qni_var_num[0], mbo ) ){
success = true;
d_qni_bound[0] = d_qni_var_num[0];
@@ -1524,7 +1526,7 @@ bool MatchGen::doMatching( QuantConflictFind * p, QuantInfo * qi ) {
if( it != d_qn[index]->d_data.end() ) {
d_qni.push_back( it );
//set the match
- if( qi->setMatch( p, d_qni_bound[index], it->first ) ){
+ if( it->first.getType().isSubtypeOf( qi->d_var_types[repVar] ) && qi->setMatch( p, d_qni_bound[index], it->first ) ){
Debug("qcf-match-debug") << " Binding variable" << std::endl;
if( d_qn.size()<d_qni_size ){
d_qn.push_back( &it->second );
@@ -1660,7 +1662,7 @@ bool MatchGen::isHandledUfTerm( TNode n ) {
Node MatchGen::getOperator( QuantConflictFind * p, Node n ) {
if( isHandledUfTerm( n ) ){
- return p->getQuantifiersEngine()->getTermDatabase()->getOperator( n );
+ return p->getTermDatabase()->getOperator( n );
}else{
return Node::null();
}
@@ -1884,8 +1886,7 @@ Node QuantConflictFind::evaluateTerm( Node n ) {
/** new node */
void QuantConflictFind::newEqClass( Node n ) {
- //Trace("qcf-proc-debug") << "QCF : newEqClass : " << n << std::endl;
- //Trace("qcf-proc2-debug") << "QCF : finished newEqClass : " << n << std::endl;
+
}
/** merge */
@@ -2086,26 +2087,28 @@ void QuantConflictFind::computeRelevantEqr() {
while( !eqcs_i.isFinished() ){
//nEqc++;
Node r = (*eqcs_i);
- TypeNode rtn = r.getType();
- if( options::qcfMode()==QCF_MC ){
- std::map< TypeNode, std::vector< TNode > >::iterator itt = d_eqcs.find( rtn );
- if( itt==d_eqcs.end() ){
- Node mb = getQuantifiersEngine()->getTermDatabase()->getModelBasisTerm( rtn );
- if( !getEqualityEngine()->hasTerm( mb ) ){
- Trace("qcf-warn") << "WARNING: Model basis term does not exist!" << std::endl;
- Assert( false );
- }
- Node mbr = getRepresentative( mb );
- if( mbr!=r ){
- d_eqcs[rtn].push_back( mbr );
+ if( getTermDatabase()->hasTermCurrent( r ) ){
+ TypeNode rtn = r.getType();
+ if( options::qcfMode()==QCF_MC ){
+ std::map< TypeNode, std::vector< TNode > >::iterator itt = d_eqcs.find( rtn );
+ if( itt==d_eqcs.end() ){
+ Node mb = getTermDatabase()->getModelBasisTerm( rtn );
+ if( !getEqualityEngine()->hasTerm( mb ) ){
+ Trace("qcf-warn") << "WARNING: Model basis term does not exist!" << std::endl;
+ Assert( false );
+ }
+ Node mbr = getRepresentative( mb );
+ if( mbr!=r ){
+ d_eqcs[rtn].push_back( mbr );
+ }
+ d_eqcs[rtn].push_back( r );
+ d_model_basis[rtn] = mb;
+ }else{
+ itt->second.push_back( r );
}
- d_eqcs[rtn].push_back( r );
- d_model_basis[rtn] = mb;
}else{
- itt->second.push_back( r );
+ d_eqcs[rtn].push_back( r );
}
- }else{
- d_eqcs[rtn].push_back( r );
}
++eqcs_i;
}
diff --git a/src/theory/quantifiers/quant_conflict_find.h b/src/theory/quantifiers/quant_conflict_find.h
index 93e1f72a6..b2dc680f2 100755
--- a/src/theory/quantifiers/quant_conflict_find.h
+++ b/src/theory/quantifiers/quant_conflict_find.h
@@ -118,6 +118,7 @@ public:
QuantInfo() : d_mg( NULL ) {}
~QuantInfo() { delete d_mg; }
std::vector< TNode > d_vars;
+ std::vector< TypeNode > d_var_types;
std::map< TNode, int > d_var_num;
std::vector< int > d_tsym_vars;
std::map< TNode, bool > d_inMatchConstraint;
diff --git a/src/theory/quantifiers/quant_util.cpp b/src/theory/quantifiers/quant_util.cpp
index b39d7fff6..62a87bb99 100644
--- a/src/theory/quantifiers/quant_util.cpp
+++ b/src/theory/quantifiers/quant_util.cpp
@@ -241,6 +241,7 @@ void QuantPhaseReq::computePhaseReqs( Node n, bool polarity, std::map< Node, int
}
void QuantPhaseReq::getPolarity( Node n, int child, bool hasPol, bool pol, bool& newHasPol, bool& newPol ) {
+ Assert( n.getKind()!=IMPLIES && n.getKind()!=XOR );
newHasPol = hasPol;
newPol = pol;
if( n.getKind()==NOT ){
diff --git a/src/theory/quantifiers/quantifiers_attributes.cpp b/src/theory/quantifiers/quantifiers_attributes.cpp
index 48608cb4e..ef5b71f9d 100644
--- a/src/theory/quantifiers/quantifiers_attributes.cpp
+++ b/src/theory/quantifiers/quantifiers_attributes.cpp
@@ -33,6 +33,10 @@ void QuantifiersAttributes::setUserAttribute( const std::string& attr, Node n, s
Trace("quant-attr-debug") << "Set conjecture " << n << std::endl;
ConjectureAttribute ca;
n.setAttribute( ca, true );
+ }else if( attr=="fun-def" ){
+ Trace("quant-attr-debug") << "Set function definition " << n << std::endl;
+ FunDefAttribute fda;
+ n.setAttribute( fda, true );
}else if( attr=="sygus" ){
Trace("quant-attr-debug") << "Set sygus " << n << std::endl;
SygusAttribute ca;
diff --git a/src/theory/quantifiers/quantifiers_rewriter.cpp b/src/theory/quantifiers/quantifiers_rewriter.cpp
index fb7ff679b..1e6ec3a02 100644
--- a/src/theory/quantifiers/quantifiers_rewriter.cpp
+++ b/src/theory/quantifiers/quantifiers_rewriter.cpp
@@ -105,6 +105,7 @@ void QuantifiersRewriter::computeArgs( std::vector< Node >& args, std::map< Node
}
void QuantifiersRewriter::computeArgVec( std::vector< Node >& args, std::vector< Node >& activeArgs, Node n ) {
+ Assert( activeArgs.empty() );
std::map< Node, bool > activeMap;
computeArgs( args, activeMap, n );
for( unsigned i=0; i<args.size(); i++ ){
@@ -114,12 +115,23 @@ void QuantifiersRewriter::computeArgVec( std::vector< Node >& args, std::vector<
}
}
+void QuantifiersRewriter::computeArgVec2( std::vector< Node >& args, std::vector< Node >& activeArgs, Node n, Node ipl ) {
+ Assert( activeArgs.empty() );
+ std::map< Node, bool > activeMap;
+ computeArgs( args, activeMap, n );
+ computeArgs( args, activeMap, ipl );
+ for( unsigned i=0; i<args.size(); i++ ){
+ if( activeMap[args[i]] ){
+ activeArgs.push_back( args[i] );
+ }
+ }
+}
bool QuantifiersRewriter::hasArg( std::vector< Node >& args, Node n ){
if( std::find( args.begin(), args.end(), n )!=args.end() ){
return true;
}else{
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
if( hasArg( args, n[i] ) ){
return true;
}
@@ -128,6 +140,19 @@ bool QuantifiersRewriter::hasArg( std::vector< Node >& args, Node n ){
}
}
+bool QuantifiersRewriter::hasArg1( Node a, Node n ) {
+ if( n==a ){
+ return true;
+ }else{
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ if( hasArg1( a, n[i] ) ){
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
void QuantifiersRewriter::setNestedQuantifiers( Node n, Node q ){
std::vector< Node > processed;
setNestedQuantifiers2( n, q, processed );
@@ -284,11 +309,19 @@ Node QuantifiersRewriter::computeNNF( Node body ){
}else{
std::vector< Node > children;
Kind k = body[0].getKind();
+
if( body[0].getKind()==OR || body[0].getKind()==AND ){
+ k = body[0].getKind()==AND ? OR : AND;
for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
- children.push_back( computeNNF( body[0][i].notNode() ) );
+ Node nc = computeNNF( body[0][i].notNode() );
+ if( nc.getKind()==k ){
+ for( unsigned j=0; j<nc.getNumChildren(); j++ ){
+ children.push_back( nc[j] );
+ }
+ }else{
+ children.push_back( nc );
+ }
}
- k = body[0].getKind()==AND ? OR : AND;
}else if( body[0].getKind()==IFF ){
for( int i=0; i<2; i++ ){
Node nn = i==0 ? body[0][i] : body[0][i].notNode();
@@ -310,10 +343,18 @@ Node QuantifiersRewriter::computeNNF( Node body ){
}else{
std::vector< Node > children;
bool childrenChanged = false;
+ bool isAssoc = body.getKind()==AND || body.getKind()==OR;
for( int i=0; i<(int)body.getNumChildren(); i++ ){
Node nc = computeNNF( body[i] );
- children.push_back( nc );
- childrenChanged = childrenChanged || nc!=body[i];
+ if( isAssoc && nc.getKind()==body.getKind() ){
+ for( unsigned j=0; j<nc.getNumChildren(); j++ ){
+ children.push_back( nc[j] );
+ }
+ childrenChanged = true;
+ }else{
+ children.push_back( nc );
+ childrenChanged = childrenChanged || nc!=body[i];
+ }
}
if( childrenChanged ){
return NodeManager::currentNM()->mkNode( body.getKind(), children );
@@ -323,43 +364,88 @@ Node QuantifiersRewriter::computeNNF( Node body ){
}
}
-Node QuantifiersRewriter::computeSimpleIteLift( Node body ) {
- if( body.getKind()==EQUAL ){
- for( size_t i=0; i<2; i++ ){
- if( body[i].getKind()==ITE ){
- Node no = i==0 ? body[1] : body[0];
- bool doRewrite = false;
- std::vector< Node > children;
- children.push_back( body[i][0] );
- for( size_t j=1; j<=2; j++ ){
- //check if it rewrites to a constant
- Node nn = NodeManager::currentNM()->mkNode( EQUAL, no, body[i][j] );
- nn = Rewriter::rewrite( nn );
- children.push_back( nn );
- if( nn.isConst() ){
- doRewrite = true;
+Node QuantifiersRewriter::computeProcessIte( Node body, bool hasPol, bool pol ) {
+ if( body.getType().isBoolean() ){
+ if( body.getKind()==EQUAL && options::simpleIteLiftQuant() ){
+ for( size_t i=0; i<2; i++ ){
+ if( body[i].getKind()==ITE ){
+ Node no = i==0 ? body[1] : body[0];
+ bool doRewrite = false;
+ std::vector< Node > children;
+ children.push_back( body[i][0] );
+ for( size_t j=1; j<=2; j++ ){
+ //check if it rewrites to a constant
+ Node nn = NodeManager::currentNM()->mkNode( EQUAL, no, body[i][j] );
+ nn = Rewriter::rewrite( nn );
+ children.push_back( nn );
+ if( nn.isConst() ){
+ doRewrite = true;
+ }
+ }
+ if( doRewrite ){
+ return NodeManager::currentNM()->mkNode( ITE, children );
+ }
+ }
+ }
+ }else if( body.getKind()==ITE && hasPol && options::iteCondVarSplitQuant() ){
+ for( unsigned r=0; r<2; r++ ){
+ //check if there is a variable elimination
+ Node b = r==0 ? body[0] : body[0].negate();
+ QuantPhaseReq qpr( b );
+ std::vector< Node > vars;
+ std::vector< Node > subs;
+ Trace("ite-var-split-quant") << "phase req " << body[0] << " #: " << qpr.d_phase_reqs.size() << std::endl;
+ for( std::map< Node, bool >::iterator it = qpr.d_phase_reqs.begin(); it != qpr.d_phase_reqs.end(); ++it ){
+ Trace("ite-var-split-quant") << "phase req " << it->first << " -> " << it->second << std::endl;
+ if( it->second ){
+ if( it->first.getKind()==EQUAL ){
+ for( unsigned i=0; i<2; i++ ){
+ if( it->first[i].getKind()==BOUND_VARIABLE ){
+ unsigned j = i==0 ? 1 : 0;
+ if( !hasArg1( it->first[i], it->first[j] ) ){
+ vars.push_back( it->first[i] );
+ subs.push_back( it->first[j] );
+ break;
+ }
+ }
+ }
+ }
}
}
- if( doRewrite ){
- return NodeManager::currentNM()->mkNode( ITE, children );
+ if( !vars.empty() ){
+ //bool cpol = (r==1);
+ Node pos = NodeManager::currentNM()->mkNode( OR, body[0].negate(), body[1] );
+ //pos = pos.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ //pos = Rewriter::rewrite( pos );
+ Node neg = NodeManager::currentNM()->mkNode( OR, body[0], body[2] );
+ //Trace("ite-var-split-quant") << "Split ITE " << body << " into : " << std::endl;
+ //Trace("ite-var-split-quant") << " " << pos << std::endl;
+ //Trace("ite-var-split-quant") << " " << neg << std::endl;
+ return NodeManager::currentNM()->mkNode( AND, pos, neg );
}
}
}
- }else if( body.getKind()!=APPLY_UF && body.getType()==NodeManager::currentNM()->booleanType() ){
- bool changed = false;
- std::vector< Node > children;
- for( size_t i=0; i<body.getNumChildren(); i++ ){
- Node nn = computeSimpleIteLift( body[i] );
- children.push_back( nn );
- changed = changed || nn!=body[i];
- }
- if( changed ){
- return NodeManager::currentNM()->mkNode( body.getKind(), children );
+ if( body.getKind()!=EQUAL && body.getKind()!=APPLY_UF ){
+ bool changed = false;
+ std::vector< Node > children;
+ for( size_t i=0; i<body.getNumChildren(); i++ ){
+ bool newHasPol;
+ bool newPol;
+ QuantPhaseReq::getPolarity( body, i, hasPol, pol, newHasPol, newPol );
+ Node nn = computeProcessIte( body[i], newHasPol, newPol );
+ children.push_back( nn );
+ changed = changed || nn!=body[i];
+ }
+ if( changed ){
+ return NodeManager::currentNM()->mkNode( body.getKind(), children );
+ }
}
}
return body;
}
+
+
Node QuantifiersRewriter::computeVarElimination( Node body, std::vector< Node >& args, Node& ipl ){
Trace("var-elim-quant-debug") << "Compute var elimination for " << body << std::endl;
QuantPhaseReq qpr( body );
@@ -373,9 +459,7 @@ Node QuantifiersRewriter::computeVarElimination( Node body, std::vector< Node >&
int j = i==0 ? 1 : 0;
std::vector< Node >::iterator ita = std::find( args.begin(), args.end(), it->first[i] );
if( ita!=args.end() ){
- std::vector< Node > temp;
- temp.push_back( it->first[i] );
- if( !hasArg( temp, it->first[j] ) ){
+ if( !hasArg1( it->first[i], it->first[j] ) ){
vars.push_back( it->first[i] );
subs.push_back( it->first[j] );
args.erase( ita );
@@ -595,18 +679,22 @@ Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, b
}else{
return body;
}
- }else if( body.getKind()==ITE || body.getKind()==XOR || body.getKind()==IFF ){
- return body;
}else{
Assert( body.getKind()!=EXISTS );
bool childrenChanged = false;
std::vector< Node > newChildren;
for( int i=0; i<(int)body.getNumChildren(); i++ ){
- bool newPol = body.getKind()==NOT ? !pol : pol;
- Node n = computePrenex( body[i], args, newPol );
- newChildren.push_back( n );
- if( n!=body[i] ){
- childrenChanged = true;
+ bool newHasPol;
+ bool newPol;
+ QuantPhaseReq::getPolarity( body, i, true, pol, newHasPol, newPol );
+ if( newHasPol ){
+ Node n = computePrenex( body[i], args, newPol );
+ newChildren.push_back( n );
+ if( n!=body[i] ){
+ childrenChanged = true;
+ }
+ }else{
+ newChildren.push_back( body[i] );
}
}
if( childrenChanged ){
@@ -728,7 +816,7 @@ Node QuantifiersRewriter::computeSplit( Node f, Node body, std::vector< Node >&
Node QuantifiersRewriter::mkForAll( std::vector< Node >& args, Node body, Node ipl ){
std::vector< Node > activeArgs;
- computeArgVec( args, activeArgs, body );
+ computeArgVec2( args, activeArgs, body, ipl );
if( activeArgs.empty() ){
return body;
}else{
@@ -947,8 +1035,8 @@ bool QuantifiersRewriter::doOperation( Node f, bool isNested, int computeOption
return options::aggressiveMiniscopeQuant();
}else if( computeOption==COMPUTE_NNF ){
return options::nnfQuant();
- }else if( computeOption==COMPUTE_SIMPLE_ITE_LIFT ){
- return options::simpleIteLiftQuant();
+ }else if( computeOption==COMPUTE_PROCESS_ITE ){
+ return options::iteCondVarSplitQuant() || options::simpleIteLiftQuant();
}else if( computeOption==COMPUTE_PRENEX ){
return options::prenexQuant()!=PRENEX_NONE && !options::aggressiveMiniscopeQuant();
}else if( computeOption==COMPUTE_VAR_ELIMINATION ){
@@ -985,8 +1073,8 @@ Node QuantifiersRewriter::computeOperation( Node f, bool isNested, int computeOp
return computeAggressiveMiniscoping( args, n, isNested );
}else if( computeOption==COMPUTE_NNF ){
n = computeNNF( n );
- }else if( computeOption==COMPUTE_SIMPLE_ITE_LIFT ){
- n = computeSimpleIteLift( n );
+ }else if( computeOption==COMPUTE_PROCESS_ITE ){
+ n = computeProcessIte( n, true, true );
}else if( computeOption==COMPUTE_PRENEX ){
n = computePrenex( n, args, true );
}else if( computeOption==COMPUTE_VAR_ELIMINATION ){
diff --git a/src/theory/quantifiers/quantifiers_rewriter.h b/src/theory/quantifiers/quantifiers_rewriter.h
index e2137b9f4..badf97c46 100644
--- a/src/theory/quantifiers/quantifiers_rewriter.h
+++ b/src/theory/quantifiers/quantifiers_rewriter.h
@@ -40,7 +40,9 @@ private:
static Node mkForAll( std::vector< Node >& args, Node body, Node ipl );
static void computeArgs( std::vector< Node >& args, std::map< Node, bool >& activeMap, Node n );
static void computeArgVec( std::vector< Node >& args, std::vector< Node >& activeArgs, Node n );
+ static void computeArgVec2( std::vector< Node >& args, std::vector< Node >& activeArgs, Node n, Node ipl );
static bool hasArg( std::vector< Node >& args, Node n );
+ static bool hasArg1( Node a, Node n );
static void setNestedQuantifiers( Node n, Node q );
static void setNestedQuantifiers2( Node n, Node q, std::vector< Node >& processed );
static Node computeClause( Node n );
@@ -50,7 +52,7 @@ private:
static Node computeMiniscoping( Node f, std::vector< Node >& args, Node body, Node ipl, bool isNested = false );
static Node computeAggressiveMiniscoping( std::vector< Node >& args, Node body, bool isNested = false );
static Node computeNNF( Node body );
- static Node computeSimpleIteLift( Node body );
+ static Node computeProcessIte( Node body, bool hasPol, bool pol );
static Node computeVarElimination( Node body, std::vector< Node >& args, Node& ipl );
static Node computeCNF( Node body, std::vector< Node >& args, NodeBuilder<>& defs, bool forcePred );
static Node computePrenex( Node body, std::vector< Node >& args, bool pol );
@@ -61,7 +63,7 @@ private:
COMPUTE_MINISCOPING,
COMPUTE_AGGRESSIVE_MINISCOPING,
COMPUTE_NNF,
- COMPUTE_SIMPLE_ITE_LIFT,
+ COMPUTE_PROCESS_ITE,
COMPUTE_PRENEX,
COMPUTE_VAR_ELIMINATION,
//COMPUTE_FLATTEN_ARGS_UF,
diff --git a/src/theory/quantifiers/term_database.cpp b/src/theory/quantifiers/term_database.cpp
index 9c1eeb9b4..34c40c8c4 100644
--- a/src/theory/quantifiers/term_database.cpp
+++ b/src/theory/quantifiers/term_database.cpp
@@ -111,20 +111,23 @@ Node TermDb::getOperator( Node n ) {
}
}
-void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant ){
+void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant, bool withinInstClosure ){
//don't add terms in quantifier bodies
if( withinQuant && !options::registerQuantBodyTerms() ){
return;
}
+ bool rec = false;
if( d_processed.find( n )==d_processed.end() ){
d_processed.insert(n);
+ if( withinInstClosure ){
+ d_iclosure_processed.insert( n );
+ }
d_type_map[ n.getType() ].push_back( n );
//if this is an atomic trigger, consider adding it
//Call the children?
if( inst::Trigger::isAtomicTrigger( n ) ){
if( !TermDb::hasInstConstAttr(n) ){
Trace("term-db") << "register term in db " << n << std::endl;
- //std::cout << "register trigger term " << n << std::endl;
Node op = getOperator( n );
/*
int occ = d_op_ccount[op];
@@ -138,9 +141,8 @@ void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant ){
d_op_map[op].push_back( n );
added.insert( n );
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- addTerm( n[i], added, withinQuant );
- if( options::eagerInstQuant() ){
+ if( options::eagerInstQuant() ){
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
if( !n.hasAttribute(InstLevelAttribute()) && n.getAttribute(InstLevelAttribute())==0 ){
int addedLemmas = 0;
for( size_t i=0; i<d_op_triggers[op].size(); i++ ){
@@ -150,10 +152,15 @@ void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant ){
}
}
}
- }else{
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- addTerm( n[i], added, withinQuant );
- }
+ }
+ rec = true;
+ }else if( withinInstClosure && d_iclosure_processed.find( n )==d_iclosure_processed.end() ){
+ d_iclosure_processed.insert( n );
+ rec = true;
+ }
+ if( rec ){
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ addTerm( n[i], added, withinQuant, withinInstClosure );
}
}
}
@@ -174,10 +181,12 @@ void TermDb::computeUfEqcTerms( TNode f ) {
eq::EqualityEngine * ee = d_quantEngine->getTheoryEngine()->getMasterEqualityEngine();
for( unsigned i=0; i<d_op_map[f].size(); i++ ){
TNode n = d_op_map[f][i];
- if( !n.getAttribute(NoMatchAttribute()) ){
- computeArgReps( n );
- TNode r = ee->hasTerm( n ) ? ee->getRepresentative( n ) : n;
- d_func_map_eqc_trie[f].d_data[r].addTerm( n, d_arg_reps[n] );
+ if( hasTermCurrent( n ) ){
+ if( !n.getAttribute(NoMatchAttribute()) ){
+ computeArgReps( n );
+ TNode r = ee->hasTerm( n ) ? ee->getRepresentative( n ) : n;
+ d_func_map_eqc_trie[f].d_data[r].addTerm( n, d_arg_reps[n] );
+ }
}
}
}
@@ -315,51 +324,162 @@ bool TermDb::isEntailed( TNode n, std::map< TNode, TNode >& subs, bool subsRep,
return false;
}
+bool TermDb::hasTermCurrent( Node n ) {
+ if( options::termDbInstClosure() && d_iclosure_processed.find( n )==d_iclosure_processed.end() ){
+ return false;
+ }else{
+ //return d_quantEngine->getMasterEqualityEngine()->hasTerm( n ); //some assertions are not sent to EE
+ if( options::termDbMode()==TERM_DB_ALL ){
+ return true;
+ }else if( options::termDbMode()==TERM_DB_RELEVANT ){
+ return d_has_map.find( n )!=d_has_map.end();
+ }else{
+ Assert( false );
+ return false;
+ }
+ }
+}
+
+Node TermDb::getHasTermEqc( Node r ) {
+ if( hasTermCurrent( r ) ){
+ return r;
+ }else{
+ if( options::termDbInstClosure() ){
+ std::map< Node, Node >::iterator it = d_has_eqc.find( r );
+ if( it==d_has_eqc.end() ){
+ Node h;
+ eq::EqualityEngine* ee = d_quantEngine->getMasterEqualityEngine();
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( r, ee );
+ while( h.isNull() && !eqc_i.isFinished() ){
+ TNode n = (*eqc_i);
+ ++eqc_i;
+ if( hasTermCurrent( n ) ){
+ h = n;
+ }
+ }
+ d_has_eqc[r] = h;
+ return h;
+ }else{
+ return it->second;
+ }
+ }else{
+ //if not using inst closure, then either all are relevant, or it is a singleton irrelevant eqc
+ return Node::null();
+ }
+ }
+}
+
+void TermDb::setHasTerm( Node n ) {
+ //if( inst::Trigger::isAtomicTrigger( n ) ){
+ if( d_has_map.find( n )==d_has_map.end() ){
+ d_has_map[n] = true;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ setHasTerm( n[i] );
+ }
+ }
+ /*
+ }else{
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ setHasTerm( n[i] );
+ }
+ }
+ */
+}
+
void TermDb::reset( Theory::Effort effort ){
- int nonCongruentCount = 0;
- int congruentCount = 0;
- int alreadyCongruentCount = 0;
- d_op_nonred_count.clear();
- d_arg_reps.clear();
- d_func_map_trie.clear();
- d_func_map_eqc_trie.clear();
- //rebuild d_func/pred_map_trie for each operation, this will calculate all congruent terms
- for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){
- d_op_nonred_count[ it->first ] = 0;
- if( !it->second.empty() ){
- for( unsigned i=0; i<it->second.size(); i++ ){
- Node n = it->second[i];
- computeModelBasisArgAttribute( n );
- if( !n.getAttribute(NoMatchAttribute()) ){
- computeArgReps( n );
- if( !d_func_map_trie[ it->first ].addTerm( n, d_arg_reps[n] ) ){
- NoMatchAttribute nma;
- n.setAttribute(nma,true);
- Debug("term-db-cong") << n << " is redundant." << std::endl;
- congruentCount++;
- }else{
- nonCongruentCount++;
- d_op_nonred_count[ it->first ]++;
- }
- }else{
- congruentCount++;
- alreadyCongruentCount++;
- }
- }
- }
- }
- Debug("term-db-cong") << "TermDb: Reset" << std::endl;
- Debug("term-db-cong") << "Congruent/Non-Congruent = ";
- Debug("term-db-cong") << congruentCount << "(" << alreadyCongruentCount << ") / " << nonCongruentCount << std::endl;
- if( Debug.isOn("term-db") ){
- Debug("term-db") << "functions : " << std::endl;
- for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){
- if( it->second.size()>0 ){
- Debug("term-db") << "- " << it->first << std::endl;
- d_func_map_trie[ it->first ].debugPrint("term-db", it->second[0]);
+ int nonCongruentCount = 0;
+ int congruentCount = 0;
+ int alreadyCongruentCount = 0;
+ int nonRelevantCount = 0;
+ d_op_nonred_count.clear();
+ d_arg_reps.clear();
+ d_func_map_trie.clear();
+ d_func_map_eqc_trie.clear();
+
+ //compute has map
+ if( options::termDbMode()==TERM_DB_RELEVANT ){
+ d_has_map.clear();
+ d_has_eqc.clear();
+ eq::EqualityEngine* ee = d_quantEngine->getMasterEqualityEngine();
+ eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );
+ while( !eqcs_i.isFinished() ){
+ TNode r = (*eqcs_i);
+ bool addedFirst = false;
+ Node first;
+ //TODO: ignoring singleton eqc isn't enough, need to ensure eqc are relevant
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( r, ee );
+ while( !eqc_i.isFinished() ){
+ TNode n = (*eqc_i);
+ if( first.isNull() ){
+ first = n;
+ }else{
+ if( !addedFirst ){
+ addedFirst = true;
+ setHasTerm( first );
+ }
+ setHasTerm( n );
+ }
+ ++eqc_i;
+ }
+ ++eqcs_i;
+ }
+ for (TheoryId theoryId = THEORY_FIRST; theoryId < THEORY_LAST; ++theoryId) {
+ Theory* theory = d_quantEngine->getTheoryEngine()->d_theoryTable[theoryId];
+ if (theory && d_quantEngine->getTheoryEngine()->d_logicInfo.isTheoryEnabled(theoryId)) {
+ context::CDList<Assertion>::const_iterator it = theory->facts_begin(), it_end = theory->facts_end();
+ for (unsigned i = 0; it != it_end; ++ it, ++i) {
+ Trace("ajr-temp") << "Set has term " << (*it).assertion << std::endl;
+ setHasTerm( (*it).assertion );
+ }
+ }
+ }
+ }
+
+
+ //rebuild d_func/pred_map_trie for each operation, this will calculate all congruent terms
+ for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){
+ d_op_nonred_count[ it->first ] = 0;
+ if( !it->second.empty() ){
+ for( unsigned i=0; i<it->second.size(); i++ ){
+ Node n = it->second[i];
+ if( hasTermCurrent( n ) ){
+ if( !n.getAttribute(NoMatchAttribute()) ){
+ if( options::finiteModelFind() ){
+ computeModelBasisArgAttribute( n );
+ }
+ computeArgReps( n );
+ if( !d_func_map_trie[ it->first ].addTerm( n, d_arg_reps[n] ) ){
+ NoMatchAttribute nma;
+ n.setAttribute(nma,true);
+ Trace("term-db-stats-debug") << n << " is redundant." << std::endl;
+ congruentCount++;
+ }else{
+ nonCongruentCount++;
+ d_op_nonred_count[ it->first ]++;
+ }
+ }else{
+ congruentCount++;
+ alreadyCongruentCount++;
+ }
+ }else{
+ Trace("term-db-stats-debug") << n << " is not relevant." << std::endl;
+ nonRelevantCount++;
}
}
- }
+ }
+ }
+ Trace("term-db-stats") << "TermDb: Reset" << std::endl;
+ Trace("term-db-stats") << "Non-Congruent/Congruent/Non-Relevant = ";
+ Trace("term-db-stats") << nonCongruentCount << " / " << congruentCount << " (" << alreadyCongruentCount << ") / " << nonRelevantCount << std::endl;
+ if( Debug.isOn("term-db") ){
+ Debug("term-db") << "functions : " << std::endl;
+ for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){
+ if( it->second.size()>0 ){
+ Debug("term-db") << "- " << it->first << std::endl;
+ d_func_map_trie[ it->first ].debugPrint("term-db", it->second[0]);
+ }
+ }
+ }
}
TermArgTrie * TermDb::getTermArgTrie( Node f ) {
@@ -773,45 +893,35 @@ Node TermDb::getEnumerateTerm( TypeNode tn, unsigned index ) {
Node TermDb::getFreeVariableForInstConstant( Node n ){
- TypeNode tn = n.getType();
+ return getFreeVariableForType( n.getType() );
+}
+
+Node TermDb::getFreeVariableForType( TypeNode tn ) {
if( d_free_vars.find( tn )==d_free_vars.end() ){
- for( unsigned i=0; i<d_type_map[ tn ].size(); i++ ){
- if( !quantifiers::TermDb::hasInstConstAttr(d_type_map[ tn ][ i ]) ){
- d_free_vars[tn] = d_type_map[ tn ][ i ];
- }
- }
- if( d_free_vars.find( tn )==d_free_vars.end() ){
+ for( unsigned i=0; i<d_type_map[ tn ].size(); i++ ){
+ if( !quantifiers::TermDb::hasInstConstAttr(d_type_map[ tn ][ i ]) ){
+ d_free_vars[tn] = d_type_map[ tn ][ i ];
+ }
+ }
+ if( d_free_vars.find( tn )==d_free_vars.end() ){
//if integer or real, make zero
if( tn.isInteger() || tn.isReal() ){
Rational z(0);
d_free_vars[tn] = NodeManager::currentNM()->mkConst( z );
}else{
- d_free_vars[tn] = NodeManager::currentNM()->mkSkolem( "freevar", tn, "is a free variable created by termdb" );
- Trace("mkVar") << "FreeVar:: Make variable " << d_free_vars[tn] << " : " << tn << std::endl;
+ Node n = NodeManager::currentNM()->mkSkolem( "freevar", tn, "is a free variable created by termdb" );
+ d_free_vars[tn] = n;
+ Trace("mkVar") << "FreeVar:: Make variable " << n << " : " << tn << std::endl;
+ //must set instantiation level attribute to 0 if we are using instantiation max level
+ if( options::instMaxLevel()!=-1 ){
+ QuantifiersEngine::setInstantiationLevelAttr( n, 0 );
+ }
}
}
}
return d_free_vars[tn];
}
-const std::vector<Node> & TermDb::getParents(TNode n, TNode f, int arg){
- std::hash_map< Node, std::hash_map< Node, std::hash_map< int, std::vector< Node > >,NodeHashFunction >,NodeHashFunction >::const_iterator
- rn = d_parents.find( n );
- if( rn !=d_parents.end() ){
- std::hash_map< Node, std::hash_map< int, std::vector< Node > > , NodeHashFunction > ::const_iterator
- rf = rn->second.find(f);
- if( rf != rn->second.end() ){
- std::hash_map< int, std::vector< Node > > ::const_iterator
- ra = rf->second.find(arg);
- if( ra != rf->second.end() ){
- return ra->second;
- }
- }
- }
- static std::vector<Node> empty;
- return empty;
-}
-
void TermDb::computeVarContains( Node n ) {
if( d_var_contains.find( n )==d_var_contains.end() ){
d_var_contains[n].clear();
@@ -1000,6 +1110,19 @@ Node TermDb::getRewriteRule( Node q ) {
}
}
+bool TermDb::isFunDef( Node q ) {
+ if( q.getKind()==FORALL && ( q[1].getKind()==EQUAL || q[1].getKind()==IFF ) && q[1][0].getKind()==APPLY_UF && q.getNumChildren()==3 ){
+ for( unsigned i=0; i<q[2].getNumChildren(); i++ ){
+ if( q[2][i].getKind()==INST_ATTRIBUTE ){
+ if( q[2][i][0].getAttribute(FunDefAttribute()) ){
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
void TermDb::computeAttributes( Node q ) {
if( q.getNumChildren()==3 ){
@@ -1015,6 +1138,18 @@ void TermDb::computeAttributes( Node q ) {
Trace("quant-attr") << "Attribute : conjecture : " << q << std::endl;
d_qattr_conjecture[q] = true;
}
+ if( avar.getAttribute(FunDefAttribute()) ){
+ Trace("quant-attr") << "Attribute : function definition : " << q << std::endl;
+ d_qattr_fundef[q] = true;
+ Assert( q[1].getKind()==EQUAL || q[1].getKind()==IFF );
+ Assert( q[1][0].getKind()==APPLY_UF );
+ Node f = q[1][0].getOperator();
+ if( d_fun_defs.find( f )!=d_fun_defs.end() ){
+ Message() << "Cannot define function " << f << " more than once." << std::endl;
+ exit( 0 );
+ }
+ d_fun_defs[f] = true;
+ }
if( avar.getAttribute(SygusAttribute()) ){
//should be nested existential
Assert( q[1].getKind()==NOT );
@@ -1074,6 +1209,15 @@ bool TermDb::isQAttrAxiom( Node q ) {
}
}
+bool TermDb::isQAttrFunDef( Node q ) {
+ std::map< Node, bool >::iterator it = d_qattr_fundef.find( q );
+ if( it==d_qattr_fundef.end() ){
+ return false;
+ }else{
+ return it->second;
+ }
+}
+
bool TermDb::isQAttrSygus( Node q ) {
std::map< Node, bool >::iterator it = d_qattr_sygus.find( q );
if( it==d_qattr_sygus.end() ){
diff --git a/src/theory/quantifiers/term_database.h b/src/theory/quantifiers/term_database.h
index 25ef9c81c..cb9f5eeef 100644
--- a/src/theory/quantifiers/term_database.h
+++ b/src/theory/quantifiers/term_database.h
@@ -34,6 +34,10 @@ typedef expr::Attribute< AxiomAttributeId, bool > AxiomAttribute;
struct ConjectureAttributeId {};
typedef expr::Attribute< ConjectureAttributeId, bool > ConjectureAttribute;
+/** Attribute true for function definition quantifiers */
+struct FunDefAttributeId {};
+typedef expr::Attribute< FunDefAttributeId, bool > FunDefAttribute;
+
/** Attribute true for quantifiers that are SyGus conjectures */
struct SygusAttributeId {};
typedef expr::Attribute< SygusAttributeId, bool > SygusAttribute;
@@ -119,11 +123,15 @@ private:
QuantifiersEngine* d_quantEngine;
/** terms processed */
std::hash_set< Node, NodeHashFunction > d_processed;
+ /** terms processed */
+ std::hash_set< Node, NodeHashFunction > d_iclosure_processed;
private:
/** select op map */
std::map< Node, std::map< TypeNode, Node > > d_par_op_map;
/** count number of ground terms per operator (user-context dependent) */
NodeIntMap d_op_ccount;
+ /** set has term */
+ void setHasTerm( Node n );
public:
TermDb( context::Context* c, context::UserContext* u, QuantifiersEngine* qe );
~TermDb(){}
@@ -136,6 +144,10 @@ public:
std::map< Node, int > d_op_nonred_count;
/** map from APPLY_UF operators to ground terms for that operator */
std::map< Node, std::vector< Node > > d_op_map;
+ /** has map */
+ std::map< Node, bool > d_has_map;
+ /** map from reps to a term in eqc in d_has_map */
+ std::map< Node, Node > d_has_eqc;
/** map from APPLY_UF functions to trie */
std::map< Node, TermArgTrie > d_func_map_trie;
std::map< Node, TermArgTrie > d_func_map_eqc_trie;
@@ -144,7 +156,7 @@ public:
/** map from type nodes to terms of that type */
std::map< TypeNode, std::vector< Node > > d_type_map;
/** add a term to the database */
- void addTerm( Node n, std::set< Node >& added, bool withinQuant = false );
+ void addTerm( Node n, std::set< Node >& added, bool withinQuant = false, bool withinInstClosure = false );
/** reset (calculate which terms are active) */
void reset( Theory::Effort effort );
/** get operator*/
@@ -166,17 +178,11 @@ public:
TNode evaluateTerm( TNode n );
/** is entailed (incomplete check) */
bool isEntailed( TNode n, std::map< TNode, TNode >& subs, bool subsRep, bool pol );
-public:
- /** parent structure (for efficient E-matching):
- n -> op -> index -> L
- map from node "n" to a list of nodes "L", where each node n' in L
- has operator "op", and n'["index"] = n.
- for example, d_parents[n][f][1] = { f( t1, n ), f( t2, n ), ... }
- */
- /* Todo replace int by size_t */
- std::hash_map< Node, std::hash_map< Node, std::hash_map< int, std::vector< Node > >, NodeHashFunction > , NodeHashFunction > d_parents;
- const std::vector<Node> & getParents(TNode n, TNode f, int arg);
-
+ /** has term */
+ bool hasTermCurrent( Node n );
+ /** get has term eqc */
+ Node getHasTermEqc( Node r );
+
//for model basis
private:
//map from types to model basis terms
@@ -279,6 +285,8 @@ public:
public:
/** get free variable for instantiation constant */
Node getFreeVariableForInstConstant( Node n );
+ /** get free variable for type */
+ Node getFreeVariableForType( TypeNode tn );
//for triggers
private:
@@ -306,17 +314,20 @@ public:
/** filter all nodes that have instances */
void filterInstances( std::vector< Node >& nodes );
-
+private:
+ std::map< Node, bool > d_fun_defs;
public: //general queries concerning quantified formulas wrt modules
/** is quantifier treated as a rewrite rule? */
static bool isRewriteRule( Node q );
/** get the rewrite rule associated with the quanfied formula */
static Node getRewriteRule( Node q );
-
+ /** is fun def */
+ static bool isFunDef( Node q );
//attributes
private:
std::map< Node, bool > d_qattr_conjecture;
std::map< Node, bool > d_qattr_axiom;
+ std::map< Node, bool > d_qattr_fundef;
std::map< Node, bool > d_qattr_sygus;
std::map< Node, bool > d_qattr_synthesis;
std::map< Node, int > d_qattr_rr_priority;
@@ -328,6 +339,8 @@ public:
bool isQAttrConjecture( Node q );
/** is axiom */
bool isQAttrAxiom( Node q );
+ /** is function definition */
+ bool isQAttrFunDef( Node q );
/** is sygus conjecture */
bool isQAttrSygus( Node q );
/** is synthesis conjecture */
diff --git a/src/theory/quantifiers/theory_quantifiers.cpp b/src/theory/quantifiers/theory_quantifiers.cpp
index f7c4c745f..de0f98af6 100644
--- a/src/theory/quantifiers/theory_quantifiers.cpp
+++ b/src/theory/quantifiers/theory_quantifiers.cpp
@@ -35,13 +35,13 @@ using namespace CVC4::theory::quantifiers;
TheoryQuantifiers::TheoryQuantifiers(Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo) :
Theory(THEORY_QUANTIFIERS, c, u, out, valuation, logicInfo),
- d_numRestarts(0),
d_masterEqualityEngine(0)
{
d_numInstantiations = 0;
d_baseDecLevel = -1;
out.handleUserAttribute( "axiom", this );
out.handleUserAttribute( "conjecture", this );
+ out.handleUserAttribute( "fun-def", this );
out.handleUserAttribute( "sygus", this );
out.handleUserAttribute( "synthesis", this );
out.handleUserAttribute( "quant-inst-max-level", this );
@@ -96,6 +96,10 @@ Node TheoryQuantifiers::getValue(TNode n) {
}
}
+void TheoryQuantifiers::computeCareGraph() {
+ //do nothing
+}
+
void TheoryQuantifiers::collectModelInfo(TheoryModel* m, bool fullModel) {
if(fullModel) {
for(assertions_iterator i = facts_begin(); i != facts_end(); ++i) {
@@ -115,7 +119,7 @@ void TheoryQuantifiers::check(Effort e) {
return;
}
- CodeTimer codeTimer(d_theoryTime);
+ TimerStat::CodeTimer checkTimer(d_checkTime);
Trace("quantifiers-check") << "quantifiers::check(" << e << ")" << std::endl;
while(!done()) {
@@ -125,12 +129,22 @@ void TheoryQuantifiers::check(Effort e) {
case kind::FORALL:
assertUniversal( assertion );
break;
+ case kind::INST_CLOSURE:
+ getQuantifiersEngine()->addTermToDatabase( assertion[0], false, true );
+ break;
+ case kind::EQUAL:
+ //do nothing
+ break;
case kind::NOT:
{
switch( assertion[0].getKind()) {
case kind::FORALL:
assertExistential( assertion );
break;
+ case kind::EQUAL:
+ //do nothing
+ break;
+ case kind::INST_CLOSURE: //cannot negate inst closure
default:
Unhandled(assertion[0].getKind());
break;
@@ -147,7 +161,6 @@ void TheoryQuantifiers::check(Effort e) {
}
void TheoryQuantifiers::propagate(Effort level){
- //CodeTimer codeTimer(d_theoryTime);
//getQuantifiersEngine()->propagate( level );
}
@@ -182,23 +195,7 @@ bool TheoryQuantifiers::flipDecision(){
//}else{
// return false;
//}
-
- if( !d_out->flipDecision() ){
- return restart();
- }
- return true;
-}
-
-bool TheoryQuantifiers::restart(){
- static const int restartLimit = 0;
- if( d_numRestarts==restartLimit ){
- Debug("quantifiers-flip") << "No more restarts." << std::endl;
- return false;
- }else{
- d_numRestarts++;
- Debug("quantifiers-flip") << "Do restart." << std::endl;
- return true;
- }
+ return false;
}
void TheoryQuantifiers::setUserAttribute(const std::string& attr, Node n, std::vector<Node> node_values, std::string str_value){
diff --git a/src/theory/quantifiers/theory_quantifiers.h b/src/theory/quantifiers/theory_quantifiers.h
index 6febc8417..6d3fa4d46 100644
--- a/src/theory/quantifiers/theory_quantifiers.h
+++ b/src/theory/quantifiers/theory_quantifiers.h
@@ -44,19 +44,15 @@ private:
/** number of instantiations */
int d_numInstantiations;
int d_baseDecLevel;
- /** number of restarts */
- int d_numRestarts;
-
- KEEP_STATISTIC(TimerStat, d_theoryTime, "theory::quantifiers::theoryTime");
eq::EqualityEngine* d_masterEqualityEngine;
-
+private:
+ void computeCareGraph();
public:
TheoryQuantifiers(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo);
~TheoryQuantifiers();
void setMasterEqualityEngine(eq::EqualityEngine* eq);
-
void addSharedTerm(TNode t);
void notifyEq(TNode lhs, TNode rhs);
void preRegisterTerm(TNode n);
@@ -75,7 +71,6 @@ public:
private:
void assertUniversal( Node n );
void assertExistential( Node n );
- bool restart();
};/* class TheoryQuantifiers */
}/* CVC4::theory::quantifiers namespace */
diff --git a/src/theory/quantifiers/theory_quantifiers_type_rules.h b/src/theory/quantifiers/theory_quantifiers_type_rules.h
index 5d86c29c0..341e656c7 100644
--- a/src/theory/quantifiers/theory_quantifiers_type_rules.h
+++ b/src/theory/quantifiers/theory_quantifiers_type_rules.h
@@ -84,6 +84,12 @@ struct QuantifierInstPatternTypeRule {
inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
throw(TypeCheckingExceptionPrivate) {
Assert(n.getKind() == kind::INST_PATTERN );
+ if( check ){
+ TypeNode tn = n[0].getType(check);
+ if( tn.isFunction() ){
+ throw TypeCheckingExceptionPrivate(n[0], "Pattern must be a list of fully-applied terms.");
+ }
+ }
return nodeManager->instPatternType();
}
};/* struct QuantifierInstPatternTypeRule */
@@ -120,6 +126,20 @@ struct QuantifierInstPatternListTypeRule {
};/* struct QuantifierInstPatternListTypeRule */
+struct QuantifierInstClosureTypeRule {
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw(TypeCheckingExceptionPrivate) {
+ Assert(n.getKind() == kind::INST_CLOSURE );
+ if( check ){
+ TypeNode tn = n[0].getType(check);
+ if( tn.isBoolean() ){
+ throw TypeCheckingExceptionPrivate(n, "argument of inst-closure must be non-boolean");
+ }
+ }
+ return nodeManager->booleanType();
+ }
+};/* struct QuantifierInstClosureTypeRule */
+
class RewriteRuleTypeRule {
public:
diff --git a/src/theory/quantifiers/trigger.cpp b/src/theory/quantifiers/trigger.cpp
index b2b8e7197..65b976b4a 100644
--- a/src/theory/quantifiers/trigger.cpp
+++ b/src/theory/quantifiers/trigger.cpp
@@ -47,7 +47,7 @@ d_quantEngine( qe ), d_f( f ){
d_mg->setActiveAdd(true);
}
}else{
- d_mg = new InstMatchGeneratorMulti( f, d_nodes, qe, matchOption );
+ d_mg = new InstMatchGeneratorMulti( f, d_nodes, qe );
//d_mg = InstMatchGenerator::mkInstMatchGenerator( d_nodes, qe );
//d_mg->setActiveAdd();
}
@@ -385,6 +385,8 @@ bool Trigger::collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map<
}
}
+
+
bool Trigger::isBooleanTermTrigger( Node n ) {
if( n.getKind()==ITE ){
//check for boolean term converted to ITE
@@ -414,6 +416,38 @@ bool Trigger::isPureTheoryTrigger( Node n ) {
}
}
+bool Trigger::isLocalTheoryExt( Node n, std::vector< Node >& vars, std::vector< Node >& patTerms ) {
+ if( !n.getType().isBoolean() && n.getKind()==APPLY_UF ){
+ if( std::find( patTerms.begin(), patTerms.end(), n )==patTerms.end() ){
+ bool hasVar = false;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ if( n[i].getKind()==INST_CONSTANT ){
+ hasVar = true;
+ if( std::find( vars.begin(), vars.end(), n[i] )==vars.end() ){
+ vars.push_back( n[i] );
+ }else{
+ //do not allow duplicate variables
+ return false;
+ }
+ }else{
+ //do not allow nested function applications
+ return false;
+ }
+ }
+ if( hasVar ){
+ patTerms.push_back( n );
+ }
+ }
+ }else{
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ if( !isLocalTheoryExt( n[i], vars, patTerms ) ){
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
void Trigger::collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, std::vector< Node >& exclude, bool filterInst ){
std::map< Node, bool > patMap;
if( filterInst ){
diff --git a/src/theory/quantifiers/trigger.h b/src/theory/quantifiers/trigger.h
index 75ada4f83..28da9f959 100644
--- a/src/theory/quantifiers/trigger.h
+++ b/src/theory/quantifiers/trigger.h
@@ -111,6 +111,7 @@ public:
static bool isSimpleTrigger( Node n );
static bool isBooleanTermTrigger( Node n );
static bool isPureTheoryTrigger( Node n );
+ static bool isLocalTheoryExt( Node n, std::vector< Node >& vars, std::vector< Node >& patTerms );
/** return data structure for producing matches for this trigger. */
static InstMatchGenerator* getInstMatchGenerator( Node n );
static Node getInversionVariable( Node n );
diff --git a/src/theory/quantifiers_engine.cpp b/src/theory/quantifiers_engine.cpp
index 88b56b6bb..4dc8df09d 100644
--- a/src/theory/quantifiers_engine.cpp
+++ b/src/theory/quantifiers_engine.cpp
@@ -34,7 +34,6 @@
#include "theory/uf/options.h"
#include "theory/uf/theory_uf.h"
#include "theory/quantifiers/full_model_check.h"
-#include "theory/quantifiers/qinterval_builder.h"
#include "theory/quantifiers/ambqi_builder.h"
using namespace std;
@@ -91,8 +90,6 @@ d_lemmas_produced_c(u){
options::mbqiMode()==quantifiers::MBQI_FMC_INTERVAL || options::fmfBoundInt() ||
options::mbqiMode()==quantifiers::MBQI_TRUST ){
d_model = new quantifiers::fmcheck::FirstOrderModelFmc( this, c, "FirstOrderModelFmc" );
- }else if( options::mbqiMode()==quantifiers::MBQI_INTERVAL ){
- d_model = new quantifiers::FirstOrderModelQInt( this, c, "FirstOrderModelQInt" );
}else if( options::mbqiMode()==quantifiers::MBQI_ABS ){
d_model = new quantifiers::FirstOrderModelAbs( this, c, "FirstOrderModelAbs" );
}else{
@@ -163,15 +160,9 @@ d_lemmas_produced_c(u){
options::mbqiMode()==quantifiers::MBQI_TRUST || options::fmfBoundInt() ){
Trace("quant-engine-debug") << "...make fmc builder." << std::endl;
d_builder = new quantifiers::fmcheck::FullModelChecker( c, this );
- }else if( options::mbqiMode()==quantifiers::MBQI_INTERVAL ){
- Trace("quant-engine-debug") << "...make interval builder." << std::endl;
- d_builder = new quantifiers::QIntervalBuilder( c, this );
}else if( options::mbqiMode()==quantifiers::MBQI_ABS ){
Trace("quant-engine-debug") << "...make abs mbqi builder." << std::endl;
d_builder = new quantifiers::AbsMbqiBuilder( c, this );
- }else if( options::mbqiMode()==quantifiers::MBQI_INST_GEN ){
- Trace("quant-engine-debug") << "...make inst-gen builder." << std::endl;
- d_builder = new quantifiers::QModelBuilderInstGen( c, this );
}else{
Trace("quant-engine-debug") << "...make default model builder." << std::endl;
d_builder = new quantifiers::QModelBuilderDefault( c, this );
@@ -256,8 +247,13 @@ bool QuantifiersEngine::hasOwnership( Node q, QuantifiersModule * m ) {
void QuantifiersEngine::check( Theory::Effort e ){
CodeTimer codeTimer(d_time);
+ if( !getMasterEqualityEngine()->consistent() ){
+ Trace("quant-engine-debug") << "Master equality engine not consistent, return." << std::endl;
+ return;
+ }
bool needsCheck = false;
bool needsModel = false;
+ bool needsFullModel = false;
std::vector< QuantifiersModule* > qm;
if( d_model->getNumAssertedQuantifiers()>0 ){
needsCheck = e>=Theory::EFFORT_LAST_CALL; //always need to check at or above last call
@@ -267,6 +263,9 @@ void QuantifiersEngine::check( Theory::Effort e ){
needsCheck = true;
if( d_modules[i]->needsModel( e ) ){
needsModel = true;
+ if( d_modules[i]->needsFullModel( e ) ){
+ needsFullModel = true;
+ }
}
}
}
@@ -285,10 +284,6 @@ void QuantifiersEngine::check( Theory::Effort e ){
Trace("quant-engine-ee") << "Equality engine : " << std::endl;
debugPrintEqualityEngine( "quant-engine-ee" );
- if( !getMasterEqualityEngine()->consistent() ){
- Trace("quant-engine") << "Master equality engine not consistent, return." << std::endl;
- return;
- }
Trace("quant-engine-debug") << "Resetting all modules..." << std::endl;
//reset relevant information
d_conflict = false;
@@ -300,13 +295,15 @@ void QuantifiersEngine::check( Theory::Effort e ){
return;
}
+ Trace("quant-engine-debug2") << "Reset term db..." << std::endl;
d_term_db->reset( e );
d_eq_query->reset();
if( d_rel_dom ){
d_rel_dom->reset();
}
d_model->reset_round();
- for( int i=0; i<(int)d_modules.size(); i++ ){
+ for( unsigned i=0; i<d_modules.size(); i++ ){
+ Trace("quant-engine-debug2") << "Reset " << d_modules[i]->identify().c_str() << std::endl;
d_modules[i]->reset_round( e );
}
Trace("quant-engine-debug") << "Done resetting all modules." << std::endl;
@@ -328,9 +325,9 @@ void QuantifiersEngine::check( Theory::Effort e ){
//build the model if any module requested it
if( quant_e==QEFFORT_MODEL && needsModel ){
Assert( d_builder!=NULL );
- Trace("quant-engine-debug") << "Build model, fullModel = " << d_builder->optBuildAtFullModel() << "..." << std::endl;
+ Trace("quant-engine-debug") << "Build model, fullModel = " << ( needsFullModel || d_builder->optBuildAtFullModel() ) << "..." << std::endl;
d_builder->d_addedLemmas = 0;
- d_builder->buildModel( d_model, d_builder->optBuildAtFullModel() );
+ d_builder->buildModel( d_model, needsFullModel || d_builder->optBuildAtFullModel() );
//we are done if model building was unsuccessful
if( d_builder->d_addedLemmas>0 ){
success = false;
@@ -338,7 +335,7 @@ void QuantifiersEngine::check( Theory::Effort e ){
}
if( success ){
//check each module
- for( int i=0; i<(int)qm.size(); i++ ){
+ for( unsigned i=0; i<qm.size(); i++ ){
Trace("quant-engine-debug") << "Check " << qm[i]->identify().c_str() << " at effort " << quant_e << "..." << std::endl;
qm[i]->check( e, quant_e );
}
@@ -349,7 +346,7 @@ void QuantifiersEngine::check( Theory::Effort e ){
if( d_hasAddedLemma ){
break;
//otherwise, complete the model generation if necessary
- }else if( quant_e==QEFFORT_MODEL && needsModel && options::produceModels() && !d_builder->optBuildAtFullModel() ){
+ }else if( quant_e==QEFFORT_MODEL && needsModel && options::produceModels() && !needsFullModel && !d_builder->optBuildAtFullModel() ){
Trace("quant-engine-debug") << "Build completed model..." << std::endl;
d_builder->buildModel( d_model, true );
}
@@ -475,9 +472,9 @@ Node QuantifiersEngine::getNextDecisionRequest(){
return Node::null();
}
-void QuantifiersEngine::addTermToDatabase( Node n, bool withinQuant ){
+void QuantifiersEngine::addTermToDatabase( Node n, bool withinQuant, bool withinInstClosure ){
std::set< Node > added;
- getTermDatabase()->addTerm( n, added, withinQuant );
+ getTermDatabase()->addTerm( n, added, withinQuant, withinInstClosure );
//maybe have triggered instantiations if we are doing eager instantiation
if( options::eagerInstQuant() ){
flushLemmas();
@@ -520,6 +517,7 @@ bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& vars, std
for( int i=0; i<(int)terms.size(); i++ ){
Trace("inst") << " " << terms[i];
Trace("inst") << std::endl;
+ Assert( terms[i].getType().isSubtypeOf( f[0][i].getType() ) );
}
if( options::cbqi() ){
for( int i=0; i<(int)terms.size(); i++ ){
@@ -671,6 +669,7 @@ Node QuantifiersEngine::getInstantiation( Node f, std::vector< Node >& terms ) {
return getInstantiation( f, d_term_db->d_inst_constants[f], terms );
}
+/*
bool QuantifiersEngine::existsInstantiation( Node f, InstMatch& m, bool modEq, bool modInst ){
if( options::incrementalSolving() ){
if( d_c_inst_match_trie.find( f )!=d_c_inst_match_trie.end() ){
@@ -691,6 +690,7 @@ bool QuantifiersEngine::existsInstantiation( Node f, InstMatch& m, bool modEq, b
}
return false;
}
+*/
bool QuantifiersEngine::addLemma( Node lem, bool doCache ){
if( doCache ){
diff --git a/src/theory/quantifiers_engine.h b/src/theory/quantifiers_engine.h
index 75b55ca4a..2b466b96b 100644
--- a/src/theory/quantifiers_engine.h
+++ b/src/theory/quantifiers_engine.h
@@ -55,6 +55,8 @@ public:
virtual bool needsCheck( Theory::Effort e ) { return e>=Theory::EFFORT_LAST_CALL; }
/* whether this module needs a model built */
virtual bool needsModel( Theory::Effort e ) { return false; }
+ /* whether this module needs a model built */
+ virtual bool needsFullModel( Theory::Effort e ) { return false; }
/* reset at a round */
virtual void reset_round( Theory::Effort e ){}
/* Call during quantifier engine's check */
@@ -254,7 +256,7 @@ public:
/** do substitution */
Node getSubstitute( Node n, std::vector< Node >& terms );
/** exist instantiation ? */
- bool existsInstantiation( Node f, InstMatch& m, bool modEq = true, bool modInst = false );
+ //bool existsInstantiation( Node f, InstMatch& m, bool modEq = true, bool modInst = false );
/** add lemma lem */
bool addLemma( Node lem, bool doCache = true );
/** add require phase */
@@ -288,7 +290,7 @@ public:
/** get trigger database */
inst::TriggerTrie* getTriggerDatabase() { return d_tr_trie; }
/** add term to database */
- void addTermToDatabase( Node n, bool withinQuant = false );
+ void addTermToDatabase( Node n, bool withinQuant = false, bool withinInstClosure = false );
/** get the master equality engine */
eq::EqualityEngine* getMasterEqualityEngine() ;
/** debug print equality engine */
diff --git a/src/theory/rep_set.cpp b/src/theory/rep_set.cpp
index ee14d6fc1..db0524034 100644
--- a/src/theory/rep_set.cpp
+++ b/src/theory/rep_set.cpp
@@ -28,6 +28,15 @@ void RepSet::clear(){
d_tmap.clear();
}
+bool RepSet::hasRep( TypeNode tn, Node n ) {
+ std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.find( tn );
+ if( it==d_type_reps.end() ){
+ return false;
+ }else{
+ return std::find( it->second.begin(), it->second.end(), n )!=it->second.end();
+ }
+}
+
int RepSet::getNumRepresentatives( TypeNode tn ) const{
std::map< TypeNode, std::vector< Node > >::const_iterator it = d_type_reps.find( tn );
if( it!=d_type_reps.end() ){
diff --git a/src/theory/rep_set.h b/src/theory/rep_set.h
index 23db36ead..19bb6d3d3 100644
--- a/src/theory/rep_set.h
+++ b/src/theory/rep_set.h
@@ -37,6 +37,8 @@ public:
void clear();
/** has type */
bool hasType( TypeNode tn ) const { return d_type_reps.find( tn )!=d_type_reps.end(); }
+ /** has rep */
+ bool hasRep( TypeNode tn, Node n );
/** get cardinality for type */
int getNumRepresentatives( TypeNode tn ) const;
/** add representative for type */
diff --git a/src/theory/rewriter.cpp b/src/theory/rewriter.cpp
index 960602846..a940bcc3d 100644
--- a/src/theory/rewriter.cpp
+++ b/src/theory/rewriter.cpp
@@ -18,12 +18,16 @@
#include "theory/theory.h"
#include "theory/rewriter.h"
#include "theory/rewriter_tables.h"
+#include "smt/smt_engine_scope.h"
+#include "util/resource_manager.h"
using namespace std;
namespace CVC4 {
namespace theory {
+unsigned long Rewriter::d_iterationCount = 0;
+
static TheoryId theoryOf(TNode node) {
return Theory::theoryOf(THEORY_OF_TYPE_BASED, node);
}
@@ -76,7 +80,7 @@ struct RewriteStackElement {
}
};
-Node Rewriter::rewrite(TNode node) {
+Node Rewriter::rewrite(TNode node) throw (UnsafeInterruptException){
return rewriteTo(theoryOf(node), node);
}
@@ -102,9 +106,20 @@ Node Rewriter::rewriteTo(theory::TheoryId theoryId, Node node) {
vector<RewriteStackElement> rewriteStack;
rewriteStack.push_back(RewriteStackElement(node, theoryId));
+ ResourceManager* rm = NULL;
+ bool hasSmtEngine = smt::smtEngineInScope();
+ if (hasSmtEngine) {
+ rm = NodeManager::currentResourceManager();
+ }
// Rewrite until the stack is empty
for (;;){
+ if (hasSmtEngine &&
+ d_iterationCount % ResourceManager::getFrequencyCount() == 0) {
+ rm->spendResource();
+ d_iterationCount = 0;
+ }
+
// Get the top of the recursion stack
RewriteStackElement& rewriteStackTop = rewriteStack.back();
@@ -139,7 +154,7 @@ Node Rewriter::rewriteTo(theory::TheoryId theoryId, Node node) {
rewriteStackTop.theoryId = theoryOf(cached);
}
}
-
+
rewriteStackTop.original =rewriteStackTop.node;
// Now it's time to rewrite the children, check if this has already been done
Node cached = Rewriter::getPostRewriteCache((TheoryId) rewriteStackTop.theoryId, rewriteStackTop.node);
@@ -233,5 +248,15 @@ Node Rewriter::rewriteTo(theory::TheoryId theoryId, Node node) {
return Node::null();
}/* Rewriter::rewriteTo() */
+void Rewriter::clearCaches() {
+#ifdef CVC4_ASSERTIONS
+ if(s_rewriteStack != NULL) {
+ delete s_rewriteStack;
+ s_rewriteStack = NULL;
+ }
+#endif
+ Rewriter::clearCachesInternal();
+}
+
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/rewriter.h b/src/theory/rewriter.h
index b150b186a..44035e7d9 100644
--- a/src/theory/rewriter.h
+++ b/src/theory/rewriter.h
@@ -19,6 +19,8 @@
#pragma once
#include "expr/node.h"
+#include "util/unsafe_interrupt_exception.h"
+
//#include "expr/attribute.h"
namespace CVC4 {
@@ -56,7 +58,7 @@ class RewriterInitializer;
class Rewriter {
friend class RewriterInitializer;
-
+ static unsigned long d_iterationCount;
/** Returns the appropriate cache for a node */
static Node getPreRewriteCache(theory::TheoryId theoryId, TNode node);
@@ -100,20 +102,19 @@ class Rewriter {
* Should be called to clean up any state.
*/
static void shutdown();
-
+ static void clearCachesInternal();
public:
/**
* Rewrites the node using theoryOf() to determine which rewriter to
* use on the node.
*/
- static Node rewrite(TNode node);
+ static Node rewrite(TNode node) throw (UnsafeInterruptException);
/**
* Garbage collects the rewrite caches.
*/
- static void garbageCollect();
-
+ static void clearCaches();
};/* class Rewriter */
}/* CVC4::theory namespace */
diff --git a/src/theory/rewriter_tables_template.h b/src/theory/rewriter_tables_template.h
index 9b51d2b32..d79f464b5 100644
--- a/src/theory/rewriter_tables_template.h
+++ b/src/theory/rewriter_tables_template.h
@@ -85,7 +85,7 @@ void Rewriter::shutdown() {
${rewrite_shutdown}
}
-void Rewriter::garbageCollect() {
+void Rewriter::clearCachesInternal() {
typedef CVC4::expr::attr::AttributeUniqueId AttributeUniqueId;
std::vector<AttributeUniqueId> preids;
${pre_rewrite_attribute_ids}
diff --git a/src/theory/sets/normal_form.h b/src/theory/sets/normal_form.h
index bc34ea6f1..13da6d57e 100644
--- a/src/theory/sets/normal_form.h
+++ b/src/theory/sets/normal_form.h
@@ -26,7 +26,8 @@ namespace sets {
class NormalForm {
public:
- static Node elementsToSet(std::set<TNode> elements, TypeNode setType)
+ template<bool ref_count>
+ static Node elementsToSet(std::set<NodeTemplate<ref_count> > elements, TypeNode setType)
{
NodeManager* nm = NodeManager::currentNM();
@@ -43,6 +44,63 @@ public:
}
}
+ static bool checkNormalConstant(TNode n) {
+ Debug("sets-checknormal") << "[sets-checknormal] checkNormal " << n << " :" << std::endl;
+ if(n.getKind() == kind::EMPTYSET) {
+ return true;
+ } else if(n.getKind() == kind::SINGLETON) {
+ return n[0].isConst();
+ } else if(n.getKind() == kind::UNION) {
+
+ // assuming (union ... (union {SmallestNodeID} {BiggerNodeId}) ... {BiggestNodeId})
+
+ // store BiggestNodeId in prvs
+ if(n[1].getKind() != kind::SINGLETON) return false;
+ if( !n[1][0].isConst() ) return false;
+ Debug("sets-checknormal") << "[sets-checknormal] frst element = " << n[1][0] << " " << n[1][0].getId() << std::endl;
+ TNode prvs = n[1][0];
+ n = n[0];
+
+ // check intermediate nodes
+ while(n.getKind() == kind::UNION) {
+ if(n[1].getKind() != kind::SINGLETON) return false;
+ if( !n[1].isConst() ) return false;
+ Debug("sets-checknormal") << "[sets-checknormal] element = " << n[1][0] << " " << n[1][0].getId() << std::endl;
+ if( n[1][0] >= prvs ) return false;
+ TNode prvs = n[1][0];
+ n = n[0];
+ }
+
+ // check SmallestNodeID is smallest
+ if(n.getKind() != kind::SINGLETON) return false;
+ if( !n[0].isConst() ) return false;
+ Debug("sets-checknormal") << "[sets-checknormal] lst element = " << n[0] << " " << n[0].getId() << std::endl;
+ if( n[0] >= prvs ) return false;
+
+ // we made it
+ return true;
+
+ } else {
+ return false;
+ }
+ }
+
+ static std::set<Node> getElementsFromNormalConstant(TNode n) {
+ Assert(n.isConst());
+ std::set<Node> ret;
+ if(n.getKind() == kind::EMPTYSET) {
+ return ret;
+ }
+ while(n.getKind() == kind::UNION) {
+ Assert(n[1].getKind() == kind::SINGLETON);
+ ret.insert(ret.begin(), n[1][0]);
+ n = n[0];
+ }
+ Assert(n.getKind() == kind::SINGLETON);
+ ret.insert(n[0]);
+ return ret;
+ }
+
};
}
diff --git a/src/theory/sets/theory_sets.cpp b/src/theory/sets/theory_sets.cpp
index 106ad6e56..db93c597c 100644
--- a/src/theory/sets/theory_sets.cpp
+++ b/src/theory/sets/theory_sets.cpp
@@ -42,6 +42,7 @@ void TheorySets::check(Effort e) {
if (done() && !fullEffort(e)) {
return;
}
+ TimerStat::CodeTimer checkTimer(d_checkTime);
d_internal->check(e);
}
diff --git a/src/theory/sets/theory_sets_private.cpp b/src/theory/sets/theory_sets_private.cpp
index 57b761500..e229d3a6f 100644
--- a/src/theory/sets/theory_sets_private.cpp
+++ b/src/theory/sets/theory_sets_private.cpp
@@ -42,8 +42,6 @@ const char* element_of_str = " \u2208 ";
void TheorySetsPrivate::check(Theory::Effort level) {
- CodeTimer checkCodeTimer(d_statistics.d_checkTime);
-
while(!d_external.done() && !d_conflict) {
// Get all the assertions
Assertion assertion = d_external.get();
@@ -734,7 +732,7 @@ Node TheorySetsPrivate::elementsToShape(Elements elements, TypeNode setType) con
NodeManager* nm = NodeManager::currentNM();
if(elements.size() == 0) {
- return nm->mkConst(EmptySet(nm->toType(setType)));
+ return nm->mkConst<EmptySet>(EmptySet(nm->toType(setType)));
} else {
Elements::iterator it = elements.begin();
Node cur = SINGLETON(*it);
@@ -749,7 +747,7 @@ Node TheorySetsPrivate::elementsToShape(set<Node> elements, TypeNode setType) co
NodeManager* nm = NodeManager::currentNM();
if(elements.size() == 0) {
- return nm->mkConst(EmptySet(nm->toType(setType)));
+ return nm->mkConst<EmptySet>(EmptySet(nm->toType(setType)));
} else {
typeof(elements.begin()) it = elements.begin();
Node cur = SINGLETON(*it);
@@ -767,18 +765,20 @@ void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel)
set<Node> terms;
+ if(Trace.isOn("sets-assertions")) {
+ dumpAssertionsHumanified();
+ }
+
// Compute terms appearing assertions and shared terms
d_external.computeRelevantTerms(terms);
// Compute for each setterm elements that it contains
SettermElementsMap settermElementsMap;
- TNode true_atom = NodeManager::currentNM()->mkConst<bool>(true);
- TNode false_atom = NodeManager::currentNM()->mkConst<bool>(false);
- for(eq::EqClassIterator it_eqclasses(true_atom, &d_equalityEngine);
+ for(eq::EqClassIterator it_eqclasses(d_trueNode, &d_equalityEngine);
! it_eqclasses.isFinished() ; ++it_eqclasses) {
TNode n = (*it_eqclasses);
if(n.getKind() == kind::MEMBER) {
- Assert(d_equalityEngine.areEqual(n, true_atom));
+ Assert(d_equalityEngine.areEqual(n, d_trueNode));
TNode x = d_equalityEngine.getRepresentative(n[0]);
TNode S = d_equalityEngine.getRepresentative(n[1]);
settermElementsMap[S].insert(x);
@@ -795,7 +795,7 @@ void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel)
}
if(Debug.isOn("sets-model-details")) {
- for(eq::EqClassIterator it_eqclasses(false_atom, &d_equalityEngine);
+ for(eq::EqClassIterator it_eqclasses(d_trueNode, &d_equalityEngine);
! it_eqclasses.isFinished() ; ++it_eqclasses) {
TNode n = (*it_eqclasses);
vector<TNode> explanation;
@@ -856,8 +856,8 @@ void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel)
checkPassed &= checkModel(settermElementsMap, term);
}
}
- if(Debug.isOn("sets-checkmodel-ignore")) {
- Debug("sets-checkmodel-ignore") << "[sets-checkmodel-ignore] checkPassed value was " << checkPassed << std::endl;
+ if(Trace.isOn("sets-checkmodel-ignore")) {
+ Trace("sets-checkmodel-ignore") << "[sets-checkmodel-ignore] checkPassed value was " << checkPassed << std::endl;
} else {
Assert( checkPassed,
"THEORY_SETS check-model failed. Run with -d sets-model for details." );
@@ -916,12 +916,10 @@ Node mkAnd(const std::vector<TNode>& conjunctions) {
TheorySetsPrivate::Statistics::Statistics() :
- d_checkTime("theory::sets::time")
- , d_getModelValueTime("theory::sets::getModelValueTime")
+ d_getModelValueTime("theory::sets::getModelValueTime")
, d_memberLemmas("theory::sets::lemmas::member", 0)
, d_disequalityLemmas("theory::sets::lemmas::disequality", 0)
{
- StatisticsRegistry::registerStat(&d_checkTime);
StatisticsRegistry::registerStat(&d_getModelValueTime);
StatisticsRegistry::registerStat(&d_memberLemmas);
StatisticsRegistry::registerStat(&d_disequalityLemmas);
@@ -929,7 +927,6 @@ TheorySetsPrivate::Statistics::Statistics() :
TheorySetsPrivate::Statistics::~Statistics() {
- StatisticsRegistry::unregisterStat(&d_checkTime);
StatisticsRegistry::unregisterStat(&d_getModelValueTime);
StatisticsRegistry::unregisterStat(&d_memberLemmas);
StatisticsRegistry::unregisterStat(&d_disequalityLemmas);
@@ -942,7 +939,7 @@ bool TheorySetsPrivate::present(TNode atom) {
bool TheorySetsPrivate::holds(TNode atom, bool polarity) {
- Node polarity_atom = NodeManager::currentNM()->mkConst<bool>(polarity);
+ TNode polarity_atom = polarity ? d_trueNode : d_falseNode;
Node atomModEq = NodeManager::currentNM()->mkNode
(atom.getKind(), d_equalityEngine.getRepresentative(atom[0]),
@@ -998,21 +995,44 @@ void TheorySetsPrivate::finishPropagation()
void TheorySetsPrivate::addToPending(Node n) {
Debug("sets-pending") << "[sets-pending] addToPending " << n << std::endl;
- if(d_pendingEverInserted.find(n) == d_pendingEverInserted.end()) {
- if(n.getKind() == kind::MEMBER) {
- Debug("sets-pending") << "[sets-pending] \u2514 added to member queue"
- << std::endl;
- ++d_statistics.d_memberLemmas;
- d_pending.push(n);
- } else {
- Debug("sets-pending") << "[sets-pending] \u2514 added to equality queue"
- << std::endl;
- Assert(n.getKind() == kind::EQUAL);
- ++d_statistics.d_disequalityLemmas;
- d_pendingDisequal.push(n);
+
+ if(d_pendingEverInserted.find(n) != d_pendingEverInserted.end()) {
+ Debug("sets-pending") << "[sets-pending] \u2514 skipping " << n
+ << " as lemma already generated." << std::endl;
+ return;
+ }
+
+ if(n.getKind() == kind::MEMBER) {
+
+ Node nRewritten = theory::Rewriter::rewrite(n);
+
+ if(nRewritten.isConst()) {
+ Debug("sets-pending") << "[sets-pending] \u2514 skipping " << n
+ << " as we can learn one of the sides." << std::endl;
+ Assert(nRewritten == d_trueNode || nRewritten == d_falseNode);
+
+ bool polarity = (nRewritten == d_trueNode);
+ learnLiteral(n, polarity, d_trueNode);
+ return;
}
- d_external.d_out->lemma(getLemma());
+
+ Debug("sets-pending") << "[sets-pending] \u2514 added to member queue"
+ << std::endl;
+ ++d_statistics.d_memberLemmas;
+ d_pending.push(n);
+ d_external.d_out->splitLemma(getLemma());
Assert(isComplete());
+
+ } else {
+
+ Debug("sets-pending") << "[sets-pending] \u2514 added to equality queue"
+ << std::endl;
+ Assert(n.getKind() == kind::EQUAL);
+ ++d_statistics.d_disequalityLemmas;
+ d_pendingDisequal.push(n);
+ d_external.d_out->splitLemma(getLemma());
+ Assert(isComplete());
+
}
}
@@ -1047,13 +1067,15 @@ Node TheorySetsPrivate::getLemma() {
d_pendingEverInserted.insert(n);
Assert(n.getKind() == kind::EQUAL && n[0].getType().isSet());
- Node x = NodeManager::currentNM()->mkSkolem("sde_", n[0].getType().getSetElementType() );
+ TypeNode elementType = n[0].getType().getSetElementType();
+ Node x = NodeManager::currentNM()->mkSkolem("sde_", elementType);
Node l1 = MEMBER(x, n[0]), l2 = MEMBER(x, n[1]);
lemma = OR(n, AND(l1, NOT(l2)), AND(NOT(l1), l2));
}
- Debug("sets-lemma") << "[sets-lemma] Generating for " << n << ", lemma: " << lemma << std::endl;
+ Debug("sets-lemma") << "[sets-lemma] Generating for " << n
+ << ", lemma: " << lemma << std::endl;
return lemma;
}
@@ -1065,6 +1087,8 @@ TheorySetsPrivate::TheorySetsPrivate(TheorySets& external,
d_external(external),
d_notify(*this),
d_equalityEngine(d_notify, c, "theory::sets::TheorySetsPrivate"),
+ d_trueNode(NodeManager::currentNM()->mkConst<bool>(true)),
+ d_falseNode(NodeManager::currentNM()->mkConst<bool>(false)),
d_conflict(c),
d_termInfoManager(NULL),
d_propagationQueue(c),
@@ -1114,7 +1138,7 @@ void TheorySetsPrivate::propagate(Theory::Effort effort) {
}
const CDNodeSet& terms = (d_termInfoManager->d_terms);
- for(typeof(terms.begin()) it = terms.begin(); it != terms.end(); ++it) {
+ for(typeof(terms.key_begin()) it = terms.key_begin(); it != terms.key_end(); ++it) {
Node node = (*it);
Kind k = node.getKind();
if(k == kind::UNION && node[0].getKind() == kind::SINGLETON ) {
@@ -1219,12 +1243,10 @@ void TheorySetsPrivate::preRegisterTerm(TNode node)
default:
d_termInfoManager->addTerm(node);
d_equalityEngine.addTriggerTerm(node, THEORY_SETS);
- // d_equalityEngine.addTerm(node);
}
+
if(node.getKind() == kind::SINGLETON) {
- Node true_node = NodeManager::currentNM()->mkConst<bool>(true);
- learnLiteral(MEMBER(node[0], node), true, true_node);
- //intentional fallthrough
+ learnLiteral(MEMBER(node[0], node), true, d_trueNode);
}
}
@@ -1361,25 +1383,40 @@ const CDTNodeList* TheorySetsPrivate::TermInfoManager::getNonMembers(TNode S) {
}
void TheorySetsPrivate::TermInfoManager::addTerm(TNode n) {
- unsigned numChild = n.getNumChildren();
+ if(d_terms.contains(n)) {
+ return;
+ }
+ d_terms.insert(n);
- if(!d_terms.contains(n)) {
- d_terms.insert(n);
- d_info[n] = new TheorySetsTermInfo(d_context);
+ if(d_info.find(n) == d_info.end()) {
+ d_info.insert(make_pair(n, new TheorySetsTermInfo(d_context)));
}
if(n.getKind() == kind::UNION ||
n.getKind() == kind::INTERSECTION ||
n.getKind() == kind::SETMINUS) {
+ unsigned numChild = n.getNumChildren();
+
for(unsigned i = 0; i < numChild; ++i) {
+ Assert(d_terms.contains(n[i]));
if(d_terms.contains(n[i])) {
Debug("sets-parent") << "Adding " << n << " to parent list of "
<< n[i] << std::endl;
d_info[n[i]]->parents->push_back(n);
+
+ typeof(d_info.begin()) ita = d_info.find(d_eqEngine->getRepresentative(n[i]));
+ Assert(ita != d_info.end());
+ CDTNodeList* l = (*ita).second->elementsNotInThisSet;
+ for(typeof(l->begin()) it = l->begin(); it != l->end(); ++it) {
+ d_theory.d_settermPropagationQueue.push_back( std::make_pair( (*it), n ) );
+ }
+ l = (*ita).second->elementsInThisSet;
+ for(typeof(l->begin()) it = l->begin(); it != l->end(); ++it) {
+ d_theory.d_settermPropagationQueue.push_back( std::make_pair( (*it), n ) );
+ }
}
}
-
}
}
diff --git a/src/theory/sets/theory_sets_private.h b/src/theory/sets/theory_sets_private.h
index 536987073..ad273c546 100644
--- a/src/theory/sets/theory_sets_private.h
+++ b/src/theory/sets/theory_sets_private.h
@@ -73,7 +73,6 @@ private:
class Statistics {
public:
- TimerStat d_checkTime;
TimerStat d_getModelValueTime;
IntStat d_memberLemmas;
IntStat d_disequalityLemmas;
@@ -101,6 +100,10 @@ private:
/** Equality engine */
eq::EqualityEngine d_equalityEngine;
+ /** True and false constant nodes */
+ Node d_trueNode;
+ Node d_falseNode;
+
context::CDO<bool> d_conflict;
Node d_conflictNode;
diff --git a/src/theory/sets/theory_sets_rewriter.cpp b/src/theory/sets/theory_sets_rewriter.cpp
index 226eca62b..635f9856a 100644
--- a/src/theory/sets/theory_sets_rewriter.cpp
+++ b/src/theory/sets/theory_sets_rewriter.cpp
@@ -26,9 +26,6 @@ typedef std::hash_map<TNode, Elements, TNodeHashFunction> SettermElementsMap;
bool checkConstantMembership(TNode elementTerm, TNode setTerm)
{
- // Assume from pre-rewrite constant sets look like the following:
- // (union (setenum bla) (union (setenum bla) ... (union (setenum bla) (setenum bla) ) ... ))
-
if(setTerm.getKind() == kind::EMPTYSET) {
return false;
}
@@ -40,25 +37,9 @@ bool checkConstantMembership(TNode elementTerm, TNode setTerm)
Assert(setTerm.getKind() == kind::UNION && setTerm[1].getKind() == kind::SINGLETON,
"kind was %d, term: %s", setTerm.getKind(), setTerm.toString().c_str());
- return elementTerm == setTerm[1][0] || checkConstantMembership(elementTerm, setTerm[0]);
-
- // switch(setTerm.getKind()) {
- // case kind::EMPTYSET:
- // return false;
- // case kind::SINGLETON:
- // return elementTerm == setTerm[0];
- // case kind::UNION:
- // return checkConstantMembership(elementTerm, setTerm[0]) ||
- // checkConstantMembership(elementTerm, setTerm[1]);
- // case kind::INTERSECTION:
- // return checkConstantMembership(elementTerm, setTerm[0]) &&
- // checkConstantMembership(elementTerm, setTerm[1]);
- // case kind::SETMINUS:
- // return checkConstantMembership(elementTerm, setTerm[0]) &&
- // !checkConstantMembership(elementTerm, setTerm[1]);
- // default:
- // Unhandled();
- // }
+ return
+ elementTerm == setTerm[1][0] ||
+ checkConstantMembership(elementTerm, setTerm[0]);
}
// static
@@ -66,6 +47,12 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
NodeManager* nm = NodeManager::currentNM();
Kind kind = node.getKind();
+
+ if(node.isConst()) {
+ // Dare you touch the const and mangle it to something else.
+ return RewriteResponse(REWRITE_DONE, node);
+ }
+
switch(kind) {
case kind::MEMBER: {
@@ -79,6 +66,10 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
}//kind::MEMBER
case kind::SUBSET: {
+ Assert(false, "TheorySets::postRrewrite(): Subset is handled in preRewrite.");
+
+ // but in off-chance we do end up here, let us do our best
+
// rewrite (A subset-or-equal B) as (A union B = B)
TNode A = node[0];
TNode B = node[1];
@@ -118,6 +109,16 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
node[1].getKind() == kind::EMPTYSET) {
Trace("sets-postrewrite") << "Sets::postRewrite returning " << node[0] << std::endl;
return RewriteResponse(REWRITE_DONE, node[0]);
+ } else if(node[0].isConst() && node[1].isConst()) {
+ std::set<Node> left = NormalForm::getElementsFromNormalConstant(node[0]);
+ std::set<Node> right = NormalForm::getElementsFromNormalConstant(node[1]);
+ std::set<Node> newSet;
+ std::set_difference(left.begin(), left.end(), right.begin(), right.end(),
+ std::inserter(newSet, newSet.begin()));
+ Node newNode = NormalForm::elementsToSet(newSet, node.getType());
+ Assert(newNode.isConst());
+ Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
+ return RewriteResponse(REWRITE_DONE, newNode);
}
break;
}//kind::INTERSECION
@@ -130,6 +131,16 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
return RewriteResponse(REWRITE_DONE, node[0]);
} else if(node[1].getKind() == kind::EMPTYSET) {
return RewriteResponse(REWRITE_DONE, node[1]);
+ } else if(node[0].isConst() && node[1].isConst()) {
+ std::set<Node> left = NormalForm::getElementsFromNormalConstant(node[0]);
+ std::set<Node> right = NormalForm::getElementsFromNormalConstant(node[1]);
+ std::set<Node> newSet;
+ std::set_intersection(left.begin(), left.end(), right.begin(), right.end(),
+ std::inserter(newSet, newSet.begin()));
+ Node newNode = NormalForm::elementsToSet(newSet, node.getType());
+ Assert(newNode.isConst());
+ Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
+ return RewriteResponse(REWRITE_DONE, newNode);
} else if (node[0] > node[1]) {
Node newNode = nm->mkNode(node.getKind(), node[1], node[0]);
Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
@@ -139,6 +150,7 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
}//kind::INTERSECION
case kind::UNION: {
+ // NOTE: case where it is CONST is taken care of at the top
if(node[0] == node[1]) {
Trace("sets-postrewrite") << "Sets::postRewrite returning " << node[0] << std::endl;
return RewriteResponse(REWRITE_DONE, node[0]);
@@ -146,6 +158,16 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
return RewriteResponse(REWRITE_DONE, node[1]);
} else if(node[1].getKind() == kind::EMPTYSET) {
return RewriteResponse(REWRITE_DONE, node[0]);
+ } else if(node[0].isConst() && node[1].isConst()) {
+ std::set<Node> left = NormalForm::getElementsFromNormalConstant(node[0]);
+ std::set<Node> right = NormalForm::getElementsFromNormalConstant(node[1]);
+ std::set<Node> newSet;
+ std::set_union(left.begin(), left.end(), right.begin(), right.end(),
+ std::inserter(newSet, newSet.begin()));
+ Node newNode = NormalForm::elementsToSet(newSet, node.getType());
+ Assert(newNode.isConst());
+ Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
+ return RewriteResponse(REWRITE_DONE, newNode);
} else if (node[0] > node[1]) {
Node newNode = nm->mkNode(node.getKind(), node[1], node[0]);
Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
@@ -162,83 +184,42 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
return RewriteResponse(REWRITE_DONE, node);
}
-const Elements& collectConstantElements(TNode setterm, SettermElementsMap& settermElementsMap) {
- SettermElementsMap::const_iterator it = settermElementsMap.find(setterm);
- if(it == settermElementsMap.end() ) {
-
- Kind k = setterm.getKind();
- unsigned numChildren = setterm.getNumChildren();
- Elements cur;
- if(numChildren == 2) {
- const Elements& left = collectConstantElements(setterm[0], settermElementsMap);
- const Elements& right = collectConstantElements(setterm[1], settermElementsMap);
- switch(k) {
- case kind::UNION:
- if(left.size() >= right.size()) {
- cur = left; cur.insert(right.begin(), right.end());
- } else {
- cur = right; cur.insert(left.begin(), left.end());
- }
- break;
- case kind::INTERSECTION:
- std::set_intersection(left.begin(), left.end(), right.begin(), right.end(),
- std::inserter(cur, cur.begin()) );
- break;
- case kind::SETMINUS:
- std::set_difference(left.begin(), left.end(), right.begin(), right.end(),
- std::inserter(cur, cur.begin()) );
- break;
- default:
- Unhandled();
- }
- } else {
- switch(k) {
- case kind::EMPTYSET:
- /* assign emptyset, which is default */
- break;
- case kind::SINGLETON:
- Assert(setterm[0].isConst());
- cur.insert(TheorySetsRewriter::preRewrite(setterm[0]).node);
- break;
- default:
- Unhandled();
- }
- }
- Debug("sets-rewrite-constant") << "[sets-rewrite-constant] "<< setterm << " " << setterm.getId() << std::endl;
-
- it = settermElementsMap.insert(SettermElementsMap::value_type(setterm, cur)).first;
- }
- return it->second;
-}
-
// static
RewriteResponse TheorySetsRewriter::preRewrite(TNode node) {
NodeManager* nm = NodeManager::currentNM();
- // do nothing
- if(node.getKind() == kind::EQUAL && node[0] == node[1])
- return RewriteResponse(REWRITE_DONE, nm->mkConst(true));
- // Further optimization, if constants but differing ones
+ if(node.getKind() == kind::EQUAL) {
+
+ if(node[0] == node[1]) {
+ return RewriteResponse(REWRITE_DONE, nm->mkConst(true));
+ }
+
+ }//kind::EQUAL
+ else if(node.getKind() == kind::INSERT) {
- if(node.getKind() == kind::INSERT) {
Node insertedElements = nm->mkNode(kind::SINGLETON, node[0]);
size_t setNodeIndex = node.getNumChildren()-1;
for(size_t i = 1; i < setNodeIndex; ++i) {
- insertedElements = nm->mkNode(kind::UNION, insertedElements, nm->mkNode(kind::SINGLETON, node[i]));
+ insertedElements = nm->mkNode(kind::UNION,
+ insertedElements,
+ nm->mkNode(kind::SINGLETON, node[i]));
}
- return RewriteResponse(REWRITE_AGAIN, nm->mkNode(kind::UNION, insertedElements, node[setNodeIndex]));
+ return RewriteResponse(REWRITE_AGAIN,
+ nm->mkNode(kind::UNION,
+ insertedElements,
+ node[setNodeIndex]));
+
}//kind::INSERT
+ else if(node.getKind() == kind::SUBSET) {
- if(node.getType().isSet() && node.isConst()) {
- //rewrite set to normal form
- SettermElementsMap setTermElementsMap; // cache
- const Elements& elements = collectConstantElements(node, setTermElementsMap);
- RewriteResponse response(REWRITE_DONE, NormalForm::elementsToSet(elements, node.getType()));
- Debug("sets-rewrite-constant") << "[sets-rewrite-constant] Rewriting " << node << std::endl
- << "[sets-rewrite-constant] to " << response.node << std::endl;
- return response;
- }
+ // rewrite (A subset-or-equal B) as (A union B = B)
+ return RewriteResponse(REWRITE_AGAIN,
+ nm->mkNode(kind::EQUAL,
+ nm->mkNode(kind::UNION, node[0], node[1]),
+ node[1]) );
+
+ }//kind::SUBSET
return RewriteResponse(REWRITE_DONE, node);
}
diff --git a/src/theory/sets/theory_sets_type_enumerator.h b/src/theory/sets/theory_sets_type_enumerator.h
index 718c329fd..551c0b0ee 100644
--- a/src/theory/sets/theory_sets_type_enumerator.h
+++ b/src/theory/sets/theory_sets_type_enumerator.h
@@ -97,6 +97,7 @@ public:
Node n = NormalForm::elementsToSet(std::set<TNode>(elements.begin(), elements.end()),
getType());
+ Assert(n.isConst());
Assert(n == Rewriter::rewrite(n));
return n;
diff --git a/src/theory/sets/theory_sets_type_rules.h b/src/theory/sets/theory_sets_type_rules.h
index 6754bbb9e..d0e1f18f1 100644
--- a/src/theory/sets/theory_sets_type_rules.h
+++ b/src/theory/sets/theory_sets_type_rules.h
@@ -19,6 +19,8 @@
#ifndef __CVC4__THEORY__SETS__THEORY_SETS_TYPE_RULES_H
#define __CVC4__THEORY__SETS__THEORY_SETS_TYPE_RULES_H
+#include "theory/sets/normal_form.h"
+
namespace CVC4 {
namespace theory {
namespace sets {
@@ -67,7 +69,11 @@ struct SetsBinaryOperatorTypeRule {
Assert(n.getKind() == kind::UNION ||
n.getKind() == kind::INTERSECTION ||
n.getKind() == kind::SETMINUS);
- return n[0].isConst() && n[1].isConst();
+ if(n.getKind() == kind::UNION) {
+ return NormalForm::checkNormalConstant(n);
+ } else {
+ return false;
+ }
}
};/* struct SetUnionTypeRule */
@@ -154,7 +160,7 @@ struct InsertTypeRule {
inline static bool computeIsConst(NodeManager* nodeManager, TNode n) {
Assert(n.getKind() == kind::INSERT);
- return n[0].isConst() && n[1].isConst();
+ return false;
}
};/* struct InsertTypeRule */
@@ -162,7 +168,8 @@ struct InsertTypeRule {
struct SetsProperties {
inline static Cardinality computeCardinality(TypeNode type) {
Assert(type.getKind() == kind::SET_TYPE);
- Cardinality elementCard = type[0].getCardinality();
+ Cardinality elementCard = 2;
+ elementCard ^= type[0].getCardinality();
return elementCard;
}
diff --git a/src/theory/strings/theory_strings.cpp b/src/theory/strings/theory_strings.cpp
index 782a68e18..0df551847 100644
--- a/src/theory/strings/theory_strings.cpp
+++ b/src/theory/strings/theory_strings.cpp
@@ -2,8 +2,8 @@
/*! \file theory_strings.cpp
** \verbatim
** Original author: Tianyi Liang
- ** Major contributors: none
- ** Minor contributors (to current version): Andrew Reynolds, Martin Brain <>, Morgan Deters
+ ** Major contributors: Andrew Reynolds
+ ** Minor contributors (to current version): Martin Brain <>, Morgan Deters
** This file is part of the CVC4 project.
** Copyright (c) 2009-2014 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
@@ -45,7 +45,6 @@ TheoryStrings::TheoryStrings(context::Context* c, context::UserContext* u, Outpu
d_loop_antec(u),
d_length_intro_vars(u),
d_registed_terms_cache(u),
- d_length_nodes(u),
d_length_inst(u),
d_str_pos_ctn(c),
d_str_neg_ctn(c),
@@ -158,11 +157,11 @@ Node TheoryStrings::getLengthTerm( Node t ) {
Node TheoryStrings::getLength( Node t ) {
Node retNode;
- if(t.isConst()) {
- retNode = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, t );
- } else {
+ //if(t.isConst()) {
+ // retNode = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, t );
+ //} else {
retNode = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, getLengthTerm( t ) );
- }
+ //}
return Rewriter::rewrite( retNode );
}
@@ -219,7 +218,9 @@ void TheoryStrings::explain(TNode literal, std::vector<TNode>& assumptions){
unsigned ps = assumptions.size();
std::vector< TNode > tassumptions;
if (atom.getKind() == kind::EQUAL || atom.getKind() == kind::IFF) {
- d_equalityEngine.explainEquality(atom[0], atom[1], polarity, tassumptions);
+ if( atom[0]!=atom[1] ){
+ d_equalityEngine.explainEquality(atom[0], atom[1], polarity, tassumptions);
+ }
} else {
d_equalityEngine.explainPredicate(atom, polarity, tassumptions);
}
@@ -559,6 +560,8 @@ void TheoryStrings::check(Effort e) {
return;
}
+ TimerStat::CodeTimer checkTimer(d_checkTime);
+
bool polarity;
TNode atom;
@@ -606,6 +609,7 @@ void TheoryStrings::check(Effort e) {
bool addedLemma = false;
if( e == EFFORT_FULL && !d_conflict && !d_valuation.needCheck() ) {
+ Trace("strings-check") << "Theory of strings full effort check " << std::endl;
//addedLemma = checkSimple();
//Trace("strings-process") << "Done simple checking, addedLemma = " << addedLemma << ", d_conflict = " << d_conflict << std::endl;
//if( !addedLemma ) {
@@ -628,6 +632,7 @@ void TheoryStrings::check(Effort e) {
}
}
//}
+ Trace("strings-check") << "Theory of strings done full effort check " << addedLemma << " " << d_conflict << std::endl;
}
if(!d_conflict && !d_terms_cache.empty()) {
appendTermLemma();
@@ -706,6 +711,7 @@ void TheoryStrings::eqNotifyPreMerge(TNode t1, TNode t2){
e1->d_normalized_length.set( e2->d_normalized_length );
}
}
+ /*
if( hasTerm( d_zero ) ){
Node leqc;
if( areEqual(d_zero, t1) ){
@@ -734,6 +740,7 @@ void TheoryStrings::eqNotifyPreMerge(TNode t1, TNode t2){
}
}
}
+ */
}
/** called when two equivalance classes have merged */
@@ -754,7 +761,7 @@ void TheoryStrings::assertPendingFact(Node fact, Node exp) {
Trace("strings-pending") << "Assert pending fact : " << fact << " from " << exp << std::endl;
bool polarity = fact.getKind() != kind::NOT;
TNode atom = polarity ? fact : fact[0];
- Assert(atom.getKind() != kind::OR, "Infer error: a split.");
+ Assert(atom.getKind() != kind::OR, "Infer error: a split.");
if (atom.getKind() == kind::EQUAL) {
for( unsigned j=0; j<2; j++ ) {
if( !d_equalityEngine.hasTerm( atom[j] ) ) {
@@ -1208,7 +1215,9 @@ bool TheoryStrings::processNEqc(std::vector< std::vector< Node > > &normal_forms
std::vector< Node > curr_exp;
curr_exp.insert(curr_exp.end(), normal_forms_exp[i].begin(), normal_forms_exp[i].end() );
curr_exp.insert(curr_exp.end(), normal_forms_exp[j].begin(), normal_forms_exp[j].end() );
- curr_exp.push_back( NodeManager::currentNM()->mkNode( kind::EQUAL, normal_form_src[i], normal_form_src[j] ) );
+ if( normal_form_src[i]!=normal_form_src[j] ){
+ curr_exp.push_back( normal_form_src[i].eqNode( normal_form_src[j] ) );
+ }
//process the reverse direction first (check for easy conflicts and inferences)
if( processReverseNEq( normal_forms, normal_form_src, curr_exp, i, j ) ){
@@ -1422,7 +1431,7 @@ bool TheoryStrings::processSimpleNEq( std::vector< std::vector< Node > > &normal
if(areEqual(normal_forms[i][index_i], normal_forms[j][index_j])) {
Trace("strings-solve-debug") << "Simple Case 1 : strings are equal" << std::endl;
//terms are equal, continue
- if( normal_forms[i][index_i]!=normal_forms[j][index_j] ) {
+ if( normal_forms[i][index_i]!=normal_forms[j][index_j] ){
Node eq = normal_forms[i][index_i].eqNode(normal_forms[j][index_j]);
Trace("strings-solve-debug") << "Add to explanation : " << eq << std::endl;
curr_exp.push_back(eq);
@@ -1578,7 +1587,7 @@ bool TheoryStrings::normalizeEquivalenceClass( Node eqc, std::vector< Node > & v
nf.insert( nf.end(), normal_forms[0].begin(), normal_forms[0].end() );
nf_exp.insert( nf_exp.end(), normal_forms_exp[0].begin(), normal_forms_exp[0].end() );
if( eqc!=normal_form_src[0] ){
- nf_exp.push_back( NodeManager::currentNM()->mkNode( kind::EQUAL, eqc, normal_form_src[0] ) );
+ nf_exp.push_back( eqc.eqNode( normal_form_src[0] ) );
}
Trace("strings-solve-debug2") << "just take the first normal form ... done" << std::endl;
}
@@ -1843,38 +1852,32 @@ bool TheoryStrings::registerTerm( Node n ) {
}
if( n.getKind()!=kind::STRING_CONCAT && n.getKind()!=kind::CONST_STRING ) {
if( d_length_intro_vars.find(n)==d_length_intro_vars.end() ) {
- Node n_len = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, n);
- Node n_len_eq_z = n_len.eqNode( d_zero );
- n_len_eq_z = Rewriter::rewrite( n_len_eq_z );
- Node n_len_geq_zero = NodeManager::currentNM()->mkNode( kind::OR, n_len_eq_z,
- NodeManager::currentNM()->mkNode( kind::GT, n_len, d_zero) );
- Trace("strings-lemma") << "Strings::Lemma LENGTH >= 0 : " << n_len_geq_zero << std::endl;
+ sendLengthLemma( n );
++(d_statistics.d_splits);
- d_out->lemma(n_len_geq_zero);
- d_out->requirePhase( n_len_eq_z, true );
- d_length_intro_vars.insert(n);
}
} else {
- if( d_length_nodes.find(n)==d_length_nodes.end() ) {
- Node sk = mkSkolemS("lsym", 2);
- Node eq = Rewriter::rewrite( sk.eqNode(n) );
- Trace("strings-lemma") << "Strings::Lemma LENGTH Term : " << eq << std::endl;
- d_out->lemma(eq);
- Node skl = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, sk );
- Node lsum;
- if( n.getKind() == kind::STRING_CONCAT ) {
- std::vector<Node> node_vec;
- for( unsigned i=0; i<n.getNumChildren(); i++ ) {
- Node lni = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, n[i] );
- node_vec.push_back(lni);
- }
- lsum = NodeManager::currentNM()->mkNode( kind::PLUS, node_vec );
- } else if( n.getKind() == kind::CONST_STRING ) {
- lsum = NodeManager::currentNM()->mkConst( ::CVC4::Rational( n.getConst<String>().size() ) );
+ Node sk = mkSkolemS("lsym", 2);
+ Node eq = Rewriter::rewrite( sk.eqNode(n) );
+ Trace("strings-lemma") << "Strings::Lemma LENGTH Term : " << eq << std::endl;
+ d_out->lemma(eq);
+ Node skl = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, sk );
+ Node lsum;
+ if( n.getKind() == kind::STRING_CONCAT ) {
+ std::vector<Node> node_vec;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ) {
+ Node lni = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, n[i] );
+ node_vec.push_back(lni);
}
- Node ceq = Rewriter::rewrite( skl.eqNode( lsum ) );
- Trace("strings-lemma") << "Strings::Lemma LENGTH : " << ceq << std::endl;
- d_out->lemma(ceq);
+ lsum = NodeManager::currentNM()->mkNode( kind::PLUS, node_vec );
+ } else if( n.getKind() == kind::CONST_STRING ) {
+ lsum = NodeManager::currentNM()->mkConst( ::CVC4::Rational( n.getConst<String>().size() ) );
+ }
+ Node ceq = Rewriter::rewrite( skl.eqNode( lsum ) );
+ Trace("strings-lemma") << "Strings::Lemma LENGTH : " << ceq << std::endl;
+ d_out->lemma(ceq);
+ //also add this to the equality engine
+ if( n.getKind() == kind::CONST_STRING ) {
+ d_equalityEngine.assertEquality( ceq, true, d_true );
}
}
d_registed_terms_cache.insert(n);
@@ -1925,6 +1928,20 @@ void TheoryStrings::sendSplit( Node a, Node b, const char * c, bool preq ) {
++(d_statistics.d_splits);
}
+
+void TheoryStrings::sendLengthLemma( Node n ){
+ Node n_len = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, n);
+ //Node n_len_eq_z = n_len.eqNode( d_zero );
+ //registerTerm( d_emptyString );
+ Node n_len_eq_z = n.eqNode( d_emptyString );
+ n_len_eq_z = Rewriter::rewrite( n_len_eq_z );
+ Node n_len_geq_zero = NodeManager::currentNM()->mkNode( kind::OR, n_len_eq_z,
+ NodeManager::currentNM()->mkNode( kind::GT, n_len, d_zero) );
+ Trace("strings-lemma") << "Strings::Lemma LENGTH >= 0 : " << n_len_geq_zero << std::endl;
+ d_out->lemma(n_len_geq_zero);
+ d_out->requirePhase( n_len_eq_z, true );
+}
+
Node TheoryStrings::mkConcat( Node n1, Node n2 ) {
Node ret = Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::STRING_CONCAT, n1, n2 ) );
collectTerm(ret);
@@ -1947,17 +1964,11 @@ Node TheoryStrings::mkConcat( const std::vector< Node >& c ) {
//isLenSplit: 0-yes, 1-no, 2-ignore
Node TheoryStrings::mkSkolemS( const char *c, int isLenSplit ) {
Node n = NodeManager::currentNM()->mkSkolem( c, NodeManager::currentNM()->stringType(), "string sko" );
+ d_length_intro_vars.insert(n);
++(d_statistics.d_new_skolems);
if(isLenSplit == 0) {
- Node n_len = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, n);
- Node n_len_eq_z = n_len.eqNode( d_zero );
- n_len_eq_z = Rewriter::rewrite( n_len_eq_z );
- Node n_len_geq_zero = NodeManager::currentNM()->mkNode( kind::OR, n_len_eq_z,
- NodeManager::currentNM()->mkNode( kind::GT, n_len, d_zero) );
- Trace("strings-lemma") << "Strings::Lemma LENGTH >= 0 : " << n_len_geq_zero << std::endl;
+ sendLengthLemma( n );
++(d_statistics.d_splits);
- d_out->lemma(n_len_geq_zero);
- d_out->requirePhase( n_len_eq_z, true );
} else if(isLenSplit == 1) {
d_equalityEngine.assertEquality(n.eqNode(d_emptyString), false, d_true);
Node len_n_gt_z = NodeManager::currentNM()->mkNode(kind::GT,
@@ -1965,7 +1976,6 @@ Node TheoryStrings::mkSkolemS( const char *c, int isLenSplit ) {
Trace("strings-lemma") << "Strings::Lemma SK-NON-ZERO : " << len_n_gt_z << std::endl;
d_out->lemma(len_n_gt_z);
}
- d_length_intro_vars.insert(n);
return n;
}
@@ -1975,6 +1985,7 @@ void TheoryStrings::collectTerm( Node n ) {
}
}
+
void TheoryStrings::appendTermLemma() {
for(std::vector< Node >::const_iterator it=d_terms_cache.begin();
it!=d_terms_cache.begin();it++) {
@@ -2056,10 +2067,9 @@ void TheoryStrings::getConcatVec( Node n, std::vector< Node >& c ) {
c.push_back( n );
}
}
-
+/*
bool TheoryStrings::checkSimple() {
bool addedLemma = false;
-
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &d_equalityEngine );
while( !eqcs_i.isFinished() ) {
Node eqc = (*eqcs_i);
@@ -2114,6 +2124,7 @@ bool TheoryStrings::checkSimple() {
}
return addedLemma;
}
+ */
bool TheoryStrings::checkNormalForms() {
Trace("strings-process") << "Normalize equivalence classes...." << std::endl;
@@ -2227,6 +2238,7 @@ bool TheoryStrings::checkNormalForms() {
} while ( !d_conflict && d_lemma_cache.empty() && addedFact );
//process disequalities between equivalence classes
+ Trace("strings-process") << "Check disequalities..." << std::endl;
checkDeqNF();
Trace("strings-solve") << "Finished check normal forms, #lemmas = " << d_lemma_cache.size() << ", conflict = " << d_conflict << std::endl;
@@ -3220,7 +3232,7 @@ bool TheoryStrings::checkPosContains() {
if(d_pos_ctn_cached.find(atom) == d_pos_ctn_cached.end()) {
Node sk1 = mkSkolemS( "sc1" );
Node sk2 = mkSkolemS( "sc2" );
- Node eq = Rewriter::rewrite( x.eqNode( mkConcat( sk1, s, sk2 ) ) );
+ Node eq = Rewriter::rewrite( x.eqNode( mkConcat( sk1, s, sk2 ) ) );
sendLemma( atom, eq, "POS-INC" );
addedLemma = true;
d_pos_ctn_cached.insert( atom );
@@ -3573,8 +3585,8 @@ Node TheoryStrings::getNextDecisionRequest() {
if( in_var_lsum.isNull() && !d_input_vars.empty() ){
Trace("strings-fmf-debug") << "Input variables: ";
std::vector< Node > ll;
- for(NodeSet::const_iterator itr = d_input_vars.begin();
- itr != d_input_vars.end(); ++itr) {
+ for(NodeSet::key_iterator itr = d_input_vars.key_begin();
+ itr != d_input_vars.key_end(); ++itr) {
Trace("strings-fmf-debug") << " " << (*itr) ;
ll.push_back( NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, *itr ) );
}
diff --git a/src/theory/strings/theory_strings.h b/src/theory/strings/theory_strings.h
index 06c95a476..623647942 100644
--- a/src/theory/strings/theory_strings.h
+++ b/src/theory/strings/theory_strings.h
@@ -2,7 +2,7 @@
/*! \file theory_strings.h
** \verbatim
** Original author: Tianyi Liang
- ** Major contributors: none
+ ** Major contributors: Andrew Reynolds
** Minor contributors (to current version): Martin Brain <>, Morgan Deters
** This file is part of the CVC4 project.
** Copyright (c) 2009-2014 New York University and The University of Iowa
@@ -209,7 +209,6 @@ private:
std::map< Node, EqcInfo* > d_eqc_info;
EqcInfo * getOrMakeEqcInfo( Node eqc, bool doMake = true );
//maintain which concat terms have the length lemma instantiated
- NodeSet d_length_nodes;
NodeNodeMap d_length_inst;
private:
void mergeCstVec(std::vector< Node > &vec_strings);
@@ -240,7 +239,7 @@ private:
//bool unrollStar( Node atom );
Node mkRegExpAntec(Node atom, Node ant);
- bool checkSimple();
+ //bool checkSimple();
bool checkNormalForms();
void checkDeqNF();
bool checkLengthsEqc();
@@ -295,6 +294,7 @@ protected:
void sendLemma( Node ant, Node conc, const char * c );
void sendInfer( Node eq_exp, Node eq, const char * c );
void sendSplit( Node a, Node b, const char * c, bool preq = true );
+ void sendLengthLemma( Node n );
/** mkConcat **/
inline Node mkConcat( Node n1, Node n2 );
inline Node mkConcat( Node n1, Node n2, Node n3 );
diff --git a/src/theory/term_registration_visitor.cpp b/src/theory/term_registration_visitor.cpp
index 0e573ce62..7ece4594d 100644
--- a/src/theory/term_registration_visitor.cpp
+++ b/src/theory/term_registration_visitor.cpp
@@ -50,13 +50,36 @@ bool PreRegisterVisitor::alreadyVisited(TNode current, TNode parent) {
d_theories = Theory::setInsert(parentTheoryId, d_theories);
// Should we use the theory of the type
- bool useType = current != parent && currentTheoryId != parentTheoryId;
+ bool useType = false;
+ TheoryId typeTheoryId = THEORY_LAST;
+ if (current != parent) {
+ if (currentTheoryId != parentTheoryId) {
+ // If enclosed by different theories it's shared -- in read(a, f(a)) f(a) should be shared with integers
+ TypeNode type = current.getType();
+ useType = true;
+ typeTheoryId = Theory::theoryOf(type);
+ } else {
+ TypeNode type = current.getType();
+ typeTheoryId = Theory::theoryOf(type);
+ if (typeTheoryId != currentTheoryId) {
+ if (options::finiteModelFind() && type.isSort()) {
+ // We're looking for finite models
+ useType = true;
+ } else {
+ Cardinality card = type.getCardinality();
+ if (card.isFinite()) {
+ useType = true;
+ }
+ }
+ }
+ }
+ }
+
// Get the theories that have already visited this node
TNodeToTheorySetMap::iterator find = d_visited.find(current);
if (find == d_visited.end()) {
if (useType) {
- TheoryId typeTheoryId = Theory::theoryOf(current.getType());
d_theories = Theory::setInsert(typeTheoryId, d_theories);
}
return false;
@@ -93,8 +116,32 @@ void PreRegisterVisitor::visit(TNode current, TNode parent) {
TheoryId parentTheoryId = Theory::theoryOf(parent);
// Should we use the theory of the type
- bool useType = current != parent && currentTheoryId != parentTheoryId;
+ bool useType = false;
+ TheoryId typeTheoryId = THEORY_LAST;
+ if (current != parent) {
+ if (currentTheoryId != parentTheoryId) {
+ // If enclosed by different theories it's shared -- in read(a, f(a)) f(a) should be shared with integers
+ TypeNode type = current.getType();
+ useType = true;
+ typeTheoryId = Theory::theoryOf(type);
+ } else {
+ TypeNode type = current.getType();
+ typeTheoryId = Theory::theoryOf(type);
+ if (typeTheoryId != currentTheoryId) {
+ if (options::finiteModelFind() && type.isSort()) {
+ // We're looking for finite models
+ useType = true;
+ } else {
+ Cardinality card = type.getCardinality();
+ if (card.isFinite()) {
+ useType = true;
+ }
+ }
+ }
+ }
+ }
+
Theory::Set visitedTheories = d_visited[current];
Debug("register::internal") << "PreRegisterVisitor::visit(" << current << "," << parent << "): previously registered with " << Theory::setToString(visitedTheories) << std::endl;
if (!Theory::setContains(currentTheoryId, visitedTheories)) {
@@ -112,7 +159,6 @@ void PreRegisterVisitor::visit(TNode current, TNode parent) {
Debug("register::internal") << "PreRegisterVisitor::visit(" << current << "," << parent << "): adding " << parentTheoryId << std::endl;
}
if (useType) {
- TheoryId typeTheoryId = Theory::theoryOf(current.getType());
if (!Theory::setContains(typeTheoryId, visitedTheories)) {
visitedTheories = Theory::setInsert(typeTheoryId, visitedTheories);
d_visited[current] = visitedTheories;
@@ -187,6 +233,28 @@ bool SharedTermsVisitor::alreadyVisited(TNode current, TNode parent) const {
}
}
}
+ if (current != parent) {
+ if (currentTheoryId != parentTheoryId) {
+ // If enclosed by different theories it's shared -- in read(a, f(a)) f(a) should be shared with integers
+ TypeNode type = current.getType();
+ useType = true;
+ typeTheoryId = Theory::theoryOf(type);
+ } else {
+ TypeNode type = current.getType();
+ typeTheoryId = Theory::theoryOf(type);
+ if (typeTheoryId != currentTheoryId) {
+ if (options::finiteModelFind() && type.isSort()) {
+ // We're looking for finite models
+ useType = true;
+ } else {
+ Cardinality card = type.getCardinality();
+ if (card.isFinite()) {
+ useType = true;
+ }
+ }
+ }
+ }
+ }
if (Theory::setContains(currentTheoryId, theories)) {
if (Theory::setContains(parentTheoryId, theories)) {
diff --git a/src/theory/theory.cpp b/src/theory/theory.cpp
index 509d7be02..62f2a5ec2 100644
--- a/src/theory/theory.cpp
+++ b/src/theory/theory.cpp
@@ -46,6 +46,7 @@ std::ostream& operator<<(std::ostream& os, Theory::Effort level){
}/* ostream& operator<<(ostream&, Theory::Effort) */
Theory::~Theory() {
+ StatisticsRegistry::unregisterStat(&d_checkTime);
StatisticsRegistry::unregisterStat(&d_computeCareGraphTime);
}
diff --git a/src/theory/theory.h b/src/theory/theory.h
index 867dd7c31..2dab434d1 100644
--- a/src/theory/theory.h
+++ b/src/theory/theory.h
@@ -197,7 +197,11 @@ private:
*/
QuantifiersEngine* d_quantEngine;
+protected:
+
// === STATISTICS ===
+ /** time spent in check calls */
+ TimerStat d_checkTime;
/** time spent in theory combination */
TimerStat d_computeCareGraphTime;
@@ -207,8 +211,6 @@ private:
return ss.str();
}
-protected:
-
/**
* The only method to add suff to the care graph.
*/
@@ -255,12 +257,14 @@ protected:
, d_sharedTermsIndex(satContext, 0)
, d_careGraph(NULL)
, d_quantEngine(NULL)
+ , d_checkTime(statName(id, "checkTime"))
, d_computeCareGraphTime(statName(id, "computeCareGraphTime"))
, d_sharedTerms(satContext)
, d_out(&out)
, d_valuation(valuation)
, d_proofEnabled(false)
{
+ StatisticsRegistry::registerStat(&d_checkTime);
StatisticsRegistry::registerStat(&d_computeCareGraphTime);
}
diff --git a/src/theory/theory_engine.cpp b/src/theory/theory_engine.cpp
index ed56890ae..eae76099e 100644
--- a/src/theory/theory_engine.cpp
+++ b/src/theory/theory_engine.cpp
@@ -26,6 +26,7 @@
#include "expr/node_builder.h"
#include "options/options.h"
#include "util/lemma_output_channel.h"
+#include "util/resource_manager.h"
#include "theory/theory.h"
#include "theory/theory_engine.h"
@@ -92,19 +93,10 @@ void TheoryEngine::finishInit() {
void TheoryEngine::eqNotifyNewClass(TNode t){
d_quantEngine->addTermToDatabase( t );
- if( d_logicInfo.isQuantified() && options::quantConflictFind() ){
- d_quantEngine->getConflictFind()->newEqClass( t );
- }
}
void TheoryEngine::eqNotifyPreMerge(TNode t1, TNode t2){
- //TODO: add notification to efficient E-matching
- if( d_logicInfo.isQuantified() ){
- //d_quantEngine->getEfficientEMatcher()->merge( t1, t2 );
- if( options::quantConflictFind() ){
- d_quantEngine->getConflictFind()->merge( t1, t2 );
- }
- }
+
}
void TheoryEngine::eqNotifyPostMerge(TNode t1, TNode t2){
@@ -151,6 +143,7 @@ TheoryEngine::TheoryEngine(context::Context* context,
d_true(),
d_false(),
d_interrupted(false),
+ d_resourceManager(NodeManager::currentResourceManager()),
d_inPreregister(false),
d_factsAsserted(context, false),
d_preRegistrationVisitor(this, context),
@@ -343,8 +336,7 @@ void TheoryEngine::dumpAssertions(const char* tag) {
* @param effort the effort level to use
*/
void TheoryEngine::check(Theory::Effort effort) {
-
- d_propEngine->checkTime();
+ // spendResource();
// Reset the interrupt flag
d_interrupted = false;
@@ -387,6 +379,13 @@ void TheoryEngine::check(Theory::Effort effort) {
printAssertions("theory::assertions");
}
+ if(Theory::fullEffort(effort)) {
+ Trace("theory::assertions::fulleffort") << endl;
+ if (Trace.isOn("theory::assertions::fulleffort")) {
+ printAssertions("theory::assertions::fulleffort");
+ }
+ }
+
// Note that we've discharged all the facts
d_factsAsserted = false;
@@ -487,16 +486,16 @@ void TheoryEngine::combineTheories() {
// The equality in question (order for no repetition)
Node equality = carePair.a.eqNode(carePair.b);
- EqualityStatus es = getEqualityStatus(carePair.a, carePair.b);
- Debug("combineTheories") << "TheoryEngine::combineTheories(): " <<
- (es == EQUALITY_TRUE_AND_PROPAGATED ? "EQUALITY_TRUE_AND_PROPAGATED" :
- es == EQUALITY_FALSE_AND_PROPAGATED ? "EQUALITY_FALSE_AND_PROPAGATED" :
- es == EQUALITY_TRUE ? "EQUALITY_TRUE" :
- es == EQUALITY_FALSE ? "EQUALITY_FALSE" :
- es == EQUALITY_TRUE_IN_MODEL ? "EQUALITY_TRUE_IN_MODEL" :
- es == EQUALITY_FALSE_IN_MODEL ? "EQUALITY_FALSE_IN_MODEL" :
- es == EQUALITY_UNKNOWN ? "EQUALITY_UNKNOWN" :
- "Unexpected case") << endl;
+ // EqualityStatus es = getEqualityStatus(carePair.a, carePair.b);
+ // Debug("combineTheories") << "TheoryEngine::combineTheories(): " <<
+ // (es == EQUALITY_TRUE_AND_PROPAGATED ? "EQUALITY_TRUE_AND_PROPAGATED" :
+ // es == EQUALITY_FALSE_AND_PROPAGATED ? "EQUALITY_FALSE_AND_PROPAGATED" :
+ // es == EQUALITY_TRUE ? "EQUALITY_TRUE" :
+ // es == EQUALITY_FALSE ? "EQUALITY_FALSE" :
+ // es == EQUALITY_TRUE_IN_MODEL ? "EQUALITY_TRUE_IN_MODEL" :
+ // es == EQUALITY_FALSE_IN_MODEL ? "EQUALITY_FALSE_IN_MODEL" :
+ // es == EQUALITY_UNKNOWN ? "EQUALITY_UNKNOWN" :
+ // "Unexpected case") << endl;
// We need to split on it
Debug("combineTheories") << "TheoryEngine::combineTheories(): requesting a split " << endl;
@@ -505,8 +504,8 @@ void TheoryEngine::combineTheories() {
// but it doesn't seem to make a big difference - need to explore more -Clark
// if (true) {
// if (es == EQUALITY_TRUE || es == EQUALITY_TRUE_IN_MODEL) {
- // Node e = ensureLiteral(equality);
- // d_propEngine->requirePhase(e, true);
+ Node e = ensureLiteral(equality);
+ d_propEngine->requirePhase(e, true);
// }
// else if (es == EQUALITY_FALSE_IN_MODEL) {
// Node e = ensureLiteral(equality);
@@ -855,6 +854,7 @@ struct preprocess_stack_element {
Node TheoryEngine::preprocess(TNode assertion) {
Trace("theory::preprocess") << "TheoryEngine::preprocess(" << assertion << ")" << endl;
+ // spendResource();
// Do a topological sort of the subexpressions and substitute them
vector<preprocess_stack_element> toVisit;
@@ -1091,7 +1091,7 @@ void TheoryEngine::assertFact(TNode literal)
{
Trace("theory") << "TheoryEngine::assertFact(" << literal << ")" << endl;
- d_propEngine->checkTime();
+ // spendResource();
// If we're in conflict, nothing to do
if (d_inConflict) {
@@ -1154,7 +1154,7 @@ bool TheoryEngine::propagate(TNode literal, theory::TheoryId theory) {
Debug("theory::propagate") << "TheoryEngine::propagate(" << literal << ", " << theory << ")" << endl;
- d_propEngine->checkTime();
+ // spendResource();
if(Dump.isOn("t-propagations")) {
Dump("t-propagations") << CommentCommand("negation of theory propagation: expect valid")
@@ -1377,7 +1377,7 @@ void TheoryEngine::ensureLemmaAtoms(const std::vector<TNode>& atoms, theory::The
theory::LemmaStatus TheoryEngine::lemma(TNode node, bool negated, bool removable, bool preprocess, theory::TheoryId atomsTo) {
// For resource-limiting (also does a time check).
- spendResource();
+ // spendResource();
// Do we need to check atoms
if (atomsTo != theory::THEORY_LAST) {
@@ -1562,7 +1562,7 @@ bool TheoryEngine::donePPSimpITE(std::vector<Node>& assertions){
Chat() << "..ite simplifier did quite a bit of work.. " << nm->poolSize() << endl;
Chat() << "....node manager contains " << nm->poolSize() << " nodes before cleanup" << endl;
d_iteUtilities->clear();
- Rewriter::garbageCollect();
+ Rewriter::clearCaches();
d_iteRemover.garbageCollect();
nm->reclaimZombiesUntil(options::zombieHuntThreshold());
Chat() << "....node manager contains " << nm->poolSize() << " nodes after cleanup" << endl;
@@ -1751,3 +1751,7 @@ std::pair<bool, Node> TheoryEngine::entailmentCheck(theory::TheoryOfMode mode, T
return th->entailmentCheck(lit, params, seffects);
}
+
+void TheoryEngine::spendResource() {
+ d_resourceManager->spendResource();
+}
diff --git a/src/theory/theory_engine.h b/src/theory/theory_engine.h
index e589e8f87..6360ea5fb 100644
--- a/src/theory/theory_engine.h
+++ b/src/theory/theory_engine.h
@@ -39,6 +39,7 @@
#include "util/statistics_registry.h"
#include "util/cvc4_assert.h"
#include "util/sort_inference.h"
+#include "util/unsafe_interrupt_exception.h"
#include "theory/quantifiers/quant_conflict_find.h"
#include "theory/uf/equality_engine.h"
#include "theory/bv/bv_to_bool.h"
@@ -46,6 +47,8 @@
namespace CVC4 {
+class ResourceManager;
+
/**
* A pair of a theory and a node. This is used to mark the flow of
* propagations between theories.
@@ -83,6 +86,10 @@ namespace theory {
class EqualityEngine;
}/* CVC4::theory::eq namespace */
+ namespace quantifiers {
+ class TermDb;
+ }
+
class EntailmentCheckParameters;
class EntailmentCheckSideEffects;
}/* CVC4::theory namespace */
@@ -101,6 +108,7 @@ class TheoryEngine {
/** Shared terms database can use the internals notify the theories */
friend class SharedTermsDatabase;
+ friend class theory::quantifiers::TermDb;
/** Associated PropEngine engine */
prop::PropEngine* d_propEngine;
@@ -274,42 +282,42 @@ class TheoryEngine {
{
}
- void safePoint() throw(theory::Interrupted, AssertionException) {
+ void safePoint() throw(theory::Interrupted, UnsafeInterruptException, AssertionException) {
spendResource();
if (d_engine->d_interrupted) {
throw theory::Interrupted();
}
}
- void conflict(TNode conflictNode) throw(AssertionException) {
+ void conflict(TNode conflictNode) throw(AssertionException, UnsafeInterruptException) {
Trace("theory::conflict") << "EngineOutputChannel<" << d_theory << ">::conflict(" << conflictNode << ")" << std::endl;
++ d_statistics.conflicts;
d_engine->d_outputChannelUsed = true;
d_engine->conflict(conflictNode, d_theory);
}
- bool propagate(TNode literal) throw(AssertionException) {
+ bool propagate(TNode literal) throw(AssertionException, UnsafeInterruptException) {
Trace("theory::propagate") << "EngineOutputChannel<" << d_theory << ">::propagate(" << literal << ")" << std::endl;
++ d_statistics.propagations;
d_engine->d_outputChannelUsed = true;
return d_engine->propagate(literal, d_theory);
}
- theory::LemmaStatus lemma(TNode lemma, bool removable = false, bool preprocess = false) throw(TypeCheckingExceptionPrivate, AssertionException) {
+ theory::LemmaStatus lemma(TNode lemma, bool removable = false, bool preprocess = false) throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
Trace("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma(" << lemma << ")" << std::endl;
++ d_statistics.lemmas;
d_engine->d_outputChannelUsed = true;
return d_engine->lemma(lemma, false, removable, preprocess, theory::THEORY_LAST);
}
- theory::LemmaStatus splitLemma(TNode lemma, bool removable = false) throw(TypeCheckingExceptionPrivate, AssertionException) {
+ theory::LemmaStatus splitLemma(TNode lemma, bool removable = false) throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
Trace("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma(" << lemma << ")" << std::endl;
++ d_statistics.lemmas;
d_engine->d_outputChannelUsed = true;
return d_engine->lemma(lemma, false, removable, false, d_theory);
}
- void demandRestart() throw(TypeCheckingExceptionPrivate, AssertionException) {
+ void demandRestart() throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
NodeManager* curr = NodeManager::currentNM();
Node restartVar = curr->mkSkolem("restartVar",
curr->booleanType(),
@@ -320,7 +328,7 @@ class TheoryEngine {
}
void requirePhase(TNode n, bool phase)
- throw(theory::Interrupted, AssertionException) {
+ throw(theory::Interrupted, AssertionException, UnsafeInterruptException) {
Debug("theory") << "EngineOutputChannel::requirePhase("
<< n << ", " << phase << ")" << std::endl;
++ d_statistics.requirePhase;
@@ -328,18 +336,18 @@ class TheoryEngine {
}
bool flipDecision()
- throw(theory::Interrupted, AssertionException) {
+ throw(theory::Interrupted, AssertionException, UnsafeInterruptException) {
Debug("theory") << "EngineOutputChannel::flipDecision()" << std::endl;
++ d_statistics.flipDecision;
return d_engine->d_propEngine->flipDecision();
}
- void setIncomplete() throw(AssertionException) {
+ void setIncomplete() throw(AssertionException, UnsafeInterruptException) {
Trace("theory") << "TheoryEngine::setIncomplete()" << std::endl;
d_engine->setIncomplete(d_theory);
}
- void spendResource() throw() {
+ void spendResource() throw(UnsafeInterruptException) {
d_engine->spendResource();
}
@@ -382,12 +390,6 @@ class TheoryEngine {
d_incomplete = true;
}
- /**
- * "Spend" a resource during a search or preprocessing.
- */
- void spendResource() throw() {
- d_propEngine->spendResource();
- }
/**
* Mapping of propagations from recievers to senders.
@@ -472,6 +474,7 @@ class TheoryEngine {
/** Whether we were just interrupted (or not) */
bool d_interrupted;
+ ResourceManager* d_resourceManager;
public:
@@ -482,6 +485,10 @@ public:
~TheoryEngine();
void interrupt() throw(ModalException);
+ /**
+ * "Spend" a resource during a search or preprocessing.
+ */
+ void spendResource();
/**
* Adds a theory. Only one theory per TheoryId can be present, so if
diff --git a/src/theory/theory_model.cpp b/src/theory/theory_model.cpp
index 70ae2c03b..1c62717c8 100644
--- a/src/theory/theory_model.cpp
+++ b/src/theory/theory_model.cpp
@@ -53,6 +53,7 @@ TheoryModel::~TheoryModel() {
}
void TheoryModel::reset(){
+ d_modelCache.clear();
d_reps.clear();
d_rep_set.clear();
d_uf_terms.clear();
@@ -98,6 +99,11 @@ Cardinality TheoryModel::getCardinality( Type t ) const{
Node TheoryModel::getModelValue(TNode n, bool hasBoundVars) const
{
+ std::hash_map<Node, Node, NodeHashFunction>::iterator it = d_modelCache.find(n);
+ if (it != d_modelCache.end()) {
+ return (*it).second;
+ }
+ Node ret = n;
if(n.getKind() == kind::EXISTS || n.getKind() == kind::FORALL) {
// We should have terms, thanks to TheoryQuantifiers::collectModelInfo().
// However, if the Decision Engine stops us early, there might be a
@@ -114,19 +120,23 @@ Node TheoryModel::getModelValue(TNode n, bool hasBoundVars) const
// checkModel(), and the quantifier actually matters, we'll get an
// assert-fail since the quantifier isn't a constant.
if(!d_equalityEngine->hasTerm(Rewriter::rewrite(n))) {
- return n;
+ d_modelCache[n] = ret;
+ return ret;
} else {
- n = Rewriter::rewrite(n);
+ ret = Rewriter::rewrite(n);
}
} else {
if(n.getKind() == kind::LAMBDA) {
NodeManager* nm = NodeManager::currentNM();
Node body = getModelValue(n[1], true);
body = Rewriter::rewrite(body);
- return nm->mkNode(kind::LAMBDA, n[0], body);
+ ret = nm->mkNode(kind::LAMBDA, n[0], body);
+ d_modelCache[n] = ret;
+ return ret;
}
if(n.isConst() || (hasBoundVars && n.getKind() == kind::BOUND_VARIABLE)) {
- return n;
+ d_modelCache[n] = ret;
+ return ret;
}
TypeNode t = n.getType();
@@ -135,7 +145,9 @@ Node TheoryModel::getModelValue(TNode n, bool hasBoundVars) const
std::map< Node, Node >::const_iterator it = d_uf_models.find(n);
if (it != d_uf_models.end()) {
// Existing function
- return it->second;
+ ret = it->second;
+ d_modelCache[n] = ret;
+ return ret;
}
// Unknown function symbol: return LAMBDA x. c, where c is the first constant in the enumeration of the range type
vector<TypeNode> argTypes = t.getArgTypes();
@@ -146,7 +158,9 @@ Node TheoryModel::getModelValue(TNode n, bool hasBoundVars) const
}
Node boundVarList = nm->mkNode(kind::BOUND_VAR_LIST, args);
TypeEnumerator te(t.getRangeType());
- return nm->mkNode(kind::LAMBDA, boundVarList, *te);
+ ret = nm->mkNode(kind::LAMBDA, boundVarList, *te);
+ d_modelCache[n] = ret;
+ return ret;
}
// TODO: if func models not enabled, throw an error?
Unreachable();
@@ -155,9 +169,11 @@ Node TheoryModel::getModelValue(TNode n, bool hasBoundVars) const
if (n.getNumChildren() > 0 &&
n.getKind() != kind::BITVECTOR_ACKERMANIZE_UDIV &&
n.getKind() != kind::BITVECTOR_ACKERMANIZE_UREM) {
+ Debug("model-getvalue-debug") << "Get model value children " << n << std::endl;
std::vector<Node> children;
if (n.getKind() == APPLY_UF) {
Node op = getModelValue(n.getOperator(), hasBoundVars);
+ Debug("model-getvalue-debug") << " operator : " << op << std::endl;
children.push_back(op);
}
else if (n.getMetaKind() == kind::metakind::PARAMETERIZED) {
@@ -165,34 +181,40 @@ Node TheoryModel::getModelValue(TNode n, bool hasBoundVars) const
}
//evaluate the children
for (unsigned i = 0; i < n.getNumChildren(); ++i) {
- Node val = getModelValue(n[i], hasBoundVars);
- children.push_back(val);
+ ret = getModelValue(n[i], hasBoundVars);
+ Debug("model-getvalue-debug") << " " << n << "[" << i << "] is " << ret << std::endl;
+ children.push_back(ret);
}
- Node val = Rewriter::rewrite(NodeManager::currentNM()->mkNode(n.getKind(), children));
- if(val.getKind() == kind::CARDINALITY_CONSTRAINT) {
- val = NodeManager::currentNM()->mkConst(getCardinality(val[0].getType().toType()).getFiniteCardinality() <= val[1].getConst<Rational>().getNumerator());
+ ret = Rewriter::rewrite(NodeManager::currentNM()->mkNode(n.getKind(), children));
+ if(ret.getKind() == kind::CARDINALITY_CONSTRAINT) {
+ ret = NodeManager::currentNM()->mkConst(getCardinality(ret[0].getType().toType()).getFiniteCardinality() <= ret[1].getConst<Rational>().getNumerator());
}
- if(val.getKind() == kind::COMBINED_CARDINALITY_CONSTRAINT ){
+ if(ret.getKind() == kind::COMBINED_CARDINALITY_CONSTRAINT ){
//FIXME
- val = NodeManager::currentNM()->mkConst(false);
+ ret = NodeManager::currentNM()->mkConst(false);
}
- return val;
+ d_modelCache[n] = ret;
+ return ret;
}
if (!d_equalityEngine->hasTerm(n)) {
// Unknown term - return first enumerated value for this type
TypeEnumerator te(n.getType());
- return *te;
+ ret = *te;
+ d_modelCache[n] = ret;
+ return ret;
}
}
- Node val = d_equalityEngine->getRepresentative(n);
- Assert(d_reps.find(val) != d_reps.end());
- std::map< Node, Node >::const_iterator it = d_reps.find( val );
- if( it!=d_reps.end() ){
- return it->second;
- }else{
- return Node::null();
+ ret = d_equalityEngine->getRepresentative(ret);
+ Assert(d_reps.find(ret) != d_reps.end());
+ std::map< Node, Node >::const_iterator it2 = d_reps.find( ret );
+ if (it2 != d_reps.end()) {
+ ret = it2->second;
+ } else {
+ ret = Node::null();
}
+ d_modelCache[n] = ret;
+ return ret;
}
Node TheoryModel::getDomainValue( TypeNode tn, std::vector< Node >& exclude ){
@@ -350,6 +372,7 @@ void TheoryModel::assertEqualityEngine(const eq::EqualityEngine* ee, set<Node>*
void TheoryModel::assertRepresentative(TNode n )
{
Trace("model-builder-reps") << "Assert rep : " << n << std::endl;
+ Trace("model-builder-reps") << "Rep eqc is : " << getRepresentative( n ) << std::endl;
d_reps[ n ] = n;
}
@@ -530,7 +553,7 @@ void TheoryEngineModelBuilder::buildModel(Model* m, bool fullModel)
else if (!rep.isNull()) {
assertedReps[eqc] = rep;
typeRepSet.add(eqct.getBaseType(), eqc);
- allTypes.insert(eqct);
+ allTypes.insert(eqct.getBaseType());
}
else {
typeNoRepSet.add(eqct, eqc);
@@ -620,7 +643,7 @@ void TheoryEngineModelBuilder::buildModel(Model* m, bool fullModel)
Trace("model-builder") << " Normalizing rep (" << rep << "), normalized to (" << normalized << ")" << endl;
if (normalized.isConst()) {
changed = true;
- typeConstSet.add(t.getBaseType(), normalized);
+ typeConstSet.add(tb, normalized);
constantReps[*i] = normalized;
assertedReps.erase(*i);
i2 = i;
@@ -659,6 +682,9 @@ void TheoryEngineModelBuilder::buildModel(Model* m, bool fullModel)
continue;
}
TypeNode t = TypeSet::getType(it);
+ if(t.isTuple() || t.isRecord()) {
+ t = NodeManager::currentNM()->getDatatypeForTupleRecord(t);
+ }
TypeNode tb = t.getBaseType();
if (!assignOne) {
set<Node>* repSet = typeRepSet.getSet(tb);
diff --git a/src/theory/theory_model.h b/src/theory/theory_model.h
index 2eb33b0fb..eeaf3c8da 100644
--- a/src/theory/theory_model.h
+++ b/src/theory/theory_model.h
@@ -52,6 +52,7 @@ public:
Node d_true;
Node d_false;
context::CDO<bool> d_modelBuilt;
+ mutable std::hash_map<Node, Node, NodeHashFunction> d_modelCache;
protected:
/** reset the model */
diff --git a/src/theory/theory_test_utils.h b/src/theory/theory_test_utils.h
index 6d1275c20..46a717cc5 100644
--- a/src/theory/theory_test_utils.h
+++ b/src/theory/theory_test_utils.h
@@ -23,13 +23,13 @@
#include "expr/node.h"
#include "theory/output_channel.h"
#include "theory/interrupted.h"
+#include "util/unsafe_interrupt_exception.h"
#include <vector>
#include <utility>
#include <iostream>
namespace CVC4 {
-
namespace theory {
/**
@@ -72,42 +72,44 @@ public:
void safePoint() throw(Interrupted, AssertionException) {}
void conflict(TNode n)
- throw(AssertionException) {
+ throw(AssertionException, UnsafeInterruptException) {
push(CONFLICT, n);
}
bool propagate(TNode n)
- throw(AssertionException) {
+ throw(AssertionException, UnsafeInterruptException) {
push(PROPAGATE, n);
return true;
}
void propagateAsDecision(TNode n)
- throw(AssertionException) {
+ throw(AssertionException, UnsafeInterruptException) {
push(PROPAGATE_AS_DECISION, n);
}
- LemmaStatus lemma(TNode n, bool removable, bool preprocess) throw(AssertionException) {
+ LemmaStatus lemma(TNode n, bool removable, bool preprocess) throw(AssertionException, UnsafeInterruptException) {
push(LEMMA, n);
return LemmaStatus(Node::null(), 0);
}
- void requirePhase(TNode, bool) throw(Interrupted, AssertionException) {
+ void requirePhase(TNode, bool) throw(Interrupted, AssertionException, UnsafeInterruptException) {
}
- bool flipDecision() throw(Interrupted, AssertionException) {
+ bool flipDecision() throw(Interrupted, AssertionException, UnsafeInterruptException) {
return true;
}
- void setIncomplete() throw(AssertionException) {}
+ void setIncomplete() throw(AssertionException, UnsafeInterruptException) {
+ }
- void handleUserAttribute( const char* attr, theory::Theory* t ){}
+ void handleUserAttribute( const char* attr, theory::Theory* t ) {
+ }
void clear() {
d_callHistory.clear();
}
- LemmaStatus splitLemma(TNode n, bool removable = false) throw(TypeCheckingExceptionPrivate, AssertionException){
+ LemmaStatus splitLemma(TNode n, bool removable = false) throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
push(LEMMA, n);
return LemmaStatus(Node::null(), 0);
}
@@ -125,7 +127,7 @@ public:
return d_callHistory.size();
}
- void printIth(std::ostream& os, int i){
+ void printIth(std::ostream& os, int i) {
os << "[TestOutputChannel " << i;
os << " " << getIthCallType(i);
os << " " << getIthNode(i) << "]";
diff --git a/src/theory/uf/equality_engine.cpp b/src/theory/uf/equality_engine.cpp
index 441d843fe..d1f1e9ed3 100644
--- a/src/theory/uf/equality_engine.cpp
+++ b/src/theory/uf/equality_engine.cpp
@@ -308,20 +308,6 @@ void EqualityEngine::addTermInternal(TNode t, bool isOperator) {
// We set this here as this only applies to actual terms, not the
// intermediate application terms
d_isBoolean[result] = true;
- } else if (d_isConstant[result]) {
- // Non-Boolean constants are trigger terms for all tags
- EqualityNodeId tId = getNodeId(t);
- d_newSetTags = 0;
- d_newSetTriggersSize = THEORY_LAST;
- for (TheoryId currentTheory = THEORY_FIRST; currentTheory != THEORY_LAST; ++ currentTheory) {
- d_newSetTags = Theory::setInsert(currentTheory, d_newSetTags);
- d_newSetTriggers[currentTheory] = tId;
- }
- // Add it to the list for backtracking
- d_triggerTermSetUpdates.push_back(TriggerSetUpdate(tId, null_set_id));
- d_triggerTermSetUpdatesSize = d_triggerTermSetUpdatesSize + 1;
- // Mark the the new set as a trigger
- d_nodeIndividualTrigger[tId] = newTriggerTermSet();
}
// If this is not an internal node, add it to the master
@@ -662,8 +648,9 @@ bool EqualityEngine::merge(EqualityNode& class1, EqualityNode& class2, std::vect
TriggerTermSet& class2triggers = getTriggerTermSet(class2triggerRef);
// Initialize the merged set
- d_newSetTags = Theory::setUnion(class1triggers.tags, class2triggers.tags);
- d_newSetTriggersSize = 0;
+ Theory::Set newSetTags = Theory::setUnion(class1triggers.tags, class2triggers.tags);
+ EqualityNodeId newSetTriggers[THEORY_LAST];
+ unsigned newSetTriggersSize = 0;
int i1 = 0;
int i2 = 0;
@@ -678,15 +665,15 @@ bool EqualityEngine::merge(EqualityNode& class1, EqualityNode& class2, std::vect
{
if (tag1 < tag2) {
// copy tag1
- d_newSetTriggers[d_newSetTriggersSize++] = class1triggers.triggers[i1++];
+ newSetTriggers[newSetTriggersSize++] = class1triggers.triggers[i1++];
tag1 = Theory::setPop(tags1);
} else if (tag1 > tag2) {
// copy tag2
- d_newSetTriggers[d_newSetTriggersSize++] = class2triggers.triggers[i2++];
+ newSetTriggers[newSetTriggersSize++] = class2triggers.triggers[i2++];
tag2 = Theory::setPop(tags2);
} else {
// copy tag1
- EqualityNodeId tag1id = d_newSetTriggers[d_newSetTriggersSize++] = class1triggers.triggers[i1++];
+ EqualityNodeId tag1id = newSetTriggers[newSetTriggersSize++] = class1triggers.triggers[i1++];
// since they are both tagged notify of merge
if (d_performNotify) {
EqualityNodeId tag2id = class2triggers.triggers[i2++];
@@ -706,7 +693,7 @@ bool EqualityEngine::merge(EqualityNode& class1, EqualityNode& class2, std::vect
d_triggerTermSetUpdates.push_back(TriggerSetUpdate(class1Id, class1triggerRef));
d_triggerTermSetUpdatesSize = d_triggerTermSetUpdatesSize + 1;
// Mark the the new set as a trigger
- d_nodeIndividualTrigger[class1Id] = newTriggerTermSet();
+ d_nodeIndividualTrigger[class1Id] = newTriggerTermSet(newSetTags, newSetTriggers, newSetTriggersSize);
}
}
}
@@ -1580,36 +1567,41 @@ void EqualityEngine::addTriggerTerm(TNode t, TheoryId tag)
Theory::Set tags = Theory::setInsert(tag);
getDisequalities(!d_isConstant[classId], classId, tags, disequalitiesToNotify);
+ // Trigger data
+ Theory::Set newSetTags;
+ EqualityNodeId newSetTriggers[THEORY_LAST];
+ unsigned newSetTriggersSize;
+
// Setup the data for the new set
if (triggerSetRef != null_set_id) {
// Get the existing set
TriggerTermSet& triggerSet = getTriggerTermSet(triggerSetRef);
// Initialize the new set for copy/insert
- d_newSetTags = Theory::setInsert(tag, triggerSet.tags);
- d_newSetTriggersSize = 0;
+ newSetTags = Theory::setInsert(tag, triggerSet.tags);
+ newSetTriggersSize = 0;
// Copy into to new one, and insert the new tag/id
unsigned i = 0;
- Theory::Set tags = d_newSetTags;
+ Theory::Set tags = newSetTags;
TheoryId current;
while ((current = Theory::setPop(tags)) != THEORY_LAST) {
// Remove from the tags
tags = Theory::setRemove(current, tags);
// Insert the id into the triggers
- d_newSetTriggers[d_newSetTriggersSize++] =
+ newSetTriggers[newSetTriggersSize++] =
current == tag ? eqNodeId : triggerSet.triggers[i++];
}
} else {
// Setup a singleton
- d_newSetTags = Theory::setInsert(tag);
- d_newSetTriggers[0] = eqNodeId;
- d_newSetTriggersSize = 1;
+ newSetTags = Theory::setInsert(tag);
+ newSetTriggers[0] = eqNodeId;
+ newSetTriggersSize = 1;
}
// Add it to the list for backtracking
d_triggerTermSetUpdates.push_back(TriggerSetUpdate(classId, triggerSetRef));
d_triggerTermSetUpdatesSize = d_triggerTermSetUpdatesSize + 1;
// Mark the the new set as a trigger
- d_nodeIndividualTrigger[classId] = triggerSetRef = newTriggerTermSet();
+ d_nodeIndividualTrigger[classId] = triggerSetRef = newTriggerTermSet(newSetTags, newSetTriggers, newSetTriggersSize);
// Propagate trigger term disequalities we remembered
Debug("equality::trigger") << d_name << "::eq::addTriggerTerm(" << t << ", " << tag << "): propagating " << disequalitiesToNotify.size() << " disequalities " << std::endl;
@@ -1682,9 +1674,9 @@ void EqualityEngine::getUseListTerms(TNode t, std::set<TNode>& output) {
}
}
-EqualityEngine::TriggerTermSetRef EqualityEngine::newTriggerTermSet() {
+EqualityEngine::TriggerTermSetRef EqualityEngine::newTriggerTermSet(Theory::Set newSetTags, EqualityNodeId* newSetTriggers, unsigned newSetTriggersSize) {
// Size of the required set
- size_t size = sizeof(TriggerTermSet) + d_newSetTriggersSize*sizeof(EqualityNodeId);
+ size_t size = sizeof(TriggerTermSet) + newSetTriggersSize*sizeof(EqualityNodeId);
// Align the size
size = (size + 7) & ~((size_t)7);
// Reallocate if necessary
@@ -1698,9 +1690,9 @@ EqualityEngine::TriggerTermSetRef EqualityEngine::newTriggerTermSet() {
d_triggerDatabaseSize = d_triggerDatabaseSize + size;
// Copy the information
TriggerTermSet& newSet = getTriggerTermSet(newTriggerSetRef);
- newSet.tags = d_newSetTags;
- for (unsigned i = 0; i < d_newSetTriggersSize; ++i) {
- newSet.triggers[i] = d_newSetTriggers[i];
+ newSet.tags = newSetTags;
+ for (unsigned i = 0; i < newSetTriggersSize; ++i) {
+ newSet.triggers[i] = newSetTriggers[i];
}
// Return the new reference
return newTriggerSetRef;
diff --git a/src/theory/uf/equality_engine.h b/src/theory/uf/equality_engine.h
index bf7c765b8..25092f37f 100644
--- a/src/theory/uf/equality_engine.h
+++ b/src/theory/uf/equality_engine.h
@@ -554,15 +554,6 @@ private:
}
};/* struct EqualityEngine::TriggerTermSet */
- /** Internal tags for creating a new set */
- Theory::Set d_newSetTags;
-
- /** Internal triggers for creating a new set */
- EqualityNodeId d_newSetTriggers[THEORY_LAST];
-
- /** Size of the internal triggers array */
- unsigned d_newSetTriggersSize;
-
/** The information about trigger terms is stored in this easily maintained memory. */
char* d_triggerDatabase;
@@ -576,7 +567,7 @@ private:
static const TriggerTermSetRef null_set_id = (TriggerTermSetRef)(-1);
/** Create new trigger term set based on the internally set information */
- TriggerTermSetRef newTriggerTermSet();
+ TriggerTermSetRef newTriggerTermSet(Theory::Set newSetTags, EqualityNodeId* newSetTriggers, unsigned newSetTriggersSize);
/** Get the trigger set give a reference */
TriggerTermSet& getTriggerTermSet(TriggerTermSetRef ref) {
diff --git a/src/theory/uf/theory_uf.cpp b/src/theory/uf/theory_uf.cpp
index 2b9fc3daf..8fa7d2dbc 100644
--- a/src/theory/uf/theory_uf.cpp
+++ b/src/theory/uf/theory_uf.cpp
@@ -93,6 +93,8 @@ void TheoryUF::check(Effort level) {
return;
}
+ TimerStat::CodeTimer checkTimer(d_checkTime);
+
while (!done() && !d_conflict)
{
// Get all the assertions
diff --git a/src/theory/uf/theory_uf_strong_solver.cpp b/src/theory/uf/theory_uf_strong_solver.cpp
index cddaace3e..28ea995d9 100644
--- a/src/theory/uf/theory_uf_strong_solver.cpp
+++ b/src/theory/uf/theory_uf_strong_solver.cpp
@@ -763,6 +763,7 @@ bool StrongSolverTheoryUF::SortModel::minimize( OutputChannel* out, TheoryModel*
if( validRegionIndex!=-1 ){
combineRegions( validRegionIndex, i );
if( addSplit( d_regions[validRegionIndex], out )!=0 ){
+ Trace("uf-ss-debug") << "Minimize model : combined regions, found split. " << std::endl;
return false;
}
}else{
@@ -770,9 +771,12 @@ bool StrongSolverTheoryUF::SortModel::minimize( OutputChannel* out, TheoryModel*
}
}
}
+ Assert( validRegionIndex!=-1 );
if( addSplit( d_regions[validRegionIndex], out )!=0 ){
+ Trace("uf-ss-debug") << "Minimize model : found split. " << std::endl;
return false;
}
+ Trace("uf-ss-debug") << "Minimize success. " << std::endl;
}
}
return true;
@@ -1480,7 +1484,7 @@ Node StrongSolverTheoryUF::SortModel::getCardinalityLiteral( int c ) {
StrongSolverTheoryUF::StrongSolverTheoryUF(context::Context* c, context::UserContext* u, OutputChannel& out, TheoryUF* th) :
d_out( &out ), d_th( th ), d_conflict( c, false ), d_rep_model(), d_aloc_com_card( u, 0 ), d_com_card_assertions( c ),
-d_card_assertions_eqv_lemma( u )
+d_card_assertions_eqv_lemma( u ), d_rel_eqc( c )
{
if( options::ufssDiseqPropagation() ){
d_deq_prop = new DisequalityPropagator( th->getQuantifiersEngine(), this );
@@ -1508,26 +1512,58 @@ OutputChannel& StrongSolverTheoryUF::getOutputChannel() {
return d_th->getOutputChannel();
}
+/** ensure eqc */
+void StrongSolverTheoryUF::ensureEqc( SortModel* c, Node a ) {
+ if( !hasEqc( a ) ){
+ d_rel_eqc[a] = true;
+ Trace("uf-ss-solver") << "StrongSolverTheoryUF: New eq class " << a << " : " << a.getType() << std::endl;
+ c->newEqClass( a );
+ if( options::ufssSymBreak() ){
+ d_sym_break->newEqClass( a );
+ }
+ Trace("uf-ss-solver") << "StrongSolverTheoryUF: Done New eq class." << std::endl;
+ }
+}
+
+void StrongSolverTheoryUF::ensureEqcRec( Node n ) {
+ if( !hasEqc( n ) ){
+ SortModel* c = getSortModel( n );
+ if( c ){
+ ensureEqc( c, n );
+ }
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ ensureEqcRec( n[i] );
+ }
+ }
+}
+
+/** has eqc */
+bool StrongSolverTheoryUF::hasEqc( Node a ) {
+ return d_rel_eqc.find( a )!=d_rel_eqc.end() && d_rel_eqc[a];
+}
+
/** new node */
void StrongSolverTheoryUF::newEqClass( Node n ){
SortModel* c = getSortModel( n );
if( c ){
- Trace("uf-ss-solver") << "StrongSolverTheoryUF: New eq class " << n << " : " << n.getType() << std::endl;
- c->newEqClass( n );
- if( options::ufssSymBreak() ){
- d_sym_break->newEqClass( n );
- }
- Trace("uf-ss-solver") << "StrongSolverTheoryUF: Done New eq class." << std::endl;
+ //do nothing
}
}
/** merge */
void StrongSolverTheoryUF::merge( Node a, Node b ){
+ //TODO: ensure they are relevant
SortModel* c = getSortModel( a );
if( c ){
- Trace("uf-ss-solver") << "StrongSolverTheoryUF: Merge " << a << " " << b << " : " << a.getType() << std::endl;
- c->merge( a, b );
- Trace("uf-ss-solver") << "StrongSolverTheoryUF: Done Merge." << std::endl;
+ ensureEqc( c, a );
+ if( hasEqc( b ) ){
+ Trace("uf-ss-solver") << "StrongSolverTheoryUF: Merge " << a << " " << b << " : " << a.getType() << std::endl;
+ c->merge( a, b );
+ Trace("uf-ss-solver") << "StrongSolverTheoryUF: Done Merge." << std::endl;
+ }else{
+ //c->assignEqClass( b, a );
+ d_rel_eqc[b] = true;
+ }
}else{
if( options::ufssDiseqPropagation() ){
d_deq_prop->merge(a, b);
@@ -1539,6 +1575,8 @@ void StrongSolverTheoryUF::merge( Node a, Node b ){
void StrongSolverTheoryUF::assertDisequal( Node a, Node b, Node reason ){
SortModel* c = getSortModel( a );
if( c ){
+ ensureEqc( c, a );
+ ensureEqc( c, b );
Trace("uf-ss-solver") << "StrongSolverTheoryUF: Assert disequal " << a << " " << b << " : " << a.getType() << std::endl;
//Assert( d_th->d_equalityEngine.getRepresentative( a )==a );
//Assert( d_th->d_equalityEngine.getRepresentative( b )==b );
@@ -1554,6 +1592,7 @@ void StrongSolverTheoryUF::assertDisequal( Node a, Node b, Node reason ){
/** assert a node */
void StrongSolverTheoryUF::assertNode( Node n, bool isDecision ){
Trace("uf-ss") << "Assert " << n << " " << isDecision << std::endl;
+ ensureEqcRec( n );
bool polarity = n.getKind() != kind::NOT;
TNode lit = polarity ? n : n[0];
if( lit.getKind()==CARDINALITY_CONSTRAINT ){
diff --git a/src/theory/uf/theory_uf_strong_solver.h b/src/theory/uf/theory_uf_strong_solver.h
index 333f1717e..af316927d 100644
--- a/src/theory/uf/theory_uf_strong_solver.h
+++ b/src/theory/uf/theory_uf_strong_solver.h
@@ -321,6 +321,16 @@ private:
/** check */
void checkCombinedCardinality();
private:
+ /** relevant eqc */
+ NodeBoolMap d_rel_eqc;
+ /** ensure eqc */
+ void ensureEqc( SortModel* c, Node a );
+ /** ensure eqc for all subterms of n */
+ void ensureEqcRec( Node n );
+public:
+ /** has eqc */
+ bool hasEqc( Node a );
+private:
/** disequality propagator */
DisequalityPropagator* d_deq_prop;
/** symmetry breaking techniques */
diff --git a/src/theory/uf/theory_uf_type_rules.h b/src/theory/uf/theory_uf_type_rules.h
index c30742ac5..93fd1dc6f 100644
--- a/src/theory/uf/theory_uf_type_rules.h
+++ b/src/theory/uf/theory_uf_type_rules.h
@@ -91,8 +91,8 @@ public:
if( n[0].getKind()!=kind::CONST_RATIONAL ){
throw TypeCheckingExceptionPrivate(n, "combined cardinality constraint must be a constant");
}
- if( n[0].getConst<Rational>().getNumerator().sgn()!=1 ){
- throw TypeCheckingExceptionPrivate(n, "combined cardinality constraint must be positive");
+ if( n[0].getConst<Rational>().getNumerator().sgn()==-1 ){
+ throw TypeCheckingExceptionPrivate(n, "combined cardinality constraint must be non-negative");
}
}
return nodeManager->booleanType();
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index fc9192dd9..cca98db60 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -99,7 +99,10 @@ libutil_la_SOURCES = \
didyoumean.h \
didyoumean.cpp \
unsat_core.h \
- unsat_core.cpp
+ unsat_core.cpp \
+ resource_manager.h \
+ resource_manager.cpp \
+ unsafe_interrupt_exception.h
libstatistics_la_SOURCES = \
statistics_registry.h \
@@ -158,6 +161,8 @@ EXTRA_DIST = \
uninterpreted_constant.i \
chain.i \
regexp.i \
+ resource_manager.i \
+ unsafe_interrupt_exception.i \
proof.i \
unsat_core.i
diff --git a/src/util/resource_manager.cpp b/src/util/resource_manager.cpp
new file mode 100644
index 000000000..7aeb2fc0f
--- /dev/null
+++ b/src/util/resource_manager.cpp
@@ -0,0 +1,285 @@
+/********************* */
+/*! \file resource_manager.h
+** \verbatim
+** Original author: Liana Hadarean
+** Major contributors: none
+** Minor contributors (to current version): none
+** This file is part of the CVC4 project.
+** Copyright (c) 2009-2014 New York University and The University of Iowa
+** See the file COPYING in the top-level source directory for licensing
+** information.\endverbatim
+**
+** \brief Manages and updates various resource and time limits.
+**
+** Manages and updates various resource and time limits.
+**/
+
+#include "util/resource_manager.h"
+#include "util/output.h"
+#include "smt/smt_engine_scope.h"
+#include "smt/options.h"
+#include "theory/rewriter.h"
+
+using namespace CVC4;
+using namespace std;
+
+void Timer::set(unsigned long millis, bool wallTime) {
+ d_ms = millis;
+ Trace("limit") << "Timer::set(" << d_ms << ")" << std::endl;
+ // keep track of when it was set, even if it's disabled (i.e. == 0)
+ d_wall_time = wallTime;
+ if (d_wall_time) {
+ // Wall time
+ gettimeofday(&d_wall_limit, NULL);
+ Trace("limit") << "Timer::set(): it's " << d_wall_limit.tv_sec << "," << d_wall_limit.tv_usec << std::endl;
+ d_wall_limit.tv_sec += millis / 1000;
+ d_wall_limit.tv_usec += (millis % 1000) * 1000;
+ if(d_wall_limit.tv_usec > 1000000) {
+ ++d_wall_limit.tv_sec;
+ d_wall_limit.tv_usec -= 1000000;
+ }
+ Trace("limit") << "Timer::set(): limit is at " << d_wall_limit.tv_sec << "," << d_wall_limit.tv_usec << std::endl;
+ } else {
+ // CPU time
+ d_cpu_start_time = ((double)clock())/(CLOCKS_PER_SEC *0.001);
+ d_cpu_limit = d_cpu_start_time + d_ms;
+ }
+}
+
+/** Return the milliseconds elapsed since last set(). */
+unsigned long Timer::elapsedWall() const {
+ Assert (d_wall_time);
+ timeval tv;
+ gettimeofday(&tv, NULL);
+ Trace("limit") << "Timer::elapsedWallTime(): it's now " << tv.tv_sec << "," << tv.tv_usec << std::endl;
+ tv.tv_sec -= d_wall_limit.tv_sec - d_ms / 1000;
+ tv.tv_usec -= d_wall_limit.tv_usec - (d_ms % 1000) * 1000;
+ Trace("limit") << "Timer::elapsedWallTime(): elapsed time is " << tv.tv_sec << "," << tv.tv_usec << std::endl;
+ return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
+unsigned long Timer::elapsedCPU() const {
+ Assert (!d_wall_time);
+ clock_t elapsed = ((double)clock())/(CLOCKS_PER_SEC *0.001)- d_cpu_start_time;
+ Trace("limit") << "Timer::elapsedCPUTime(): elapsed time is " << elapsed << " ms" <<std::endl;
+ return elapsed;
+}
+
+unsigned long Timer::elapsed() const {
+ if (d_wall_time)
+ return elapsedWall();
+ return elapsedCPU();
+}
+
+bool Timer::expired() const {
+ if (!on()) return false;
+
+ if (d_wall_time) {
+ timeval tv;
+ gettimeofday(&tv, NULL);
+ Debug("limit") << "Timer::expired(): current wall time is " << tv.tv_sec << "," << tv.tv_usec << std::endl;
+ Debug("limit") << "Timer::expired(): limit wall time is " << d_wall_limit.tv_sec << "," << d_wall_limit.tv_usec << std::endl;
+ if(d_wall_limit.tv_sec < tv.tv_sec ||
+ (d_wall_limit.tv_sec == tv.tv_sec && d_wall_limit.tv_usec <= tv.tv_usec)) {
+ Debug("limit") << "Timer::expired(): OVER LIMIT!" << std::endl;
+ return true;
+ }
+ Debug("limit") << "Timer::expired(): within limit" << std::endl;
+ return false;
+ }
+
+ // cpu time
+ double current = ((double)clock())/(CLOCKS_PER_SEC*0.001);
+ Debug("limit") << "Timer::expired(): current cpu time is " << current << std::endl;
+ Debug("limit") << "Timer::expired(): limit cpu time is " << d_cpu_limit << std::endl;
+ if (current >= d_cpu_limit) {
+ Debug("limit") << "Timer::expired(): OVER LIMIT!" << current << std::endl;
+ return true;
+ }
+ return false;
+}
+
+const unsigned long ResourceManager::s_resourceCount = 1000;
+
+ResourceManager::ResourceManager()
+ : d_cumulativeTimer()
+ , d_perCallTimer()
+ , d_timeBudgetCumulative(0)
+ , d_timeBudgetPerCall(0)
+ , d_resourceBudgetCumulative(0)
+ , d_resourceBudgetPerCall(0)
+ , d_cumulativeTimeUsed(0)
+ , d_cumulativeResourceUsed(0)
+ , d_thisCallResourceUsed(0)
+ , d_thisCallTimeBudget(0)
+ , d_thisCallResourceBudget(0)
+ , d_isHardLimit()
+ , d_on(false)
+ , d_cpuTime(false)
+ , d_spendResourceCalls(0)
+{}
+
+
+void ResourceManager::setResourceLimit(unsigned long units, bool cumulative) {
+ d_on = true;
+ if(cumulative) {
+ Trace("limit") << "ResourceManager: setting cumulative resource limit to " << units << endl;
+ d_resourceBudgetCumulative = (units == 0) ? 0 : (d_cumulativeResourceUsed + units);
+ d_thisCallResourceBudget = d_resourceBudgetCumulative;
+ } else {
+ Trace("limit") << "ResourceManager: setting per-call resource limit to " << units << endl;
+ d_resourceBudgetPerCall = units;
+ }
+}
+
+void ResourceManager::setTimeLimit(unsigned long millis, bool cumulative) {
+ d_on = true;
+ if(cumulative) {
+ Trace("limit") << "ResourceManager: setting cumulative time limit to " << millis << " ms" << endl;
+ d_timeBudgetCumulative = (millis == 0) ? 0 : (d_cumulativeTimeUsed + millis);
+ d_cumulativeTimer.set(millis, !d_cpuTime);
+ } else {
+ Trace("limit") << "ResourceManager: setting per-call time limit to " << millis << " ms" << endl;
+ d_timeBudgetPerCall = millis;
+ // perCall timer will be set in beginCall
+ }
+
+}
+
+unsigned long ResourceManager::getResourceUsage() const {
+ return d_cumulativeResourceUsed;
+}
+
+unsigned long ResourceManager::getTimeUsage() const {
+ if (d_timeBudgetCumulative) {
+ return d_cumulativeTimer.elapsed();
+ }
+ return d_cumulativeTimeUsed;
+}
+
+unsigned long ResourceManager::getResourceRemaining() const {
+ if (d_thisCallResourceBudget <= d_thisCallResourceUsed)
+ return 0;
+ return d_thisCallResourceBudget - d_thisCallResourceUsed;
+}
+
+unsigned long ResourceManager::getTimeRemaining() const {
+ unsigned long time_passed = d_cumulativeTimer.elapsed();
+ if (time_passed >= d_thisCallTimeBudget)
+ return 0;
+ return d_thisCallTimeBudget - time_passed;
+}
+
+void ResourceManager::spendResource() throw (UnsafeInterruptException) {
+ ++d_spendResourceCalls;
+ ++d_cumulativeResourceUsed;
+ if (!d_on) return;
+
+ Debug("limit") << "ResourceManager::spendResource()" << std::endl;
+ ++d_thisCallResourceUsed;
+ if(out()) {
+ Trace("limit") << "ResourceManager::spendResource: interrupt!" << std::endl;
+ Trace("limit") << " on call " << d_spendResourceCalls << std::endl;
+ if (outOfTime()) {
+ Trace("limit") << "ResourceManager::spendResource: elapsed time" << d_cumulativeTimer.elapsed() << std::endl;
+ }
+
+ if (d_isHardLimit) {
+ if (smt::smtEngineInScope()) {
+ theory::Rewriter::clearCaches();
+ }
+ throw UnsafeInterruptException();
+ }
+
+ // interrupt it next time resources are checked
+ if (smt::smtEngineInScope()) {
+ smt::currentSmtEngine()->interrupt();
+ }
+ }
+}
+
+void ResourceManager::beginCall() {
+
+ d_perCallTimer.set(d_timeBudgetPerCall, !d_cpuTime);
+ d_thisCallResourceUsed = 0;
+ if (!d_on) return;
+
+ if (cumulativeLimitOn()) {
+ if (d_resourceBudgetCumulative) {
+ d_thisCallResourceBudget = d_resourceBudgetCumulative <= d_cumulativeResourceUsed ? 0 :
+ d_resourceBudgetCumulative - d_cumulativeResourceUsed;
+ }
+
+ if (d_timeBudgetCumulative) {
+
+ AlwaysAssert(d_cumulativeTimer.on());
+ // timer was on since the option was set
+ d_cumulativeTimeUsed = d_cumulativeTimer.elapsed();
+ d_thisCallTimeBudget = d_timeBudgetCumulative <= d_cumulativeTimeUsed? 0 :
+ d_timeBudgetCumulative - d_cumulativeTimeUsed;
+ d_cumulativeTimer.set(d_thisCallTimeBudget, d_cpuTime);
+ }
+ // we are out of resources so we shouldn't update the
+ // budget for this call to the per call budget
+ if (d_thisCallTimeBudget == 0 ||
+ d_thisCallResourceUsed == 0)
+ return;
+ }
+
+ if (perCallLimitOn()) {
+ // take min of what's left and per-call budget
+ if (d_resourceBudgetPerCall) {
+ d_thisCallResourceBudget = d_thisCallResourceBudget < d_resourceBudgetPerCall && d_thisCallResourceBudget != 0 ? d_thisCallResourceBudget : d_resourceBudgetPerCall;
+ }
+
+ if (d_timeBudgetPerCall) {
+ d_thisCallTimeBudget = d_thisCallTimeBudget < d_timeBudgetPerCall && d_thisCallTimeBudget != 0 ? d_thisCallTimeBudget : d_timeBudgetPerCall;
+ }
+ }
+}
+
+void ResourceManager::endCall() {
+ unsigned long usedInCall = d_perCallTimer.elapsed();
+ d_perCallTimer.set(0);
+ d_cumulativeTimeUsed += usedInCall;
+}
+
+bool ResourceManager::cumulativeLimitOn() const {
+ return d_timeBudgetCumulative || d_resourceBudgetCumulative;
+}
+
+bool ResourceManager::perCallLimitOn() const {
+ return d_timeBudgetPerCall || d_resourceBudgetPerCall;
+}
+
+bool ResourceManager::outOfResources() const {
+ // resource limiting not enabled
+ if (d_resourceBudgetPerCall == 0 &&
+ d_resourceBudgetCumulative == 0)
+ return false;
+
+ return getResourceRemaining() == 0;
+}
+
+bool ResourceManager::outOfTime() const {
+ if (d_timeBudgetPerCall == 0 &&
+ d_timeBudgetCumulative == 0)
+ return false;
+
+ return d_cumulativeTimer.expired() || d_perCallTimer.expired();
+}
+
+void ResourceManager::useCPUTime(bool cpu) {
+ Trace("limit") << "ResourceManager::useCPUTime("<< cpu <<")\n";
+ d_cpuTime = cpu;
+}
+
+void ResourceManager::setHardLimit(bool value) {
+ Trace("limit") << "ResourceManager::setHardLimit("<< value <<")\n";
+ d_isHardLimit = value;
+}
+
+void ResourceManager::enable(bool on) {
+ Trace("limit") << "ResourceManager::enable("<< on <<")\n";
+ d_on = on;
+}
diff --git a/src/util/resource_manager.h b/src/util/resource_manager.h
new file mode 100644
index 000000000..94e7dbba2
--- /dev/null
+++ b/src/util/resource_manager.h
@@ -0,0 +1,158 @@
+/********************* */
+/*! \file resource_manager.h
+** \verbatim
+** Original author: Liana Hadarean
+** Major contributors: none
+** Minor contributors (to current version): none
+** This file is part of the CVC4 project.
+** Copyright (c) 2009-2014 New York University and The University of Iowa
+** See the file COPYING in the top-level source directory for licensing
+** information.\endverbatim
+**
+** \brief Manages and updates various resource and time limits
+**
+** Manages and updates various resource and time limits.
+**/
+
+#include "cvc4_public.h"
+
+#ifndef __CVC4__RESOURCE_MANAGER_H
+#define __CVC4__RESOURCE_MANAGER_H
+
+#include <cstddef>
+#include <sys/time.h>
+
+#include "util/exception.h"
+#include "util/unsafe_interrupt_exception.h"
+
+namespace CVC4 {
+
+/**
+ * A helper class to keep track of a time budget and signal
+ * the PropEngine when the budget expires.
+ */
+class CVC4_PUBLIC Timer {
+
+ unsigned long d_ms;
+ timeval d_wall_limit;
+ clock_t d_cpu_start_time;
+ clock_t d_cpu_limit;
+
+ bool d_wall_time;
+
+ /** Return the milliseconds elapsed since last set() cpu time. */
+ unsigned long elapsedCPU() const;
+ /** Return the milliseconds elapsed since last set() wall time. */
+ unsigned long elapsedWall() const;
+
+public:
+
+ /** Construct a Timer. */
+ Timer()
+ : d_ms(0)
+ , d_cpu_start_time(0)
+ , d_cpu_limit(0)
+ , d_wall_time(true)
+ {}
+
+ /** Is the timer currently active? */
+ bool on() const {
+ return d_ms != 0;
+ }
+
+ /** Set a millisecond timer (0==off). */
+ void set(unsigned long millis, bool wall_time = true);
+ /** Return the milliseconds elapsed since last set() wall/cpu time
+ depending on d_wall_time*/
+ unsigned long elapsed() const;
+ bool expired() const;
+
+};/* class Timer */
+
+
+class CVC4_PUBLIC ResourceManager {
+
+ Timer d_cumulativeTimer;
+ Timer d_perCallTimer;
+
+ /** A user-imposed cumulative time budget, in milliseconds. 0 = no limit. */
+ unsigned long d_timeBudgetCumulative;
+ /** A user-imposed per-call time budget, in milliseconds. 0 = no limit. */
+ unsigned long d_timeBudgetPerCall;
+ /** A user-imposed cumulative resource budget. 0 = no limit. */
+ unsigned long d_resourceBudgetCumulative;
+ /** A user-imposed per-call resource budget. 0 = no limit. */
+ unsigned long d_resourceBudgetPerCall;
+
+ /** The number of milliseconds used. */
+ unsigned long d_cumulativeTimeUsed;
+ /** The amount of resource used. */
+ unsigned long d_cumulativeResourceUsed;
+
+ /** The ammount of resource used during this call. */
+ unsigned long d_thisCallResourceUsed;
+
+ /**
+ * The ammount of resource budget for this call (min between per call
+ * budget and left-over cumulative budget.
+ */
+ unsigned long d_thisCallTimeBudget;
+ unsigned long d_thisCallResourceBudget;
+
+ bool d_isHardLimit;
+ bool d_on;
+ bool d_cpuTime;
+ unsigned long d_spendResourceCalls;
+
+ /** Counter indicating how often to check resource manager in loops */
+ static const unsigned long s_resourceCount;
+
+public:
+
+ ResourceManager();
+
+ bool limitOn() const { return cumulativeLimitOn() || perCallLimitOn(); }
+ bool cumulativeLimitOn() const;
+ bool perCallLimitOn() const;
+
+ bool outOfResources() const;
+ bool outOfTime() const;
+ bool out() const { return d_on && (outOfResources() || outOfTime()); }
+
+ unsigned long getResourceUsage() const;
+ unsigned long getTimeUsage() const;
+ unsigned long getResourceRemaining() const;
+ unsigned long getTimeRemaining() const;
+
+ unsigned long getResourceBudgetForThisCall() {
+ return d_thisCallResourceBudget;
+ }
+
+ void spendResource() throw(UnsafeInterruptException);
+
+ void setHardLimit(bool value);
+ void setResourceLimit(unsigned long units, bool cumulative = false);
+ void setTimeLimit(unsigned long millis, bool cumulative = false);
+ void useCPUTime(bool cpu);
+
+ void enable(bool on);
+
+ /**
+ * Resets perCall limits to mark the start of a new call,
+ * updates budget for current call and starts the timer
+ */
+ void beginCall();
+
+ /**
+ * Marks the end of a SmtEngine check call, stops the per
+ * call timer, updates cumulative time used.
+ */
+ void endCall();
+
+ static unsigned long getFrequencyCount() { return s_resourceCount; }
+ friend class SmtEngine;
+};/* class ResourceManager */
+
+}/* CVC4 namespace */
+
+#endif /* __CVC4__RESOURCE_MANAGER_H */
diff --git a/src/util/resource_manager.i b/src/util/resource_manager.i
new file mode 100644
index 000000000..0f55c2bce
--- /dev/null
+++ b/src/util/resource_manager.i
@@ -0,0 +1,5 @@
+%{
+#include "util/resource_manager.h"
+%}
+
+%include "util/resource_manager.h"
diff --git a/src/util/sort_inference.cpp b/src/util/sort_inference.cpp
index 179bb1a23..dbd1dcd16 100644
--- a/src/util/sort_inference.cpp
+++ b/src/util/sort_inference.cpp
@@ -23,6 +23,7 @@
#include "theory/uf/options.h"
#include "smt/options.h"
#include "theory/rewriter.h"
+#include "theory/quantifiers/options.h"
using namespace CVC4;
using namespace std;
@@ -170,7 +171,9 @@ bool SortInference::simplify( std::vector< Node >& assertions ){
for( unsigned i=0; i<assertions.size(); i++ ){
Node prev = assertions[i];
std::map< Node, Node > var_bound;
+ Trace("sort-inference-debug") << "Rewrite " << assertions[i] << std::endl;
assertions[i] = simplify( assertions[i], var_bound );
+ Trace("sort-inference-debug") << "Done." << std::endl;
if( prev!=assertions[i] ){
assertions[i] = theory::Rewriter::rewrite( assertions[i] );
rewritten = true;
@@ -333,7 +336,7 @@ int SortInference::process( Node n, std::map< Node, Node >& var_bound ){
for( size_t i=0; i<n.getNumChildren(); i++ ){
bool processChild = true;
if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
- processChild = i==1;
+ processChild = options::userPatternsQuant()==theory::quantifiers::USER_PAT_MODE_IGNORE ? i==1 : i>=1;
}
if( processChild ){
children.push_back( n[i] );
@@ -511,6 +514,7 @@ Node SortInference::getNewSymbol( Node old, TypeNode tn ){
}
Node SortInference::simplify( Node n, std::map< Node, Node >& var_bound ){
+ Trace("sort-inference-debug2") << "Simplify " << n << std::endl;
std::vector< Node > children;
if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
//recreate based on types of variables
@@ -518,6 +522,7 @@ Node SortInference::simplify( Node n, std::map< Node, Node >& var_bound ){
for( size_t i=0; i<n[0].getNumChildren(); i++ ){
TypeNode tn = getOrCreateTypeForId( d_var_types[n][ n[0][i] ], n[0][i].getType() );
Node v = getNewSymbol( n[0][i], tn );
+ Trace("sort-inference-debug2") << "Map variable " << n[0][i] << " to " << v << std::endl;
new_children.push_back( v );
var_bound[ n[0][i] ] = v;
}
@@ -528,13 +533,17 @@ Node SortInference::simplify( Node n, std::map< Node, Node >& var_bound ){
if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
children.push_back( n.getOperator() );
}
+ bool childChanged = false;
for( size_t i=0; i<n.getNumChildren(); i++ ){
bool processChild = true;
if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
- processChild = i>=1;
+ processChild = options::userPatternsQuant()==theory::quantifiers::USER_PAT_MODE_IGNORE ? i==1 : i>=1;
}
if( processChild ){
- children.push_back( simplify( n[i], var_bound ) );
+ Node nc = simplify( n[i], var_bound );
+ Trace("sort-inference-debug2") << "Simplify " << i << " " << n[i] << " returned " << nc << std::endl;
+ children.push_back( nc );
+ childChanged = childChanged || nc!=n[i];
}
}
@@ -542,6 +551,7 @@ Node SortInference::simplify( Node n, std::map< Node, Node >& var_bound ){
if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
//erase from variable bound
for( size_t i=0; i<n[0].getNumChildren(); i++ ){
+ Trace("sort-inference-debug2") << "Remove bound for " << n[0][i] << std::endl;
var_bound.erase( n[0][i] );
}
return NodeManager::currentNM()->mkNode( n.getKind(), children );
@@ -595,7 +605,7 @@ Node SortInference::simplify( Node n, std::map< Node, Node >& var_bound ){
if( n[i].isConst() ){
children[i+1] = getNewSymbol( n[i], tna );
}else{
- Trace("sort-inference-warn") << "Sort inference created bad child: " << n[i] << " " << tn << " " << tna << std::endl;
+ Trace("sort-inference-warn") << "Sort inference created bad child: " << n << " " << n[i] << " " << tn << " " << tna << std::endl;
Assert( false );
}
}
@@ -615,7 +625,11 @@ Node SortInference::simplify( Node n, std::map< Node, Node >& var_bound ){
//just return n, we will fix at higher scope
return n;
}else{
- return NodeManager::currentNM()->mkNode( n.getKind(), children );
+ if( childChanged ){
+ return NodeManager::currentNM()->mkNode( n.getKind(), children );
+ }else{
+ return n;
+ }
}
}
diff --git a/src/util/unsafe_interrupt_exception.h b/src/util/unsafe_interrupt_exception.h
new file mode 100644
index 000000000..e19fc37ce
--- /dev/null
+++ b/src/util/unsafe_interrupt_exception.h
@@ -0,0 +1,43 @@
+/********************* */
+/*! \file modal_exception.h
+ ** \verbatim
+ ** Original author: Liana Hadarean
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief An exception that is thrown when the solver is out of time/resources
+ ** and is interrupted in an unsafe state
+ **/
+
+#include "cvc4_public.h"
+
+#ifndef __CVC4__UNSAFE_INTERRUPT_EXCEPTION_H
+#define __CVC4__UNSAFE_INTERRUPT_EXCEPTION_H
+
+#include "util/exception.h"
+
+namespace CVC4 {
+
+class CVC4_PUBLIC UnsafeInterruptException : public CVC4::Exception {
+public:
+ UnsafeInterruptException() :
+ Exception("Interrupted in unsafe state due to "
+ "time/resource limit.") {
+ }
+
+ UnsafeInterruptException(const std::string& msg) :
+ Exception(msg) {
+ }
+
+ UnsafeInterruptException(const char* msg) :
+ Exception(msg) {
+ }
+};/* class UnsafeInterruptException */
+
+}/* CVC4 namespace */
+
+#endif /* __CVC4__UNSAFE_INTERRUPT_EXCEPTION_H */
diff --git a/src/util/unsafe_interrupt_exception.i b/src/util/unsafe_interrupt_exception.i
new file mode 100644
index 000000000..94a552877
--- /dev/null
+++ b/src/util/unsafe_interrupt_exception.i
@@ -0,0 +1,7 @@
+%{
+#include "util/unsafe_interrupt_exception.h"
+%}
+
+%ignore CVC4::UnsafeInterruptException::UnsafeInterruptException(const char*);
+
+%include "util/unsafe_interrupt_exception.h"
diff --git a/test/regress/README b/test/regress/README
index 58cd2f2e7..6fcdf16a3 100644
--- a/test/regress/README
+++ b/test/regress/README
@@ -3,7 +3,7 @@ Regressions
To insert a new regression, add the file to Subversion, for example:
- svn add regress/regress0/testMyFunctionality.cvc
+ git add regress/regress0/testMyFunctionality.cvc
Also add it to the relevant Makefile.am, here, in regress/regress0/Makefile.am.
diff --git a/test/regress/regress0/Makefile.am b/test/regress/regress0/Makefile.am
index fae563973..68d002367 100644
--- a/test/regress/regress0/Makefile.am
+++ b/test/regress/regress0/Makefile.am
@@ -106,8 +106,8 @@ CVC_TESTS = \
wiki.20.cvc \
wiki.21.cvc \
queries0.cvc \
- print_lambda.cvc \
- trim.cvc
+ trim.cvc \
+ print_lambda.cvc
# Regression tests for TPTP inputs
TPTP_TESTS =
@@ -166,7 +166,11 @@ BUG_TESTS = \
bug578.smt2 \
bug585.cvc \
bug586.cvc \
- bug590.smt2
+ bug590.smt2 \
+ bug593.smt2 \
+ bug595.cvc \
+ bug596.cvc \
+ bug596b.cvc
TESTS = $(SMT_TESTS) $(SMT2_TESTS) $(CVC_TESTS) $(TPTP_TESTS) $(BUG_TESTS)
diff --git a/test/regress/regress0/arrays/Makefile.am b/test/regress/regress0/arrays/Makefile.am
index 804987da2..a90b238e2 100644
--- a/test/regress/regress0/arrays/Makefile.am
+++ b/test/regress/regress0/arrays/Makefile.am
@@ -40,7 +40,6 @@ TESTS = \
swap_t1_np_nf_ai_00005_007.cvc.smt \
x2.smt \
x3.smt \
- parsing_ringer.cvc \
bug272.smt \
bug272.minimized.smt \
constarr.smt2 \
@@ -48,7 +47,8 @@ TESTS = \
constarr3.smt2 \
constarr.cvc \
constarr2.cvc \
- constarr3.cvc
+ constarr3.cvc \
+ parsing_ringer.cvc
EXTRA_DIST = $(TESTS)
diff --git a/test/regress/regress0/bug590.smt2 b/test/regress/regress0/bug590.smt2
index 06dc1fe58..68665f629 100644
--- a/test/regress/regress0/bug590.smt2
+++ b/test/regress/regress0/bug590.smt2
@@ -2,7 +2,7 @@
(set-option :strings-exp true)
(set-option :produce-models true)
(set-info :smt-lib-version 2.0)
-(set-info :status sat)
+(set-info :status unknown)
(declare-fun text () String)
(declare-fun output () String)
diff --git a/test/regress/regress0/bug590.smt2.expect b/test/regress/regress0/bug590.smt2.expect
index 67f25bb72..987ace150 100644
--- a/test/regress/regress0/bug590.smt2.expect
+++ b/test/regress/regress0/bug590.smt2.expect
@@ -1,2 +1,2 @@
-% EXPECT: sat
-% EXPECT: ((charlst2 (store ((as const (Array Int String)) "C") 0 "&lt;")))
+% EXPECT: unknown
+% EXPECT: ((charlst2 (store ((as const (Array Int String)) "C") 0 "&gt;")))
diff --git a/test/regress/regress0/bug593.smt2 b/test/regress/regress0/bug593.smt2
new file mode 100644
index 000000000..2c28bb47c
--- /dev/null
+++ b/test/regress/regress0/bug593.smt2
@@ -0,0 +1,20 @@
+(set-logic QF_UFBV)
+(set-info :status unsat)
+
+(declare-sort A 0)
+
+(declare-fun f ((_ BitVec 1)) A)
+(declare-fun g (A) (_ BitVec 1))
+
+(declare-fun x () A)
+(declare-fun y () A)
+(declare-fun z () A)
+
+(assert (and
+
+(not (= (f (g x)) (f (g y))))
+(not (= (f (g x)) (f (g z))))
+(not (= (f (g y)) (f (g z))))))
+
+(check-sat)
+
diff --git a/test/regress/regress0/bug595.cvc b/test/regress/regress0/bug595.cvc
new file mode 100644
index 000000000..c11cfb6e4
--- /dev/null
+++ b/test/regress/regress0/bug595.cvc
@@ -0,0 +1,7 @@
+% EXPECT: sat
+
+f : INT -> [# i:INT, b:INT #];
+a : INT;
+ASSERT f(a) /= (# i := 0, b := 0 #);
+
+CHECKSAT;
diff --git a/test/regress/regress0/bug596.cvc b/test/regress/regress0/bug596.cvc
new file mode 100644
index 000000000..8e1f6f7e3
--- /dev/null
+++ b/test/regress/regress0/bug596.cvc
@@ -0,0 +1,7 @@
+% EXPECT: sat
+
+f : INT -> [# i:INT, b:BOOLEAN #];
+a : INT;
+ASSERT f(a) /= (# i := 0, b := FALSE #);
+
+CHECKSAT;
diff --git a/test/regress/regress0/bug596b.cvc b/test/regress/regress0/bug596b.cvc
new file mode 100644
index 000000000..4765e03b2
--- /dev/null
+++ b/test/regress/regress0/bug596b.cvc
@@ -0,0 +1,7 @@
+% EXPECT: sat
+
+f : INT -> [ INT, BOOLEAN ];
+a : INT;
+ASSERT f(a) /= ( 0, FALSE );
+
+CHECKSAT;
diff --git a/test/regress/regress0/datatypes/Makefile.am b/test/regress/regress0/datatypes/Makefile.am
index 05eb710df..80fea45fc 100644
--- a/test/regress/regress0/datatypes/Makefile.am
+++ b/test/regress/regress0/datatypes/Makefile.am
@@ -60,7 +60,8 @@ TESTS = \
bug438.cvc \
bug438b.cvc \
wrong-sel-simp.cvc \
- tenum-bug.smt2
+ tenum-bug.smt2 \
+ cdt-non-canon-stream.smt2
FAILING_TESTS = \
datatype-dump.cvc
diff --git a/test/regress/regress0/datatypes/cdt-non-canon-stream.smt2 b/test/regress/regress0/datatypes/cdt-non-canon-stream.smt2
new file mode 100644
index 000000000..4a111b41b
--- /dev/null
+++ b/test/regress/regress0/datatypes/cdt-non-canon-stream.smt2
@@ -0,0 +1,11 @@
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+(declare-codatatypes () ((list (cons (head Int) (tail list)))))
+
+(declare-fun x () list)
+(declare-fun y () list)
+
+(assert (= x (cons 0 (cons 0 x))))
+(assert (= y (cons 0 y)))
+(assert (not (= x y)))
+(check-sat)
diff --git a/test/regress/regress0/fmf/Makefile.am b/test/regress/regress0/fmf/Makefile.am
index e3bfd39b8..ca3907b0b 100644
--- a/test/regress/regress0/fmf/Makefile.am
+++ b/test/regress/regress0/fmf/Makefile.am
@@ -34,12 +34,12 @@ TESTS = \
fc-unsat-tot-2.smt2 \
fc-unsat-pent.smt2 \
fc-pigeonhole19.smt2 \
- Hoare-z3.931718.smt
+ Hoare-z3.931718.smt \
+ bug0909.smt2 \
+ lst-no-self-rev-exp.smt2
EXTRA_DIST = $(TESTS)
-# disabled for now :
-# bug0909.smt2
#if CVC4_BUILD_PROFILE_COMPETITION
#else
diff --git a/test/regress/regress0/fmf/lst-no-self-rev-exp.smt2 b/test/regress/regress0/fmf/lst-no-self-rev-exp.smt2
new file mode 100644
index 000000000..5e1f3de30
--- /dev/null
+++ b/test/regress/regress0/fmf/lst-no-self-rev-exp.smt2
@@ -0,0 +1,35 @@
+; COMMAND-LINE: --finite-model-find --dt-rewrite-error-sel
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(declare-datatypes () ((Nat (succ (pred Nat)) (zero)) (Lst (cons (hd Nat) (tl Lst)) (nil))))
+
+(declare-fun app (Lst Lst) Lst)
+(declare-fun rev (Lst) Lst)
+
+(declare-sort I_app 0)
+(declare-sort I_rev 0)
+
+(declare-fun a () I_app)
+(declare-fun b () I_app)
+(assert (not (= a b)))
+
+(declare-fun app_0_3 (I_app) Lst)
+(declare-fun app_1_4 (I_app) Lst)
+(declare-fun rev_0_5 (I_rev) Lst)
+
+(declare-fun xs () Lst)
+
+(assert (and
+
+(forall ((?i I_app)) (= (app (app_0_3 ?i) (app_1_4 ?i)) (ite (is-cons (app_0_3 ?i)) (cons (hd (app_0_3 ?i)) (app (tl (app_0_3 ?i)) (app_1_4 ?i))) (app_1_4 ?i))) )
+
+(forall ((?i I_rev)) (= (rev (rev_0_5 ?i)) (ite (is-cons (rev_0_5 ?i)) (app (rev (tl (rev_0_5 ?i))) (cons (hd (rev_0_5 ?i)) nil)) nil)) )
+
+(forall ((?i I_rev)) (or (not (is-cons (rev_0_5 ?i))) (and (not (forall ((?z I_app)) (not (and (= (app_0_3 ?z) (rev (tl (rev_0_5 ?i)))) (= (app_1_4 ?z) (cons (hd (rev_0_5 ?i)) nil)))) )) (not (forall ((?z I_rev)) (not (= (rev_0_5 ?z) (tl (rev_0_5 ?i)) )) )))) )
+
+(not (or (= xs (rev xs)) (forall ((?z I_rev)) (not (= (rev_0_5 ?z) xs)) )))
+
+))
+
+(check-sat)
+
diff --git a/test/regress/regress0/quantifiers/Makefile.am b/test/regress/regress0/quantifiers/Makefile.am
index 41f66f92f..f8cc9ea35 100644
--- a/test/regress/regress0/quantifiers/Makefile.am
+++ b/test/regress/regress0/quantifiers/Makefile.am
@@ -44,7 +44,8 @@ TESTS = \
ARI176e1.smt2 \
bi-artm-s.smt2 \
simp-typ-test.smt2 \
- macros-int-real.smt2
+ macros-int-real.smt2 \
+ stream-x2014-09-18-unsat.smt2
# regression can be solved with --finite-model-find --fmf-inst-engine
# set3.smt2
diff --git a/test/regress/regress0/quantifiers/burns4.smt2 b/test/regress/regress0/quantifiers/burns4.smt2
index 886d6f5c8..72023fd4f 100644
--- a/test/regress/regress0/quantifiers/burns4.smt2
+++ b/test/regress/regress0/quantifiers/burns4.smt2
@@ -1,3 +1,5 @@
+; COMMAND-LINE: --full-saturate-quant
+; EXPECT: unsat
(set-logic AUFLIA)
(set-info :source | Burns mutual exclusion protocol. This is a benchmark of the haRVey theorem prover. It was translated to SMT-LIB by Leonardo de Moura |)
(set-info :smt-lib-version 2.0)
diff --git a/test/regress/regress0/quantifiers/stream-x2014-09-18-unsat.smt2 b/test/regress/regress0/quantifiers/stream-x2014-09-18-unsat.smt2
new file mode 100644
index 000000000..615d43fe8
--- /dev/null
+++ b/test/regress/regress0/quantifiers/stream-x2014-09-18-unsat.smt2
@@ -0,0 +1,183 @@
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+(declare-sort A$ 0)
+(declare-sort B$ 0)
+(declare-sort A_set$ 0)
+(declare-sort B_set$ 0)
+(declare-sort A_a_fun$ 0)
+(declare-sort A_b_fun$ 0)
+(declare-sort B_a_fun$ 0)
+(declare-sort B_b_fun$ 0)
+(declare-sort A_stream_set$ 0)
+(declare-sort B_stream_set$ 0)
+(declare-sort A_a_stream_fun$ 0)
+(declare-sort A_b_stream_fun$ 0)
+(declare-sort A_stream_a_fun$ 0)
+(declare-sort A_stream_b_fun$ 0)
+(declare-sort B_a_stream_fun$ 0)
+(declare-sort B_b_stream_fun$ 0)
+(declare-sort B_stream_a_fun$ 0)
+(declare-sort B_stream_b_fun$ 0)
+(declare-sort A_stream_stream_set$ 0)
+(declare-sort B_stream_stream_set$ 0)
+(declare-sort A_stream_a_stream_fun$ 0)
+(declare-sort B_stream_b_stream_fun$ 0)
+(declare-sort A_stream_stream_a_stream_stream_fun$ 0)
+(declare-sort B_stream_stream_b_stream_stream_fun$ 0)
+(declare-sort A_stream_stream_stream_a_stream_stream_stream_fun$ 0)
+(declare-sort B_stream_stream_stream_b_stream_stream_stream_fun$ 0)
+(declare-datatypes () ((Nat$ (zero$) (suc$ (pred$ Nat$)))))
+(declare-codatatypes () ((A_stream$ (sCons$ (shd$ A$) (stl$ A_stream$)))
+ (B_stream$ (sCons$a (shd$a B$) (stl$a B_stream$)))
+ (B_stream_stream$ (sCons$b (shd$b B_stream$) (stl$b B_stream_stream$)))
+ (B_stream_stream_stream$ (sCons$c (shd$c B_stream_stream$) (stl$c B_stream_stream_stream$)))
+ (A_stream_stream$ (sCons$d (shd$d A_stream$) (stl$d A_stream_stream$)))
+ (A_stream_stream_stream$ (sCons$e (shd$e A_stream_stream$) (stl$e A_stream_stream_stream$)))))
+(declare-fun f$ () B_a_fun$)
+(declare-fun x$ () B$)
+(declare-fun id$ () B_b_fun$)
+(declare-fun id$a () A_a_fun$)
+(declare-fun id$b () B_stream_stream_b_stream_stream_fun$)
+(declare-fun id$c () A_stream_stream_a_stream_stream_fun$)
+(declare-fun id$d () A_stream_a_stream_fun$)
+(declare-fun id$e () B_stream_b_stream_fun$)
+(declare-fun id$f () B_stream_stream_stream_b_stream_stream_stream_fun$)
+(declare-fun id$g () A_stream_stream_stream_a_stream_stream_stream_fun$)
+(declare-fun smap$ (B_a_fun$ B_stream$) A_stream$)
+(declare-fun snth$ (B_stream_stream$ Nat$) B_stream$)
+(declare-fun sdrop$ (Nat$ B_stream_stream$) B_stream_stream$)
+(declare-fun smap$a (B_b_fun$) B_stream_b_stream_fun$)
+(declare-fun smap$b (A_a_fun$) A_stream_a_stream_fun$)
+(declare-fun smap$c (B_stream_stream_b_stream_stream_fun$) B_stream_stream_stream_b_stream_stream_stream_fun$)
+(declare-fun smap$d (A_stream_stream_a_stream_stream_fun$) A_stream_stream_stream_a_stream_stream_stream_fun$)
+(declare-fun smap$e (A_stream_a_stream_fun$) A_stream_stream_a_stream_stream_fun$)
+(declare-fun smap$f (B_stream_b_stream_fun$) B_stream_stream_b_stream_stream_fun$)
+(declare-fun smap$g (B_b_stream_fun$ B_stream$) B_stream_stream$)
+(declare-fun smap$h (B_a_stream_fun$ B_stream$) A_stream_stream$)
+(declare-fun smap$i (A_b_stream_fun$ A_stream$) B_stream_stream$)
+(declare-fun smap$j (A_a_stream_fun$ A_stream$) A_stream_stream$)
+(declare-fun smap$k (A_b_fun$ A_stream$) B_stream$)
+(declare-fun smap$l (B_stream_b_fun$ B_stream_stream$) B_stream$)
+(declare-fun smap$m (A_stream_b_fun$ A_stream_stream$) B_stream$)
+(declare-fun smap$n (B_stream_a_fun$ B_stream_stream$) A_stream$)
+(declare-fun smap$o (A_stream_a_fun$ A_stream_stream$) A_stream$)
+(declare-fun snth$a (B_stream$ Nat$) B$)
+(declare-fun snth$b (A_stream_stream$ Nat$) A_stream$)
+(declare-fun snth$c (A_stream$ Nat$) A$)
+(declare-fun member$ (B_stream$ B_stream_set$) Bool)
+(declare-fun sdrop$a (Nat$ B_stream$) B_stream$)
+(declare-fun sdrop$b (Nat$ A_stream_stream$) A_stream_stream$)
+(declare-fun sdrop$c (Nat$ A_stream$) A_stream$)
+(declare-fun fun_app$ (B_b_stream_fun$ B$) B_stream$)
+(declare-fun member$a (B$ B_set$) Bool)
+(declare-fun member$b (A$ A_set$) Bool)
+(declare-fun member$c (A_stream$ A_stream_set$) Bool)
+(declare-fun member$d (B_stream_stream$ B_stream_stream_set$) Bool)
+(declare-fun member$e (A_stream_stream$ A_stream_stream_set$) Bool)
+(declare-fun streams$ (B_set$) B_stream_set$)
+(declare-fun fun_app$a (A_a_stream_fun$ A$) A_stream$)
+(declare-fun fun_app$b (B_a_fun$ B$) A$)
+(declare-fun fun_app$c (B_stream_b_stream_fun$ B_stream$) B_stream$)
+(declare-fun fun_app$d (B_b_fun$ B$) B$)
+(declare-fun fun_app$e (A_stream_a_stream_fun$ A_stream$) A_stream$)
+(declare-fun fun_app$f (A_a_fun$ A$) A$)
+(declare-fun fun_app$g (B_stream_stream_stream_b_stream_stream_stream_fun$ B_stream_stream_stream$) B_stream_stream_stream$)
+(declare-fun fun_app$h (A_stream_stream_stream_a_stream_stream_stream_fun$ A_stream_stream_stream$) A_stream_stream_stream$)
+(declare-fun fun_app$i (A_stream_stream_a_stream_stream_fun$ A_stream_stream$) A_stream_stream$)
+(declare-fun fun_app$j (B_stream_stream_b_stream_stream_fun$ B_stream_stream$) B_stream_stream$)
+(declare-fun fun_app$k (B_a_stream_fun$ B$) A_stream$)
+(declare-fun fun_app$l (A_b_stream_fun$ A$) B_stream$)
+(declare-fun fun_app$m (A_b_fun$ A$) B$)
+(declare-fun fun_app$n (B_stream_b_fun$ B_stream$) B$)
+(declare-fun fun_app$o (A_stream_b_fun$ A_stream$) B$)
+(declare-fun fun_app$p (B_stream_a_fun$ B_stream$) A$)
+(declare-fun fun_app$q (A_stream_a_fun$ A_stream$) A$)
+(declare-fun siterate$ (B_b_fun$) B_b_stream_fun$)
+(declare-fun streams$a (A_set$) A_stream_set$)
+(declare-fun streams$b (B_stream_set$) B_stream_stream_set$)
+(declare-fun streams$c (A_stream_set$) A_stream_stream_set$)
+(declare-fun siterate$a (A_a_fun$) A_a_stream_fun$)
+(assert (! (not (= (smap$ f$ (fun_app$ (siterate$ id$) x$)) (fun_app$a (siterate$a id$a) (fun_app$b f$ x$)))) :named a0))
+(assert (! (forall ((?v0 B_b_fun$) (?v1 B$)) (= (fun_app$c (smap$a ?v0) (fun_app$ (siterate$ ?v0) ?v1)) (fun_app$ (siterate$ ?v0) (fun_app$d ?v0 ?v1)))) :named a1))
+(assert (! (forall ((?v0 A_a_fun$) (?v1 A$)) (= (fun_app$e (smap$b ?v0) (fun_app$a (siterate$a ?v0) ?v1)) (fun_app$a (siterate$a ?v0) (fun_app$f ?v0 ?v1)))) :named a2))
+(assert (! (forall ((?v0 B_stream_stream_stream$)) (= (fun_app$g (smap$c id$b) ?v0) ?v0)) :named a3))
+(assert (! (forall ((?v0 A_stream_stream_stream$)) (= (fun_app$h (smap$d id$c) ?v0) ?v0)) :named a4))
+(assert (! (forall ((?v0 A_stream_stream$)) (= (fun_app$i (smap$e id$d) ?v0) ?v0)) :named a5))
+(assert (! (forall ((?v0 B_stream_stream$)) (= (fun_app$j (smap$f id$e) ?v0) ?v0)) :named a6))
+(assert (! (forall ((?v0 B_stream$)) (= (fun_app$c (smap$a id$) ?v0) ?v0)) :named a7))
+(assert (! (forall ((?v0 A_stream$)) (= (fun_app$e (smap$b id$a) ?v0) ?v0)) :named a8))
+(assert (! (= (smap$c id$b) id$f) :named a9))
+(assert (! (= (smap$d id$c) id$g) :named a10))
+(assert (! (= (smap$e id$d) id$c) :named a11))
+(assert (! (= (smap$f id$e) id$b) :named a12))
+(assert (! (= (smap$a id$) id$e) :named a13))
+(assert (! (= (smap$b id$a) id$d) :named a14))
+(assert (! (forall ((?v0 B_stream_stream$)) (! (= (fun_app$j id$b ?v0) ?v0) :pattern ((fun_app$j id$b ?v0)))) :named a15))
+(assert (! (forall ((?v0 A_stream_stream$)) (! (= (fun_app$i id$c ?v0) ?v0) :pattern ((fun_app$i id$c ?v0)))) :named a16))
+(assert (! (forall ((?v0 A_stream$)) (! (= (fun_app$e id$d ?v0) ?v0) :pattern ((fun_app$e id$d ?v0)))) :named a17))
+(assert (! (forall ((?v0 B_stream$)) (! (= (fun_app$c id$e ?v0) ?v0) :pattern ((fun_app$c id$e ?v0)))) :named a18))
+(assert (! (forall ((?v0 B$)) (! (= (fun_app$d id$ ?v0) ?v0) :pattern ((fun_app$d id$ ?v0)))) :named a19))
+(assert (! (forall ((?v0 A$)) (! (= (fun_app$f id$a ?v0) ?v0) :pattern ((fun_app$f id$a ?v0)))) :named a20))
+(assert (! (forall ((?v0 B_stream_stream$)) (! (= (fun_app$j id$b ?v0) ?v0) :pattern ((fun_app$j id$b ?v0)))) :named a21))
+(assert (! (forall ((?v0 A_stream_stream$)) (! (= (fun_app$i id$c ?v0) ?v0) :pattern ((fun_app$i id$c ?v0)))) :named a22))
+(assert (! (forall ((?v0 A_stream$)) (! (= (fun_app$e id$d ?v0) ?v0) :pattern ((fun_app$e id$d ?v0)))) :named a23))
+(assert (! (forall ((?v0 B_stream$)) (! (= (fun_app$c id$e ?v0) ?v0) :pattern ((fun_app$c id$e ?v0)))) :named a24))
+(assert (! (forall ((?v0 B$)) (! (= (fun_app$d id$ ?v0) ?v0) :pattern ((fun_app$d id$ ?v0)))) :named a25))
+(assert (! (forall ((?v0 A$)) (! (= (fun_app$f id$a ?v0) ?v0) :pattern ((fun_app$f id$a ?v0)))) :named a26))
+(assert (! (forall ((?v0 B_b_stream_fun$) (?v1 B_stream$) (?v2 Nat$)) (= (snth$ (smap$g ?v0 ?v1) ?v2) (fun_app$ ?v0 (snth$a ?v1 ?v2)))) :named a27))
+(assert (! (forall ((?v0 B_a_stream_fun$) (?v1 B_stream$) (?v2 Nat$)) (= (snth$b (smap$h ?v0 ?v1) ?v2) (fun_app$k ?v0 (snth$a ?v1 ?v2)))) :named a28))
+(assert (! (forall ((?v0 A_b_stream_fun$) (?v1 A_stream$) (?v2 Nat$)) (= (snth$ (smap$i ?v0 ?v1) ?v2) (fun_app$l ?v0 (snth$c ?v1 ?v2)))) :named a29))
+(assert (! (forall ((?v0 A_a_stream_fun$) (?v1 A_stream$) (?v2 Nat$)) (= (snth$b (smap$j ?v0 ?v1) ?v2) (fun_app$a ?v0 (snth$c ?v1 ?v2)))) :named a30))
+(assert (! (forall ((?v0 A_b_fun$) (?v1 A_stream$) (?v2 Nat$)) (= (snth$a (smap$k ?v0 ?v1) ?v2) (fun_app$m ?v0 (snth$c ?v1 ?v2)))) :named a31))
+(assert (! (forall ((?v0 A_a_fun$) (?v1 A_stream$) (?v2 Nat$)) (= (snth$c (fun_app$e (smap$b ?v0) ?v1) ?v2) (fun_app$f ?v0 (snth$c ?v1 ?v2)))) :named a32))
+(assert (! (forall ((?v0 B_b_fun$) (?v1 B_stream$) (?v2 Nat$)) (= (snth$a (fun_app$c (smap$a ?v0) ?v1) ?v2) (fun_app$d ?v0 (snth$a ?v1 ?v2)))) :named a33))
+(assert (! (forall ((?v0 B_a_fun$) (?v1 B_stream$) (?v2 Nat$)) (= (snth$c (smap$ ?v0 ?v1) ?v2) (fun_app$b ?v0 (snth$a ?v1 ?v2)))) :named a34))
+(assert (! (forall ((?v0 Nat$) (?v1 B_b_stream_fun$) (?v2 B_stream$)) (= (sdrop$ ?v0 (smap$g ?v1 ?v2)) (smap$g ?v1 (sdrop$a ?v0 ?v2)))) :named a35))
+(assert (! (forall ((?v0 Nat$) (?v1 B_a_stream_fun$) (?v2 B_stream$)) (= (sdrop$b ?v0 (smap$h ?v1 ?v2)) (smap$h ?v1 (sdrop$a ?v0 ?v2)))) :named a36))
+(assert (! (forall ((?v0 Nat$) (?v1 A_b_stream_fun$) (?v2 A_stream$)) (= (sdrop$ ?v0 (smap$i ?v1 ?v2)) (smap$i ?v1 (sdrop$c ?v0 ?v2)))) :named a37))
+(assert (! (forall ((?v0 Nat$) (?v1 A_a_stream_fun$) (?v2 A_stream$)) (= (sdrop$b ?v0 (smap$j ?v1 ?v2)) (smap$j ?v1 (sdrop$c ?v0 ?v2)))) :named a38))
+(assert (! (forall ((?v0 Nat$) (?v1 A_b_fun$) (?v2 A_stream$)) (= (sdrop$a ?v0 (smap$k ?v1 ?v2)) (smap$k ?v1 (sdrop$c ?v0 ?v2)))) :named a39))
+(assert (! (forall ((?v0 Nat$) (?v1 A_a_fun$) (?v2 A_stream$)) (= (sdrop$c ?v0 (fun_app$e (smap$b ?v1) ?v2)) (fun_app$e (smap$b ?v1) (sdrop$c ?v0 ?v2)))) :named a40))
+(assert (! (forall ((?v0 Nat$) (?v1 B_b_fun$) (?v2 B_stream$)) (= (sdrop$a ?v0 (fun_app$c (smap$a ?v1) ?v2)) (fun_app$c (smap$a ?v1) (sdrop$a ?v0 ?v2)))) :named a41))
+(assert (! (forall ((?v0 Nat$) (?v1 B_a_fun$) (?v2 B_stream$)) (= (sdrop$c ?v0 (smap$ ?v1 ?v2)) (smap$ ?v1 (sdrop$a ?v0 ?v2)))) :named a42))
+(assert (! (forall ((?v0 B_b_stream_fun$) (?v1 B_stream$)) (= (shd$b (smap$g ?v0 ?v1)) (fun_app$ ?v0 (shd$a ?v1)))) :named a43))
+(assert (! (forall ((?v0 B_a_stream_fun$) (?v1 B_stream$)) (= (shd$d (smap$h ?v0 ?v1)) (fun_app$k ?v0 (shd$a ?v1)))) :named a44))
+(assert (! (forall ((?v0 A_b_stream_fun$) (?v1 A_stream$)) (= (shd$b (smap$i ?v0 ?v1)) (fun_app$l ?v0 (shd$ ?v1)))) :named a45))
+(assert (! (forall ((?v0 A_a_stream_fun$) (?v1 A_stream$)) (= (shd$d (smap$j ?v0 ?v1)) (fun_app$a ?v0 (shd$ ?v1)))) :named a46))
+(assert (! (forall ((?v0 A_b_fun$) (?v1 A_stream$)) (= (shd$a (smap$k ?v0 ?v1)) (fun_app$m ?v0 (shd$ ?v1)))) :named a47))
+(assert (! (forall ((?v0 A_a_fun$) (?v1 A_stream$)) (= (shd$ (fun_app$e (smap$b ?v0) ?v1)) (fun_app$f ?v0 (shd$ ?v1)))) :named a48))
+(assert (! (forall ((?v0 B_b_fun$) (?v1 B_stream$)) (= (shd$a (fun_app$c (smap$a ?v0) ?v1)) (fun_app$d ?v0 (shd$a ?v1)))) :named a49))
+(assert (! (forall ((?v0 B_a_fun$) (?v1 B_stream$)) (= (shd$ (smap$ ?v0 ?v1)) (fun_app$b ?v0 (shd$a ?v1)))) :named a50))
+(assert (! (forall ((?v0 B_b_stream_fun$) (?v1 B_stream$)) (= (stl$b (smap$g ?v0 ?v1)) (smap$g ?v0 (stl$a ?v1)))) :named a51))
+(assert (! (forall ((?v0 B_a_stream_fun$) (?v1 B_stream$)) (= (stl$d (smap$h ?v0 ?v1)) (smap$h ?v0 (stl$a ?v1)))) :named a52))
+(assert (! (forall ((?v0 A_b_stream_fun$) (?v1 A_stream$)) (= (stl$b (smap$i ?v0 ?v1)) (smap$i ?v0 (stl$ ?v1)))) :named a53))
+(assert (! (forall ((?v0 A_a_stream_fun$) (?v1 A_stream$)) (= (stl$d (smap$j ?v0 ?v1)) (smap$j ?v0 (stl$ ?v1)))) :named a54))
+(assert (! (forall ((?v0 A_b_fun$) (?v1 A_stream$)) (= (stl$a (smap$k ?v0 ?v1)) (smap$k ?v0 (stl$ ?v1)))) :named a55))
+(assert (! (forall ((?v0 A_a_fun$) (?v1 A_stream$)) (= (stl$ (fun_app$e (smap$b ?v0) ?v1)) (fun_app$e (smap$b ?v0) (stl$ ?v1)))) :named a56))
+(assert (! (forall ((?v0 B_b_fun$) (?v1 B_stream$)) (= (stl$a (fun_app$c (smap$a ?v0) ?v1)) (fun_app$c (smap$a ?v0) (stl$a ?v1)))) :named a57))
+(assert (! (forall ((?v0 B_a_fun$) (?v1 B_stream$)) (= (stl$ (smap$ ?v0 ?v1)) (smap$ ?v0 (stl$a ?v1)))) :named a58))
+(assert (! (forall ((?v0 B_b_stream_fun$) (?v1 B_stream$) (?v2 B_stream_stream$)) (= (= (smap$g ?v0 ?v1) ?v2) (forall ((?v3 Nat$)) (= (fun_app$ ?v0 (snth$a ?v1 ?v3)) (snth$ ?v2 ?v3))))) :named a59))
+(assert (! (forall ((?v0 B_a_stream_fun$) (?v1 B_stream$) (?v2 A_stream_stream$)) (= (= (smap$h ?v0 ?v1) ?v2) (forall ((?v3 Nat$)) (= (fun_app$k ?v0 (snth$a ?v1 ?v3)) (snth$b ?v2 ?v3))))) :named a60))
+(assert (! (forall ((?v0 A_b_stream_fun$) (?v1 A_stream$) (?v2 B_stream_stream$)) (= (= (smap$i ?v0 ?v1) ?v2) (forall ((?v3 Nat$)) (= (fun_app$l ?v0 (snth$c ?v1 ?v3)) (snth$ ?v2 ?v3))))) :named a61))
+(assert (! (forall ((?v0 A_a_stream_fun$) (?v1 A_stream$) (?v2 A_stream_stream$)) (= (= (smap$j ?v0 ?v1) ?v2) (forall ((?v3 Nat$)) (= (fun_app$a ?v0 (snth$c ?v1 ?v3)) (snth$b ?v2 ?v3))))) :named a62))
+(assert (! (forall ((?v0 A_b_fun$) (?v1 A_stream$) (?v2 B_stream$)) (= (= (smap$k ?v0 ?v1) ?v2) (forall ((?v3 Nat$)) (= (fun_app$m ?v0 (snth$c ?v1 ?v3)) (snth$a ?v2 ?v3))))) :named a63))
+(assert (! (forall ((?v0 A_a_fun$) (?v1 A_stream$) (?v2 A_stream$)) (= (= (fun_app$e (smap$b ?v0) ?v1) ?v2) (forall ((?v3 Nat$)) (= (fun_app$f ?v0 (snth$c ?v1 ?v3)) (snth$c ?v2 ?v3))))) :named a64))
+(assert (! (forall ((?v0 B_b_fun$) (?v1 B_stream$) (?v2 B_stream$)) (= (= (fun_app$c (smap$a ?v0) ?v1) ?v2) (forall ((?v3 Nat$)) (= (fun_app$d ?v0 (snth$a ?v1 ?v3)) (snth$a ?v2 ?v3))))) :named a65))
+(assert (! (forall ((?v0 B_a_fun$) (?v1 B_stream$) (?v2 A_stream$)) (= (= (smap$ ?v0 ?v1) ?v2) (forall ((?v3 Nat$)) (= (fun_app$b ?v0 (snth$a ?v1 ?v3)) (snth$c ?v2 ?v3))))) :named a66))
+(assert (! (forall ((?v0 B_stream$) (?v1 B_set$) (?v2 B_a_fun$) (?v3 A_set$)) (=> (and (member$ ?v0 (streams$ ?v1)) (forall ((?v4 B$)) (=> (member$a ?v4 ?v1) (member$b (fun_app$b ?v2 ?v4) ?v3)))) (member$c (smap$ ?v2 ?v0) (streams$a ?v3)))) :named a67))
+(assert (! (forall ((?v0 A_stream$) (?v1 A_set$) (?v2 A_b_fun$) (?v3 B_set$)) (=> (and (member$c ?v0 (streams$a ?v1)) (forall ((?v4 A$)) (=> (member$b ?v4 ?v1) (member$a (fun_app$m ?v2 ?v4) ?v3)))) (member$ (smap$k ?v2 ?v0) (streams$ ?v3)))) :named a68))
+(assert (! (forall ((?v0 A_stream$) (?v1 A_set$) (?v2 A_a_fun$) (?v3 A_set$)) (=> (and (member$c ?v0 (streams$a ?v1)) (forall ((?v4 A$)) (=> (member$b ?v4 ?v1) (member$b (fun_app$f ?v2 ?v4) ?v3)))) (member$c (fun_app$e (smap$b ?v2) ?v0) (streams$a ?v3)))) :named a69))
+(assert (! (forall ((?v0 B_stream$) (?v1 B_set$) (?v2 B_b_fun$) (?v3 B_set$)) (=> (and (member$ ?v0 (streams$ ?v1)) (forall ((?v4 B$)) (=> (member$a ?v4 ?v1) (member$a (fun_app$d ?v2 ?v4) ?v3)))) (member$ (fun_app$c (smap$a ?v2) ?v0) (streams$ ?v3)))) :named a70))
+(assert (! (forall ((?v0 B_stream_stream$) (?v1 B_stream_set$) (?v2 B_stream_b_fun$) (?v3 B_set$)) (=> (and (member$d ?v0 (streams$b ?v1)) (forall ((?v4 B_stream$)) (=> (member$ ?v4 ?v1) (member$a (fun_app$n ?v2 ?v4) ?v3)))) (member$ (smap$l ?v2 ?v0) (streams$ ?v3)))) :named a71))
+(assert (! (forall ((?v0 A_stream_stream$) (?v1 A_stream_set$) (?v2 A_stream_b_fun$) (?v3 B_set$)) (=> (and (member$e ?v0 (streams$c ?v1)) (forall ((?v4 A_stream$)) (=> (member$c ?v4 ?v1) (member$a (fun_app$o ?v2 ?v4) ?v3)))) (member$ (smap$m ?v2 ?v0) (streams$ ?v3)))) :named a72))
+(assert (! (forall ((?v0 B_stream_stream$) (?v1 B_stream_set$) (?v2 B_stream_a_fun$) (?v3 A_set$)) (=> (and (member$d ?v0 (streams$b ?v1)) (forall ((?v4 B_stream$)) (=> (member$ ?v4 ?v1) (member$b (fun_app$p ?v2 ?v4) ?v3)))) (member$c (smap$n ?v2 ?v0) (streams$a ?v3)))) :named a73))
+(assert (! (forall ((?v0 A_stream_stream$) (?v1 A_stream_set$) (?v2 A_stream_a_fun$) (?v3 A_set$)) (=> (and (member$e ?v0 (streams$c ?v1)) (forall ((?v4 A_stream$)) (=> (member$c ?v4 ?v1) (member$b (fun_app$q ?v2 ?v4) ?v3)))) (member$c (smap$o ?v2 ?v0) (streams$a ?v3)))) :named a74))
+(assert (! (forall ((?v0 B_stream$) (?v1 B_set$) (?v2 B_b_stream_fun$) (?v3 B_stream_set$)) (=> (and (member$ ?v0 (streams$ ?v1)) (forall ((?v4 B$)) (=> (member$a ?v4 ?v1) (member$ (fun_app$ ?v2 ?v4) ?v3)))) (member$d (smap$g ?v2 ?v0) (streams$b ?v3)))) :named a75))
+(assert (! (forall ((?v0 B_stream$) (?v1 B_set$) (?v2 B_a_stream_fun$) (?v3 A_stream_set$)) (=> (and (member$ ?v0 (streams$ ?v1)) (forall ((?v4 B$)) (=> (member$a ?v4 ?v1) (member$c (fun_app$k ?v2 ?v4) ?v3)))) (member$e (smap$h ?v2 ?v0) (streams$c ?v3)))) :named a76))
+(assert (! (forall ((?v0 B_b_fun$) (?v1 B$)) (= (shd$a (fun_app$ (siterate$ ?v0) ?v1)) ?v1)) :named a77))
+(assert (! (forall ((?v0 A_a_fun$) (?v1 A$)) (= (shd$ (fun_app$a (siterate$a ?v0) ?v1)) ?v1)) :named a78))
+(assert (! (forall ((?v0 B_b_fun$) (?v1 B$)) (= (stl$a (fun_app$ (siterate$ ?v0) ?v1)) (fun_app$ (siterate$ ?v0) (fun_app$d ?v0 ?v1)))) :named a79))
+(assert (! (forall ((?v0 A_a_fun$) (?v1 A$)) (= (stl$ (fun_app$a (siterate$a ?v0) ?v1)) (fun_app$a (siterate$a ?v0) (fun_app$f ?v0 ?v1)))) :named a80))
+(assert (! (forall ((?v0 B_b_fun$) (?v1 B$)) (= (fun_app$ (siterate$ ?v0) ?v1) (sCons$a ?v1 (fun_app$ (siterate$ ?v0) (fun_app$d ?v0 ?v1))))) :named a81))
+(assert (! (forall ((?v0 A_a_fun$) (?v1 A$)) (= (fun_app$a (siterate$a ?v0) ?v1) (sCons$ ?v1 (fun_app$a (siterate$a ?v0) (fun_app$f ?v0 ?v1))))) :named a82))
+(check-sat)
diff --git a/test/regress/regress0/strings/Makefile.am b/test/regress/regress0/strings/Makefile.am
index bd8e9ea93..c15e93cd8 100644
--- a/test/regress/regress0/strings/Makefile.am
+++ b/test/regress/regress0/strings/Makefile.am
@@ -47,8 +47,7 @@ TESTS = \
loop007.smt2 \
loop008.smt2 \
loop009.smt2 \
- reloop.smt2 \
- artemis-0512-nonterm.smt2
+ reloop.smt2
FAILING_TESTS =
@@ -57,6 +56,7 @@ EXTRA_DIST = $(TESTS) \
regexp002.smt2 \
type002.smt2
+# slow after changes on Nov 20 : artemis-0512-nonterm.smt2
# and make sure to distribute it
EXTRA_DIST +=
diff --git a/test/regress/run_regression b/test/regress/run_regression
index d234153a3..062458055 100755
--- a/test/regress/run_regression
+++ b/test/regress/run_regression
@@ -11,7 +11,7 @@
#
# ulimit -t 1 # For detecting long running regressions
-ulimit -s 10240 # Needed for some (esp. portfolio)
+ulimit -s 65000 # Needed for some (esp. portfolio and model-building)
prog=`basename "$0"`
diff --git a/test/unit/theory/theory_bv_white.h b/test/unit/theory/theory_bv_white.h
index eed173366..8fddf7394 100644
--- a/test/unit/theory/theory_bv_white.h
+++ b/test/unit/theory/theory_bv_white.h
@@ -53,21 +53,21 @@ public:
TheoryBVWhite() {}
-
void setUp() {
d_em = new ExprManager();
d_nm = NodeManager::fromExprManager(d_em);
d_smt = new SmtEngine(d_em);
d_scope = new SmtScope(d_smt);
d_smt->setOption("bitblast", SExpr("eager"));
- d_bb = new EagerBitblaster(NULL);
-
+ d_bb = new EagerBitblaster(dynamic_cast<TheoryBV*>(d_smt->d_theoryEngine->d_theoryTable[THEORY_BV]));
}
+
void tearDown() {
- // delete d_bb;
+ delete d_bb;
+ delete d_scope;
+ delete d_smt;
delete d_em;
}
-
void testBitblasterCore() {
Node x = d_nm->mkVar("x", d_nm->mkBitVectorType(16));
@@ -84,5 +84,4 @@ public:
bool res = d_bb->solve();
TS_ASSERT (res == false);
}
-
-};
+};/* class TheoryBVWhite */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback