summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am49
-rw-r--r--src/compat/cvc3_compat.cpp2
-rw-r--r--src/context/cdinsert_hashmap.h2
-rw-r--r--src/context/cdtrail_hashmap.h4
-rw-r--r--src/decision/decision_engine.cpp2
-rw-r--r--src/decision/decision_strategy.h2
-rw-r--r--src/decision/justification_heuristic.cpp585
-rw-r--r--src/decision/justification_heuristic.h139
-rw-r--r--src/expr/command.cpp8
-rw-r--r--src/expr/command.h2
-rw-r--r--src/expr/expr_template.h17
-rwxr-xr-xsrc/expr/mkexpr7
-rwxr-xr-xsrc/expr/mkkind7
-rwxr-xr-xsrc/expr/mkmetakind7
-rw-r--r--src/expr/node_builder.h25
-rw-r--r--src/expr/node_manager.cpp3
-rw-r--r--src/expr/options4
-rw-r--r--src/expr/options_handlers.h3
-rw-r--r--src/expr/type.i18
-rw-r--r--src/main/command_executor.cpp4
-rw-r--r--src/main/driver_unified.cpp40
-rw-r--r--src/main/main.cpp1
-rw-r--r--src/main/main.h4
-rw-r--r--src/main/options2
-rw-r--r--src/main/options_handlers.h12
-rw-r--r--src/main/util.cpp10
-rwxr-xr-xsrc/options/mkoptions10
-rw-r--r--src/parser/bounded_token_buffer.cpp2
-rw-r--r--src/parser/cvc/Cvc.g11
-rw-r--r--src/parser/smt1/Smt1.g17
-rw-r--r--src/parser/smt2/Smt2.g6
-rw-r--r--src/parser/smt2/smt2_input.h2
-rw-r--r--src/parser/tptp/Tptp.g6
-rw-r--r--src/parser/tptp/tptp.cpp2
-rw-r--r--src/printer/cvc/cvc_printer.cpp53
-rw-r--r--src/printer/smt2/smt2_printer.cpp46
-rw-r--r--src/proof/sat_proof.h4
-rw-r--r--src/prop/bvminisat/Makefile4
-rw-r--r--src/smt/boolean_terms.cpp18
-rw-r--r--src/smt/options2
-rw-r--r--src/smt/smt_engine.cpp569
-rw-r--r--src/smt/smt_engine.h2
-rw-r--r--src/theory/arith/arith_static_learner.cpp131
-rw-r--r--src/theory/arith/arith_static_learner.h18
-rw-r--r--src/theory/arith/constraint.cpp20
-rw-r--r--src/theory/arith/constraint.h8
-rw-r--r--src/theory/arith/delta_rational.h2
-rw-r--r--src/theory/arith/options8
-rw-r--r--src/theory/arith/options_handlers.h2
-rw-r--r--src/theory/arrays/theory_arrays.cpp6
-rw-r--r--src/theory/arrays/theory_arrays_model.cpp2
-rw-r--r--src/theory/arrays/theory_arrays_model.h100
-rw-r--r--src/theory/arrays/theory_arrays_rewriter.h11
-rw-r--r--src/theory/booleans/circuit_propagator.h18
-rw-r--r--src/theory/bv/bitblast_strategies.cpp102
-rw-r--r--src/theory/bv/bv_subtheory.h24
-rw-r--r--src/theory/bv/bv_subtheory_bitblast.cpp25
-rw-r--r--src/theory/bv/bv_subtheory_bitblast.h2
-rw-r--r--src/theory/bv/bv_subtheory_core.cpp102
-rw-r--r--src/theory/bv/bv_subtheory_core.h11
-rw-r--r--src/theory/bv/bv_subtheory_eq.cpp4
-rw-r--r--src/theory/bv/cd_set_collection.h8
-rw-r--r--src/theory/bv/slicer.cpp15
-rw-r--r--src/theory/bv/slicer.h54
-rw-r--r--src/theory/bv/theory_bv.cpp30
-rw-r--r--src/theory/bv/theory_bv.h6
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules.h6
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules_constant_evaluation.h46
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules_core.h26
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules_normalization.h36
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h38
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules_simplification.h76
-rw-r--r--src/theory/bv/theory_bv_utils.h6
-rw-r--r--src/theory/datatypes/theory_datatypes_type_rules.h4
-rw-r--r--src/theory/datatypes/type_enumerator.h90
-rwxr-xr-xsrc/theory/mkrewriter7
-rwxr-xr-xsrc/theory/mktheorytraits7
-rw-r--r--src/theory/model.cpp3
-rw-r--r--src/theory/model.h2
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/inst_gen.cpp594
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/inst_gen.h120
-rw-r--r--src/theory/quantifiers/inst_match.cpp12
-rw-r--r--src/theory/quantifiers/inst_match.h2
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/inst_match_generator.cpp1322
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/inst_match_generator.h386
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/inst_strategy_cbqi.cpp810
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/inst_strategy_cbqi.h218
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/inst_strategy_e_matching.cpp754
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/inst_strategy_e_matching.h272
-rw-r--r--src/theory/quantifiers/instantiation_engine.cpp22
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/macros.cpp750
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/macros.h124
-rw-r--r--src/theory/quantifiers/model_builder.cpp29
-rw-r--r--src/theory/quantifiers/model_builder.h2
-rw-r--r--src/theory/quantifiers/model_engine.cpp17
-rw-r--r--src/theory/quantifiers/options12
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/quant_util.cpp290
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/quant_util.h198
-rw-r--r--src/theory/quantifiers/quantifiers_attributes.cpp68
-rw-r--r--src/theory/quantifiers/quantifiers_attributes.h88
-rw-r--r--src/theory/quantifiers/quantifiers_rewriter.cpp211
-rw-r--r--src/theory/quantifiers/quantifiers_rewriter.h6
-rw-r--r--src/theory/quantifiers/term_database.cpp47
-rw-r--r--src/theory/quantifiers/term_database.h4
-rw-r--r--src/theory/quantifiers/theory_quantifiers.cpp6
-rw-r--r--src/theory/quantifiers/trigger.cpp91
-rw-r--r--src/theory/quantifiers/trigger.h4
-rw-r--r--src/theory/quantifiers_engine.cpp117
-rw-r--r--src/theory/quantifiers_engine.h13
-rw-r--r--src/theory/rep_set.cpp443
-rw-r--r--src/theory/rep_set.h210
-rw-r--r--[-rwxr-xr-x]src/theory/rewriterules/efficient_e_matching.cpp1372
-rw-r--r--[-rwxr-xr-x]src/theory/rewriterules/efficient_e_matching.h900
-rw-r--r--src/theory/rewriterules/rr_candidate_generator.h4
-rw-r--r--src/theory/rewriterules/rr_inst_match.h6
-rw-r--r--src/theory/rewriterules/rr_trigger.h1
-rw-r--r--src/theory/substitutions.cpp37
-rw-r--r--src/theory/substitutions.h6
-rw-r--r--src/theory/theory_engine.cpp14
-rw-r--r--src/theory/theory_engine.h30
-rw-r--r--src/theory/uf/options6
-rw-r--r--src/theory/uf/theory_uf.cpp12
-rw-r--r--src/theory/uf/theory_uf.h8
-rw-r--r--src/theory/uf/theory_uf_strong_solver.cpp807
-rw-r--r--src/theory/uf/theory_uf_strong_solver.h156
-rw-r--r--src/util/configuration.cpp29
-rw-r--r--src/util/configuration.h10
-rw-r--r--src/util/configuration_private.h7
-rw-r--r--src/util/integer.h.in2
-rw-r--r--src/util/rational.h.in2
-rw-r--r--[-rwxr-xr-x]src/util/sort_inference.cpp836
-rw-r--r--[-rwxr-xr-x]src/util/sort_inference.h148
-rw-r--r--src/util/tls.h.in2
133 files changed, 7579 insertions, 6827 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 40d3823e9..c9f928ba8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,8 +30,8 @@ libcvc4_la_LDFLAGS = -version-info $(LIBCVC4_VERSION)
# as a C library, which messes up exception handling support)
nodist_EXTRA_libcvc4_noinst_la_SOURCES = dummy.cpp
nodist_EXTRA_libcvc4_la_SOURCES = dummy.cpp
-libcvc4_noinst_la_SOURCES = subversion_versioninfo.cpp
-libcvc4_la_SOURCES = subversion_versioninfo.cpp
+libcvc4_noinst_la_SOURCES = git_versioninfo.cpp svn_versioninfo.cpp
+libcvc4_la_SOURCES = git_versioninfo.cpp svn_versioninfo.cpp
libcvc4_la_LIBADD = \
@builddir@/options/liboptions.la \
@builddir@/util/libutil.la \
@@ -67,9 +67,12 @@ libcvc4_noinst_la_LIBADD += \
endif
CLEANFILES = \
- subversion_versioninfo.cpp \
+ svn_versioninfo.cpp \
svninfo.tmp \
- svninfo
+ svninfo \
+ git_versioninfo.cpp \
+ gitinfo.tmp \
+ gitinfo
EXTRA_DIST = \
include/cvc4_private_library.h \
@@ -80,13 +83,13 @@ EXTRA_DIST = \
include/cvc4.h \
cvc4.i
-subversion_versioninfo.cpp: svninfo
+svn_versioninfo.cpp: svninfo
$(AM_V_GEN)( \
if test -s svninfo; then \
issvn=true; \
branch=`grep '^URL: ' svninfo | sed 's,.*/cvc4/,,'`; \
rev=`grep '^Revision: ' svninfo | awk '{print$$2}'`; \
- mods=`grep '^Modifications: ' svninfo | awk '{print$$2}'`; \
+ mods=`grep '^Modifications: ' svninfo | awk '{print$$2} END { if(!NR) print "false" }'`; \
else \
issvn=false; \
branch=unknown; \
@@ -108,6 +111,34 @@ svninfo: svninfo.tmp
svninfo.tmp:
$(AM_V_GEN)(cd "$(top_srcdir)" && svn info && echo "Modifications: `test -z \"\`svn status -q\`\" && echo false || echo true`") >"$@" 2>/dev/null || true
+git_versioninfo.cpp: gitinfo
+ $(AM_V_GEN)( \
+ if test -s gitinfo; then \
+ isgit=true; \
+ branch=`head -1 gitinfo`; \
+ rev=`head -2 gitinfo | tail -1 | awk '{print$$1}'`; \
+ mods=`grep '^Modifications: ' gitinfo | awk '{print$$2} END { if(!NR) print "false" }'`; \
+ else \
+ isgit=false; \
+ branch=unknown; \
+ rev=unknown; \
+ mods=false; \
+ fi; \
+ echo "#include \"util/configuration.h\""; \
+ echo "const bool ::CVC4::Configuration::IS_GIT_BUILD = $$isgit;"; \
+ echo "const char* const ::CVC4::Configuration::GIT_BRANCH_NAME = \"$$branch\";"; \
+ echo "const char* const ::CVC4::Configuration::GIT_COMMIT = \"$$rev\";"; \
+ echo "const bool ::CVC4::Configuration::GIT_HAS_MODIFICATIONS = $$mods;"; \
+ ) >"$@"
+# This .tmp business is to keep from having to re-compile options.cpp
+# (and then re-link the libraries) if nothing has changed.
+gitinfo: gitinfo.tmp
+ $(AM_V_GEN)diff -q gitinfo.tmp gitinfo &>/dev/null || mv gitinfo.tmp gitinfo || true
+# .PHONY ensures the .tmp version is always rebuilt (to check for any changes)
+.PHONY: gitinfo.tmp
+gitinfo.tmp:
+ $(AM_V_GEN)(cd "$(top_srcdir)" && sed 's,^ref: refs/heads/,,' .git/HEAD && git show-ref refs/heads/`sed 's,^ref: refs/heads/,,' .git/HEAD` && echo "Modifications: `test -z \"\`git status -s -uno\`\" && echo false || echo true`") >"$@" 2>/dev/null || true
+
install-data-local:
(echo include/cvc4.h; \
echo include/cvc4_public.h; \
@@ -120,7 +151,7 @@ install-data-local:
(cd "$(srcdir)" && find * -name '*.h' | \
xargs grep -l '^# *include *"cvc4.*_public\.h"')) | \
while read f; do \
- if expr "$$f" : ".*_\(template\|private\|test_utils\)\.h$$" &>/dev/null; then \
+ if expr "$$f" : ".*_\(template\|private\|private_library\|test_utils\)\.h$$" &>/dev/null; then \
continue; \
fi; \
d="$$(echo "$$f" | sed 's,^include/,,')"; \
@@ -150,7 +181,7 @@ uninstall-local:
(cd "$(srcdir)" && find * -name '*.h' | \
xargs grep -l '^# *include *"cvc4.*_public\.h"')) | \
while read f; do \
- if expr "$$f" : ".*_\(template\|private\|test_utils\)\.h$$" &>/dev/null; then \
+ if expr "$$f" : ".*_\(template\|private\|private_library\|test_utils\)\.h$$" &>/dev/null; then \
continue; \
fi; \
d="$$(echo "$$f" | sed 's,^include/,,')"; \
@@ -175,7 +206,7 @@ mostlyclean-local:
(cd "$(srcdir)" && find * -name '*.h' | \
xargs grep -l '^# *include *"cvc4.*_public\.h"')) | \
while read f; do \
- if expr "$$f" : ".*_\(template\|private\|test_utils\)\.h$$" &>/dev/null; then \
+ if expr "$$f" : ".*_\(template\|private\|private_library\|test_utils\)\.h$$" &>/dev/null; then \
continue; \
fi; \
d="$$(echo "$$f" | sed 's,^include/,,')"; \
diff --git a/src/compat/cvc3_compat.cpp b/src/compat/cvc3_compat.cpp
index 2a8673451..0cd35ce0d 100644
--- a/src/compat/cvc3_compat.cpp
+++ b/src/compat/cvc3_compat.cpp
@@ -1075,7 +1075,7 @@ Type ValidityChecker::subrangeType(const Expr& l, const Expr& r) {
}
Type ValidityChecker::subtypeType(const Expr& pred, const Expr& witness) {
- Unimplemented("Records not supported by CVC4 yet (sorry!)");
+ Unimplemented("Predicate subtyping not supported by CVC4 yet (sorry!)");
/*
if(witness.isNull()) {
return d_em->mkPredicateSubtype(pred);
diff --git a/src/context/cdinsert_hashmap.h b/src/context/cdinsert_hashmap.h
index 0c84eda80..74e2fcf28 100644
--- a/src/context/cdinsert_hashmap.h
+++ b/src/context/cdinsert_hashmap.h
@@ -392,7 +392,7 @@ class CDInsertHashMap <TNode, Data, HashFcn > : public ContextObj {
* If the key is a TNode and the backing (the hard node reference)
* for the key in another data structure removes the key at the same context
* the ref count could drop to 0. The key would then not be eligible to be
- * hashed. Getting the order right with a guarentee is to hard.
+ * hashed. Getting the order right with a guarantee is too hard.
*/
BOOST_STATIC_ASSERT(sizeof(Data) == 0);
diff --git a/src/context/cdtrail_hashmap.h b/src/context/cdtrail_hashmap.h
index 5f090341d..2d2020a16 100644
--- a/src/context/cdtrail_hashmap.h
+++ b/src/context/cdtrail_hashmap.h
@@ -540,7 +540,7 @@ public:
return d_trailMap->find(k);
}
- /** Returns an iterator to the begining of the map. */
+ /** Returns an iterator to the beginning of the map. */
const_iterator begin() const{
return d_trailMap->begin();
}
@@ -561,7 +561,7 @@ class CDTrailHashMap <TNode, Data, HashFcn > : public ContextObj {
* If the key is a TNode and the backing (the hard node reference)
* for the key in another data structure removes the key at the same context
* the ref count could drop to 0. The key would then not be eligible to be
- * hashed. Getting the order right with a guarentee is to hard.
+ * hashed. Getting the order right with a guarantee is too hard.
*/
BOOST_STATIC_ASSERT(sizeof(Data) == 0);
diff --git a/src/decision/decision_engine.cpp b/src/decision/decision_engine.cpp
index 9e8add752..08a3e49d0 100644
--- a/src/decision/decision_engine.cpp
+++ b/src/decision/decision_engine.cpp
@@ -96,7 +96,7 @@ bool DecisionEngine::isRelevant(SatVariable var)
SatValue DecisionEngine::getPolarity(SatVariable var)
{
- Debug("decision") << "getPolariry(" << var <<")" << std::endl;
+ Debug("decision") << "getPolarity(" << var <<")" << std::endl;
if(d_relevancyStrategy != NULL) {
Assert(isRelevant(var));
return d_relevancyStrategy->getPolarity( d_cnfStream->getNode(SatLiteral(var)) );
diff --git a/src/decision/decision_strategy.h b/src/decision/decision_strategy.h
index a3c0d1684..a2fda44fe 100644
--- a/src/decision/decision_strategy.h
+++ b/src/decision/decision_strategy.h
@@ -9,7 +9,7 @@
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
- ** \brief Decision stategy
+ ** \brief Decision strategy
**
** Decision strategy
**/
diff --git a/src/decision/justification_heuristic.cpp b/src/decision/justification_heuristic.cpp
index 46ec6f09f..0b63dfbe1 100644
--- a/src/decision/justification_heuristic.cpp
+++ b/src/decision/justification_heuristic.cpp
@@ -16,25 +16,6 @@
**
** It needs access to the simplified but non-clausal formula.
**/
-/*****************************************************************************/
-/*!
- * file search_sat.cpp
- * brief Implementation of Search engine with generic external sat solver
- *
- * Author: Clark Barrett
- *
- * Created: Wed Dec 7 21:00:24 2005
- *
- * <hr>
- *
- * License to use, copy, modify, sell and/or distribute this software
- * and its documentation for any purpose is hereby granted without
- * royalty, subject to the terms and conditions defined in the \ref
- * LICENSE file provided with this distribution.
- *
- * <hr>
- */
-/*****************************************************************************/
#include "justification_heuristic.h"
@@ -43,7 +24,158 @@
#include "theory/rewriter.h"
#include "util/ite_removal.h"
-// JustificationHeuristic stuff
+
+using namespace CVC4;
+
+JustificationHeuristic::JustificationHeuristic(CVC4::DecisionEngine* de,
+ context::Context *uc,
+ context::Context *c):
+ ITEDecisionStrategy(de, c),
+ d_justified(c),
+ d_prvsIndex(c, 0),
+ d_helfulness("decision::jh::helpfulness", 0),
+ d_giveup("decision::jh::giveup", 0),
+ d_timestat("decision::jh::time"),
+ d_assertions(uc),
+ d_iteAssertions(uc),
+ d_iteCache(),
+ d_visited(),
+ d_visitedComputeITE(),
+ d_curDecision() {
+ StatisticsRegistry::registerStat(&d_helfulness);
+ StatisticsRegistry::registerStat(&d_giveup);
+ StatisticsRegistry::registerStat(&d_timestat);
+ Trace("decision") << "Justification heuristic enabled" << std::endl;
+}
+
+JustificationHeuristic::~JustificationHeuristic() {
+ StatisticsRegistry::unregisterStat(&d_helfulness);
+ StatisticsRegistry::unregisterStat(&d_giveup);
+ StatisticsRegistry::unregisterStat(&d_timestat);
+}
+
+CVC4::prop::SatLiteral JustificationHeuristic::getNext(bool &stopSearch) {
+ Trace("decision") << "JustificationHeuristic::getNext()" << std::endl;
+ TimerStat::CodeTimer codeTimer(d_timestat);
+
+ d_visited.clear();
+
+ if(Trace.isOn("justified")) {
+ for(JustifiedSet::key_iterator i = d_justified.key_begin();
+ i != d_justified.key_end(); ++i) {
+ TNode n = *i;
+ SatLiteral l = d_decisionEngine->hasSatLiteral(n) ?
+ d_decisionEngine->getSatLiteral(n) : -1;
+ SatValue v = tryGetSatValue(n);
+ Trace("justified") <<"{ "<<l<<"}" << n <<": "<<v << std::endl;
+ }
+ }
+
+ for(unsigned i = d_prvsIndex; i < d_assertions.size(); ++i) {
+ Debug("decision") << "---" << std::endl << d_assertions[i] << std::endl;
+
+ // Sanity check: if it was false, aren't we inconsistent?
+ Assert( tryGetSatValue(d_assertions[i]) != SAT_VALUE_FALSE);
+
+ SatValue desiredVal = SAT_VALUE_TRUE;
+ SatLiteral litDecision;
+
+ litDecision = findSplitter(d_assertions[i], desiredVal);
+
+ if(litDecision != undefSatLiteral) {
+ d_prvsIndex = i;
+ return litDecision;
+ }
+ }
+
+ Trace("decision") << "jh: Nothing to split on " << std::endl;
+
+#if defined CVC4_DEBUG
+ bool alljustified = true;
+ for(unsigned i = 0 ; i < d_assertions.size() && alljustified ; ++i) {
+ TNode curass = d_assertions[i];
+ while(curass.getKind() == kind::NOT)
+ curass = curass[0];
+ alljustified &= checkJustified(curass);
+
+ if(Debug.isOn("decision")) {
+ if(!checkJustified(curass))
+ Debug("decision") << "****** Not justified [i="<<i<<"]: "
+ << d_assertions[i] << std::endl;
+ }
+ }
+ Assert(alljustified);
+#endif
+
+ // SAT solver can stop...
+ stopSearch = true;
+ d_decisionEngine->setResult(SAT_VALUE_TRUE);
+ return prop::undefSatLiteral;
+}
+
+
+inline void computeXorIffDesiredValues
+(Kind k, SatValue desiredVal, SatValue &desiredVal1, SatValue &desiredVal2)
+{
+ Assert(k == kind::IFF || k == kind::XOR);
+
+ bool shouldInvert =
+ (desiredVal == SAT_VALUE_TRUE && k == kind::IFF) ||
+ (desiredVal == SAT_VALUE_FALSE && k == kind::XOR);
+
+ if(desiredVal1 == SAT_VALUE_UNKNOWN &&
+ desiredVal2 == SAT_VALUE_UNKNOWN) {
+ // CHOICE: pick one of them arbitarily
+ desiredVal1 = SAT_VALUE_FALSE;
+ }
+
+ if(desiredVal2 == SAT_VALUE_UNKNOWN) {
+ desiredVal2 = shouldInvert ? invertValue(desiredVal1) : desiredVal1;
+ } else if(desiredVal1 == SAT_VALUE_UNKNOWN) {
+ desiredVal1 = shouldInvert ? invertValue(desiredVal2) : desiredVal2;
+ }
+}
+
+
+
+void JustificationHeuristic::addAssertions
+(const std::vector<Node> &assertions,
+ unsigned assertionsEnd,
+ IteSkolemMap iteSkolemMap) {
+
+ Trace("decision")
+ << "JustificationHeuristic::addAssertions()"
+ << " size = " << assertions.size()
+ << " assertionsEnd = " << assertionsEnd
+ << std::endl;
+
+ // Save the 'real' assertions locally
+ for(unsigned i = 0; i < assertionsEnd; ++i)
+ d_assertions.push_back(assertions[i]);
+
+ // Save mapping between ite skolems and ite assertions
+ for(IteSkolemMap::iterator i = iteSkolemMap.begin();
+ i != iteSkolemMap.end(); ++i) {
+
+ Trace("decision::jh::ite")
+ << " jh-ite: " << (i->first) << " maps to "
+ << assertions[(i->second)] << std::endl;
+ Assert(i->second >= assertionsEnd && i->second < assertions.size());
+
+ d_iteAssertions[i->first] = assertions[i->second];
+ }
+}
+
+SatLiteral JustificationHeuristic::findSplitter(TNode node,
+ SatValue desiredVal)
+{
+ d_curDecision = undefSatLiteral;
+ if(findSplitterRec(node, desiredVal)) {
+ ++d_helfulness;
+ }
+ return d_curDecision;
+}
+
void JustificationHeuristic::setJustified(TNode n)
{
@@ -67,9 +199,25 @@ SatValue JustificationHeuristic::tryGetSatValue(Node n)
}//end of else
}
+const JustificationHeuristic::IteList&
+JustificationHeuristic::getITEs(TNode n)
+{
+ IteCache::iterator it = d_iteCache.find(n);
+ if(it != d_iteCache.end()) {
+ return it->second;
+ } else {
+ // Compute the list of ITEs
+ // TODO: optimize by avoiding multiple lookup for d_iteCache[n]
+ d_iteCache[n] = IteList();
+ d_visitedComputeITE.clear();
+ computeITEs(n, d_iteCache[n]);
+ return d_iteCache[n];
+ }
+}
+
void JustificationHeuristic::computeITEs(TNode n, IteList &l)
{
- Trace("jh-ite") << " computeITEs( " << n << ", &l)\n";
+ Trace("decision::jh::ite") << " computeITEs( " << n << ", &l)\n";
d_visitedComputeITE.insert(n);
for(unsigned i=0; i<n.getNumChildren(); ++i) {
SkolemMap::iterator it2 = d_iteAssertions.find(n[i]);
@@ -84,35 +232,19 @@ void JustificationHeuristic::computeITEs(TNode n, IteList &l)
}
}
-const JustificationHeuristic::IteList& JustificationHeuristic::getITEs(TNode n)
-{
- IteCache::iterator it = d_iteCache.find(n);
- if(it != d_iteCache.end()) {
- return it->second;
- } else {
- // Compute the list of ITEs
- // TODO: optimize by avoiding multiple lookup for d_iteCache[n]
- d_iteCache[n] = IteList();
- d_visitedComputeITE.clear();
- computeITEs(n, d_iteCache[n]);
- return d_iteCache[n];
- }
-}
-
bool JustificationHeuristic::findSplitterRec(TNode node,
- SatValue desiredVal,
- SatLiteral* litDecision)
+ SatValue desiredVal)
{
/**
* Main idea
*
* Given a boolean formula "node", the goal is to try to make it
- * evaluate to "desiredVal" (true/false). for instance if "node" is a AND
+ * evaluate to "desiredVal" (true/false). for instance if "node" is a OR
* formula we want to make it evaluate to true, we'd like one of the
* children to be true. this is done recursively.
*/
- Trace("jh-findSplitterRec")
+ Trace("decision::jh")
<< "findSplitterRec(" << node << ", "
<< desiredVal << ", .. )" << std::endl;
@@ -122,13 +254,9 @@ bool JustificationHeuristic::findSplitterRec(TNode node,
node = node[0];
}
- if(Debug.isOn("decision")) {
- if(checkJustified(node))
- Debug("decision") << " justified, returning" << std::endl;
- }
-
/* Base case */
if (checkJustified(node)) {
+ Debug("decision::jh") << " justified, returning" << std::endl;
return false;
}
@@ -141,7 +269,6 @@ bool JustificationHeuristic::findSplitterRec(TNode node,
Debug("decision") << "no sat literal for this node" << std::endl;
}
}
- //Assert(litPresent); -- fails
#endif
// Get value of sat literal for the node, if there is one
@@ -151,11 +278,6 @@ bool JustificationHeuristic::findSplitterRec(TNode node,
Assert(desiredVal != SAT_VALUE_UNKNOWN, "expected known value");
/* Good luck, hope you can get what you want */
- // if(not (litVal == desiredVal || litVal == SAT_VALUE_UNKNOWN)) {
- // Warning() << "WARNING: IMPORTANT: Please look into this. Sat solver is asking for a decision" << std::endl
- // << "when the assertion we are trying to justify is already unsat. OR there is a bug" << std::endl;
- // GiveUpException();
- // }
Assert(litVal == desiredVal || litVal == SAT_VALUE_UNKNOWN,
"invariant violated");
@@ -164,247 +286,192 @@ bool JustificationHeuristic::findSplitterRec(TNode node,
theory::TheoryId tId = theory::kindToTheoryId(k);
/* Some debugging stuff */
- Debug("jh-findSplitterRec") << "kind = " << k << std::endl;
- Debug("jh-findSplitterRec") << "theoryId = " << tId << std::endl;
- Debug("jh-findSplitterRec") << "node = " << node << std::endl;
- Debug("jh-findSplitterRec") << "litVal = " << litVal << std::endl;
+ Debug("decision::jh") << "kind = " << k << std::endl
+ << "theoryId = " << tId << std::endl
+ << "node = " << node << std::endl
+ << "litVal = " << litVal << std::endl;
/**
- * If not in theory of booleans, and not a "boolean" EQUAL (IFF),
- * then check if this is something to split-on.
+ * If not in theory of booleans, check if this is something to split-on.
*/
- if(tId != theory::THEORY_BOOL
- // && !(k == kind::EQUAL && node[0].getType().isBoolean())
- ) {
-
- // if node has embedded ites -- which currently happens iff it got
- // replaced during ite removal -- then try to resolve that first
- const IteList& l = getITEs(node);
- Trace("jh-ite") << " ite size = " << l.size() << std::endl;
- /*d_visited.insert(node);*/
- for(IteList::const_iterator i = l.begin(); i != l.end(); ++i) {
- if(d_visited.find(i->first) == d_visited.end()) {
- d_visited.insert(i->first);
- Debug("jh-ite") << "jh-ite: adding visited " << i->first << std::endl;
- if(findSplitterRec(i->second, SAT_VALUE_TRUE, litDecision))
- return true;
- Debug("jh-ite") << "jh-ite: removing visited " << i->first << std::endl;
- d_visited.erase(i->first);
- } else {
- Debug("jh-ite") << "jh-ite: already visited " << i->first << std::endl;
- }
- }
+ if(tId != theory::THEORY_BOOL) {
+
+ // if node has embedded ites, resolve that first
+ if(handleEmbeddedITEs(node))
+ return true;
if(litVal != SAT_VALUE_UNKNOWN) {
setJustified(node);
return false;
- } else {
- Assert(d_decisionEngine->hasSatLiteral(node));
- /* if(not d_decisionEngine->hasSatLiteral(node))
- throw GiveUpException(); */
+ }
+ else {
Assert(d_decisionEngine->hasSatLiteral(node));
- SatVariable v = d_decisionEngine->getSatLiteral(node).getSatVariable();
- *litDecision = SatLiteral(v, desiredVal != SAT_VALUE_TRUE );
- Trace("decision") << "decision " << *litDecision << std::endl;
- Trace("decision") << "Found something to split. Glad to be able to serve you." << std::endl;
+ SatVariable v =
+ d_decisionEngine->getSatLiteral(node).getSatVariable();
+ d_curDecision = SatLiteral(v, desiredVal != SAT_VALUE_TRUE );
return true;
}
}
- SatValue valHard = SAT_VALUE_FALSE;
+ bool ret = false;
switch (k) {
case kind::CONST_BOOLEAN:
Assert(node.getConst<bool>() == false || desiredVal == SAT_VALUE_TRUE);
- Assert(node.getConst<bool>() == true || desiredVal == SAT_VALUE_FALSE);
- setJustified(node);
- return false;
+ Assert(node.getConst<bool>() == true || desiredVal == SAT_VALUE_FALSE);
+ break;
case kind::AND:
- valHard = SAT_VALUE_TRUE;
+ if (desiredVal == SAT_VALUE_FALSE)
+ ret = handleAndOrEasy(node, desiredVal);
+ else
+ ret = handleAndOrHard(node, desiredVal);
+ break;
case kind::OR:
- if (desiredVal == valHard) {
- int n = node.getNumChildren();
- for(int i = 0; i < n; ++i) {
- if (findSplitterRec(node[i], valHard, litDecision)) {
- return true;
- }
- }
- Assert(litPresent == false || litVal == valHard,
- "Output should be justified");
- setJustified(node);
- return false;
- }
- else {
- SatValue valEasy = invertValue(valHard);
- int n = node.getNumChildren();
- for(int i = 0; i < n; ++i) {
- Debug("jh-findSplitterRec") << " node[i] = " << node[i] << " "
- << tryGetSatValue(node[i]) << std::endl;
- if ( tryGetSatValue(node[i]) != valHard) {
- Debug("jh-findSplitterRec") << "hi"<< std::endl;
- if (findSplitterRec(node[i], valEasy, litDecision)) {
- return true;
- }
- Assert(litPresent == false || litVal == valEasy, "Output should be justified");
- setJustified(node);
- return false;
- }
- }
- if(Debug.isOn("jh-findSplitterRec")) {
- Debug("jh-findSplitterRec") << " * ** " << std::endl;
- Debug("jh-findSplitterRec") << node.getKind() << " "
- << node << std::endl;
- for(unsigned i = 0; i < node.getNumChildren(); ++i)
- Debug("jh-findSplitterRec") << "child: " << tryGetSatValue(node[i])
- << std::endl;
- Debug("jh-findSplitterRec") << "node: " << tryGetSatValue(node)
- << std::endl;
- }
- Assert(false, "No controlling input found (2)");
- }
+ if (desiredVal == SAT_VALUE_FALSE)
+ ret = handleAndOrHard(node, desiredVal);
+ else
+ ret = handleAndOrEasy(node, desiredVal);
break;
case kind::IMPLIES:
- //throw GiveUpException();
- Assert(node.getNumChildren() == 2, "Expected 2 fanins");
- if (desiredVal == SAT_VALUE_FALSE) {
- if (findSplitterRec(node[0], SAT_VALUE_TRUE, litDecision)) {
- return true;
- }
- if (findSplitterRec(node[1], SAT_VALUE_FALSE, litDecision)) {
- return true;
- }
- Assert(litPresent == false || litVal == SAT_VALUE_FALSE,
- "Output should be justified");
- setJustified(node);
- return false;
- }
- else {
- if (tryGetSatValue(node[0]) != SAT_VALUE_TRUE) {
- if (findSplitterRec(node[0], SAT_VALUE_FALSE, litDecision)) {
- return true;
- }
- Assert(litPresent == false || litVal == SAT_VALUE_TRUE,
- "Output should be justified");
- setJustified(node);
- return false;
- }
- if (tryGetSatValue(node[1]) != SAT_VALUE_FALSE) {
- if (findSplitterRec(node[1], SAT_VALUE_TRUE, litDecision)) {
- return true;
- }
- Assert(litPresent == false || litVal == SAT_VALUE_TRUE,
- "Output should be justified");
- setJustified(node);
- return false;
- }
- Assert(false, "No controlling input found (3)");
- }
- break;
-
- case kind::IFF:
- //throw GiveUpException();
- {
- SatValue val = tryGetSatValue(node[0]);
- if (val != SAT_VALUE_UNKNOWN) {
- if (findSplitterRec(node[0], val, litDecision)) {
- return true;
- }
- if (desiredVal == SAT_VALUE_FALSE) val = invertValue(val);
+ if (desiredVal == SAT_VALUE_FALSE)
+ ret = handleBinaryHard(node[0], SAT_VALUE_TRUE,
+ node[1], SAT_VALUE_FALSE);
- if (findSplitterRec(node[1], val, litDecision)) {
- return true;
- }
- Assert(litPresent == false || litVal == desiredVal,
- "Output should be justified");
- setJustified(node);
- return false;
- }
- else {
- val = tryGetSatValue(node[1]);
- if (val == SAT_VALUE_UNKNOWN) val = SAT_VALUE_FALSE;
- if (desiredVal == SAT_VALUE_FALSE) val = invertValue(val);
- if (findSplitterRec(node[0], val, litDecision)) {
- return true;
- }
- Assert(false, "Unable to find controlling input (4)");
- }
+ else
+ ret = handleBinaryEasy(node[0], SAT_VALUE_FALSE,
+ node[1], SAT_VALUE_TRUE);
break;
- }
-
- case kind::XOR:
- //throw GiveUpException();
- {
- SatValue val = tryGetSatValue(node[0]);
- if (val != SAT_VALUE_UNKNOWN) {
- if (findSplitterRec(node[0], val, litDecision)) {
- return true;
- }
- if (desiredVal == SAT_VALUE_TRUE) val = invertValue(val);
- if (findSplitterRec(node[1], val, litDecision)) {
- return true;
- }
- Assert(litPresent == false || litVal == desiredVal,
- "Output should be justified");
- setJustified(node);
- return false;
- }
- else {
- SatValue val = tryGetSatValue(node[1]);
- if (val == SAT_VALUE_UNKNOWN) val = SAT_VALUE_FALSE;
- if (desiredVal == SAT_VALUE_TRUE) val = invertValue(val);
- if (findSplitterRec(node[0], val, litDecision)) {
- return true;
- }
- Assert(false, "Unable to find controlling input (5)");
- }
+ case kind::XOR:
+ case kind::IFF: {
+ SatValue desiredVal1 = tryGetSatValue(node[0]);
+ SatValue desiredVal2 = tryGetSatValue(node[1]);
+ computeXorIffDesiredValues(k, desiredVal, desiredVal1, desiredVal2);
+ ret = handleBinaryHard(node[0], desiredVal1,
+ node[1], desiredVal2);
break;
}
- case kind::ITE: {
- //[0]: if, [1]: then, [2]: else
- SatValue ifVal = tryGetSatValue(node[0]);
- if (ifVal == SAT_VALUE_UNKNOWN) {
-
- // are we better off trying false? if not, try true
- SatValue ifDesiredVal =
- (tryGetSatValue(node[2]) == desiredVal ||
- tryGetSatValue(node[1]) == invertValue(desiredVal))
- ? SAT_VALUE_FALSE : SAT_VALUE_TRUE;
-
- if(findSplitterRec(node[0], ifDesiredVal, litDecision)) {
- return true;
- }
- Assert(false, "No controlling input found (6)");
- } else {
-
- // Try to justify 'if'
- if (findSplitterRec(node[0], ifVal, litDecision)) {
- return true;
- }
-
- // If that was successful, we need to go into only one of 'then'
- // or 'else'
- int ch = (ifVal == SAT_VALUE_TRUE) ? 1 : 2;
- int chVal = tryGetSatValue(node[ch]);
- if( (chVal == SAT_VALUE_UNKNOWN || chVal == desiredVal)
- && findSplitterRec(node[ch], desiredVal, litDecision) ) {
- return true;
- }
- }
- Assert(litPresent == false || litVal == desiredVal,
- "Output should be justified");
- setJustified(node);
- return false;
- }
+ case kind::ITE:
+ ret = handleITE(node, desiredVal);
+ break;
default:
Assert(false, "Unexpected Boolean operator");
break;
}//end of switch(k)
- Unreachable();
+ if(ret == false) {
+ Assert(litPresent == false || litVal == desiredVal,
+ "Output should be justified");
+ setJustified(node);
+ }
+ return ret;
}/* findRecSplit method */
+
+bool JustificationHeuristic::handleAndOrEasy(TNode node,
+ SatValue desiredVal)
+{
+ Assert( (node.getKind() == kind::AND and desiredVal == SAT_VALUE_FALSE) or
+ (node.getKind() == kind::OR and desiredVal == SAT_VALUE_TRUE) );
+
+ int numChildren = node.getNumChildren();
+ SatValue desiredValInverted = invertValue(desiredVal);
+ for(int i = 0; i < numChildren; ++i)
+ if ( tryGetSatValue(node[i]) != desiredValInverted )
+ return findSplitterRec(node[i], desiredVal);
+ Assert(false, "handleAndOrEasy: No controlling input found");
+ return false;
+}
+
+bool JustificationHeuristic::handleAndOrHard(TNode node,
+ SatValue desiredVal) {
+ Assert( (node.getKind() == kind::AND and desiredVal == SAT_VALUE_TRUE) or
+ (node.getKind() == kind::OR and desiredVal == SAT_VALUE_FALSE) );
+
+ int numChildren = node.getNumChildren();
+ for(int i = 0; i < numChildren; ++i)
+ if (findSplitterRec(node[i], desiredVal))
+ return true;
+ return false;
+}
+
+bool JustificationHeuristic::handleBinaryEasy(TNode node1,
+ SatValue desiredVal1,
+ TNode node2,
+ SatValue desiredVal2)
+{
+ if ( tryGetSatValue(node1) != invertValue(desiredVal1) )
+ return findSplitterRec(node1, desiredVal1);
+ if ( tryGetSatValue(node2) != invertValue(desiredVal2) )
+ return findSplitterRec(node2, desiredVal2);
+ Assert(false, "handleBinaryEasy: No controlling input found");
+ return false;
+}
+
+bool JustificationHeuristic::handleBinaryHard(TNode node1,
+ SatValue desiredVal1,
+ TNode node2,
+ SatValue desiredVal2)
+{
+ if( findSplitterRec(node1, desiredVal1) )
+ return true;
+ return findSplitterRec(node2, desiredVal2);
+}
+
+bool JustificationHeuristic::handleITE(TNode node, SatValue desiredVal)
+{
+ Debug("decision::jh") << " handleITE (" << node << ", "
+ << desiredVal << std::endl;
+
+ //[0]: if, [1]: then, [2]: else
+ SatValue ifVal = tryGetSatValue(node[0]);
+ if (ifVal == SAT_VALUE_UNKNOWN) {
+
+ // are we better off trying false? if not, try true [CHOICE]
+ SatValue ifDesiredVal =
+ (tryGetSatValue(node[2]) == desiredVal ||
+ tryGetSatValue(node[1]) == invertValue(desiredVal))
+ ? SAT_VALUE_FALSE : SAT_VALUE_TRUE;
+
+ if(findSplitterRec(node[0], ifDesiredVal)) return true;
+
+ Assert(false, "No controlling input found (6)");
+ } else {
+ // Try to justify 'if'
+ if(findSplitterRec(node[0], ifVal)) return true;
+
+ // If that was successful, we need to go into only one of 'then'
+ // or 'else'
+ int ch = (ifVal == SAT_VALUE_TRUE) ? 1 : 2;
+
+ // STALE code: remove after tests or mar 2013, whichever earlier
+ // int chVal = tryGetSatValue(node[ch]);
+ // Assert(chVal == SAT_VALUE_UNKNOWN || chVal == desiredVal);
+ // end STALE code: remove
+
+ if( findSplitterRec(node[ch], desiredVal) ) {
+ return true;
+ }
+ }// else (...ifVal...)
+ return false;
+}
+
+bool JustificationHeuristic::handleEmbeddedITEs(TNode node)
+{
+ const IteList& l = getITEs(node);
+ Trace("decision::jh::ite") << " ite size = " << l.size() << std::endl;
+
+ for(IteList::const_iterator i = l.begin(); i != l.end(); ++i) {
+ if(d_visited.find(i->first) == d_visited.end()) {
+ d_visited.insert(i->first);
+ if(findSplitterRec(i->second, SAT_VALUE_TRUE))
+ return true;
+ d_visited.erase(i->first);
+ }
+ }
+ return false;
+}
diff --git a/src/decision/justification_heuristic.h b/src/decision/justification_heuristic.h
index ea67fee29..91c21d981 100644
--- a/src/decision/justification_heuristic.h
+++ b/src/decision/justification_heuristic.h
@@ -36,13 +36,6 @@ namespace CVC4 {
namespace decision {
-class GiveUpException : public Exception {
-public:
- GiveUpException() :
- Exception("justification heuristic: giving up") {
- }
-};/* class GiveUpException */
-
class JustificationHeuristic : public ITEDecisionStrategy {
typedef std::vector<pair<TNode,TNode> > IteList;
typedef hash_map<TNode,IteList,TNodeHashFunction> IteCache;
@@ -84,130 +77,29 @@ class JustificationHeuristic : public ITEDecisionStrategy {
* function
*/
hash_set<TNode,TNodeHashFunction> d_visitedComputeITE;
+
+ /** current decision for the recursive call */
+ SatLiteral d_curDecision;
public:
JustificationHeuristic(CVC4::DecisionEngine* de,
context::Context *uc,
- context::Context *c):
- ITEDecisionStrategy(de, c),
- d_justified(c),
- d_prvsIndex(c, 0),
- d_helfulness("decision::jh::helpfulness", 0),
- d_giveup("decision::jh::giveup", 0),
- d_timestat("decision::jh::time"),
- d_assertions(uc),
- d_iteAssertions(uc) {
- StatisticsRegistry::registerStat(&d_helfulness);
- StatisticsRegistry::registerStat(&d_giveup);
- StatisticsRegistry::registerStat(&d_timestat);
- Trace("decision") << "Justification heuristic enabled" << std::endl;
- }
- ~JustificationHeuristic() {
- StatisticsRegistry::unregisterStat(&d_helfulness);
- StatisticsRegistry::unregisterStat(&d_giveup);
- StatisticsRegistry::unregisterStat(&d_timestat);
- }
- prop::SatLiteral getNext(bool &stopSearch) {
- Trace("decision") << "JustificationHeuristic::getNext()" << std::endl;
- TimerStat::CodeTimer codeTimer(d_timestat);
-
- d_visited.clear();
-
- if(Trace.isOn("justified")) {
- for(JustifiedSet::key_iterator i = d_justified.key_begin();
- i != d_justified.key_end(); ++i) {
- TNode n = *i;
- SatLiteral l = d_decisionEngine->hasSatLiteral(n) ?
- d_decisionEngine->getSatLiteral(n) : -1;
- SatValue v = tryGetSatValue(n);
- Trace("justified") <<"{ "<<l<<"}" << n <<": "<<v << std::endl;
- }
- }
-
- for(unsigned i = d_prvsIndex; i < d_assertions.size(); ++i) {
- Debug("decision") << "---" << std::endl << d_assertions[i] << std::endl;
-
- // Sanity check: if it was false, aren't we inconsistent?
- Assert( tryGetSatValue(d_assertions[i]) != SAT_VALUE_FALSE);
-
- SatValue desiredVal = SAT_VALUE_TRUE;
- SatLiteral litDecision;
- try {
- litDecision = findSplitter(d_assertions[i], desiredVal);
- }catch(GiveUpException &e) {
- return prop::undefSatLiteral;
- }
-
- if(litDecision != undefSatLiteral)
- return litDecision;
- }
-
- Trace("decision") << "jh: Nothing to split on " << std::endl;
-
-#if defined CVC4_DEBUG
- bool alljustified = true;
- for(unsigned i = 0 ; i < d_assertions.size() && alljustified ; ++i) {
- TNode curass = d_assertions[i];
- while(curass.getKind() == kind::NOT)
- curass = curass[0];
- alljustified &= checkJustified(curass);
-
- if(Debug.isOn("decision")) {
- if(!checkJustified(curass))
- Debug("decision") << "****** Not justified [i="<<i<<"]: "
- << d_assertions[i] << std::endl;
- }
- }
- Assert(alljustified);
-#endif
-
- // SAT solver can stop...
- stopSearch = true;
- d_decisionEngine->setResult(SAT_VALUE_TRUE);
- return prop::undefSatLiteral;
- }
+ context::Context *c);
+
+ ~JustificationHeuristic();
+
+ prop::SatLiteral getNext(bool &stopSearch);
void addAssertions(const std::vector<Node> &assertions,
unsigned assertionsEnd,
- IteSkolemMap iteSkolemMap) {
- Trace("decision")
- << "JustificationHeuristic::addAssertions()"
- << " size = " << assertions.size()
- << " assertionsEnd = " << assertionsEnd
- << std::endl;
-
- // Save the 'real' assertions locally
- for(unsigned i = 0; i < assertionsEnd; ++i)
- d_assertions.push_back(assertions[i]);
-
- // Save mapping between ite skolems and ite assertions
- for(IteSkolemMap::iterator i = iteSkolemMap.begin();
- i != iteSkolemMap.end(); ++i) {
- Trace("jh-ite") << " jh-ite: " << (i->first) << " maps to "
- << assertions[(i->second)] << std::endl;
- Assert(i->second >= assertionsEnd && i->second < assertions.size());
- d_iteAssertions[i->first] = assertions[i->second];
- }
- }
+ IteSkolemMap iteSkolemMap);
private:
- SatLiteral findSplitter(TNode node, SatValue desiredVal)
- {
- bool ret;
- SatLiteral litDecision;
- ret = findSplitterRec(node, desiredVal, &litDecision);
- if(ret == true) {
- Debug("decision") << "Yippee!!" << std::endl;
- ++d_helfulness;
- return litDecision;
- } else {
- return undefSatLiteral;
- }
- }
+ SatLiteral findSplitter(TNode node, SatValue desiredVal);
/**
* Do all the hard work.
*/
- bool findSplitterRec(TNode node, SatValue value, SatLiteral* litDecision);
+ bool findSplitterRec(TNode node, SatValue value);
/* Helper functions */
void setJustified(TNode);
@@ -222,6 +114,15 @@ private:
/* Compute all term-ITEs in a node recursively */
void computeITEs(TNode n, IteList &l);
+
+ bool handleAndOrEasy(TNode node, SatValue desiredVal);
+ bool handleAndOrHard(TNode node, SatValue desiredVal);
+ bool handleBinaryEasy(TNode node1, SatValue desiredVal1,
+ TNode node2, SatValue desiredVal2);
+ bool handleBinaryHard(TNode node1, SatValue desiredVal1,
+ TNode node2, SatValue desiredVal2);
+ bool handleITE(TNode node, SatValue desiredVal);
+ bool handleEmbeddedITEs(TNode node);
};/* class JustificationHeuristic */
}/* namespace decision */
diff --git a/src/expr/command.cpp b/src/expr/command.cpp
index fa2a8d1f2..9edc77e39 100644
--- a/src/expr/command.cpp
+++ b/src/expr/command.cpp
@@ -703,8 +703,12 @@ Expr SimplifyCommand::getTerm() const throw() {
}
void SimplifyCommand::invoke(SmtEngine* smtEngine) throw() {
- d_result = smtEngine->simplify(d_term);
- d_commandStatus = CommandSuccess::instance();
+ try {
+ d_result = smtEngine->simplify(d_term);
+ d_commandStatus = CommandSuccess::instance();
+ } catch(exception& e) {
+ d_commandStatus = new CommandFailure(e.what());
+ }
}
Expr SimplifyCommand::getResult() const throw() {
diff --git a/src/expr/command.h b/src/expr/command.h
index 342aec5ff..9877044fb 100644
--- a/src/expr/command.h
+++ b/src/expr/command.h
@@ -401,7 +401,7 @@ public:
/**
* The command when an attribute is set by a user. In SMT-LIBv2 this is done
- * via the syntax (! expr :atrr)
+ * via the syntax (! expr :attr)
*/
class CVC4_PUBLIC SetUserAttributeCommand : public Command {
protected:
diff --git a/src/expr/expr_template.h b/src/expr/expr_template.h
index b353ec5dc..f5df63f8c 100644
--- a/src/expr/expr_template.h
+++ b/src/expr/expr_template.h
@@ -654,6 +654,11 @@ public:
l = options::defaultExprDepth();
}
if(l == 0) {
+ // if called from outside the library, we may not have options
+ // available to us at this point (or perhaps the output language
+ // is not set in Options). Default to something reasonable, but
+ // don't set "l" since that would make it "sticky" for this
+ // stream.
return s_defaultPrintDepth;
}
}
@@ -797,7 +802,17 @@ public:
if(l == 0) {
// set the default dag setting on this ostream
// (offset by one to detect whether default has been set yet)
- l = s_defaultDag + 1;
+ if(&Options::current() != NULL) {
+ l = options::defaultDagThresh() + 1;
+ }
+ if(l == 0) {
+ // if called from outside the library, we may not have options
+ // available to us at this point (or perhaps the output language
+ // is not set in Options). Default to something reasonable, but
+ // don't set "l" since that would make it "sticky" for this
+ // stream.
+ return s_defaultDag + 1;
+ }
}
return static_cast<size_t>(l - 1);
}
diff --git a/src/expr/mkexpr b/src/expr/mkexpr
index 5134d561e..ca89dfc91 100755
--- a/src/expr/mkexpr
+++ b/src/expr/mkexpr
@@ -2,7 +2,7 @@
#
# mkexpr
# Morgan Deters <mdeters@cs.nyu.edu> for CVC4
-# Copyright (c) 2010-2012 The CVC4 Project
+# Copyright (c) 2010-2013 The CVC4 Project
#
# The purpose of this script is to create {expr,expr_manager}.{h,cpp}
# from template files and a list of theory kinds. Basically it just
@@ -15,7 +15,7 @@
# Output is to standard out.
#
-copyright=2010-2012
+copyright=2010-2013
filename=`basename "$1" | sed 's,_template,,'`
@@ -23,7 +23,8 @@ cat <<EOF
/********************* */
/** $filename
**
- ** Copyright $copyright The AcSys Group, New York University, and as below.
+ ** Copyright $copyright New York University and The University of Iowa,
+ ** and as below.
**
** This file automatically generated by:
**
diff --git a/src/expr/mkkind b/src/expr/mkkind
index 786d6187b..f8432466d 100755
--- a/src/expr/mkkind
+++ b/src/expr/mkkind
@@ -2,7 +2,7 @@
#
# mkkind
# Morgan Deters <mdeters@cs.nyu.edu> for CVC4
-# Copyright (c) 2010-2012 The CVC4 Project
+# Copyright (c) 2010-2013 The CVC4 Project
#
# The purpose of this script is to create kind.h (and also
# type_properties.h) from a template and a list of theory kinds.
@@ -14,7 +14,7 @@
# Output is to standard out.
#
-copyright=2010-2012
+copyright=2010-2013
filename=`basename "$1" | sed 's,_template,,'`
@@ -22,7 +22,8 @@ cat <<EOF
/********************* */
/** $filename
**
- ** Copyright $copyright The AcSys Group, New York University, and as below.
+ ** Copyright $copyright New York University and The University of Iowa,
+ ** and as below.
**
** This header file automatically generated by:
**
diff --git a/src/expr/mkmetakind b/src/expr/mkmetakind
index 47ffc77f9..160a74eac 100755
--- a/src/expr/mkmetakind
+++ b/src/expr/mkmetakind
@@ -2,7 +2,7 @@
#
# mkmetakind
# Morgan Deters <mdeters@cs.nyu.edu> for CVC4
-# Copyright (c) 2010-2012 The CVC4 Project
+# Copyright (c) 2010-2013 The CVC4 Project
#
# The purpose of this script is to create metakind.h from a template
# and a list of theory kinds.
@@ -17,13 +17,14 @@
# Output is to standard out.
#
-copyright=2010-2012
+copyright=2010-2013
cat <<EOF
/********************* */
/** metakind.h
**
- ** Copyright $copyright The AcSys Group, New York University, and as below.
+ ** Copyright $copyright New York University and The University of Iowa,
+ ** and as below.
**
** This header file automatically generated by:
**
diff --git a/src/expr/node_builder.h b/src/expr/node_builder.h
index f6aa1920d..5f813dbe8 100644
--- a/src/expr/node_builder.h
+++ b/src/expr/node_builder.h
@@ -1,11 +1,11 @@
/********************* */
/*! \file node_builder.h
** \verbatim
- ** Original author: mdeters
- ** Major contributors: dejan
- ** Minor contributors (to current version): taking, cconway
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** Original author: Dejan Jovanović <dejan.jovanovic@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): Tim King <taking@cs.nyu.edu>, Christopher L. Conway <christopherleeconway@gmail.com>
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
@@ -277,7 +277,9 @@ class NodeBuilder {
* double-decremented later (on destruction/clear).
*/
inline void realloc() {
- realloc(d_nvMaxChildren * 2);
+ size_t newSize = 2 * size_t(d_nvMaxChildren);
+ size_t hardLimit = (1lu << __CVC4__EXPR__NODE_VALUE__NBITS__NCHILDREN) - 1;
+ realloc(EXPECT_FALSE( newSize > hardLimit ) ? hardLimit : newSize);
}
/**
@@ -662,6 +664,7 @@ public:
expr::NodeValue* nv = n.d_nv;
nv->inc();
d_nv->d_children[d_nv->d_nchildren++] = nv;
+ Assert(d_nv->d_nchildren <= d_nvMaxChildren);
return *this;
}
@@ -674,6 +677,7 @@ public:
expr::NodeValue* nv = typeNode.d_nv;
nv->inc();
d_nv->d_children[d_nv->d_nchildren++] = nv;
+ Assert(d_nv->d_nchildren <= d_nvMaxChildren);
return *this;
}
@@ -771,6 +775,9 @@ template <unsigned nchild_thresh>
void NodeBuilder<nchild_thresh>::realloc(size_t toSize) {
Assert( toSize > d_nvMaxChildren,
"attempt to realloc() a NodeBuilder to a smaller/equal size!" );
+ Assert( toSize < (1lu << __CVC4__EXPR__NODE_VALUE__NBITS__NCHILDREN),
+ "attempt to realloc() a NodeBuilder to size %u (beyond hard limit of %u)",
+ toSize, (1lu << __CVC4__EXPR__NODE_VALUE__NBITS__NCHILDREN) - 1 );
if(EXPECT_FALSE( nvIsAllocated() )) {
// Ensure d_nv is not modified on allocation failure
@@ -783,6 +790,7 @@ void NodeBuilder<nchild_thresh>::realloc(size_t toSize) {
throw std::bad_alloc();
}
d_nvMaxChildren = toSize;
+ Assert(d_nvMaxChildren == toSize);//overflow check
// Here, the copy (between two heap-allocated buffers) has already
// been done for us by the std::realloc().
d_nv = newBlock;
@@ -795,6 +803,7 @@ void NodeBuilder<nchild_thresh>::realloc(size_t toSize) {
throw std::bad_alloc();
}
d_nvMaxChildren = toSize;
+ Assert(d_nvMaxChildren == toSize);//overflow check
d_nv = newBlock;
d_nv->d_id = d_inlineNv.d_id;
@@ -1276,10 +1285,14 @@ void NodeBuilder<nchild_thresh>::internalCopy(const NodeBuilder<N>& nb) {
return;
}
+ bool realloced CVC4_UNUSED = false;
if(nb.d_nvMaxChildren > d_nvMaxChildren) {
+ realloced = true;
realloc(nb.d_nvMaxChildren);
}
+ Assert(nb.d_nvMaxChildren <= d_nvMaxChildren);
+ Assert(nb.d_nv->nv_end() - nb.d_nv->nv_begin() <= d_nvMaxChildren, "realloced:%s, d_nvMax:%u, size:%u, nc:%u", realloced ? "true" : "false", d_nvMaxChildren, nb.d_nv->nv_end() - nb.d_nv->nv_begin(), nb.d_nv->getNumChildren());
std::copy(nb.d_nv->nv_begin(),
nb.d_nv->nv_end(),
d_nv->nv_begin());
diff --git a/src/expr/node_manager.cpp b/src/expr/node_manager.cpp
index 59d23c6ea..a3c968158 100644
--- a/src/expr/node_manager.cpp
+++ b/src/expr/node_manager.cpp
@@ -412,6 +412,7 @@ TypeNode NodeManager::getDatatypeForTupleRecord(TypeNode t) {
dt.addConstructor(c);
dtt = TypeNode::fromType(toExprManager()->mkDatatypeType(dt));
Debug("tuprec") << "REWROTE " << t << " to " << dtt << std::endl;
+ dtt.setAttribute(DatatypeTupleAttr(), t);
} else {
const Record& rec = t.getRecord();
Datatype dt("__cvc4_record");
@@ -422,8 +423,8 @@ TypeNode NodeManager::getDatatypeForTupleRecord(TypeNode t) {
dt.addConstructor(c);
dtt = TypeNode::fromType(toExprManager()->mkDatatypeType(dt));
Debug("tuprec") << "REWROTE " << t << " to " << dtt << std::endl;
+ dtt.setAttribute(DatatypeRecordAttr(), t);
}
- dtt.setAttribute(DatatypeRecordAttr(), t);
} else {
Debug("tuprec") << "REUSING cached " << t << ": " << dtt << std::endl;
}
diff --git a/src/expr/options b/src/expr/options
index cd59e4875..223189d1b 100644
--- a/src/expr/options
+++ b/src/expr/options
@@ -5,9 +5,9 @@
module EXPR "expr/options.h" Expression package
-option defaultExprDepth --default-expr-depth=N int :predicate CVC4::expr::setDefaultExprDepth :predicate-include "expr/options_handlers.h"
+option defaultExprDepth --default-expr-depth=N int :default 0 :predicate CVC4::expr::setDefaultExprDepth :predicate-include "expr/options_handlers.h"
print exprs to depth N (0 == default, -1 == no limit)
-option - default-dag-thresh --default-dag-thresh=N argument :handler CVC4::expr::setDefaultDagThresh :handler-include "expr/options_handlers.h"
+option defaultDagThresh default-dag-thresh --default-dag-thresh=N int :default 1 :predicate CVC4::expr::setDefaultDagThresh :predicate-include "expr/options_handlers.h"
dagify common subexprs appearing > N times (1 == default, 0 == don't dagify)
option - --print-expr-types void :handler CVC4::expr::setPrintExprTypes :handler-include "expr/options_handlers.h"
print types with variables when printing exprs
diff --git a/src/expr/options_handlers.h b/src/expr/options_handlers.h
index 7a1d73c36..57c4d1aa4 100644
--- a/src/expr/options_handlers.h
+++ b/src/expr/options_handlers.h
@@ -39,8 +39,7 @@ inline void setDefaultExprDepth(std::string option, int depth, SmtEngine* smt) {
// intentionally exclude Dump stream from this list
}
-inline void setDefaultDagThresh(std::string option, std::string optarg, SmtEngine* smt) {
- int dag = atoi(optarg.c_str());
+inline void setDefaultDagThresh(std::string option, int dag, SmtEngine* smt) {
if(dag < 0) {
throw OptionException("--default-dag-thresh requires a nonnegative argument.");
}
diff --git a/src/expr/type.i b/src/expr/type.i
index 870cb228c..e227cca23 100644
--- a/src/expr/type.i
+++ b/src/expr/type.i
@@ -14,24 +14,6 @@
%rename(greater) CVC4::Type::operator>(const Type&) const;
%rename(greaterEqual) CVC4::Type::operator>=(const Type&) const;
-%rename(toBooleanType) CVC4::Type::operator BooleanType() const;
-%rename(toIntegerType) CVC4::Type::operator IntegerType() const;
-%rename(toRealType) CVC4::Type::operator RealType() const;
-%rename(toStringType) CVC4::Type::operator StringType() const;
-%rename(toBitVectorType) CVC4::Type::operator BitVectorType() const;
-%rename(toFunctionType) CVC4::Type::operator FunctionType() const;
-%rename(toTupleType) CVC4::Type::operator TupleType() const;
-%rename(toSExprType) CVC4::Type::operator SExprType() const;
-%rename(toArrayType) CVC4::Type::operator ArrayType() const;
-%rename(toDatatypeType) CVC4::Type::operator DatatypeType() const;
-%rename(toConstructorType) CVC4::Type::operator ConstructorType() const;
-%rename(toSelectorType) CVC4::Type::operator SelectorType() const;
-%rename(toTesterType) CVC4::Type::operator TesterType() const;
-%rename(toSortType) CVC4::Type::operator SortType() const;
-%rename(toSortConstructorType) CVC4::Type::operator SortConstructorType() const;
-%rename(toPredicateSubtype) CVC4::Type::operator PredicateSubtype() const;
-%rename(toSubrangeType) CVC4::Type::operator SubrangeType() const;
-
namespace CVC4 {
namespace expr {
%ignore exportTypeInternal;
diff --git a/src/main/command_executor.cpp b/src/main/command_executor.cpp
index 14625f1d8..6a4e18b5b 100644
--- a/src/main/command_executor.cpp
+++ b/src/main/command_executor.cpp
@@ -48,7 +48,7 @@ bool CommandExecutor::doCommand(Command* cmd)
return status;
} else {
- if(d_options[options::verbosity] > 0) {
+ if(d_options[options::verbosity] > 2) {
*d_options[options::out] << "Invoking: " << *cmd << std::endl;
}
@@ -59,7 +59,7 @@ bool CommandExecutor::doCommand(Command* cmd)
bool CommandExecutor::doCommandSingleton(Command *cmd)
{
bool status = true;
- if(d_options[options::verbosity] >= 0) {
+ if(d_options[options::verbosity] >= -1) {
status = smtEngineInvoke(&d_smtEngine, cmd, d_options[options::out]);
} else {
status = smtEngineInvoke(&d_smtEngine, cmd, NULL);
diff --git a/src/main/driver_unified.cpp b/src/main/driver_unified.cpp
index b429ad0c2..9fa40d3ab 100644
--- a/src/main/driver_unified.cpp
+++ b/src/main/driver_unified.cpp
@@ -26,6 +26,7 @@
#include "cvc4autoconfig.h"
#include "main/main.h"
#include "main/interactive_shell.h"
+#include "main/options.h"
#include "parser/parser.h"
#include "parser/parser_builder.h"
#include "parser/parser_exception.h"
@@ -43,6 +44,7 @@
#include "util/output.h"
#include "util/dump.h"
#include "util/result.h"
+#include "util/statistics_registry.h"
using namespace std;
using namespace CVC4;
@@ -63,6 +65,9 @@ namespace CVC4 {
/** A pointer to the CommandExecutor (the signal handlers need it) */
CVC4::main::CommandExecutor* pExecutor = NULL;
+ /** A pointer to the totalTime driver stat (the signal handlers need it) */
+ CVC4::TimerStat* pTotalTime = NULL;
+
}/* CVC4::main namespace */
}/* CVC4 namespace */
@@ -84,8 +89,8 @@ void printUsage(Options& opts, bool full) {
int runCvc4(int argc, char* argv[], Options& opts) {
// Timer statistic
- TimerStat s_totalTime("totalTime");
- s_totalTime.start();
+ pTotalTime = new TimerStat("totalTime");
+ pTotalTime->start();
// For the signal handlers' benefit
pOptions = &opts;
@@ -183,17 +188,22 @@ int runCvc4(int argc, char* argv[], Options& opts) {
DumpChannel.getStream() << Expr::setlanguage(opts[options::outputLanguage]);
// Create the expression manager using appropriate options
+ ExprManager* exprMgr;
# ifndef PORTFOLIO_BUILD
- ExprManager* exprMgr = new ExprManager(opts);
-# else
- vector<Options> threadOpts = parseThreadSpecificOptions(opts);
- ExprManager* exprMgr = new ExprManager(threadOpts[0]);
-# endif
-
-# ifndef PORTFOLIO_BUILD
+ exprMgr = new ExprManager(opts);
pExecutor = new CommandExecutor(*exprMgr, opts);
# else
- pExecutor = new CommandExecutorPortfolio(*exprMgr, opts, threadOpts);
+ vector<Options> threadOpts = parseThreadSpecificOptions(opts);
+ if(opts[options::incrementalSolving] && !opts[options::incrementalParallel]) {
+ Notice() << "Notice: In --incremental mode, using the sequential solver unless forced by...\n"
+ << "Notice: ...the experimental --incremental-parallel option.\n";
+ exprMgr = new ExprManager(opts);
+ pExecutor = new CommandExecutor(*exprMgr, opts);
+ }
+ else {
+ exprMgr = new ExprManager(threadOpts[0]);
+ pExecutor = new CommandExecutorPortfolio(*exprMgr, opts, threadOpts);
+ }
# endif
Parser* replayParser = NULL;
@@ -216,7 +226,7 @@ int runCvc4(int argc, char* argv[], Options& opts) {
int returnValue = 0;
{
// Timer statistic
- RegisterStatistic statTotalTime(&pExecutor->getStatisticsRegistry(), &s_totalTime);
+ RegisterStatistic statTotalTime(&pExecutor->getStatisticsRegistry(), pTotalTime);
// Filename statistics
ReferenceStat< const char* > s_statFilename("filename", filename);
@@ -229,7 +239,9 @@ int runCvc4(int argc, char* argv[], Options& opts) {
InteractiveShell shell(*exprMgr, opts);
Message() << Configuration::getPackageName()
<< " " << Configuration::getVersionString();
- if(Configuration::isSubversionBuild()) {
+ if(Configuration::isGitBuild()) {
+ Message() << " [" << Configuration::getGitId() << "]";
+ } else if(Configuration::isSubversionBuild()) {
Message() << " [" << Configuration::getSubversionId() << "]";
}
Message() << (Configuration::isDebugBuild() ? " DEBUG" : "")
@@ -304,7 +316,7 @@ int runCvc4(int argc, char* argv[], Options& opts) {
ReferenceStat< Result > s_statSatResult("sat/unsat", result);
RegisterStatistic statSatResultReg(&pExecutor->getStatisticsRegistry(), &s_statSatResult);
- s_totalTime.stop();
+ pTotalTime->stop();
// Set the global executor pointer to NULL first. If we get a
// signal while dumping statistics, we don't want to try again.
@@ -334,9 +346,11 @@ int runCvc4(int argc, char* argv[], Options& opts) {
// On exceptional exit, these are leaked, but that's okay... they
// need to be around in that case for main() to print statistics.
+ delete pTotalTime;
delete pExecutor;
delete exprMgr;
+ pTotalTime = NULL;
pExecutor = NULL;
return returnValue;
diff --git a/src/main/main.cpp b/src/main/main.cpp
index 3e45b4f14..a83baf45f 100644
--- a/src/main/main.cpp
+++ b/src/main/main.cpp
@@ -66,6 +66,7 @@ int main(int argc, char* argv[]) {
#endif
*opts[options::err] << "CVC4 Error:" << endl << e << endl;
if(opts[options::statistics] && pExecutor != NULL) {
+ pTotalTime->stop();
pExecutor->flushStatistics(*opts[options::err]);
}
}
diff --git a/src/main/main.h b/src/main/main.h
index 5b202c532..56cd866da 100644
--- a/src/main/main.h
+++ b/src/main/main.h
@@ -23,6 +23,7 @@
#include "util/exception.h"
#include "util/statistics.h"
#include "util/tls.h"
+#include "util/statistics_registry.h"
#include "cvc4autoconfig.h"
#ifndef __CVC4__MAIN__MAIN_H
@@ -42,6 +43,9 @@ extern const char* progName;
/** A reference for use by the signal handlers to print statistics */
extern CVC4::main::CommandExecutor* pExecutor;
+/** A reference for use by the signal handlers to print statistics */
+extern CVC4::TimerStat* pTotalTime;
+
/**
* If true, will not spin on segfault even when CVC4_DEBUG is on.
* Useful for nightly regressions, noninteractive performance runs
diff --git a/src/main/options b/src/main/options
index 53c04a2c4..caea63f5a 100644
--- a/src/main/options
+++ b/src/main/options
@@ -37,6 +37,8 @@ option sharingFilterByLength --filter-lemma-length=N int :default -1 :read-write
don't share (among portfolio threads) lemmas strictly longer than N
option fallbackSequential --fallback-sequential bool :default false
Switch to sequential mode (instead of printing an error) if it can't be solved in portfolio mode
+option incrementalParallel --incremental-parallel bool :default false :link --incremental
+ Use parallel solver even in incremental mode (may print 'unknown's at times)
expert-option waitToJoin --wait-to-join bool :default true
wait for other threads to join before quitting
diff --git a/src/main/options_handlers.h b/src/main/options_handlers.h
index c2eb489ed..f14a67d5f 100644
--- a/src/main/options_handlers.h
+++ b/src/main/options_handlers.h
@@ -26,14 +26,20 @@ inline void showConfiguration(std::string option, SmtEngine* smt) {
fputs(Configuration::about().c_str(), stdout);
printf("\n");
printf("version : %s\n", Configuration::getVersionString().c_str());
- if(Configuration::isSubversionBuild()) {
- printf("subversion : yes [%s r%u%s]\n",
+ if(Configuration::isGitBuild()) {
+ printf("scm : git [%s %s%s]\n",
+ Configuration::getGitBranchName(),
+ std::string(Configuration::getGitCommit()).substr(0, 8).c_str(),
+ Configuration::hasGitModifications() ?
+ " (with modifications)" : "");
+ } else if(Configuration::isSubversionBuild()) {
+ printf("scm : svn [%s r%u%s]\n",
Configuration::getSubversionBranchName(),
Configuration::getSubversionRevision(),
Configuration::hasSubversionModifications() ?
" (with modifications)" : "");
} else {
- printf("subversion : %s\n", Configuration::isSubversionBuild() ? "yes" : "no");
+ printf("scm : no\n");
}
printf("\n");
printf("library : %u.%u.%u\n",
diff --git a/src/main/util.cpp b/src/main/util.cpp
index 9ade23630..a6fcddf3b 100644
--- a/src/main/util.cpp
+++ b/src/main/util.cpp
@@ -65,6 +65,7 @@ void* cvc4StackBase;
void timeout_handler(int sig, siginfo_t* info, void*) {
fprintf(stderr, "CVC4 interrupted by timeout.\n");
if((*pOptions)[options::statistics] && pExecutor != NULL) {
+ pTotalTime->stop();
pExecutor->flushStatistics(cerr);
}
abort();
@@ -74,6 +75,7 @@ void timeout_handler(int sig, siginfo_t* info, void*) {
void sigint_handler(int sig, siginfo_t* info, void*) {
fprintf(stderr, "CVC4 interrupted by user.\n");
if((*pOptions)[options::statistics] && pExecutor != NULL) {
+ pTotalTime->stop();
pExecutor->flushStatistics(cerr);
}
abort();
@@ -99,6 +101,7 @@ void segv_handler(int sig, siginfo_t* info, void* c) {
if(segvNoSpin) {
fprintf(stderr, "No-spin requested, aborting...\n");
if((*pOptions)[options::statistics] && pExecutor != NULL) {
+ pTotalTime->stop();
pExecutor->flushStatistics(cerr);
}
abort();
@@ -119,6 +122,7 @@ void segv_handler(int sig, siginfo_t* info, void* c) {
cerr << "Looks like a NULL pointer was dereferenced." << endl;
}
if((*pOptions)[options::statistics] && pExecutor != NULL) {
+ pTotalTime->stop();
pExecutor->flushStatistics(cerr);
}
abort();
@@ -132,6 +136,7 @@ void ill_handler(int sig, siginfo_t* info, void*) {
if(segvNoSpin) {
fprintf(stderr, "No-spin requested, aborting...\n");
if((*pOptions)[options::statistics] && pExecutor != NULL) {
+ pTotalTime->stop();
pExecutor->flushStatistics(cerr);
}
abort();
@@ -145,6 +150,7 @@ void ill_handler(int sig, siginfo_t* info, void*) {
#else /* CVC4_DEBUG */
fprintf(stderr, "CVC4 executed an illegal instruction.\n");
if((*pOptions)[options::statistics] && pExecutor != NULL) {
+ pTotalTime->stop();
pExecutor->flushStatistics(cerr);
}
abort();
@@ -171,6 +177,7 @@ void cvc4unexpected() {
if(segvNoSpin) {
fprintf(stderr, "No-spin requested.\n");
if((*pOptions)[options::statistics] && pExecutor != NULL) {
+ pTotalTime->stop();
pExecutor->flushStatistics(cerr);
}
set_terminate(default_terminator);
@@ -184,6 +191,7 @@ void cvc4unexpected() {
#else /* CVC4_DEBUG */
fprintf(stderr, "CVC4 threw an \"unexpected\" exception.\n");
if((*pOptions)[options::statistics] && pExecutor != NULL) {
+ pTotalTime->stop();
pExecutor->flushStatistics(cerr);
}
set_terminate(default_terminator);
@@ -197,6 +205,7 @@ void cvc4terminate() {
"Perhaps an exception was thrown during stack unwinding. "
"(Don't do that.)\n");
if((*pOptions)[options::statistics] && pExecutor != NULL) {
+ pTotalTime->stop();
pExecutor->flushStatistics(cerr);
}
default_terminator();
@@ -205,6 +214,7 @@ void cvc4terminate() {
"CVC4 was terminated by the C++ runtime.\n"
"Perhaps an exception was thrown during stack unwinding.\n");
if((*pOptions)[options::statistics] && pExecutor != NULL) {
+ pTotalTime->stop();
pExecutor->flushStatistics(cerr);
}
default_terminator();
diff --git a/src/options/mkoptions b/src/options/mkoptions
index 0632cb3f9..fa6c4c260 100755
--- a/src/options/mkoptions
+++ b/src/options/mkoptions
@@ -2,7 +2,7 @@
#
# mkoptions
# Morgan Deters <mdeters@cs.nyu.edu> for CVC4
-# Copyright (c) 2011-2012 The CVC4 Project
+# Copyright (c) 2011-2013 The CVC4 Project
#
# The purpose of this script is to create options.{h,cpp}
# from template files and a list of options.
@@ -12,7 +12,7 @@
# mkoptions (template-file output-file)+ -t options.h-template options.cpp-template (options-file output-dir)+
#
-copyright=2011-2012
+copyright=2011-2013
me=$(basename "$0")
@@ -1314,7 +1314,8 @@ function output_module {
/********************* */
/** $filename
**
- ** Copyright $copyright The AcSys Group, New York University, and as below.
+ ** Copyright $copyright New York University and The University of Iowa,
+ ** and as below.
**
** This file automatically generated by:
**
@@ -1496,7 +1497,8 @@ cat <<EOF
/********************* */
/** $filename
**
- ** Copyright $copyright The AcSys Group, New York University, and as below.
+ ** Copyright $copyright New York University and The University of Iowa,
+ ** and as below.
**
** This file automatically generated by:
**
diff --git a/src/parser/bounded_token_buffer.cpp b/src/parser/bounded_token_buffer.cpp
index 904f9a7fa..6a6ae8609 100644
--- a/src/parser/bounded_token_buffer.cpp
+++ b/src/parser/bounded_token_buffer.cpp
@@ -512,7 +512,7 @@ static pANTLR3_COMMON_TOKEN nextToken(pBOUNDED_TOKEN_BUFFER buffer) {
}
-/// Return a string that represents the name assoicated with the input source
+/// Return a string that represents the name associated with the input source
///
/// /param[in] is The ANTLR3_INT_STREAM interface that is representing this token stream.
///
diff --git a/src/parser/cvc/Cvc.g b/src/parser/cvc/Cvc.g
index d0fe9036b..b8ec160e8 100644
--- a/src/parser/cvc/Cvc.g
+++ b/src/parser/cvc/Cvc.g
@@ -416,10 +416,8 @@ Expr addNots(ExprManager* em, size_t n, Expr e) {
@header {
/**
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
+ ** This file is part of CVC4.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.
**/
@@ -742,10 +740,7 @@ mainCommand[CVC4::Command*& cmd]
| ECHO_TOK
( simpleSymbolicExpr[sexpr]
- { std::stringstream ss;
- ss << sexpr;
- cmd = new EchoCommand(ss.str());
- }
+ { cmd = new EchoCommand(sexpr.getValue()); }
| { cmd = new EchoCommand(); }
)
diff --git a/src/parser/smt1/Smt1.g b/src/parser/smt1/Smt1.g
index 0f76baace..f8331c899 100644
--- a/src/parser/smt1/Smt1.g
+++ b/src/parser/smt1/Smt1.g
@@ -1,3 +1,4 @@
+/* ******************* */
/*! \file Smt1.g
** \verbatim
** Original author: cconway
@@ -30,10 +31,8 @@ options {
@header {
/**
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
+ ** This file is part of CVC4.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.
**/
@@ -783,7 +782,15 @@ FLET_IDENTIFIER
*/
userValue[std::string& s]
: USER_VALUE
- { s = AntlrInput::tokenText($USER_VALUE); }
+ { s = AntlrInput::tokenText($USER_VALUE);
+ assert(*s.begin() == '{');
+ assert(*s.rbegin() == '}');
+ // trim whitespace
+ s.erase(s.begin(), s.begin() + 1);
+ s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
+ s.erase(s.end() - 1);
+ s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
+ }
;
PATTERN_ANNOTATION_BEGIN
diff --git a/src/parser/smt2/Smt2.g b/src/parser/smt2/Smt2.g
index 648666091..1ee288aa4 100644
--- a/src/parser/smt2/Smt2.g
+++ b/src/parser/smt2/Smt2.g
@@ -31,10 +31,8 @@ options {
@header {
/**
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
+ ** This file is part of CVC4.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.
**/
diff --git a/src/parser/smt2/smt2_input.h b/src/parser/smt2/smt2_input.h
index 62ed33632..62959c766 100644
--- a/src/parser/smt2/smt2_input.h
+++ b/src/parser/smt2/smt2_input.h
@@ -41,7 +41,7 @@ class Smt2Input : public AntlrInput {
/** The ANTLR3 SMT2 lexer for the input. */
pSmt2Lexer d_pSmt2Lexer;
- /** The ANTLR3 CVC parser for the input. */
+ /** The ANTLR3 SMT2 parser for the input. */
pSmt2Parser d_pSmt2Parser;
/**
diff --git a/src/parser/tptp/Tptp.g b/src/parser/tptp/Tptp.g
index 2180255ca..ec6868c5b 100644
--- a/src/parser/tptp/Tptp.g
+++ b/src/parser/tptp/Tptp.g
@@ -32,10 +32,8 @@ options {
@header {
/**
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
+ ** This file is part of CVC4.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.
**/
diff --git a/src/parser/tptp/tptp.cpp b/src/parser/tptp/tptp.cpp
index 1e40ea63f..59b1d205b 100644
--- a/src/parser/tptp/tptp.cpp
+++ b/src/parser/tptp/tptp.cpp
@@ -151,7 +151,7 @@ void Tptp::includeFile(std::string fileName){
if( d_tptpDir.empty() ){
parseError("Couldn't open included file: " + fileName
- + " at " + currentDirFileName + " and the TPTP directory is not specified (environnement variable TPTP)");
+ + " at " + currentDirFileName + " and the TPTP directory is not specified (environment variable TPTP)");
};
std::string tptpDirFileName = d_tptpDir + fileName;
diff --git a/src/printer/cvc/cvc_printer.cpp b/src/printer/cvc/cvc_printer.cpp
index e0d4656f4..0206c4252 100644
--- a/src/printer/cvc/cvc_printer.cpp
+++ b/src/printer/cvc/cvc_printer.cpp
@@ -21,7 +21,9 @@
#include "expr/command.h"
#include "theory/substitutions.h"
#include "smt/smt_engine.h"
+#include "smt/options.h"
#include "theory/model.h"
+#include "theory/arrays/theory_arrays_rewriter.h"
#include <iostream>
#include <vector>
@@ -813,21 +815,34 @@ void CvcPrinter::toStream(std::ostream& out, Model& m, const Command* c) const t
theory::TheoryModel& tm = (theory::TheoryModel&) m;
if(dynamic_cast<const DeclareTypeCommand*>(c) != NULL) {
TypeNode tn = TypeNode::fromType( ((const DeclareTypeCommand*)c)->getType() );
- if( tn.isSort() ){
- // print the cardinality
- if( tm.d_rep_set.d_type_reps.find( tn )!=tm.d_rep_set.d_type_reps.end() ){
- out << "; cardinality of " << tn << " is " << (*tm.d_rep_set.d_type_reps.find(tn)).second.size() << std::endl;
+ if( options::modelUninterpDtEnum() && tn.isSort() &&
+ tm.d_rep_set.d_type_reps.find( tn )!=tm.d_rep_set.d_type_reps.end() ){
+ out << "DATATYPE " << std::endl;
+ out << " " << dynamic_cast<const DeclareTypeCommand*>(c)->getSymbol() << " = ";
+ for( size_t i=0; i<(*tm.d_rep_set.d_type_reps.find(tn)).second.size(); i++ ){
+ if (i>0) {
+ out << "| ";
+ }
+ out << (*tm.d_rep_set.d_type_reps.find(tn)).second[i] << " ";
}
- }
- out << c << std::endl;
- if( tn.isSort() ){
- // print the representatives
- if( tm.d_rep_set.d_type_reps.find( tn )!=tm.d_rep_set.d_type_reps.end() ){
- for( size_t i=0; i<(*tm.d_rep_set.d_type_reps.find(tn)).second.size(); i++ ){
- if( (*tm.d_rep_set.d_type_reps.find(tn)).second[i].isVar() ){
- out << (*tm.d_rep_set.d_type_reps.find(tn)).second[i] << " : " << tn << ";" << std::endl;
- }else{
- out << "% rep: " << (*tm.d_rep_set.d_type_reps.find(tn)).second[i] << std::endl;
+ out << std::endl << "END;" << std::endl;
+ } else {
+ if( tn.isSort() ){
+ // print the cardinality
+ if( tm.d_rep_set.d_type_reps.find( tn )!=tm.d_rep_set.d_type_reps.end() ){
+ out << "% cardinality of " << tn << " is " << (*tm.d_rep_set.d_type_reps.find(tn)).second.size() << std::endl;
+ }
+ }
+ out << c << std::endl;
+ if( tn.isSort() ){
+ // print the representatives
+ if( tm.d_rep_set.d_type_reps.find( tn )!=tm.d_rep_set.d_type_reps.end() ){
+ for( size_t i=0; i<(*tm.d_rep_set.d_type_reps.find(tn)).second.size(); i++ ){
+ if( (*tm.d_rep_set.d_type_reps.find(tn)).second[i].isVar() ){
+ out << (*tm.d_rep_set.d_type_reps.find(tn)).second[i] << " : " << tn << ";" << std::endl;
+ }else{
+ out << "% rep: " << (*tm.d_rep_set.d_type_reps.find(tn)).second[i] << std::endl;
+ }
}
}
}
@@ -850,7 +865,15 @@ void CvcPrinter::toStream(std::ostream& out, Model& m, const Command* c) const t
}else{
out << tn;
}
- out << " = " << Node::fromExpr(tm.getSmtEngine()->getValue(n.toExpr())) << ";" << std::endl;
+ Node val = Node::fromExpr(tm.getSmtEngine()->getValue(n.toExpr()));
+ if( options::modelUninterpDtEnum() && val.getKind() == kind::STORE ) {
+ TypeNode tn = val[1].getType();
+ if (tn.isSort() && tm.d_rep_set.d_type_reps.find( tn )!=tm.d_rep_set.d_type_reps.end() ){
+ Cardinality indexCard((*tm.d_rep_set.d_type_reps.find(tn)).second.size());
+ val = theory::arrays::TheoryArraysRewriter::normalizeConstant( val, indexCard );
+ }
+ }
+ out << " = " << val << ";" << std::endl;
/*
//for table format (work in progress)
diff --git a/src/printer/smt2/smt2_printer.cpp b/src/printer/smt2/smt2_printer.cpp
index 000fd2fbf..8541ca6ae 100644
--- a/src/printer/smt2/smt2_printer.cpp
+++ b/src/printer/smt2/smt2_printer.cpp
@@ -27,8 +27,10 @@
#include "theory/substitutions.h"
#include "util/language.h"
#include "smt/smt_engine.h"
+#include "smt/options.h"
#include "theory/model.h"
+#include "theory/arrays/theory_arrays_rewriter.h"
using namespace std;
@@ -552,21 +554,30 @@ void Smt2Printer::toStream(std::ostream& out, Model& m, const Command* c) const
theory::TheoryModel& tm = (theory::TheoryModel&) m;
if(dynamic_cast<const DeclareTypeCommand*>(c) != NULL) {
TypeNode tn = TypeNode::fromType( ((const DeclareTypeCommand*)c)->getType() );
- if( tn.isSort() ){
- //print the cardinality
- if( tm.d_rep_set.d_type_reps.find( tn )!=tm.d_rep_set.d_type_reps.end() ){
- out << "; cardinality of " << tn << " is " << (*tm.d_rep_set.d_type_reps.find(tn)).second.size() << std::endl;
+ if( options::modelUninterpDtEnum() && tn.isSort() &&
+ tm.d_rep_set.d_type_reps.find( tn )!=tm.d_rep_set.d_type_reps.end() ){
+ out << "(declare-datatypes () ((" << dynamic_cast<const DeclareTypeCommand*>(c)->getSymbol() << " ";
+ for( size_t i=0; i<(*tm.d_rep_set.d_type_reps.find(tn)).second.size(); i++ ){
+ out << "(" << (*tm.d_rep_set.d_type_reps.find(tn)).second[i] << ")";
}
- }
- out << c << std::endl;
- if( tn.isSort() ){
- //print the representatives
- if( tm.d_rep_set.d_type_reps.find( tn )!=tm.d_rep_set.d_type_reps.end() ){
- for( size_t i=0; i<(*tm.d_rep_set.d_type_reps.find(tn)).second.size(); i++ ){
- if( (*tm.d_rep_set.d_type_reps.find(tn)).second[i].isVar() ){
- out << "(declare-fun " << (*tm.d_rep_set.d_type_reps.find(tn)).second[i] << " () " << tn << ")" << std::endl;
- }else{
- out << "; rep: " << (*tm.d_rep_set.d_type_reps.find(tn)).second[i] << std::endl;
+ out << ")))" << std::endl;
+ } else {
+ if( tn.isSort() ){
+ //print the cardinality
+ if( tm.d_rep_set.d_type_reps.find( tn )!=tm.d_rep_set.d_type_reps.end() ){
+ out << "; cardinality of " << tn << " is " << (*tm.d_rep_set.d_type_reps.find(tn)).second.size() << std::endl;
+ }
+ }
+ out << c << std::endl;
+ if( tn.isSort() ){
+ //print the representatives
+ if( tm.d_rep_set.d_type_reps.find( tn )!=tm.d_rep_set.d_type_reps.end() ){
+ for( size_t i=0; i<(*tm.d_rep_set.d_type_reps.find(tn)).second.size(); i++ ){
+ if( (*tm.d_rep_set.d_type_reps.find(tn)).second[i].isVar() ){
+ out << "(declare-fun " << (*tm.d_rep_set.d_type_reps.find(tn)).second[i] << " () " << tn << ")" << std::endl;
+ }else{
+ out << "; rep: " << (*tm.d_rep_set.d_type_reps.find(tn)).second[i] << std::endl;
+ }
}
}
}
@@ -583,6 +594,13 @@ void Smt2Printer::toStream(std::ostream& out, Model& m, const Command* c) const
<< " " << n.getType().getRangeType()
<< " " << val[1] << ")" << std::endl;
} else {
+ if( options::modelUninterpDtEnum() && val.getKind() == kind::STORE ) {
+ TypeNode tn = val[1].getType();
+ if (tn.isSort() && tm.d_rep_set.d_type_reps.find( tn )!=tm.d_rep_set.d_type_reps.end() ){
+ Cardinality indexCard((*tm.d_rep_set.d_type_reps.find(tn)).second.size());
+ val = theory::arrays::TheoryArraysRewriter::normalizeConstant( val, indexCard );
+ }
+ }
out << "(define-fun " << n << " () "
<< n.getType() << " " << val << ")" << std::endl;
}
diff --git a/src/proof/sat_proof.h b/src/proof/sat_proof.h
index 324988585..ccbde6e80 100644
--- a/src/proof/sat_proof.h
+++ b/src/proof/sat_proof.h
@@ -160,8 +160,8 @@ protected:
* Does a depth first search on removed literals and adds the literals
* to be removed in the proper order to the stack.
*
- * @param lit the literal we are recusing on
- * @param removedSet the previously computed set of redundantant literals
+ * @param lit the literal we are recursing on
+ * @param removedSet the previously computed set of redundant literals
* @param removeStack the stack of literals in reverse order of resolution
*/
void removedDfs(::Minisat::Lit lit, LitSet* removedSet, LitVector& removeStack, LitSet& inClause, LitSet& seen);
diff --git a/src/prop/bvminisat/Makefile b/src/prop/bvminisat/Makefile
new file mode 100644
index 000000000..71888016d
--- /dev/null
+++ b/src/prop/bvminisat/Makefile
@@ -0,0 +1,4 @@
+topdir = ../../..
+srcdir = src/prop/bvminisat
+
+include $(topdir)/Makefile.subdir
diff --git a/src/smt/boolean_terms.cpp b/src/smt/boolean_terms.cpp
index 696622cfe..262244f42 100644
--- a/src/smt/boolean_terms.cpp
+++ b/src/smt/boolean_terms.cpp
@@ -39,6 +39,13 @@ static inline bool isBoolean(TNode top, unsigned i) {
case kind::IMPLIES:
case kind::OR:
case kind::XOR:
+ case kind::FORALL:
+ case kind::EXISTS:
+ case kind::REWRITE_RULE:
+ case kind::RR_REWRITE:
+ case kind::RR_DEDUCTION:
+ case kind::RR_REDUCTION:
+ case kind::INST_PATTERN:
return true;
case kind::ITE:
@@ -289,13 +296,16 @@ Node BooleanTermConverter::rewriteBooleanTerms(TNode top, bool boolParent) throw
}
switch(k) {
case kind::LAMBDA:
- case kind::FORALL:
- case kind::EXISTS:
+ Unreachable("not expecting a LAMBDA in boolean-term conversion: %s", top.toString().c_str());
+
+ case kind::BOUND_VAR_LIST:
+ return top;
+
case kind::REWRITE_RULE:
case kind::RR_REWRITE:
- case kind::RR_REDUCTION:
case kind::RR_DEDUCTION:
- //Assert(false, "not yet supported");
+ case kind::RR_REDUCTION:
+ // not yet supported
return top;
default:
diff --git a/src/smt/options b/src/smt/options
index fc5ccf4c4..2680f4105 100644
--- a/src/smt/options
+++ b/src/smt/options
@@ -54,6 +54,8 @@ common-option incrementalSolving incremental -i --incremental bool
option abstractValues abstract-values --abstract-values bool :default false
in models, output arrays (and in future, maybe others) using abstract values, as required by the SMT-LIB standard
+option modelUninterpDtEnum --model-u-dt-enum bool :default false
+ in models, output uninterpreted sorts as datatype enumerations
option - regular-output-channel argument :handler CVC4::smt::setRegularOutputChannel :handler-include "smt/options_handlers.h"
set the regular output channel of the solver
diff --git a/src/smt/smt_engine.cpp b/src/smt/smt_engine.cpp
index 1d98ce115..8eb6664ca 100644
--- a/src/smt/smt_engine.cpp
+++ b/src/smt/smt_engine.cpp
@@ -36,6 +36,7 @@
#include "expr/metakind.h"
#include "expr/node_builder.h"
#include "expr/node.h"
+#include "expr/node_self_iterator.h"
#include "prop/prop_engine.h"
#include "smt/modal_exception.h"
#include "smt/smt_engine.h"
@@ -111,7 +112,11 @@ struct SmtEngineStatistics {
TimerStat d_rewriteBooleanTermsTime;
/** time spent in non-clausal simplification */
TimerStat d_nonclausalSimplificationTime;
- /** Num of constant propagations found during nonclausal simp */
+ /** time spent in miplib pass */
+ TimerStat d_miplibPassTime;
+ /** number of assertions removed by miplib pass */
+ IntStat d_numMiplibAssertionsRemoved;
+ /** number of constant propagations found during nonclausal simp */
IntStat d_numConstantProps;
/** time spent in static learning */
TimerStat d_staticLearningTime;
@@ -136,6 +141,8 @@ struct SmtEngineStatistics {
d_definitionExpansionTime("smt::SmtEngine::definitionExpansionTime"),
d_rewriteBooleanTermsTime("smt::SmtEngine::rewriteBooleanTermsTime"),
d_nonclausalSimplificationTime("smt::SmtEngine::nonclausalSimplificationTime"),
+ d_miplibPassTime("smt::SmtEngine::miplibPassTime"),
+ d_numMiplibAssertionsRemoved("smt::SmtEngine::numMiplibAssertionsRemoved", 0),
d_numConstantProps("smt::SmtEngine::numConstantProps", 0),
d_staticLearningTime("smt::SmtEngine::staticLearningTime"),
d_simpITETime("smt::SmtEngine::simpITETime"),
@@ -150,6 +157,8 @@ struct SmtEngineStatistics {
StatisticsRegistry::registerStat(&d_definitionExpansionTime);
StatisticsRegistry::registerStat(&d_rewriteBooleanTermsTime);
StatisticsRegistry::registerStat(&d_nonclausalSimplificationTime);
+ StatisticsRegistry::registerStat(&d_miplibPassTime);
+ StatisticsRegistry::registerStat(&d_numMiplibAssertionsRemoved);
StatisticsRegistry::registerStat(&d_numConstantProps);
StatisticsRegistry::registerStat(&d_staticLearningTime);
StatisticsRegistry::registerStat(&d_simpITETime);
@@ -166,6 +175,8 @@ struct SmtEngineStatistics {
StatisticsRegistry::unregisterStat(&d_definitionExpansionTime);
StatisticsRegistry::unregisterStat(&d_rewriteBooleanTermsTime);
StatisticsRegistry::unregisterStat(&d_nonclausalSimplificationTime);
+ StatisticsRegistry::unregisterStat(&d_miplibPassTime);
+ StatisticsRegistry::unregisterStat(&d_numMiplibAssertionsRemoved);
StatisticsRegistry::unregisterStat(&d_numConstantProps);
StatisticsRegistry::unregisterStat(&d_staticLearningTime);
StatisticsRegistry::unregisterStat(&d_simpITETime);
@@ -210,6 +221,8 @@ class SmtEnginePrivate : public NodeManagerListener {
/** A circuit propagator for non-clausal propositional deduction */
booleans::CircuitPropagator d_propagator;
+ bool d_propagatorNeedsFinish;
+ std::vector<Node> d_boolVars;
/** Assertions to push to sat */
vector<Node> d_assertionsToCheck;
@@ -333,6 +346,14 @@ private:
void constrainSubtypes(TNode n, std::vector<Node>& assertions)
throw();
+ // trace nodes back to their assertions using CircuitPropagator's BackEdgesMap
+ void traceBackToAssertions(const std::vector<Node>& nodes, std::vector<TNode>& assertions);
+ // remove conjuncts in toRemove from conjunction n; return # of removed conjuncts
+ size_t removeFromConjunction(Node& n, const std::hash_set<unsigned>& toRemove);
+
+ // scrub miplib encodings
+ void doMiplibTrick();
+
/**
* Perform non-clausal simplification of a Node. This involves
* Theory implementations, but does NOT involve the SAT solver in
@@ -351,6 +372,7 @@ public:
d_realAssertionsEnd(0),
d_booleanTermConverter(d_smt),
d_propagator(d_nonClausalLearnedLiterals, true, true),
+ d_propagatorNeedsFinish(false),
d_assertionsToCheck(),
d_fakeContext(),
d_abstractValueMap(&d_fakeContext),
@@ -365,6 +387,14 @@ public:
d_smt.d_nodeManager->subscribeEvents(this);
}
+ ~SmtEnginePrivate() {
+ if(d_propagatorNeedsFinish) {
+ d_propagator.finish();
+ d_propagatorNeedsFinish = false;
+ }
+ d_smt.d_nodeManager->unsubscribeEvents(this);
+ }
+
void nmNotifyNewSort(TypeNode tn) {
DeclareTypeCommand c(tn.getAttribute(expr::VarNameAttr()),
0,
@@ -389,10 +419,13 @@ public:
n.toExpr(),
n.getType().toType());
d_smt.addToModelCommandAndDump(c, isGlobal);
+ if(n.getType().isBoolean() && !options::incrementalSolving()) {
+ d_boolVars.push_back(n);
+ }
}
void nmNotifyNewSkolem(TNode n, const std::string& comment, bool isGlobal) {
- std::string id = n.getAttribute(expr::VarNameAttr());
+ string id = n.getAttribute(expr::VarNameAttr());
DeclareFunctionCommand c(id,
n.toExpr(),
n.getType().toType());
@@ -400,6 +433,9 @@ public:
Dump("skolems") << CommentCommand(id + " is " + comment);
}
d_smt.addToModelCommandAndDump(c, isGlobal, false, "skolems");
+ if(n.getType().isBoolean() && !options::incrementalSolving()) {
+ d_boolVars.push_back(n);
+ }
}
Node applySubstitutions(TNode node) const {
@@ -506,8 +542,6 @@ public:
}/* namespace CVC4::smt */
-using namespace CVC4::smt;
-
SmtEngine::SmtEngine(ExprManager* em) throw() :
d_context(em->getContext()),
d_userLevels(),
@@ -623,17 +657,17 @@ void SmtEngine::finalOptionsAreSet() {
if(options::checkModels()) {
if(! options::produceModels()) {
- Notice() << "SmtEngine: turning on produce-models to support check-model" << std::endl;
+ Notice() << "SmtEngine: turning on produce-models to support check-model" << endl;
setOption("produce-models", SExpr("true"));
}
if(! options::interactive()) {
- Notice() << "SmtEngine: turning on interactive-mode to support check-model" << std::endl;
+ Notice() << "SmtEngine: turning on interactive-mode to support check-model" << endl;
setOption("interactive-mode", SExpr("true"));
}
}
if(options::produceAssignments() && !options::produceModels()) {
- Notice() << "SmtEngine: turning on produce-models to support produce-assignments" << std::endl;
+ Notice() << "SmtEngine: turning on produce-models to support produce-assignments" << endl;
setOption("produce-models", SExpr("true"));
}
@@ -784,15 +818,15 @@ void SmtEngine::setLogicInternal() throw() {
// by default, symmetry breaker is on only for QF_UF
if(! options::ufSymmetryBreaker.wasSetByUser()) {
bool qf_uf = d_logic.isPure(THEORY_UF) && !d_logic.isQuantified();
- Trace("smt") << "setting uf symmetry breaker to " << qf_uf << std::endl;
+ Trace("smt") << "setting uf symmetry breaker to " << qf_uf << endl;
options::ufSymmetryBreaker.set(qf_uf);
}
// by default, nonclausal simplification is off for QF_SAT and for quantifiers
if(! options::simplificationMode.wasSetByUser()) {
bool qf_sat = d_logic.isPure(THEORY_BOOL) && !d_logic.isQuantified();
bool quantifiers = d_logic.isQuantified();
- Trace("smt") << "setting simplification mode to <" << d_logic.getLogicString() << "> " << (!qf_sat && !quantifiers) << std::endl;
- //simplifaction=none works better for SMT LIB benchmarks with quantifiers, not others
+ Trace("smt") << "setting simplification mode to <" << d_logic.getLogicString() << "> " << (!qf_sat && !quantifiers) << endl;
+ //simplification=none works better for SMT LIB benchmarks with quantifiers, not others
//options::simplificationMode.set(qf_sat || quantifiers ? SIMPLIFICATION_MODE_NONE : SIMPLIFICATION_MODE_BATCH);
options::simplificationMode.set(qf_sat ? SIMPLIFICATION_MODE_NONE : SIMPLIFICATION_MODE_BATCH);
}
@@ -808,14 +842,14 @@ void SmtEngine::setLogicInternal() throw() {
bool iteSimp = !d_logic.isQuantified() &&
((d_logic.isPure(THEORY_ARITH) && d_logic.isLinear() && !d_logic.isDifferenceLogic() && !d_logic.areRealsUsed()) ||
(d_logic.isTheoryEnabled(THEORY_ARRAY) && d_logic.isTheoryEnabled(THEORY_UF) && d_logic.isTheoryEnabled(THEORY_BV)));
- Trace("smt") << "setting ite simplification to " << iteSimp << std::endl;
+ Trace("smt") << "setting ite simplification to " << iteSimp << endl;
options::doITESimp.set(iteSimp);
}
// Turn on multiple-pass non-clausal simplification for QF_AUFBV
if(! options::repeatSimp.wasSetByUser()) {
bool repeatSimp = !d_logic.isQuantified() &&
(d_logic.isTheoryEnabled(THEORY_ARRAY) && d_logic.isTheoryEnabled(THEORY_UF) && d_logic.isTheoryEnabled(THEORY_BV));
- Trace("smt") << "setting repeat simplification to " << repeatSimp << std::endl;
+ Trace("smt") << "setting repeat simplification to " << repeatSimp << endl;
options::repeatSimp.set(repeatSimp);
}
// Turn on unconstrained simplification for QF_AUFBV
@@ -824,24 +858,24 @@ void SmtEngine::setLogicInternal() throw() {
// bool uncSimp = false && !qf_sat && !options::incrementalSolving();
bool uncSimp = !options::incrementalSolving() && !d_logic.isQuantified() && !options::produceModels() && !options::checkModels() &&
(d_logic.isTheoryEnabled(THEORY_ARRAY) && d_logic.isTheoryEnabled(THEORY_BV));
- Trace("smt") << "setting unconstrained simplification to " << uncSimp << std::endl;
+ Trace("smt") << "setting unconstrained simplification to " << uncSimp << endl;
options::unconstrainedSimp.set(uncSimp);
}
// Unconstrained simp currently does *not* support model generation
if (options::unconstrainedSimp.wasSetByUser() && options::unconstrainedSimp()) {
if (options::produceModels()) {
- Notice() << "SmtEngine: turning off produce-models to support unconstrainedSimp" << std::endl;
+ Notice() << "SmtEngine: turning off produce-models to support unconstrainedSimp" << endl;
setOption("produce-models", SExpr("false"));
}
if (options::checkModels()) {
- Notice() << "SmtEngine: turning off check-models to support unconstrainedSimp" << std::endl;
+ Notice() << "SmtEngine: turning off check-models to support unconstrainedSimp" << endl;
setOption("check-models", SExpr("false"));
}
}
// Turn on arith rewrite equalities only for pure arithmetic
if(! options::arithRewriteEq.wasSetByUser()) {
bool arithRewriteEq = d_logic.isPure(THEORY_ARITH) && !d_logic.isQuantified();
- Trace("smt") << "setting arith rewrite equalities " << arithRewriteEq << std::endl;
+ Trace("smt") << "setting arith rewrite equalities " << arithRewriteEq << endl;
options::arithRewriteEq.set(arithRewriteEq);
}
if(! options::arithHeuristicPivots.wasSetByUser()) {
@@ -853,7 +887,7 @@ void SmtEngine::setLogicInternal() throw() {
heuristicPivots = 0;
}
}
- Trace("smt") << "setting arithHeuristicPivots " << heuristicPivots << std::endl;
+ Trace("smt") << "setting arithHeuristicPivots " << heuristicPivots << endl;
options::arithHeuristicPivots.set(heuristicPivots);
}
if(! options::arithPivotThreshold.wasSetByUser()){
@@ -863,7 +897,7 @@ void SmtEngine::setLogicInternal() throw() {
pivotThreshold = 16;
}
}
- Trace("smt") << "setting arith arithPivotThreshold " << pivotThreshold << std::endl;
+ Trace("smt") << "setting arith arithPivotThreshold " << pivotThreshold << endl;
options::arithPivotThreshold.set(pivotThreshold);
}
if(! options::arithStandardCheckVarOrderPivots.wasSetByUser()){
@@ -871,7 +905,7 @@ void SmtEngine::setLogicInternal() throw() {
if(d_logic.isPure(THEORY_ARITH) && !d_logic.isQuantified()){
varOrderPivots = 200;
}
- Trace("smt") << "setting arithStandardCheckVarOrderPivots " << varOrderPivots << std::endl;
+ Trace("smt") << "setting arithStandardCheckVarOrderPivots " << varOrderPivots << endl;
options::arithStandardCheckVarOrderPivots.set(varOrderPivots);
}
// Turn off early theory preprocessing if arithRewriteEq is on
@@ -930,7 +964,7 @@ void SmtEngine::setLogicInternal() throw() {
? true : false
);
- Trace("smt") << "setting decision mode to " << decMode << std::endl;
+ Trace("smt") << "setting decision mode to " << decMode << endl;
options::decisionMode.set(decMode);
options::decisionStopOnly.set(stoponly);
}
@@ -938,7 +972,7 @@ void SmtEngine::setLogicInternal() throw() {
//for finite model finding
if( ! options::instWhenMode.wasSetByUser()){
if( options::fmfInstEngine() ){
- Trace("smt") << "setting inst when mode to LAST_CALL" << std::endl;
+ Trace("smt") << "setting inst when mode to LAST_CALL" << endl;
options::instWhenMode.set( INST_WHEN_LAST_CALL );
}
}
@@ -951,11 +985,11 @@ void SmtEngine::setLogicInternal() throw() {
}
else if (options::minisatUseElim()) {
if (options::produceModels()) {
- Notice() << "SmtEngine: turning off produce-models to support minisatUseElim" << std::endl;
+ Notice() << "SmtEngine: turning off produce-models to support minisatUseElim" << endl;
setOption("produce-models", SExpr("false"));
}
if (options::checkModels()) {
- Notice() << "SmtEngine: turning off check-models to support minisatUseElim" << std::endl;
+ Notice() << "SmtEngine: turning off check-models to support minisatUseElim" << endl;
setOption("check-models", SExpr("false"));
}
}
@@ -970,11 +1004,11 @@ void SmtEngine::setLogicInternal() throw() {
if (d_logic.isTheoryEnabled(theory::THEORY_ARITH) &&
!d_logic.isLinear()) {
if (options::produceModels()) {
- Warning() << "SmtEngine: turning off produce-models because unsupported for nonlinear arith" << std::endl;
+ Warning() << "SmtEngine: turning off produce-models because unsupported for nonlinear arith" << endl;
setOption("produce-models", SExpr("false"));
}
if (options::checkModels()) {
- Warning() << "SmtEngine: turning off check-models because unsupported for nonlinear arith" << std::endl;
+ Warning() << "SmtEngine: turning off check-models because unsupported for nonlinear arith" << endl;
setOption("check-models", SExpr("false"));
}
}
@@ -995,7 +1029,7 @@ void SmtEngine::setInfo(const std::string& key, const CVC4::SExpr& value)
Trace("smt") << "SMT setInfo(" << key << ", " << value << ")" << endl;
if(Dump.isOn("benchmark")) {
if(key == "status") {
- std::string s = value.getValue();
+ string s = value.getValue();
BenchmarkStatus status =
(s == "sat") ? SMT_SATISFIABLE :
((s == "unsat") ? SMT_UNSATISFIABLE : SMT_UNKNOWN);
@@ -1175,7 +1209,7 @@ void SmtEngine::defineFunction(Expr func,
// Permit (check-sat) (define-fun ...) (get-value ...) sequences.
// Otherwise, (check-sat) (get-value ((! foo :named bar))) breaks
// d_haveAdditions = true;
- Debug("smt") << "definedFunctions insert " << funcNode << " " << formNode << std::endl;
+ Debug("smt") << "definedFunctions insert " << funcNode << " " << formNode << endl;
d_definedFunctions->insert(funcNode, def);
}
@@ -1185,7 +1219,7 @@ Node SmtEnginePrivate::getBVDivByZero(Kind k, unsigned width) {
if (k == kind::BITVECTOR_UDIV) {
if (d_BVDivByZero.find(width) == d_BVDivByZero.end()) {
// lazily create the function symbols
- std::ostringstream os;
+ ostringstream os;
os << "BVUDivByZero_" << width;
Node divByZero = nm->mkSkolem(os.str(),
nm->mkFunctionType(nm->mkBitVectorType(width), nm->mkBitVectorType(width)),
@@ -1196,7 +1230,7 @@ Node SmtEnginePrivate::getBVDivByZero(Kind k, unsigned width) {
}
else if (k == kind::BITVECTOR_UREM) {
if (d_BVRemByZero.find(width) == d_BVRemByZero.end()) {
- std::ostringstream os;
+ ostringstream os;
os << "BVURemByZero_" << width;
Node divByZero = nm->mkSkolem(os.str(),
nm->mkFunctionType(nm->mkBitVectorType(width), nm->mkBitVectorType(width)),
@@ -1236,7 +1270,7 @@ Node SmtEnginePrivate::expandDefinitions(TNode n, hash_map<Node, Node, NodeHashF
if(i != d_smt.d_definedFunctions->end()) {
// replacement must be closed
if((*i).second.getFormals().size() > 0) {
- throw TypeCheckingException(n.toExpr(), std::string("Defined function requires arguments: `") + n.toString() + "'");
+ throw TypeCheckingException(n.toExpr(), string("Defined function requires arguments: `") + n.toString() + "'");
}
// don't bother putting in the cache
return (*i).second.getFormula();
@@ -1265,9 +1299,9 @@ Node SmtEnginePrivate::expandDefinitions(TNode n, hash_map<Node, Node, NodeHashF
break;
}
- case kind::BITVECTOR_UDIV:
- case kind::BITVECTOR_UREM: {
- node = expandBVDivByZero(node);
+ case kind::BITVECTOR_UDIV:
+ case kind::BITVECTOR_UREM: {
+ node = expandBVDivByZero(node);
break;
}
case kind::DIVISION: {
@@ -1339,7 +1373,7 @@ Node SmtEnginePrivate::expandDefinitions(TNode n, hash_map<Node, Node, NodeHashF
Debug("expand") << " : \"" << name << "\"" << endl;
}
if(i == d_smt.d_definedFunctions->end()) {
- throw TypeCheckingException(n.toExpr(), std::string("Undefined function: `") + func.toString() + "'");
+ throw TypeCheckingException(n.toExpr(), string("Undefined function: `") + func.toString() + "'");
}
if(Debug.isOn("expand")) {
Debug("expand") << " defn: " << def.getFunction() << endl
@@ -1408,16 +1442,16 @@ static bool containsQuantifiers(Node n) {
}
Node SmtEnginePrivate::preSkolemizeQuantifiers( Node n, bool polarity, std::vector< Node >& fvs ){
- Trace("pre-sk") << "Pre-skolem " << n << " " << polarity << " " << fvs.size() << std::endl;
+ Trace("pre-sk") << "Pre-skolem " << n << " " << polarity << " " << fvs.size() << endl;
if( n.getKind()==kind::NOT ){
Node nn = preSkolemizeQuantifiers( n[0], !polarity, fvs );
return nn.negate();
}else if( n.getKind()==kind::FORALL ){
if( polarity ){
- std::vector< Node > children;
+ vector< Node > children;
children.push_back( n[0] );
//add children to current scope
- std::vector< Node > fvss;
+ vector< Node > fvss;
fvss.insert( fvss.begin(), fvs.begin(), fvs.end() );
for( int i=0; i<(int)n[0].getNumChildren(); i++ ){
fvss.push_back( n[0][i] );
@@ -1433,13 +1467,13 @@ Node SmtEnginePrivate::preSkolemizeQuantifiers( Node n, bool polarity, std::vect
//process body
Node nn = preSkolemizeQuantifiers( n[1], polarity, fvs );
//now, substitute skolems for the variables
- std::vector< TypeNode > argTypes;
+ vector< TypeNode > argTypes;
for( int i=0; i<(int)fvs.size(); i++ ){
argTypes.push_back( fvs[i].getType() );
}
//calculate the variables and substitution
- std::vector< Node > vars;
- std::vector< Node > subs;
+ vector< Node > vars;
+ vector< Node > subs;
for( int i=0; i<(int)n[0].getNumChildren(); i++ ){
vars.push_back( n[0][i] );
}
@@ -1452,7 +1486,7 @@ Node SmtEnginePrivate::preSkolemizeQuantifiers( Node n, bool polarity, std::vect
TypeNode typ = NodeManager::currentNM()->mkFunctionType( argTypes, n[0][i].getType() );
Node op = NodeManager::currentNM()->mkSkolem( "skop_$$", typ, "op created during pre-skolemization" );
//DOTHIS: set attribute on op, marking that it should not be selected as trigger
- std::vector< Node > funcArgs;
+ vector< Node > funcArgs;
funcArgs.push_back( op );
funcArgs.insert( funcArgs.end(), fvs.begin(), fvs.end() );
subs.push_back( NodeManager::currentNM()->mkNode( kind::APPLY_UF, funcArgs ) );
@@ -1492,7 +1526,7 @@ Node SmtEnginePrivate::preSkolemizeQuantifiers( Node n, bool polarity, std::vect
return preSkolemizeQuantifiers( nn, polarity, fvs );
}else{
Assert( n.getKind() == kind::AND || n.getKind() == kind::OR );
- std::vector< Node > children;
+ vector< Node > children;
for( int i=0; i<(int)n.getNumChildren(); i++ ){
children.push_back( preSkolemizeQuantifiers( n[i], polarity, fvs ) );
}
@@ -1541,7 +1575,7 @@ void SmtEnginePrivate::staticLearning() {
static void dumpAssertions(const char* key,
const std::vector<Node>& assertionList) {
if( Dump.isOn("assertions") &&
- Dump.isOn(std::string("assertions:") + key) ) {
+ Dump.isOn(string("assertions:") + key) ) {
// Push the simplified assertions to the dump output stream
for(unsigned i = 0; i < assertionList.size(); ++ i) {
TNode n = assertionList[i];
@@ -1558,6 +1592,10 @@ bool SmtEnginePrivate::nonClausalSimplify() {
Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify()" << endl;
+ if(d_propagatorNeedsFinish) {
+ d_propagator.finish();
+ d_propagatorNeedsFinish = false;
+ }
d_propagator.initialize();
// Assert all the assertions to the propagator
@@ -1577,7 +1615,7 @@ bool SmtEnginePrivate::nonClausalSimplify() {
<< "conflict in non-clausal propagation" << endl;
d_assertionsToPreprocess.clear();
d_assertionsToCheck.push_back(NodeManager::currentNM()->mkConst<bool>(false));
- d_propagator.finish();
+ d_propagatorNeedsFinish = true;
return false;
}
@@ -1612,7 +1650,7 @@ bool SmtEnginePrivate::nonClausalSimplify() {
<< d_nonClausalLearnedLiterals[i] << endl;
d_assertionsToPreprocess.clear();
d_assertionsToCheck.push_back(NodeManager::currentNM()->mkConst<bool>(false));
- d_propagator.finish();
+ d_propagatorNeedsFinish = true;
return false;
}
}
@@ -1644,7 +1682,7 @@ bool SmtEnginePrivate::nonClausalSimplify() {
<< learnedLiteral << endl;
d_assertionsToPreprocess.clear();
d_assertionsToCheck.push_back(NodeManager::currentNM()->mkConst<bool>(false));
- d_propagator.finish();
+ d_propagatorNeedsFinish = true;
return false;
default:
if (d_doConstantProp && learnedLiteral.getKind() == kind::EQUAL && (learnedLiteral[0].isConst() || learnedLiteral[1].isConst())) {
@@ -1714,6 +1752,17 @@ bool SmtEnginePrivate::nonClausalSimplify() {
// Resize the learnt
d_nonClausalLearnedLiterals.resize(j);
+ //must add substitutions to model
+ TheoryModel* m = d_smt.d_theoryEngine->getModel();
+ if(m != NULL) {
+ for( SubstitutionMap::iterator pos = d_topLevelSubstitutions.begin(); pos != d_topLevelSubstitutions.end(); ++pos) {
+ Node n = (*pos).first;
+ Node v = (*pos).second;
+ Trace("model") << "Add substitution : " << n << " " << v << std::endl;
+ m->addSubstitution( n, v );
+ }
+ }
+
hash_set<TNode, TNodeHashFunction> s;
for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
Node assertion = d_assertionsToPreprocess[i];
@@ -1812,7 +1861,7 @@ bool SmtEnginePrivate::nonClausalSimplify() {
Rewriter::rewrite(Node(learnedBuilder));
}
- d_propagator.finish();
+ d_propagatorNeedsFinish = true;
return true;
}
@@ -1894,6 +1943,366 @@ void SmtEnginePrivate::constrainSubtypes(TNode top, std::vector<Node>& assertion
} while(! worklist.empty());
}
+void SmtEnginePrivate::traceBackToAssertions(const std::vector<Node>& nodes, std::vector<TNode>& assertions) {
+ const booleans::CircuitPropagator::BackEdgesMap& backEdges = d_propagator.getBackEdges();
+ for(vector<Node>::const_iterator i = nodes.begin(); i != nodes.end(); ++i) {
+ booleans::CircuitPropagator::BackEdgesMap::const_iterator j = backEdges.find(*i);
+ // term must appear in map, otherwise how did we get here?!
+ Assert(j != backEdges.end());
+ // if term maps to empty, that means it's a top-level assertion
+ if(!(*j).second.empty()) {
+ traceBackToAssertions((*j).second, assertions);
+ } else {
+ assertions.push_back(*i);
+ }
+ }
+}
+
+size_t SmtEnginePrivate::removeFromConjunction(Node& n, const std::hash_set<unsigned>& toRemove) {
+ Assert(n.getKind() == kind::AND);
+ Node trueNode = NodeManager::currentNM()->mkConst(true);
+ size_t removals = 0;
+ for(Node::iterator j = n.begin(); j != n.end(); ++j) {
+ size_t subremovals = 0;
+ Node sub = *j;
+ if(toRemove.find(sub.getId()) != toRemove.end() ||
+ (sub.getKind() == kind::AND && (subremovals = removeFromConjunction(sub, toRemove)) > 0)) {
+ NodeBuilder<> b(kind::AND);
+ b.append(n.begin(), j);
+ if(subremovals > 0) {
+ removals += subremovals;
+ b << sub;
+ } else {
+ ++removals;
+ }
+ for(++j; j != n.end(); ++j) {
+ if(toRemove.find((*j).getId()) != toRemove.end()) {
+ ++removals;
+ } else if((*j).getKind() == kind::AND) {
+ sub = *j;
+ if((subremovals = removeFromConjunction(sub, toRemove)) > 0) {
+ removals += subremovals;
+ b << sub;
+ } else {
+ b << *j;
+ }
+ } else {
+ b << *j;
+ }
+ }
+ if(b.getNumChildren() == 0) {
+ n = trueNode;
+ b.clear();
+ } else if(b.getNumChildren() == 1) {
+ n = b[0];
+ b.clear();
+ } else {
+ n = b;
+ }
+ n = Rewriter::rewrite(n);
+ return removals;
+ }
+ }
+
+ Assert(removals == 0);
+ return 0;
+}
+
+void SmtEnginePrivate::doMiplibTrick() {
+ Assert(d_assertionsToPreprocess.empty());
+ Assert(d_realAssertionsEnd == d_assertionsToCheck.size());
+ Assert(!options::incrementalSolving());
+
+ const booleans::CircuitPropagator::BackEdgesMap& backEdges = d_propagator.getBackEdges();
+ hash_set<unsigned> removeAssertions;
+
+ NodeManager* nm = NodeManager::currentNM();
+ Node zero = nm->mkConst(Rational(0)), one = nm->mkConst(Rational(1));
+
+ hash_map<TNode, Node, TNodeHashFunction> intVars;
+ for(vector<Node>::const_iterator i = d_boolVars.begin(); i != d_boolVars.end(); ++i) {
+ if(d_propagator.isAssigned(*i)) {
+ Debug("miplib") << "ineligible: " << *i << " because assigned " << d_propagator.getAssignment(*i) << endl;
+ continue;
+ }
+
+ vector<TNode> assertions;
+ booleans::CircuitPropagator::BackEdgesMap::const_iterator j = backEdges.find(*i);
+ // if not in back edges map, the bool var is unconstrained, showing up in no assertions.
+ // if maps to an empty vector, that means the bool var was asserted itself.
+ if(j != backEdges.end()) {
+ if(!(*j).second.empty()) {
+ traceBackToAssertions((*j).second, assertions);
+ } else {
+ assertions.push_back(*i);
+ }
+ }
+ Debug("miplib") << "for " << *i << endl;
+ bool eligible = true;
+ map<pair<Node, Node>, uint64_t> marks;
+ map<pair<Node, Node>, vector<Rational> > coef;
+ map<pair<Node, Node>, vector<Rational> > checks;
+ map<pair<Node, Node>, vector<TNode> > asserts;
+ for(vector<TNode>::const_iterator j = assertions.begin(); j != assertions.end(); ++j) {
+ Debug("miplib") << " found: " << *j << endl;
+ if((*j).getKind() != kind::IMPLIES) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (not =>)" << endl;
+ break;
+ }
+ Node conj = BooleanSimplification::simplify((*j)[0]);
+ if(conj.getKind() == kind::AND && conj.getNumChildren() > 6) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (N-ary /\\ too big)" << endl;
+ break;
+ }
+ if(conj.getKind() != kind::AND && !conj.isVar() && !(conj.getKind() == kind::NOT && conj[0].isVar())) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (not /\\ or literal)" << endl;
+ break;
+ }
+ if((*j)[1].getKind() != kind::EQUAL ||
+ !( ( (*j)[1][0].isVar() &&
+ (*j)[1][1].getKind() == kind::CONST_RATIONAL ) ||
+ ( (*j)[1][0].getKind() == kind::CONST_RATIONAL &&
+ (*j)[1][1].isVar() ) )) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (=> (and X X) X)" << endl;
+ break;
+ }
+ if(conj.getKind() == kind::AND) {
+ vector<Node> posv;
+ bool found_x = false;
+ map<TNode, bool> neg;
+ for(Node::iterator ii = conj.begin(); ii != conj.end(); ++ii) {
+ if((*ii).isVar()) {
+ posv.push_back(*ii);
+ neg[*ii] = false;
+ found_x = found_x || *i == *ii;
+ } else if((*ii).getKind() == kind::NOT && (*ii)[0].isVar()) {
+ posv.push_back((*ii)[0]);
+ neg[(*ii)[0]] = true;
+ found_x = found_x || *i == (*ii)[0];
+ } else {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (non-var: " << *ii << ")" << endl;
+ break;
+ }
+ if(d_propagator.isAssigned(posv.back())) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (" << posv.back() << " asserted)" << endl;
+ break;
+ }
+ }
+ if(!eligible) {
+ break;
+ }
+ if(!found_x) {
+ eligible = false;
+ Debug("miplib") << " --INELIGIBLE -- (couldn't find " << *i << " in conjunction)" << endl;
+ break;
+ }
+ sort(posv.begin(), posv.end());
+ const Node pos = NodeManager::currentNM()->mkNode(kind::AND, posv);
+ const TNode var = ((*j)[1][0].getKind() == kind::CONST_RATIONAL) ? (*j)[1][1] : (*j)[1][0];
+ const pair<Node, Node> pos_var(pos, var);
+ const Rational& constant = ((*j)[1][0].getKind() == kind::CONST_RATIONAL) ? (*j)[1][0].getConst<Rational>() : (*j)[1][1].getConst<Rational>();
+ uint64_t mark = 0;
+ unsigned countneg = 0, thepos = 0;
+ for(unsigned ii = 0; ii < pos.getNumChildren(); ++ii) {
+ if(neg[pos[ii]]) {
+ ++countneg;
+ } else {
+ thepos = ii;
+ mark |= (0x1 << ii);
+ }
+ }
+ if((marks[pos_var] & (1lu << mark)) != 0) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (remarked)" << endl;
+ break;
+ }
+ Debug("miplib") << "mark is " << mark << " -- " << (1lu << mark) << endl;
+ marks[pos_var] |= (1lu << mark);
+ Debug("miplib") << "marks[" << pos << "," << var << "] now " << marks[pos_var] << endl;
+ if(countneg == pos.getNumChildren()) {
+ if(constant != 0) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (nonzero constant)" << endl;
+ break;
+ }
+ } else if(countneg == pos.getNumChildren() - 1) {
+ Assert(coef[pos_var].size() <= 6 && thepos < 6);
+ coef[pos_var].resize(6);
+ coef[pos_var][thepos] = constant;
+ } else {
+ if(checks[pos_var].size() <= mark) {
+ checks[pos_var].resize(mark + 1);
+ }
+ checks[pos_var][mark] = constant;
+ }
+ asserts[pos_var].push_back(*j);
+ } else {
+ TNode x = conj;
+ if(x != *i && x != (*i).notNode()) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (x not present where I expect it)" << endl;
+ break;
+ }
+ const bool xneg = (x.getKind() == kind::NOT);
+ x = xneg ? x[0] : x;
+ Debug("miplib") << " x:" << x << " " << xneg << endl;
+ const TNode var = ((*j)[1][0].getKind() == kind::CONST_RATIONAL) ? (*j)[1][1] : (*j)[1][0];
+ const pair<Node, Node> x_var(x, var);
+ const Rational& constant = ((*j)[1][0].getKind() == kind::CONST_RATIONAL) ? (*j)[1][0].getConst<Rational>() : (*j)[1][1].getConst<Rational>();
+ unsigned mark = (xneg ? 0 : 1);
+ if((marks[x_var] & (1u << mark)) != 0) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (remarked)" << endl;
+ break;
+ }
+ marks[x_var] |= (1u << mark);
+ if(xneg) {
+ if(constant != 0) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (nonzero constant)" << endl;
+ break;
+ }
+ } else {
+ Assert(coef[x_var].size() <= 6);
+ coef[x_var].resize(6);
+ coef[x_var][0] = constant;
+ if(checks[x_var].size() <= mark) {
+ checks[x_var].resize(mark + 1);
+ }
+ checks[x_var][mark] = constant;
+ }
+ asserts[x_var].push_back(*j);
+ }
+ }
+ if(eligible) {
+ for(map<pair<Node, Node>, uint64_t>::const_iterator j = marks.begin(); j != marks.end(); ++j) {
+ const TNode pos = (*j).first.first;
+ const TNode var = (*j).first.second;
+ const pair<Node, Node>& pos_var = (*j).first;
+ const uint64_t mark = (*j).second;
+ const unsigned numVars = pos.getKind() == kind::AND ? pos.getNumChildren() : 1;
+ uint64_t expected = (uint64_t(1) << (1 << numVars)) - 1;
+ expected = (expected == 0) ? -1 : expected;// fix for overflow
+ Debug("miplib") << "[" << pos << "] => " << hex << mark << " expect " << expected << dec << endl;
+ Assert(pos.getKind() == kind::AND || pos.isVar());
+ if(mark != expected) {
+ Debug("miplib") << " -- INELIGIBLE " << pos << " -- (insufficiently marked, got " << mark << " for " << numVars << " vars, expected " << expected << endl;
+ } else {
+ if(false) { //checks[pos] != coef[pos][0] + coef[pos][1]) {
+ Debug("miplib") << " -- INELIGIBLE " << pos << " -- (not linear combination)" << endl;
+ } else {
+ Debug("miplib") << " -- ELIGIBLE " << *i << " , " << pos << " --" << endl;
+ vector<Node> newVars;
+ expr::NodeSelfIterator ii, iiend;
+ if(pos.getKind() == kind::AND) {
+ ii = pos.begin();
+ iiend = pos.end();
+ } else {
+ ii = expr::NodeSelfIterator::self(pos);
+ iiend = expr::NodeSelfIterator::selfEnd(pos);
+ }
+ for(; ii != iiend; ++ii) {
+ Node& varRef = intVars[*ii];
+ if(varRef.isNull()) {
+ stringstream ss;
+ ss << "mipvar_" << *ii;
+ Node newVar = nm->mkSkolem(ss.str(), nm->integerType(), "a variable introduced due to scrubbing a miplib encoding", NodeManager::SKOLEM_EXACT_NAME);
+ Node geq = Rewriter::rewrite(nm->mkNode(kind::GEQ, newVar, zero));
+ Node leq = Rewriter::rewrite(nm->mkNode(kind::LEQ, newVar, one));
+ d_assertionsToCheck.push_back(Rewriter::rewrite(geq.andNode(leq)));
+ SubstitutionMap nullMap(&d_fakeContext);
+ Theory::PPAssertStatus status CVC4_UNUSED;// just for assertions
+ status = d_smt.d_theoryEngine->solve(geq, nullMap);
+ Assert(status == Theory::PP_ASSERT_STATUS_UNSOLVED,
+ "unexpected solution from arith's ppAssert()");
+ Assert(nullMap.empty(),
+ "unexpected substitution from arith's ppAssert()");
+ status = d_smt.d_theoryEngine->solve(leq, nullMap);
+ Assert(status == Theory::PP_ASSERT_STATUS_UNSOLVED,
+ "unexpected solution from arith's ppAssert()");
+ Assert(nullMap.empty(),
+ "unexpected substitution from arith's ppAssert()");
+ d_smt.d_theoryEngine->getModel()->addSubstitution(*ii, newVar.eqNode(one));
+ newVars.push_back(newVar);
+ varRef = newVar;
+ } else {
+ newVars.push_back(varRef);
+ }
+ if(!d_smt.d_logic.areIntegersUsed()) {
+ d_smt.d_logic = d_smt.d_logic.getUnlockedCopy();
+ d_smt.d_logic.enableIntegers();
+ d_smt.d_logic.lock();
+ }
+ }
+ Node sum;
+ if(pos.getKind() == kind::AND) {
+ NodeBuilder<> sumb(kind::PLUS);
+ for(size_t ii = 0; ii < pos.getNumChildren(); ++ii) {
+ sumb << nm->mkNode(kind::MULT, nm->mkConst(coef[pos_var][ii]), newVars[ii]);
+ }
+ sum = sumb;
+ } else {
+ sum = nm->mkNode(kind::MULT, nm->mkConst(coef[pos_var][0]), newVars[0]);
+ }
+ Debug("miplib") << "vars[] " << var << endl
+ << " eq " << Rewriter::rewrite(sum) << endl;
+ Node newAssertion = var.eqNode(Rewriter::rewrite(sum));
+ if(d_topLevelSubstitutions.hasSubstitution(newAssertion[0])) {
+ //Warning() << "RE-SUBSTITUTION " << newAssertion[0] << endl;
+ //Warning() << "REPLACE " << newAssertion[1] << endl;
+ //Warning() << "ORIG " << d_topLevelSubstitutions.getSubstitution(newAssertion[0]) << endl;
+ Assert(d_topLevelSubstitutions.getSubstitution(newAssertion[0]) == newAssertion[1]);
+ } else if(pos.getNumChildren() <= options::arithMLTrickSubstitutions()) {
+ d_topLevelSubstitutions.addSubstitution(newAssertion[0], newAssertion[1]);
+ Debug("miplib") << "addSubs: " << newAssertion[0] << " to " << newAssertion[1] << endl;
+ } else {
+ Debug("miplib") << "skipSubs: " << newAssertion[0] << " to " << newAssertion[1] << " (threshold is " << options::arithMLTrickSubstitutions() << ")" << endl;
+ }
+ newAssertion = Rewriter::rewrite(newAssertion);
+ Debug("miplib") << " " << newAssertion << endl;
+ d_assertionsToCheck.push_back(newAssertion);
+ Debug("miplib") << " assertions to remove: " << endl;
+ for(vector<TNode>::const_iterator k = asserts[pos_var].begin(), k_end = asserts[pos_var].end(); k != k_end; ++k) {
+ Debug("miplib") << " " << *k << endl;
+ removeAssertions.insert((*k).getId());
+ }
+ }
+ }
+ }
+ }
+ }
+ if(!removeAssertions.empty()) {
+ Debug("miplib") << "SmtEnginePrivate::simplify(): scrubbing miplib encoding..." << endl;
+ Node trueNode = nm->mkConst(true);
+ for(size_t i = 0; i < d_realAssertionsEnd; ++i) {
+ if(removeAssertions.find(d_assertionsToCheck[i].getId()) != removeAssertions.end()) {
+ Debug("miplib") << "SmtEnginePrivate::simplify(): - removing " << d_assertionsToCheck[i] << endl;
+ d_assertionsToCheck[i] = trueNode;
+ ++d_smt.d_stats->d_numMiplibAssertionsRemoved;
+ } else if(d_assertionsToCheck[i].getKind() == kind::AND) {
+ size_t removals = removeFromConjunction(d_assertionsToCheck[i], removeAssertions);
+ if(removals > 0) {
+ Debug("miplib") << "SmtEnginePrivate::simplify(): - reduced " << d_assertionsToCheck[i] << endl;
+ Debug("miplib") << "SmtEnginePrivate::simplify(): - by " << removals << " conjuncts" << endl;
+ d_smt.d_stats->d_numMiplibAssertionsRemoved += removals;
+ }
+ }
+ Debug("miplib") << "had: " << d_assertionsToCheck[i] << endl;
+ d_assertionsToCheck[i] = Rewriter::rewrite(d_topLevelSubstitutions.apply(d_assertionsToCheck[i]));
+ Debug("miplib") << "now: " << d_assertionsToCheck[i] << endl;
+ }
+ } else {
+ Debug("miplib") << "SmtEnginePrivate::simplify(): miplib pass found nothing." << endl;
+ }
+ d_realAssertionsEnd = d_assertionsToCheck.size();
+}
+
// returns false if simplification led to "false"
bool SmtEnginePrivate::simplifyAssertions()
throw(TypeCheckingException, LogicException) {
@@ -1904,21 +2313,49 @@ bool SmtEnginePrivate::simplifyAssertions()
if(options::simplificationMode() != SIMPLIFICATION_MODE_NONE) {
// Perform non-clausal simplification
+ Chat() << "...performing nonclausal simplification..." << endl;
Trace("simplify") << "SmtEnginePrivate::simplify(): "
<< "performing non-clausal simplification" << endl;
bool noConflict = nonClausalSimplify();
- if(!noConflict) return false;
+ if(!noConflict) {
+ return false;
+ }
+
+ // We piggy-back off of the BackEdgesMap in the CircuitPropagator to
+ // do the miplib trick.
+ if( // check that option is on
+ options::arithMLTrick() &&
+ // miplib rewrites aren't safe in incremental mode
+ ! options::incrementalSolving() &&
+ // only useful in arith
+ d_smt.d_logic.isTheoryEnabled(theory::THEORY_ARITH) &&
+ // we add new assertions and need this (in practice, this
+ // restriction only disables miplib processing during
+ // re-simplification, which we don't expect to be useful anyway)
+ d_realAssertionsEnd == d_assertionsToCheck.size() ) {
+ Chat() << "...fixing miplib encodings..." << endl;
+ Trace("simplify") << "SmtEnginePrivate::simplify(): "
+ << "looking for miplib pseudobooleans..." << endl;
+
+ TimerStat::CodeTimer miplibTimer(d_smt.d_stats->d_miplibPassTime);
+
+ doMiplibTrick();
+ } else {
+ Trace("simplify") << "SmtEnginePrivate::simplify(): "
+ << "skipping miplib pseudobooleans pass (either incrementalSolving is on, or miplib pbs are turned off)..." << endl;
+ }
} else {
Assert(d_assertionsToCheck.empty());
d_assertionsToCheck.swap(d_assertionsToPreprocess);
}
- Trace("smt") << "POST nonClasualSimplify" << std::endl;
+ Trace("smt") << "POST nonClausalSimplify" << endl;
Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
// Theory preprocessing
if (d_smt.d_earlyTheoryPP) {
+ Chat() << "...doing early theory preprocessing..." << endl;
TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_theoryPreprocessTime);
// Call the theory preprocessors
d_smt.d_theoryEngine->preprocessStart();
@@ -1929,31 +2366,34 @@ bool SmtEnginePrivate::simplifyAssertions()
}
}
- Trace("smt") << "POST theoryPP" << std::endl;
+ Trace("smt") << "POST theoryPP" << endl;
Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
// ITE simplification
if(options::doITESimp()) {
+ Chat() << "...doing ITE simplification..." << endl;
simpITE();
}
- Trace("smt") << "POST iteSimp" << std::endl;
+ Trace("smt") << "POST iteSimp" << endl;
Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
// Unconstrained simplification
if(options::unconstrainedSimp()) {
+ Chat() << "...doing unconstrained simplification..." << endl;
unconstrainedSimp();
}
- Trace("smt") << "POST unconstrainedSimp" << std::endl;
+ Trace("smt") << "POST unconstrainedSimp" << endl;
Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
if(options::repeatSimp() && options::simplificationMode() != SIMPLIFICATION_MODE_NONE) {
+ Chat() << "...doing another round of nonclausal simplification..." << endl;
Trace("simplify") << "SmtEnginePrivate::simplify(): "
- << " doing repeated simplification" << std::endl;
+ << " doing repeated simplification" << endl;
d_assertionsToCheck.swap(d_assertionsToPreprocess);
Assert(d_assertionsToCheck.empty());
bool noConflict = nonClausalSimplify();
@@ -1962,7 +2402,7 @@ bool SmtEnginePrivate::simplifyAssertions()
}
}
- Trace("smt") << "POST repeatSimp" << std::endl;
+ Trace("smt") << "POST repeatSimp" << endl;
Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
@@ -2012,6 +2452,7 @@ Result SmtEngine::check() {
resource = d_resourceBudgetPerCall;
}
+ Chat() << "solving..." << endl;
Trace("smt") << "SmtEngine::check(): running check" << endl;
Result result = d_propEngine->checkSat(millis, resource);
@@ -2188,11 +2629,11 @@ void SmtEnginePrivate::processAssertions() {
//apply pre-skolemization to existential quantifiers
for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
Node prev = d_assertionsToPreprocess[i];
- std::vector< Node > fvs;
+ vector< Node > fvs;
d_assertionsToPreprocess[i] = Rewriter::rewrite( preSkolemizeQuantifiers( d_assertionsToPreprocess[i], true, fvs ) );
if( prev!=d_assertionsToPreprocess[i] ){
- Trace("quantifiers-rewrite") << "*** Pre-skolemize " << prev << std::endl;
- Trace("quantifiers-rewrite") << " ...got " << d_assertionsToPreprocess[i] << std::endl;
+ Trace("quantifiers-rewrite") << "*** Pre-skolemize " << prev << endl;
+ Trace("quantifiers-rewrite") << " ...got " << d_assertionsToPreprocess[i] << endl;
}
}
}
@@ -2209,8 +2650,7 @@ void SmtEnginePrivate::processAssertions() {
if( options::sortInference() ){
//sort inference technique
- SortInference si;
- si.simplify( d_assertionsToPreprocess );
+ d_smt.d_theoryEngine->getSortInference()->simplify( d_assertionsToPreprocess );
}
dumpAssertions("pre-simplify", d_assertionsToPreprocess);
@@ -2242,7 +2682,7 @@ void SmtEnginePrivate::processAssertions() {
dumpAssertions("pre-repeat-simplify", d_assertionsToCheck);
if(options::repeatSimp()) {
d_assertionsToCheck.swap(d_assertionsToPreprocess);
- Chat() << "simplifying assertions..." << endl;
+ Chat() << "re-simplifying assertions..." << endl;
noConflict &= simplifyAssertions();
if (noConflict) {
// Need to fix up assertion list to maintain invariants:
@@ -2600,7 +3040,7 @@ Expr SmtEngine::expandDefinitions(const Expr& ex) throw(TypeCheckingException, L
return n.toExpr();
}
-Expr SmtEngine::getValue(const Expr& ex) throw(ModalException, LogicException) {
+Expr SmtEngine::getValue(const Expr& ex) throw(ModalException, TypeCheckingException, LogicException) {
Assert(ex.getExprManager() == d_exprManager);
SmtScope smts(this);
@@ -2908,6 +3348,7 @@ void SmtEngine::checkModel(bool hardFailure) {
hash_map<Node, Node, NodeHashFunction> cache;
n = d_private->expandDefinitions(n, cache);
}
+ Notice() << "SmtEngine::checkModel(): -- expands to " << n << endl;
// Apply our model value substitutions.
n = substitutions.apply(n);
@@ -2929,6 +3370,12 @@ void SmtEngine::checkModel(bool hardFailure) {
continue;
}
+ // As a last-ditch effort, ask model to simplify it.
+ // Presently, this is only an issue for quantifiers, which can have a value
+ // but don't show up in our substitution map above.
+ n = m->getValue(n);
+ Notice() << "SmtEngine::checkModel(): -- model-substitutes to " << n << endl;
+
// The result should be == true.
if(n != NodeManager::currentNM()->mkConst(true)) {
Notice() << "SmtEngine::checkModel(): *** PROBLEM: EXPECTED `TRUE' ***"
diff --git a/src/smt/smt_engine.h b/src/smt/smt_engine.h
index cdae68d96..fecfba14a 100644
--- a/src/smt/smt_engine.h
+++ b/src/smt/smt_engine.h
@@ -444,7 +444,7 @@ public:
* 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) throw(ModalException, LogicException);
+ Expr getValue(const Expr& e) throw(ModalException, TypeCheckingException, LogicException);
/**
* Add a function to the set of expressions whose value is to be
diff --git a/src/theory/arith/arith_static_learner.cpp b/src/theory/arith/arith_static_learner.cpp
index 4ee176cf1..124fa8e2a 100644
--- a/src/theory/arith/arith_static_learner.cpp
+++ b/src/theory/arith/arith_static_learner.cpp
@@ -21,8 +21,6 @@
#include "theory/arith/arith_static_learner.h"
#include "theory/arith/options.h"
-#include "util/propositional_query.h"
-
#include "expr/expr.h"
#include "expr/convenience_node_builders.h"
@@ -37,7 +35,6 @@ namespace arith {
ArithStaticLearner::ArithStaticLearner(context::Context* userContext) :
- d_miplibTrick(userContext),
d_minMap(userContext),
d_maxMap(userContext),
d_statistics()
@@ -45,30 +42,17 @@ ArithStaticLearner::ArithStaticLearner(context::Context* userContext) :
ArithStaticLearner::Statistics::Statistics():
d_iteMinMaxApplications("theory::arith::iteMinMaxApplications", 0),
- d_iteConstantApplications("theory::arith::iteConstantApplications", 0),
- d_miplibtrickApplications("theory::arith::miplibtrickApplications", 0),
- d_avgNumMiplibtrickValues("theory::arith::avgNumMiplibtrickValues")
+ d_iteConstantApplications("theory::arith::iteConstantApplications", 0)
{
StatisticsRegistry::registerStat(&d_iteMinMaxApplications);
StatisticsRegistry::registerStat(&d_iteConstantApplications);
- StatisticsRegistry::registerStat(&d_miplibtrickApplications);
- StatisticsRegistry::registerStat(&d_avgNumMiplibtrickValues);
}
ArithStaticLearner::Statistics::~Statistics(){
StatisticsRegistry::unregisterStat(&d_iteMinMaxApplications);
StatisticsRegistry::unregisterStat(&d_iteConstantApplications);
- StatisticsRegistry::unregisterStat(&d_miplibtrickApplications);
- StatisticsRegistry::unregisterStat(&d_avgNumMiplibtrickValues);
-}
-
-void ArithStaticLearner::miplibTrickInsert(Node key, Node value){
- if(options::arithMLTrick()){
- d_miplibTrick.insert(key, value);
- }
}
-
void ArithStaticLearner::staticLearning(TNode n, NodeBuilder<>& learned){
vector<TNode> workList;
@@ -111,8 +95,6 @@ void ArithStaticLearner::staticLearning(TNode n, NodeBuilder<>& learned){
process(n,learned, defTrue);
}
-
- postProcess(learned);
}
@@ -134,24 +116,6 @@ void ArithStaticLearner::process(TNode n, NodeBuilder<>& learned, const TNodeSet
iteConstant(n, learned);
}
break;
- case IMPLIES:
- // == 3-FINITE VALUE SET : Collect information ==
- if(n[1].getKind() == EQUAL &&
- n[1][0].isVar() &&
- defTrue.find(n) != defTrue.end()){
- Node eqTo = n[1][1];
- Node rewriteEqTo = Rewriter::rewrite(eqTo);
- if(rewriteEqTo.getKind() == CONST_RATIONAL){
-
- TNode var = n[1][0];
- Node current = (d_miplibTrick.find(var) == d_miplibTrick.end()) ?
- mkBoolNode(false) : d_miplibTrick[var];
-
- miplibTrickInsert(var, n.orNode(current));
- Debug("arith::miplib") << "insert " << var << " const " << n << endl;
- }
- }
- break;
case CONST_RATIONAL:
// Mark constants as minmax
d_minMap.insert(n, n.getConst<Rational>());
@@ -300,99 +264,6 @@ std::set<Node> listToSet(TNode l){
return ret;
}
-void ArithStaticLearner::postProcess(NodeBuilder<>& learned){
- // == 3-FINITE VALUE SET ==
- CDNodeToNodeListMap::const_iterator keyIter = d_miplibTrick.begin();
- CDNodeToNodeListMap::const_iterator endKeys = d_miplibTrick.end();
- while(keyIter != endKeys) {
- TNode var = (*keyIter).first;
- Node list = (*keyIter).second;
- const set<Node> imps = listToSet(list);
-
- if(imps.empty()){
- ++keyIter;
- continue;
- }
-
- Assert(!imps.empty());
- vector<Node> conditions;
- set<Rational> values;
- set<Node>::const_iterator j=imps.begin(), impsEnd=imps.end();
- for(; j != impsEnd; ++j){
- TNode imp = *j;
- Assert(imp.getKind() == IMPLIES);
- Assert(imp[1].getKind() == EQUAL);
-
- Node eqTo = imp[1][1];
- Node rewriteEqTo = Rewriter::rewrite(eqTo);
- Assert(rewriteEqTo.getKind() == CONST_RATIONAL);
-
- conditions.push_back(imp[0]);
- values.insert(rewriteEqTo.getConst<Rational>());
- }
-
- Node possibleTaut = Node::null();
- if(conditions.size() == 1){
- possibleTaut = conditions.front();
- }else{
- NodeBuilder<> orBuilder(OR);
- orBuilder.append(conditions);
- possibleTaut = orBuilder;
- }
-
-
- Debug("arith::miplib") << "var: " << var << endl;
- Debug("arith::miplib") << "possibleTaut: " << possibleTaut << endl;
-
- Result isTaut = PropositionalQuery::isTautology(possibleTaut);
- if(isTaut == Result(Result::VALID)){
- miplibTrick(var, values, learned);
- miplibTrickInsert(var, mkBoolNode(false));
- }
- ++keyIter;
- }
-}
-
-
-void ArithStaticLearner::miplibTrick(TNode var, set<Rational>& values, NodeBuilder<>& learned){
-
- Debug("arith::miplib") << var << " found a tautology!"<< endl;
-
- const Rational& min = *(values.begin());
- const Rational& max = *(values.rbegin());
-
- Debug("arith::miplib") << "min: " << min << endl;
- Debug("arith::miplib") << "max: " << max << endl;
-
- Assert(min <= max);
- ++(d_statistics.d_miplibtrickApplications);
- (d_statistics.d_avgNumMiplibtrickValues).addEntry(values.size());
-
- Node nGeqMin = NodeBuilder<2>(GEQ) << var << mkRationalNode(min);
- Node nLeqMax = NodeBuilder<2>(LEQ) << var << mkRationalNode(max);
- Debug("arith::miplib") << nGeqMin << nLeqMax << endl;
- learned << nGeqMin << nLeqMax;
- set<Rational>::iterator valuesIter = values.begin();
- set<Rational>::iterator valuesEnd = values.end();
- set<Rational>::iterator valuesPrev = valuesIter;
- ++valuesIter;
- for(; valuesIter != valuesEnd; valuesPrev = valuesIter, ++valuesIter){
- const Rational& prev = *valuesPrev;
- const Rational& curr = *valuesIter;
- Assert(prev < curr);
-
- //The interval (last,curr) can be excluded:
- //(not (and (> var prev) (< var curr))
- //<=> (or (not (> var prev)) (not (< var curr)))
- //<=> (or (<= var prev) (>= var curr))
- Node leqPrev = NodeBuilder<2>(LEQ) << var << mkRationalNode(prev);
- Node geqCurr = NodeBuilder<2>(GEQ) << var << mkRationalNode(curr);
- Node excludedMiddle = NodeBuilder<2>(OR) << leqPrev << geqCurr;
- Debug("arith::miplib") << excludedMiddle << endl;
- learned << excludedMiddle;
- }
-}
-
void ArithStaticLearner::addBound(TNode n) {
CDNodeToMinMaxMap::const_iterator minFind = d_minMap.find(n[0]);
diff --git a/src/theory/arith/arith_static_learner.h b/src/theory/arith/arith_static_learner.h
index 041ae6339..48ee6a3bb 100644
--- a/src/theory/arith/arith_static_learner.h
+++ b/src/theory/arith/arith_static_learner.h
@@ -37,16 +37,6 @@ namespace arith {
class ArithStaticLearner {
private:
- /* Maps a variable, x, to the set of defTrue nodes of the form
- * (=> _ (= x c))
- * where c is a constant.
- */
- typedef context::CDTrailHashMap<Node, Node, NodeHashFunction> CDNodeToNodeListMap;
- // The domain is an implicit list OR(x, OR(y, ..., FALSE ))
- // or FALSE
- CDNodeToNodeListMap d_miplibTrick;
- void miplibTrickInsert(Node key, Node value);
-
/**
* Map from a node to it's minimum and maximum.
*/
@@ -63,23 +53,15 @@ public:
private:
void process(TNode n, NodeBuilder<>& learned, const TNodeSet& defTrue);
- void postProcess(NodeBuilder<>& learned);
-
void iteMinMax(TNode n, NodeBuilder<>& learned);
void iteConstant(TNode n, NodeBuilder<>& learned);
- void miplibTrick(TNode var, std::set<Rational>& values, NodeBuilder<>& learned);
-
-
/** These fields are designed to be accessible to ArithStaticLearner methods. */
class Statistics {
public:
IntStat d_iteMinMaxApplications;
IntStat d_iteConstantApplications;
- IntStat d_miplibtrickApplications;
- AverageStat d_avgNumMiplibtrickValues;
-
Statistics();
~Statistics();
};
diff --git a/src/theory/arith/constraint.cpp b/src/theory/arith/constraint.cpp
index cf3aeafee..4655ea34e 100644
--- a/src/theory/arith/constraint.cpp
+++ b/src/theory/arith/constraint.cpp
@@ -371,8 +371,8 @@ void ConstraintValue::setAssertedToTheTheory(TNode witness) {
d_database->pushAssertionOrderWatch(this, witness);
}
-// bool ConstraintValue::isPsuedoConstraint() const {
-// return d_proof == d_database->d_psuedoConstraintProof;
+// bool ConstraintValue::isPseudoConstraint() const {
+// return d_proof == d_database->d_pseudoConstraintProof;
// }
bool ConstraintValue::isSelfExplaining() const {
@@ -486,7 +486,7 @@ ConstraintDatabase::ConstraintDatabase(context::Context* satContext, context::Co
d_equalityEngineProof = d_proofs.size();
d_proofs.push_back(NullConstraint);
- // d_psuedoConstraintProof = d_proofs.size();
+ // d_pseudoConstraintProof = d_proofs.size();
// d_proofs.push_back(NullConstraint);
}
@@ -833,11 +833,11 @@ void ConstraintValue::impliedBy(const std::vector<Constraint>& b){
}
}
-// void ConstraintValue::setPsuedoConstraint(){
+// void ConstraintValue::setPseudoConstraint(){
// Assert(truthIsUnknown());
// Assert(!hasLiteral());
-// d_database->pushProofWatch(this, d_database->d_psuedoConstraintProof);
+// d_database->pushProofWatch(this, d_database->d_pseudoConstraintProof);
// }
void ConstraintValue::setEqualityEngineProof(){
@@ -856,7 +856,7 @@ void ConstraintValue::markAsTrue(){
void ConstraintValue::markAsTrue(Constraint imp){
Assert(truthIsUnknown());
Assert(imp->hasProof());
- //Assert(!imp->isPsuedoConstraint());
+ //Assert(!imp->isPseudoConstraint());
d_database->d_proofs.push_back(NullConstraint);
d_database->d_proofs.push_back(imp);
@@ -868,8 +868,8 @@ void ConstraintValue::markAsTrue(Constraint impA, Constraint impB){
Assert(truthIsUnknown());
Assert(impA->hasProof());
Assert(impB->hasProof());
- //Assert(!impA->isPsuedoConstraint());
- //Assert(!impB->isPsuedoConstraint());
+ //Assert(!impA->isPseudoConstraint());
+ //Assert(!impB->isPseudoConstraint());
d_database->d_proofs.push_back(NullConstraint);
d_database->d_proofs.push_back(impA);
@@ -886,7 +886,7 @@ void ConstraintValue::markAsTrue(const vector<Constraint>& a){
for(vector<Constraint>::const_iterator i = a.begin(), end = a.end(); i != end; ++i){
Constraint c_i = *i;
Assert(c_i->hasProof());
- //Assert(!c_i->isPsuedoConstraint());
+ //Assert(!c_i->isPseudoConstraint());
d_database->d_proofs.push_back(c_i);
}
@@ -903,7 +903,7 @@ SortedConstraintMap& ConstraintValue::constraintSet() const{
bool ConstraintValue::proofIsEmpty() const{
Assert(hasProof());
bool result = d_database->d_proofs[d_proof] == NullConstraint;
- //Assert((!result) || isSelfExplaining() || hasEqualityEngineProof() || isPsuedoConstraint());
+ //Assert((!result) || isSelfExplaining() || hasEqualityEngineProof() || isPseudoConstraint());
Assert((!result) || isSelfExplaining() || hasEqualityEngineProof());
return result;
}
diff --git a/src/theory/arith/constraint.h b/src/theory/arith/constraint.h
index 52aa5a5ce..82023a48b 100644
--- a/src/theory/arith/constraint.h
+++ b/src/theory/arith/constraint.h
@@ -273,7 +273,7 @@ private:
*/
AssertionOrder _d_assertionOrder;
/**
- * This is guarenteed to be on the fact queue.
+ * This is guaranteed to be on the fact queue.
* For example if x + y = x + 1 is on the fact queue, then use this
*/
TNode d_witness;
@@ -491,8 +491,8 @@ public:
* The explanation is the constant true.
* explainInto() does nothing.
*/
- //void setPsuedoConstraint();
- //bool isPsuedoConstraint() const;
+ //void setPseudoConstraint();
+ //bool isPseudoConstraint() const;
/**
* Returns a explanation of the constraint that is appropriate for conflicts.
@@ -709,7 +709,7 @@ private:
*
* This is a special proof that is always a member of the list.
*/
- //ProofId d_psuedoConstraintProof;
+ //ProofId d_pseudoConstraintProof;
typedef context::CDList<Constraint, ConstraintValue::ProofCleanup> ProofCleanupList;
typedef context::CDList<Constraint, ConstraintValue::CanBePropagatedCleanup> CBPList;
diff --git a/src/theory/arith/delta_rational.h b/src/theory/arith/delta_rational.h
index 19a16d558..51c1e5138 100644
--- a/src/theory/arith/delta_rational.h
+++ b/src/theory/arith/delta_rational.h
@@ -249,7 +249,7 @@ public:
}
/**
- * Computes a sufficient upperbound to seperate two DeltaRationals.
+ * Computes a sufficient upperbound to separate two DeltaRationals.
* This value is stored in res.
* For any rational d such that
* 0 < d < res
diff --git a/src/theory/arith/options b/src/theory/arith/options
index 719c826ae..efe594766 100644
--- a/src/theory/arith/options
+++ b/src/theory/arith/options
@@ -51,13 +51,15 @@ option arithRewriteEq --enable-arith-rewrite-equalities/--disable-arith-rewrite-
turns on the preprocessing rewrite turning equalities into a conjunction of inequalities
/turns off the preprocessing rewrite turning equalities into a conjunction of inequalities
-option arithMLTrick --enable-miplib-trick/--disable-miplib-trick bool :default false :read-write
+option arithMLTrick miplib-trick --enable-miplib-trick/--disable-miplib-trick bool :default false
turns on the preprocessing step of attempting to infer bounds on miplib problems
/turns off the preprocessing step of attempting to infer bounds on miplib problems
+option arithMLTrickSubstitutions miplib-trick-subs --miplib-trick-subs unsigned :default 1
+ do substitution for miplib 'tmp' vars if defined in <= N eliminated vars
+
option doCutAllBounded --enable-cut-all-bounded/--disable-cut-all-bounded bool :default false :read-write
turns on the integer solving step of periodically cutting all integer variables that have both upper and lower bounds
-/ turns off the integer solving step of periodically cutting all integer variables that have both upper and lower bounds
-
+/turns off the integer solving step of periodically cutting all integer variables that have both upper and lower bounds
endmodule
diff --git a/src/theory/arith/options_handlers.h b/src/theory/arith/options_handlers.h
index 52e7cbf2a..f8f851964 100644
--- a/src/theory/arith/options_handlers.h
+++ b/src/theory/arith/options_handlers.h
@@ -52,7 +52,7 @@ This decides on kind of propagation arithmetic attempts to do during the search.
";
static const std::string heuristicPivotRulesHelp = "\
-This decides on the rule used by simplex during hueristic rounds\n\
+This decides on the rule used by simplex during heuristic rounds\n\
for deciding the next basic variable to select.\n\
Heuristic pivot rules available:\n\
+min\n\
diff --git a/src/theory/arrays/theory_arrays.cpp b/src/theory/arrays/theory_arrays.cpp
index aabd3a62d..dcf4813fc 100644
--- a/src/theory/arrays/theory_arrays.cpp
+++ b/src/theory/arrays/theory_arrays.cpp
@@ -1324,7 +1324,9 @@ void TheoryArrays::queueRowLemma(RowLemmaType lem)
// Prefer equality between indexes so as not to introduce new read terms
if (d_eagerIndexSplitting && !bothExist && !d_equalityEngine.areDisequal(i,j, false)) {
- d_decisionRequests.push(i.eqNode(j));
+ Node i_eq_j = d_valuation.ensureLiteral(i.eqNode(j));
+ getOutputChannel().requirePhase(i_eq_j, true);
+ d_decisionRequests.push(i_eq_j);
}
// TODO: maybe add triggers here
@@ -1392,7 +1394,7 @@ void TheoryArrays::queueRowLemma(RowLemmaType lem)
Node TheoryArrays::getNextDecisionRequest() {
if(! d_decisionRequests.empty()) {
- Node n = d_valuation.ensureLiteral(d_decisionRequests.front());
+ Node n = d_decisionRequests.front();
d_decisionRequests.pop();
return n;
} else {
diff --git a/src/theory/arrays/theory_arrays_model.cpp b/src/theory/arrays/theory_arrays_model.cpp
index 86bdad53f..4f7584ac1 100644
--- a/src/theory/arrays/theory_arrays_model.cpp
+++ b/src/theory/arrays/theory_arrays_model.cpp
@@ -41,7 +41,7 @@ Node ArrayModel::getValue( TheoryModel* m, Node i ){
return it->second;
}else{
return NodeManager::currentNM()->mkNode( SELECT, getArrayValue(), i );
- //return d_default_value; //TODO: guarentee I can return this here
+ //return d_default_value; //TODO: guarantee I can return this here
}
}
diff --git a/src/theory/arrays/theory_arrays_model.h b/src/theory/arrays/theory_arrays_model.h
index 8dfc7fc4a..c82c7635d 100644
--- a/src/theory/arrays/theory_arrays_model.h
+++ b/src/theory/arrays/theory_arrays_model.h
@@ -1,58 +1,58 @@
/********************* */
/*! \file theory_arrays_model.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
- ** \brief MODEL for theory of arrays
- **/
-
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__THEORY_ARRAYS_MODEL_H
-#define __CVC4__THEORY_ARRAYS_MODEL_H
-
-#include "theory/quantifiers_engine.h"
-
-namespace CVC4 {
-namespace theory {
-
-class TheoryModel;
-
-namespace arrays {
-
-class ArrayModel{
-protected:
- /** the array this model is for */
- Node d_arr;
-public:
- ArrayModel(){}
- ArrayModel( Node arr, TheoryModel* m );
- ~ArrayModel() {}
-public:
- /** pre-defined values */
- std::map< Node, Node > d_values;
- /** base array */
- Node d_base_arr;
- /** get value, return arguments that the value depends on */
- Node getValue( TheoryModel* m, Node i );
- /** set value */
- void setValue( TheoryModel* m, Node i, Node e );
- /** set default */
- void setDefaultArray( Node arr );
-public:
- /** get array value */
- Node getArrayValue();
-};/* class ArrayModel */
-
-}
-}
-}
-
+ ** \brief MODEL for theory of arrays
+ **/
+
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY_ARRAYS_MODEL_H
+#define __CVC4__THEORY_ARRAYS_MODEL_H
+
+#include "theory/quantifiers_engine.h"
+
+namespace CVC4 {
+namespace theory {
+
+class TheoryModel;
+
+namespace arrays {
+
+class ArrayModel{
+protected:
+ /** the array this model is for */
+ Node d_arr;
+public:
+ ArrayModel(){}
+ ArrayModel( Node arr, TheoryModel* m );
+ ~ArrayModel() {}
+public:
+ /** pre-defined values */
+ std::map< Node, Node > d_values;
+ /** base array */
+ Node d_base_arr;
+ /** get value, return arguments that the value depends on */
+ Node getValue( TheoryModel* m, Node i );
+ /** set value */
+ void setValue( TheoryModel* m, Node i, Node e );
+ /** set default */
+ void setDefaultArray( Node arr );
+public:
+ /** get array value */
+ Node getArrayValue();
+};/* class ArrayModel */
+
+}
+}
+}
+
#endif \ No newline at end of file
diff --git a/src/theory/arrays/theory_arrays_rewriter.h b/src/theory/arrays/theory_arrays_rewriter.h
index da479616d..9cbb0c9e8 100644
--- a/src/theory/arrays/theory_arrays_rewriter.h
+++ b/src/theory/arrays/theory_arrays_rewriter.h
@@ -37,8 +37,12 @@ typedef expr::Attribute<attr::ArrayConstantMostFrequentValueCountTag, uint64_t>
typedef expr::Attribute<attr::ArrayConstantMostFrequentValueTag, Node> ArrayConstantMostFrequentValueAttr;
class TheoryArraysRewriter {
-
static Node normalizeConstant(TNode node) {
+ return normalizeConstant(node, node[1].getType().getCardinality());
+ }
+public:
+ //this function is called by printers when using the option "--model-u-dt-enum"
+ static Node normalizeConstant(TNode node, Cardinality indexCard) {
TNode store = node[0];
TNode index = node[1];
TNode value = node[2];
@@ -112,7 +116,6 @@ class TheoryArraysRewriter {
return n;
}
- Cardinality indexCard = index.getType().getCardinality();
if (indexCard.isInfinite()) {
return n;
}
@@ -189,13 +192,15 @@ class TheoryArraysRewriter {
std::vector<Node> newIndices;
TypeEnumerator te(index.getType());
bool needToSort = false;
- while (!te.isFinished()) {
+ unsigned numTe = 0;
+ while (!te.isFinished() && (!indexCard.isFinite() || numTe<indexCard.getFiniteCardinality().toUnsignedInt())) {
if (indexSet.find(*te) == indexSet.end()) {
if (!newIndices.empty() && (!(newIndices.back() < (*te)))) {
needToSort = true;
}
newIndices.push_back(*te);
}
+ ++numTe;
++te;
}
Assert(indexCard.compare(newIndices.size() + depth) == Cardinality::EQUAL);
diff --git a/src/theory/booleans/circuit_propagator.h b/src/theory/booleans/circuit_propagator.h
index aec0cff58..de4bb30d2 100644
--- a/src/theory/booleans/circuit_propagator.h
+++ b/src/theory/booleans/circuit_propagator.h
@@ -64,6 +64,8 @@ public:
else return ASSIGNED_TO_TRUE;
}
+ typedef std::hash_map<Node, std::vector<Node>, NodeHashFunction> BackEdgesMap;
+
private:
context::Context d_context;
@@ -96,7 +98,7 @@ private:
*/
DataClearer< std::vector<TNode> > d_propagationQueueClearer;
- /** Are we in conflict */
+ /** Are we in conflict? */
context::CDO<bool> d_conflict;
/** Map of substitutions */
@@ -107,8 +109,9 @@ private:
*/
DataClearer< std::vector<Node> > d_learnedLiteralClearer;
- /** Back edges from nodes to where they are used */
- typedef std::hash_map<Node, std::vector<Node>, NodeHashFunction> BackEdgesMap;
+ /**
+ * Back edges from nodes to where they are used.
+ */
BackEdgesMap d_backEdges;
/**
@@ -157,6 +160,7 @@ private:
}
}
+public:
/** True iff Node is assigned in circuit (either true or false). */
bool isAssigned(TNode n) const {
AssignmentMap::const_iterator i = d_state.find(n);
@@ -179,6 +183,7 @@ private:
return (*i).second == ASSIGNED_TO_TRUE;
}
+private:
/** Predicate for use in STL functions. */
class IsAssigned : public std::unary_function<TNode, bool> {
CircuitPropagator& d_circuit;
@@ -268,6 +273,13 @@ public:
*/
bool propagate() CVC4_WARN_UNUSED_RESULT;
+ /**
+ * Get the back edges of this circuit.
+ */
+ const BackEdgesMap& getBackEdges() const {
+ return d_backEdges;
+ }
+
};/* class CircuitPropagator */
}/* CVC4::theory::booleans namespace */
diff --git a/src/theory/bv/bitblast_strategies.cpp b/src/theory/bv/bitblast_strategies.cpp
index 3ce9bcb44..773685997 100644
--- a/src/theory/bv/bitblast_strategies.cpp
+++ b/src/theory/bv/bitblast_strategies.cpp
@@ -191,13 +191,13 @@ Node inline sLessThanBB(const Bits&a, const Bits& b, bool orEqual) {
Node UndefinedAtomBBStrategy(TNode node, Bitblaster* bb) {
- BVDebug("bitvector") << "TheoryBV::Bitblaster Undefined bitblasting strategy for kind: "
+ Debug("bitvector") << "TheoryBV::Bitblaster Undefined bitblasting strategy for kind: "
<< node.getKind() << "\n";
Unreachable();
}
Node DefaultEqBB(TNode node, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "Bitblasting node " << node << "\n";
+ Debug("bitvector-bb") << "Bitblasting node " << node << "\n";
Assert(node.getKind() == kind::EQUAL);
Bits lhs, rhs;
@@ -219,7 +219,7 @@ Node DefaultEqBB(TNode node, Bitblaster* bb) {
Node AdderUltBB(TNode node, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "Bitblasting node " << node << "\n";
+ Debug("bitvector-bb") << "Bitblasting node " << node << "\n";
Assert(node.getKind() == kind::BITVECTOR_ULT);
Bits a, b;
bb->bbTerm(node[0], a);
@@ -241,7 +241,7 @@ Node AdderUltBB(TNode node, Bitblaster* bb) {
Node DefaultUltBB(TNode node, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "Bitblasting node " << node << "\n";
+ Debug("bitvector-bb") << "Bitblasting node " << node << "\n";
Assert(node.getKind() == kind::BITVECTOR_ULT);
Bits a, b;
bb->bbTerm(node[0], a);
@@ -254,7 +254,7 @@ Node DefaultUltBB(TNode node, Bitblaster* bb) {
}
Node DefaultUleBB(TNode node, Bitblaster* bb){
- BVDebug("bitvector-bb") << "Bitblasting node " << node << "\n";
+ Debug("bitvector-bb") << "Bitblasting node " << node << "\n";
Assert(node.getKind() == kind::BITVECTOR_ULE);
Bits a, b;
@@ -267,31 +267,31 @@ Node DefaultUleBB(TNode node, Bitblaster* bb){
}
Node DefaultUgtBB(TNode node, Bitblaster* bb){
- BVDebug("bitvector-bb") << "Bitblasting node " << node << "\n";
+ Debug("bitvector-bb") << "Bitblasting node " << node << "\n";
// should be rewritten
Unimplemented();
}
Node DefaultUgeBB(TNode node, Bitblaster* bb){
- BVDebug("bitvector-bb") << "Bitblasting node " << node << "\n";
+ Debug("bitvector-bb") << "Bitblasting node " << node << "\n";
// should be rewritten
Unimplemented();
}
// Node DefaultSltBB(TNode node, Bitblaster* bb){
-// BVDebug("bitvector-bb") << "Bitblasting node " << node << "\n";
+// Debug("bitvector-bb") << "Bitblasting node " << node << "\n";
// // shoudl be rewritten in terms of ult
// Unimplemented();
// }
// Node DefaultSleBB(TNode node, Bitblaster* bb){
-// BVDebug("bitvector-bb") << "Bitblasting node " << node << "\n";
+// Debug("bitvector-bb") << "Bitblasting node " << node << "\n";
// // shoudl be rewritten in terms of ule
// Unimplemented();
// }
Node DefaultSltBB(TNode node, Bitblaster* bb){
- BVDebug("bitvector-bb") << "Bitblasting node " << node << "\n";
+ Debug("bitvector-bb") << "Bitblasting node " << node << "\n";
Bits a, b;
bb->bbTerm(node[0], a);
@@ -303,7 +303,7 @@ Node DefaultSltBB(TNode node, Bitblaster* bb){
}
Node DefaultSleBB(TNode node, Bitblaster* bb){
- BVDebug("bitvector-bb") << "Bitblasting node " << node << "\n";
+ Debug("bitvector-bb") << "Bitblasting node " << node << "\n";
Bits a, b;
bb->bbTerm(node[0], a);
@@ -315,13 +315,13 @@ Node DefaultSleBB(TNode node, Bitblaster* bb){
}
Node DefaultSgtBB(TNode node, Bitblaster* bb){
- BVDebug("bitvector-bb") << "Bitblasting node " << node << "\n";
+ Debug("bitvector-bb") << "Bitblasting node " << node << "\n";
// should be rewritten
Unimplemented();
}
Node DefaultSgeBB(TNode node, Bitblaster* bb){
- BVDebug("bitvector-bb") << "Bitblasting node " << node << "\n";
+ Debug("bitvector-bb") << "Bitblasting node " << node << "\n";
// should be rewritten
Unimplemented();
}
@@ -330,7 +330,7 @@ Node DefaultSgeBB(TNode node, Bitblaster* bb){
/// Term bitblasting strategies
void UndefinedTermBBStrategy(TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector") << "theory::bv:: Undefined bitblasting strategy for kind: "
+ Debug("bitvector") << "theory::bv:: Undefined bitblasting strategy for kind: "
<< node.getKind() << "\n";
Unreachable();
}
@@ -342,15 +342,15 @@ void DefaultVarBB (TNode node, Bits& bits, Bitblaster* bb) {
}
if(Debug.isOn("bitvector-bb")) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultVarBB bitblasting " << node << "\n";
- BVDebug("bitvector-bb") << " with bits " << toString(bits);
+ Debug("bitvector-bb") << "theory::bv::DefaultVarBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << " with bits " << toString(bits);
}
bb->storeVariable(node);
}
void DefaultConstBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultConstBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultConstBB bitblasting " << node << "\n";
Assert(node.getKind() == kind::CONST_BITVECTOR);
Assert(bits.size() == 0);
@@ -364,13 +364,13 @@ void DefaultConstBB (TNode node, Bits& bits, Bitblaster* bb) {
}
}
if(Debug.isOn("bitvector-bb")) {
- BVDebug("bitvector-bb") << "with bits: " << toString(bits) << "\n";
+ Debug("bitvector-bb") << "with bits: " << toString(bits) << "\n";
}
}
void DefaultNotBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultNotBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultNotBB bitblasting " << node << "\n";
Assert(node.getKind() == kind::BITVECTOR_NOT);
Assert(bits.size() == 0);
Bits bv;
@@ -379,7 +379,7 @@ void DefaultNotBB (TNode node, Bits& bits, Bitblaster* bb) {
}
void DefaultConcatBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultConcatBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultConcatBB bitblasting " << node << "\n";
Assert(bits.size() == 0);
Assert (node.getKind() == kind::BITVECTOR_CONCAT);
@@ -394,12 +394,12 @@ void DefaultConcatBB (TNode node, Bits& bits, Bitblaster* bb) {
}
Assert (bits.size() == utils::getSize(node));
if(Debug.isOn("bitvector-bb")) {
- BVDebug("bitvector-bb") << "with bits: " << toString(bits) << "\n";
+ Debug("bitvector-bb") << "with bits: " << toString(bits) << "\n";
}
}
void DefaultAndBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultAndBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultAndBB bitblasting " << node << "\n";
Assert(node.getKind() == kind::BITVECTOR_AND &&
bits.size() == 0);
@@ -417,7 +417,7 @@ void DefaultAndBB (TNode node, Bits& bits, Bitblaster* bb) {
}
void DefaultOrBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultOrBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultOrBB bitblasting " << node << "\n";
Assert(node.getKind() == kind::BITVECTOR_OR &&
bits.size() == 0);
@@ -435,7 +435,7 @@ void DefaultOrBB (TNode node, Bits& bits, Bitblaster* bb) {
}
void DefaultXorBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultXorBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultXorBB bitblasting " << node << "\n";
Assert(node.getKind() == kind::BITVECTOR_XOR &&
bits.size() == 0);
@@ -456,7 +456,7 @@ void DefaultXorBB (TNode node, Bits& bits, Bitblaster* bb) {
}
void DefaultXnorBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultXnorBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultXnorBB bitblasting " << node << "\n";
Assert(node.getNumChildren() == 2 &&
node.getKind() == kind::BITVECTOR_XNOR &&
@@ -473,17 +473,17 @@ void DefaultXnorBB (TNode node, Bits& bits, Bitblaster* bb) {
void DefaultNandBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector") << "theory::bv:: Unimplemented kind "
+ Debug("bitvector") << "theory::bv:: Unimplemented kind "
<< node.getKind() << "\n";
Unimplemented();
}
void DefaultNorBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector") << "theory::bv:: Unimplemented kind "
+ Debug("bitvector") << "theory::bv:: Unimplemented kind "
<< node.getKind() << "\n";
Unimplemented();
}
void DefaultCompBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector") << "theory::bv:: DefaultCompBB bitblasting "<< node << "\n";
+ Debug("bitvector") << "theory::bv:: DefaultCompBB bitblasting "<< node << "\n";
Assert(getSize(node) == 1 && bits.size() == 0 && node.getKind() == kind::BITVECTOR_COMP);
Bits a, b;
@@ -501,7 +501,7 @@ void DefaultCompBB (TNode node, Bits& bits, Bitblaster* bb) {
}
void DefaultMultBB (TNode node, Bits& res, Bitblaster* bb) {
- BVDebug("bitvector") << "theory::bv:: DefaultMultBB bitblasting "<< node << "\n";
+ Debug("bitvector") << "theory::bv:: DefaultMultBB bitblasting "<< node << "\n";
Assert(res.size() == 0 &&
node.getKind() == kind::BITVECTOR_MULT);
@@ -517,12 +517,12 @@ void DefaultMultBB (TNode node, Bits& res, Bitblaster* bb) {
res = newres;
}
if(Debug.isOn("bitvector-bb")) {
- BVDebug("bitvector-bb") << "with bits: " << toString(res) << "\n";
+ Debug("bitvector-bb") << "with bits: " << toString(res) << "\n";
}
}
void DefaultPlusBB (TNode node, Bits& res, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultPlusBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultPlusBB bitblasting " << node << "\n";
Assert(node.getKind() == kind::BITVECTOR_PLUS &&
res.size() == 0);
@@ -543,7 +543,7 @@ void DefaultPlusBB (TNode node, Bits& res, Bitblaster* bb) {
void DefaultSubBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultSubBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultSubBB bitblasting " << node << "\n";
Assert(node.getKind() == kind::BITVECTOR_SUB &&
node.getNumChildren() == 2 &&
bits.size() == 0);
@@ -561,7 +561,7 @@ void DefaultSubBB (TNode node, Bits& bits, Bitblaster* bb) {
}
void DefaultNegBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultNegBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultNegBB bitblasting " << node << "\n";
Assert(node.getKind() == kind::BITVECTOR_NEG);
Bits a;
@@ -639,7 +639,7 @@ void uDivModRec(const Bits& a, const Bits& b, Bits& q, Bits& r, unsigned rec_wid
}
void DefaultUdivBB (TNode node, Bits& q, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultUdivBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultUdivBB bitblasting " << node << "\n";
Assert(node.getKind() == kind::BITVECTOR_UDIV_TOTAL && q.size() == 0);
Bits a, b;
@@ -666,7 +666,7 @@ void DefaultUdivBB (TNode node, Bits& q, Bitblaster* bb) {
}
void DefaultUremBB (TNode node, Bits& rem, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultUremBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultUremBB bitblasting " << node << "\n";
Assert(node.getKind() == kind::BITVECTOR_UREM_TOTAL && rem.size() == 0);
Bits a, b;
@@ -694,23 +694,23 @@ void DefaultUremBB (TNode node, Bits& rem, Bitblaster* bb) {
void DefaultSdivBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector") << "theory::bv:: Unimplemented kind "
+ Debug("bitvector") << "theory::bv:: Unimplemented kind "
<< node.getKind() << "\n";
Unimplemented();
}
void DefaultSremBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector") << "theory::bv:: Unimplemented kind "
+ Debug("bitvector") << "theory::bv:: Unimplemented kind "
<< node.getKind() << "\n";
Unimplemented();
}
void DefaultSmodBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector") << "theory::bv:: Unimplemented kind "
+ Debug("bitvector") << "theory::bv:: Unimplemented kind "
<< node.getKind() << "\n";
Unimplemented();
}
void DefaultShlBB (TNode node, Bits& res, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultShlBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultShlBB bitblasting " << node << "\n";
Assert (node.getKind() == kind::BITVECTOR_SHL &&
res.size() == 0);
Bits a, b;
@@ -738,12 +738,12 @@ void DefaultShlBB (TNode node, Bits& res, Bitblaster* bb) {
}
}
if(Debug.isOn("bitvector-bb")) {
- BVDebug("bitvector-bb") << "with bits: " << toString(res) << "\n";
+ Debug("bitvector-bb") << "with bits: " << toString(res) << "\n";
}
}
void DefaultLshrBB (TNode node, Bits& res, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultLshrBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultLshrBB bitblasting " << node << "\n";
Assert (node.getKind() == kind::BITVECTOR_LSHR &&
res.size() == 0);
Bits a, b;
@@ -771,13 +771,13 @@ void DefaultLshrBB (TNode node, Bits& res, Bitblaster* bb) {
}
}
if(Debug.isOn("bitvector-bb")) {
- BVDebug("bitvector-bb") << "with bits: " << toString(res) << "\n";
+ Debug("bitvector-bb") << "with bits: " << toString(res) << "\n";
}
}
void DefaultAshrBB (TNode node, Bits& res, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultAshrBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultAshrBB bitblasting " << node << "\n";
Assert (node.getKind() == kind::BITVECTOR_ASHR &&
res.size() == 0);
Bits a, b;
@@ -806,7 +806,7 @@ void DefaultAshrBB (TNode node, Bits& res, Bitblaster* bb) {
}
}
if(Debug.isOn("bitvector-bb")) {
- BVDebug("bitvector-bb") << "with bits: " << toString(res) << "\n";
+ Debug("bitvector-bb") << "with bits: " << toString(res) << "\n";
}
}
@@ -825,14 +825,14 @@ void DefaultExtractBB (TNode node, Bits& bits, Bitblaster* bb) {
Assert (bits.size() == high - low + 1);
if(Debug.isOn("bitvector-bb")) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultExtractBB bitblasting " << node << "\n";
- BVDebug("bitvector-bb") << " with bits " << toString(bits);
+ Debug("bitvector-bb") << "theory::bv::DefaultExtractBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << " with bits " << toString(bits);
}
}
void DefaultRepeatBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector") << "theory::bv:: Unimplemented kind "
+ Debug("bitvector") << "theory::bv:: Unimplemented kind "
<< node.getKind() << "\n";
// this should be rewritten
Unimplemented();
@@ -840,7 +840,7 @@ void DefaultRepeatBB (TNode node, Bits& bits, Bitblaster* bb) {
void DefaultZeroExtendBB (TNode node, Bits& res_bits, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultZeroExtendBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultZeroExtendBB bitblasting " << node << "\n";
// this should be rewritten
Unimplemented();
@@ -848,7 +848,7 @@ void DefaultZeroExtendBB (TNode node, Bits& res_bits, Bitblaster* bb) {
}
void DefaultSignExtendBB (TNode node, Bits& res_bits, Bitblaster* bb) {
- BVDebug("bitvector-bb") << "theory::bv::DefaultSignExtendBB bitblasting " << node << "\n";
+ Debug("bitvector-bb") << "theory::bv::DefaultSignExtendBB bitblasting " << node << "\n";
Assert (node.getKind() == kind::BITVECTOR_SIGN_EXTEND &&
res_bits.size() == 0);
@@ -871,14 +871,14 @@ void DefaultSignExtendBB (TNode node, Bits& res_bits, Bitblaster* bb) {
}
void DefaultRotateRightBB (TNode node, Bits& res, Bitblaster* bb) {
- BVDebug("bitvector") << "theory::bv:: Unimplemented kind "
+ Debug("bitvector") << "theory::bv:: Unimplemented kind "
<< node.getKind() << "\n";
Unimplemented();
}
void DefaultRotateLeftBB (TNode node, Bits& bits, Bitblaster* bb) {
- BVDebug("bitvector") << "theory::bv:: Unimplemented kind "
+ Debug("bitvector") << "theory::bv:: Unimplemented kind "
<< node.getKind() << "\n";
Unimplemented();
}
diff --git a/src/theory/bv/bv_subtheory.h b/src/theory/bv/bv_subtheory.h
index a256b6001..d95aaa873 100644
--- a/src/theory/bv/bv_subtheory.h
+++ b/src/theory/bv/bv_subtheory.h
@@ -72,19 +72,31 @@ protected:
/** The bit-vector theory */
TheoryBV* d_bv;
-
+ context::CDQueue<TNode> d_assertionQueue;
+ context::CDO<uint32_t> d_assertionIndex;
public:
SubtheorySolver(context::Context* c, TheoryBV* bv) :
d_context(c),
- d_bv(bv)
+ d_bv(bv),
+ d_assertionQueue(c),
+ d_assertionIndex(c, 0)
{}
virtual ~SubtheorySolver() {}
+
+ virtual bool check(Theory::Effort e) = 0;
+ virtual void explain(TNode literal, std::vector<TNode>& assumptions) = 0;
+ virtual void preRegister(TNode node) {}
+ virtual void collectModelInfo(TheoryModel* m) = 0;
+ bool done() { return d_assertionQueue.size() == d_assertionIndex; }
+ TNode get() {
+ Assert (!done());
+ TNode res = d_assertionQueue[d_assertionIndex];
+ d_assertionIndex = d_assertionIndex + 1;
+ return res;
+ }
+ void assertFact(TNode fact) { d_assertionQueue.push_back(fact); }
- virtual bool addAssertions(const std::vector<TNode>& assertions, Theory::Effort e) = 0;
- virtual void explain(TNode literal, std::vector<TNode>& assumptions) = 0;
- virtual void preRegister(TNode node) {}
- virtual void collectModelInfo(TheoryModel* m) = 0;
};
}
diff --git a/src/theory/bv/bv_subtheory_bitblast.cpp b/src/theory/bv/bv_subtheory_bitblast.cpp
index 985a9b500..2f76e32d3 100644
--- a/src/theory/bv/bv_subtheory_bitblast.cpp
+++ b/src/theory/bv/bv_subtheory_bitblast.cpp
@@ -52,12 +52,21 @@ void BitblastSolver::explain(TNode literal, std::vector<TNode>& assumptions) {
d_bitblaster->explain(literal, assumptions);
}
-bool BitblastSolver::addAssertions(const std::vector<TNode>& assertions, Theory::Effort e) {
- Debug("bitvector::bitblaster") << "BitblastSolver::addAssertions (" << e << ")" << std::endl;
- Debug("bitvector::bitblaster") << "number of assertions: " << assertions.size() << std::endl;
- //// Lazy bit-blasting
+bool BitblastSolver::check(Theory::Effort e) {
+ //// Eager bit-blasting
+ if (options::bitvectorEagerBitblast()) {
+ while (!done()) {
+ TNode assertion = get();
+ TNode atom = assertion.getKind() == kind::NOT ? assertion[0] : assertion;
+ if (atom.getKind() != kind::BITVECTOR_BITOF) {
+ d_bitblaster->bbAtom(atom);
+ }
+ return true;
+ }
+ }
+ //// Lazy bit-blasting
// bit-blast enqueued nodes
while (!d_bitblastQueue.empty()) {
TNode atom = d_bitblastQueue.front();
@@ -65,9 +74,9 @@ bool BitblastSolver::addAssertions(const std::vector<TNode>& assertions, Theory:
d_bitblastQueue.pop();
}
- // propagation
- for (unsigned i = 0; i < assertions.size(); ++i) {
- TNode fact = assertions[i];
+ // Processinga ssertions
+ while (!done()) {
+ TNode fact = get();
if (!d_bv->inConflict() && !d_bv->propagatedBy(fact, SUB_BITBLAST)) {
// Some atoms have not been bit-blasted yet
d_bitblaster->bbAtom(fact);
@@ -93,7 +102,7 @@ bool BitblastSolver::addAssertions(const std::vector<TNode>& assertions, Theory:
}
}
- // solving
+ // Solving
if (e == Theory::EFFORT_FULL || options::bitvectorEagerFullcheck()) {
Assert(!d_bv->inConflict());
Debug("bitvector::bitblaster") << "BitblastSolver::addAssertions solving. \n";
diff --git a/src/theory/bv/bv_subtheory_bitblast.h b/src/theory/bv/bv_subtheory_bitblast.h
index 3396d813b..318fdd230 100644
--- a/src/theory/bv/bv_subtheory_bitblast.h
+++ b/src/theory/bv/bv_subtheory_bitblast.h
@@ -42,7 +42,7 @@ public:
~BitblastSolver();
void preRegister(TNode node);
- bool addAssertions(const std::vector<TNode>& assertions, Theory::Effort e);
+ bool check(Theory::Effort e);
void explain(TNode literal, std::vector<TNode>& assumptions);
EqualityStatus getEqualityStatus(TNode a, TNode b);
void collectModelInfo(TheoryModel* m);
diff --git a/src/theory/bv/bv_subtheory_core.cpp b/src/theory/bv/bv_subtheory_core.cpp
index 91cf29ee9..2e1320d1a 100644
--- a/src/theory/bv/bv_subtheory_core.cpp
+++ b/src/theory/bv/bv_subtheory_core.cpp
@@ -35,7 +35,9 @@ CoreSolver::CoreSolver(context::Context* c, TheoryBV* bv, Slicer* slicer)
d_assertions(c),
d_normalFormCache(),
d_slicer(slicer),
- d_isCoreTheory(c, true)
+ d_isCoreTheory(c, true),
+ d_baseChanged(false),
+ d_checkCalled(false)
{
if (d_useEqualityEngine) {
@@ -83,6 +85,7 @@ void CoreSolver::preRegister(TNode node) {
if (node.getKind() == kind::EQUAL) {
d_equalityEngine.addTriggerEquality(node);
+ d_slicer->processEquality(node);
} else {
d_equalityEngine.addTerm(node);
}
@@ -101,6 +104,11 @@ void CoreSolver::explain(TNode literal, std::vector<TNode>& assumptions) {
Node CoreSolver::getBaseDecomposition(TNode a) {
std::vector<Node> a_decomp;
+ // FIXME: hack to do bitwise decomposition
+ // for (int i = utils::getSize(a) - 1; i>= 0; --i) {
+ // Node bit = Rewriter::rewrite(utils::mkExtract(a, i, i));
+ // a_decomp.push_back(bit);
+ // }
d_slicer->getBaseDecomposition(a, a_decomp);
Node new_a = utils::mkConcat(a_decomp);
return new_a;
@@ -116,11 +124,8 @@ bool CoreSolver::decomposeFact(TNode fact) {
TNode a = eq[0];
TNode b = eq[1];
- // we need to get the old decomposition to keep track of the cuts we added
- Base a_old_base = d_slicer->getTopLevelBase(a);
- Base b_old_base = d_slicer->getTopLevelBase(b);
- d_slicer->processEquality(eq);
+ // d_slicer->processEquality(eq);
Node new_a = getBaseDecomposition(a);
Node new_b = getBaseDecomposition(b);
@@ -132,20 +137,12 @@ bool CoreSolver::decomposeFact(TNode fact) {
Node a_eq_new_a = nm->mkNode(kind::EQUAL, a, new_a);
Node b_eq_new_b = nm->mkNode(kind::EQUAL, b, new_b);
- Base a_new_base = d_slicer->getTopLevelBase(a);
- Base b_new_base = d_slicer->getTopLevelBase(b);
-
bool ok = true;
- ok = addNewSplits(a, a_old_base, a_new_base);
- if (!ok) return false;
- ok = addNewSplits(b, b_old_base, b_new_base);
- if (!ok) return false;
-
- ok = assertFact(a_eq_new_a, utils::mkTrue());
+ ok = assertFactToEqualityEngine(a_eq_new_a, utils::mkTrue());
if (!ok) return false;
- ok = assertFact(b_eq_new_b, utils::mkTrue());
+ ok = assertFactToEqualityEngine(b_eq_new_b, utils::mkTrue());
if (!ok) return false;
- ok = assertFact(fact, fact);
+ ok = assertFactToEqualityEngine(fact, fact);
if (!ok) return false;
if (fact.getKind() == kind::EQUAL) {
@@ -157,7 +154,7 @@ bool CoreSolver::decomposeFact(TNode fact) {
Assert (new_a.getNumChildren() == new_b.getNumChildren());
for (unsigned i = 0; i < new_a.getNumChildren(); ++i) {
Node eq_i = nm->mkNode(kind::EQUAL, new_a[i], new_b[i]);
- ok = assertFact(eq_i, fact);
+ ok = assertFactToEqualityEngine(eq_i, fact);
if (!ok) return false;
}
}
@@ -165,64 +162,15 @@ bool CoreSolver::decomposeFact(TNode fact) {
return true;
}
-bool CoreSolver::addNewSplits(TNode n, Base& old_base, Base& new_base) {
- if (n.getKind() == kind::BITVECTOR_EXTRACT) {
- n = n[0];
- }
- Assert (old_base.getBitwidth() == new_base.getBitwidth() &&
- utils::getSize(n) == old_base.getBitwidth());
-
- Index high, low = 0;
- std::vector<std::pair<Index, Index> > toSlice;
- bool hasNewCut = false;
- // collect the intervals that need to be sliced
- for (unsigned i = 0; i <= old_base.getBitwidth(); ++i) {
- Assert (! old_base.isCutPoint(i) || new_base.isCutPoint(i));
- if (new_base.isCutPoint(i) && !old_base.isCutPoint(i)) {
- hasNewCut = true;
- }
- if (new_base.isCutPoint(i) && old_base.isCutPoint(i)) {
- high = i;
- if (hasNewCut) {
- toSlice.push_back(std::pair<Index, Index>(high, low));
- }
- low = i;
- hasNewCut = false;
- }
- }
- // for each interval, assert the proper equality
- for (unsigned i = 0; i < toSlice.size(); ++i) {
- int high = toSlice[i].first;
- int low = toSlice[i].second;
- int prev = high;
- std::vector<Node> extracts;
- for (int k = high -1; k >= low; --k) {
- if (new_base.isCutPoint(k) && (!old_base.isCutPoint(k) || k == low)) {
- // add a new extract
- Node ex = utils::mkExtract(n, prev - 1, k);
- prev = k;
- extracts.push_back(ex);
- }
- }
- Node concat = utils::mkConcat(extracts);
- Node current = utils::mkExtract(n, high - 1, low);
- Node eq = utils::mkNode(kind::EQUAL, concat, current);
- bool ok = assertFact(eq, utils::mkTrue());
- if (!ok)
- return false;
- }
- return true;
-}
-
-
-bool CoreSolver::addAssertions(const std::vector<TNode>& assertions, Theory::Effort e) {
- Trace("bitvector::core") << "CoreSolver::addAssertions \n";
+bool CoreSolver::check(Theory::Effort e) {
+ d_checkCalled = true;
+ Trace("bitvector::core") << "CoreSolver::check \n";
Assert (!d_bv->inConflict());
bool ok = true;
std::vector<Node> core_eqs;
- for (unsigned i = 0; i < assertions.size(); ++i) {
- TNode fact = assertions[i];
+ while (! done()) {
+ TNode fact = get();
// update whether we are in the core fragment
if (d_isCoreTheory && !d_slicer->isCoreTerm(fact)) {
@@ -234,17 +182,17 @@ bool CoreSolver::addAssertions(const std::vector<TNode>& assertions, Theory::Eff
TNode eq = fact.getKind() == kind::EQUAL ? fact : fact[0];
ok = decomposeFact(fact);
} else {
- ok = assertFact(fact, fact);
+ ok = assertFactToEqualityEngine(fact, fact);
}
if (!ok)
return false;
}
-
+
return true;
}
-bool CoreSolver::assertFact(TNode fact, TNode reason) {
- Debug("bv-slicer") << "CoreSolver::assertFact fact=" << fact << endl;
+bool CoreSolver::assertFactToEqualityEngine(TNode fact, TNode reason) {
+ Debug("bv-slicer") << "CoreSolver::assertFactToEqualityEngine fact=" << fact << endl;
Debug("bv-slicer") << " reason=" << reason << endl;
// Notify the equality engine
if (d_useEqualityEngine && !d_bv->inConflict() && !d_bv->propagatedBy(fact, SUB_CORE) ) {
@@ -276,7 +224,7 @@ bool CoreSolver::assertFact(TNode fact, TNode reason) {
}
bool CoreSolver::NotifyClass::eqNotifyTriggerEquality(TNode equality, bool value) {
- BVDebug("bitvector::core") << "NotifyClass::eqNotifyTriggerEquality(" << equality << ", " << (value ? "true" : "false" )<< ")" << std::endl;
+ Debug("bitvector::core") << "NotifyClass::eqNotifyTriggerEquality(" << equality << ", " << (value ? "true" : "false" )<< ")" << std::endl;
if (value) {
return d_solver.storePropagation(equality);
} else {
@@ -285,7 +233,7 @@ bool CoreSolver::NotifyClass::eqNotifyTriggerEquality(TNode equality, bool value
}
bool CoreSolver::NotifyClass::eqNotifyTriggerPredicate(TNode predicate, bool value) {
- BVDebug("bitvector::core") << "NotifyClass::eqNotifyTriggerPredicate(" << predicate << ", " << (value ? "true" : "false" ) << ")" << std::endl;
+ Debug("bitvector::core") << "NotifyClass::eqNotifyTriggerPredicate(" << predicate << ", " << (value ? "true" : "false" ) << ")" << std::endl;
if (value) {
return d_solver.storePropagation(predicate);
} else {
diff --git a/src/theory/bv/bv_subtheory_core.h b/src/theory/bv/bv_subtheory_core.h
index 1adf813ff..d5235a864 100644
--- a/src/theory/bv/bv_subtheory_core.h
+++ b/src/theory/bv/bv_subtheory_core.h
@@ -73,16 +73,17 @@ class CoreSolver : public SubtheorySolver {
Slicer* d_slicer;
context::CDO<bool> d_isCoreTheory;
- bool assertFact(TNode fact, TNode reason);
+ bool assertFactToEqualityEngine(TNode fact, TNode reason);
bool decomposeFact(TNode fact);
Node getBaseDecomposition(TNode a);
- bool addNewSplits(TNode n, Base& old_base, Base& new_base);
+ bool d_baseChanged;
+ bool d_checkCalled;
public:
- bool isCoreTheory() {return d_isCoreTheory; }
CoreSolver(context::Context* c, TheoryBV* bv, Slicer* slicer);
- void setMasterEqualityEngine(eq::EqualityEngine* eq);
+ bool isCoreTheory() { return d_isCoreTheory; }
+ void setMasterEqualityEngine(eq::EqualityEngine* eq);
void preRegister(TNode node);
- bool addAssertions(const std::vector<TNode>& assertions, Theory::Effort e);
+ bool check(Theory::Effort e);
void explain(TNode literal, std::vector<TNode>& assumptions);
void collectModelInfo(TheoryModel* m);
void addSharedTerm(TNode t) {
diff --git a/src/theory/bv/bv_subtheory_eq.cpp b/src/theory/bv/bv_subtheory_eq.cpp
index ca3e3e35c..f11b1252b 100644
--- a/src/theory/bv/bv_subtheory_eq.cpp
+++ b/src/theory/bv/bv_subtheory_eq.cpp
@@ -131,7 +131,7 @@ bool EqualitySolver::addAssertions(const std::vector<TNode>& assertions, Theory:
}
bool EqualitySolver::NotifyClass::eqNotifyTriggerEquality(TNode equality, bool value) {
- BVDebug("bitvector::equality") << "NotifyClass::eqNotifyTriggerEquality(" << equality << ", " << (value ? "true" : "false" )<< ")" << std::endl;
+ Debug("bitvector::equality") << "NotifyClass::eqNotifyTriggerEquality(" << equality << ", " << (value ? "true" : "false" )<< ")" << std::endl;
if (value) {
return d_solver.storePropagation(equality);
} else {
@@ -140,7 +140,7 @@ bool EqualitySolver::NotifyClass::eqNotifyTriggerEquality(TNode equality, bool v
}
bool EqualitySolver::NotifyClass::eqNotifyTriggerPredicate(TNode predicate, bool value) {
- BVDebug("bitvector::equality") << "NotifyClass::eqNotifyTriggerPredicate(" << predicate << ", " << (value ? "true" : "false" ) << ")" << std::endl;
+ Debug("bitvector::equality") << "NotifyClass::eqNotifyTriggerPredicate(" << predicate << ", " << (value ? "true" : "false" ) << ")" << std::endl;
if (value) {
return d_solver.storePropagation(predicate);
} else {
diff --git a/src/theory/bv/cd_set_collection.h b/src/theory/bv/cd_set_collection.h
index e4bcbca47..ec7f6d66d 100644
--- a/src/theory/bv/cd_set_collection.h
+++ b/src/theory/bv/cd_set_collection.h
@@ -71,7 +71,7 @@ class BacktrackableSetCollection {
const tree_entry_type& node = d_memory.back();
if(Debug.isOn("cd_set_collection")) {
- BVDebug("cd_set_collection") << "BacktrackableSetCollection::backtrack(): removing " << node.getValue()
+ Debug("cd_set_collection") << "BacktrackableSetCollection::backtrack(): removing " << node.getValue()
<< " from " << internalToString(getRoot(d_memory.size()-1)) << std::endl;
}
@@ -279,7 +279,7 @@ public:
// Find the biggest node smaleer than value (it must exist)
while (set != null) {
if(Debug.isOn("set_collection")) {
- BVDebug("set_collection") << "BacktrackableSetCollection::getPrev(" << toString(set) << "," << value << ")" << std::endl;
+ Debug("set_collection") << "BacktrackableSetCollection::getPrev(" << toString(set) << "," << value << ")" << std::endl;
}
const tree_entry_type& node = d_memory[set];
if (node.getValue() >= value) {
@@ -308,7 +308,7 @@ public:
// Find the smallest node bigger than value (it must exist)
while (set != null) {
if(Debug.isOn("set_collection")) {
- BVDebug("set_collection") << "BacktrackableSetCollection::getNext(" << toString(set) << "," << value << ")" << std::endl;
+ Debug("set_collection") << "BacktrackableSetCollection::getNext(" << toString(set) << "," << value << ")" << std::endl;
}
const tree_entry_type& node = d_memory[set];
if (node.getValue() <= value) {
@@ -377,7 +377,7 @@ public:
Assert(isValid(set));
if(Debug.isOn("set_collection")) {
- BVDebug("set_collection") << "BacktrackableSetCollection::getElements(" << toString(set) << "," << lowerBound << "," << upperBound << ")" << std::endl;
+ Debug("set_collection") << "BacktrackableSetCollection::getElements(" << toString(set) << "," << lowerBound << "," << upperBound << ")" << std::endl;
}
// Empty set no elements
diff --git a/src/theory/bv/slicer.cpp b/src/theory/bv/slicer.cpp
index 2334ed2b0..ac668ab20 100644
--- a/src/theory/bv/slicer.cpp
+++ b/src/theory/bv/slicer.cpp
@@ -48,6 +48,14 @@ void Base::sliceAt(Index index) {
d_repr[vector_index] = d_repr[vector_index] | bit_mask;
}
+void Base::undoSliceAt(Index index) {
+ Index vector_index = index / 32;
+ Assert (vector_index < d_size);
+ Index int_index = index % 32;
+ uint32_t bit_mask = utils::pow2(int_index);
+ d_repr[vector_index] = d_repr[vector_index] ^ bit_mask;
+}
+
void Base::sliceWith(const Base& other) {
Assert (d_size == other.d_size);
for (unsigned i = 0; i < d_repr.size(); ++i) {
@@ -245,8 +253,9 @@ void UnionFind::split(TermId id, Index i) {
if (i == 0 || i == getBitwidth(id)) {
// nothing to do
- return;
+ return;
}
+
Assert (i < getBitwidth(id));
if (!hasChildren(id)) {
// first time we split this term
@@ -417,6 +426,7 @@ void UnionFind::ensureSlicing(const ExtractTerm& term) {
}
void UnionFind::backtrack() {
+ return;
int size = d_undoStack.size();
for (int i = size; i > d_undoStackIndex.get(); --i) {
Operation op = d_undoStack.back();
@@ -443,6 +453,9 @@ void UnionFind::undoSplit(TermId id) {
}
void UnionFind::recordOperation(OperationKind op, TermId term) {
+ if (op == SPLIT) {
+ d_newSplit = true;
+ }
d_undoStackIndex.set(d_undoStackIndex.get() + 1);
d_undoStack.push_back(Operation(op, term));
Assert (d_undoStack.size() == d_undoStackIndex);
diff --git a/src/theory/bv/slicer.h b/src/theory/bv/slicer.h
index 0508c67c1..6e09d971b 100644
--- a/src/theory/bv/slicer.h
+++ b/src/theory/bv/slicer.h
@@ -47,6 +47,7 @@ namespace bv {
typedef Index TermId;
extern const TermId UndefinedId;
+class CDBase;
/**
* Base
@@ -55,9 +56,11 @@ extern const TermId UndefinedId;
class Base {
Index d_size;
std::vector<uint32_t> d_repr;
+ void undoSliceAt(Index index);
public:
Base (Index size);
- void sliceAt(Index index);
+ void sliceAt(Index index);
+
void sliceWith(const Base& other);
bool isCutPoint(Index index) const;
void diffCutPoints(const Base& other, Base& res) const;
@@ -78,6 +81,47 @@ public:
}
return true;
}
+ friend class CDBase;
+};
+
+
+class CDBase : public context::ContextNotifyObj {
+ context::Context* d_ctx;
+ context::CDO<unsigned> d_undoIndex;
+
+ std::vector<unsigned> d_undoStack;
+ Base d_base;
+ CDBase(context::Context* ctx, Index bitwidth)
+ : ContextNotifyObj(ctx),
+ d_ctx(ctx),
+ d_undoIndex(d_ctx),
+ d_undoStack(),
+ d_base(bitwidth)
+ {}
+ void sliceAt(Index i) {
+ Assert (!d_base.isCutPoint(i));
+ d_undoStack.push_back(i);
+ d_undoIndex.set(d_undoIndex.get() + 1);
+ d_base.sliceAt(i);
+ }
+ bool isCutPoint(Index i) {
+ return d_base.isCutPoint(i);
+ }
+ Index getBitwidth() const {return d_base.getBitwidth(); }
+ virtual ~CDBase() throw(AssertionException) {}
+ void contextNotifyPop() {
+ backtrack();
+ }
+
+ void backtrack() {
+ for (unsigned i = d_undoIndex.get(); i < d_undoStack.size(); ++i) {
+ Index i = d_undoStack.back();
+ d_undoStack.pop_back();
+ d_base.undoSliceAt(i);
+ }
+ Assert(d_undoIndex.get() == d_undoStack.size());
+ }
+
};
/**
@@ -227,11 +271,11 @@ class UnionFind : public context::ContextNotifyObj {
};
Statistics d_statistics;
+ bool d_newSplit;
public:
UnionFind(context::Context* ctx)
: ContextNotifyObj(ctx),
d_nodes(),
- // d_representatives(ctx),
d_undoStack(),
d_undoStackIndex(ctx),
d_statistics()
@@ -256,6 +300,8 @@ public:
void contextNotifyPop() {
backtrack();
}
+ bool hasNewSplit() { return d_newSplit; }
+ void resetNewSplit() { d_newSplit = false; }
friend class Slicer;
};
@@ -279,7 +325,9 @@ public:
bool isCoreTerm (TNode node);
Base getTopLevelBase(TNode node);
static void splitEqualities(TNode node, std::vector<Node>& equalities);
- static unsigned d_numAddedEqualities;
+ static unsigned d_numAddedEqualities;
+ inline bool hasNewSplit() { return d_unionFind.hasNewSplit(); }
+ inline void resetNewSplit() { d_unionFind.resetNewSplit(); }
};
diff --git a/src/theory/bv/theory_bv.cpp b/src/theory/bv/theory_bv.cpp
index 6248782bd..5d034287d 100644
--- a/src/theory/bv/theory_bv.cpp
+++ b/src/theory/bv/theory_bv.cpp
@@ -41,7 +41,6 @@ TheoryBV::TheoryBV(context::Context* c, context::UserContext* u, OutputChannel&
d_alreadyPropagatedSet(c),
d_sharedTermsSet(c),
d_slicer(c),
- d_bitblastAssertionsQueue(c),
d_bitblastSolver(c, this),
d_coreSolver(c, this, &d_slicer),
d_statistics(),
@@ -110,29 +109,23 @@ void TheoryBV::check(Effort e)
return;
}
- // getting the new assertions
- std::vector<TNode> new_assertions;
while (!done()) {
- Assertion assertion = get();
- TNode fact = assertion.assertion;
- new_assertions.push_back(fact);
- d_bitblastAssertionsQueue.push_back(fact);
- Debug("bitvector-assertions") << "TheoryBV::check assertion " << fact << "\n";
+ TNode fact = get().assertion;
+ d_coreSolver.assertFact(fact);
+ d_bitblastSolver.assertFact(fact);
}
+ bool ok = true;
if (!inConflict()) {
- // sending assertions to the equality solver first
- d_coreSolver.addAssertions(new_assertions, e);
+ ok = d_coreSolver.check(e);
}
+ Assert (!ok == inConflict());
if (!inConflict() && !d_coreSolver.isCoreTheory()) {
- // sending assertions to the bitblast solver if it's not just core theory
- d_bitblastSolver.addAssertions(new_assertions, e);
- } else {
- // sending assertions to the bitblast solver if it's not just core theory
- d_bitblastSolver.addAssertions(new_assertions, EFFORT_STANDARD);
+ ok = d_bitblastSolver.check(e);
}
+ Assert (!ok == inConflict());
if (inConflict()) {
sendConflict();
}
@@ -156,7 +149,10 @@ void TheoryBV::propagate(Effort e) {
bool ok = true;
for (; d_literalsToPropagateIndex < d_literalsToPropagate.size() && ok; d_literalsToPropagateIndex = d_literalsToPropagateIndex + 1) {
TNode literal = d_literalsToPropagate[d_literalsToPropagateIndex];
- ok = d_out->propagate(literal);
+ // temporary fix for incremental bit-blasting
+ if (d_valuation.isSatLiteral(literal)) {
+ ok = d_out->propagate(literal);
+ }
}
if (!ok) {
@@ -214,7 +210,7 @@ void TheoryBV::presolve() {
bool TheoryBV::storePropagation(TNode literal, SubTheory subtheory)
{
- Debug("bitvector::propagate") << indent() << "TheoryBV::storePropagation(" << literal << ", " << subtheory << ")" << std::endl;
+ Debug("bitvector::propagate") << indent() << getSatContext()->getLevel() << " " << "TheoryBV::storePropagation(" << literal << ", " << subtheory << ")" << std::endl;
// If already in conflict, no more propagation
if (d_conflict) {
diff --git a/src/theory/bv/theory_bv.h b/src/theory/bv/theory_bv.h
index ec72f40e1..3e14584ed 100644
--- a/src/theory/bv/theory_bv.h
+++ b/src/theory/bv/theory_bv.h
@@ -25,7 +25,6 @@
#include "context/cdhashset.h"
#include "theory/bv/theory_bv_utils.h"
#include "util/statistics_registry.h"
-#include "context/cdqueue.h"
#include "theory/bv/bv_subtheory.h"
#include "theory/bv/bv_subtheory_eq.h"
#include "theory/bv/bv_subtheory_core.h"
@@ -46,11 +45,8 @@ class TheoryBV : public Theory {
context::CDHashSet<Node, NodeHashFunction> d_sharedTermsSet;
Slicer d_slicer;
-
- context::CDQueue<TNode> d_bitblastAssertionsQueue;
-
BitblastSolver d_bitblastSolver;
- CoreSolver d_coreSolver;
+ CoreSolver d_coreSolver;
public:
diff --git a/src/theory/bv/theory_bv_rewrite_rules.h b/src/theory/bv/theory_bv_rewrite_rules.h
index f9650932e..bd7a8131a 100644
--- a/src/theory/bv/theory_bv_rewrite_rules.h
+++ b/src/theory/bv/theory_bv_rewrite_rules.h
@@ -334,7 +334,7 @@ public:
template<bool checkApplies>
static inline Node run(TNode node) {
if (!checkApplies || applies(node)) {
- BVDebug("theory::bv::rewrite") << "RewriteRule<" << rule << ">(" << node << ")" << std::endl;
+ Debug("theory::bv::rewrite") << "RewriteRule<" << rule << ">(" << node << ")" << std::endl;
Assert(checkApplies || applies(node));
//++ s_statistics->d_ruleApplications;
Node result = apply(node);
@@ -355,7 +355,7 @@ public:
<< CheckSatCommand(condition.toExpr());
}
}
- BVDebug("theory::bv::rewrite") << "RewriteRule<" << rule << ">(" << node << ") => " << result << std::endl;
+ Debug("theory::bv::rewrite") << "RewriteRule<" << rule << ">(" << node << ") => " << result << std::endl;
return result;
} else {
return node;
@@ -486,7 +486,7 @@ bool RewriteRule<EmptyRule>::applies(TNode node) {
template<> inline
Node RewriteRule<EmptyRule>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EmptyRule> for " << node.getKind() <<"\n";
+ Debug("bv-rewrite") << "RewriteRule<EmptyRule> for " << node.getKind() <<"\n";
Unreachable();
return node;
}
diff --git a/src/theory/bv/theory_bv_rewrite_rules_constant_evaluation.h b/src/theory/bv/theory_bv_rewrite_rules_constant_evaluation.h
index 498378638..178b17b43 100644
--- a/src/theory/bv/theory_bv_rewrite_rules_constant_evaluation.h
+++ b/src/theory/bv/theory_bv_rewrite_rules_constant_evaluation.h
@@ -37,7 +37,7 @@ bool RewriteRule<EvalAnd>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalAnd>::apply(TNode node) {
Unreachable();
- BVDebug("bv-rewrite") << "RewriteRule<EvalAnd>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalAnd>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
BitVector b = node[1].getConst<BitVector>();
BitVector res = a & b;
@@ -56,7 +56,7 @@ bool RewriteRule<EvalOr>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalOr>::apply(TNode node) {
Unreachable();
- BVDebug("bv-rewrite") << "RewriteRule<EvalOr>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalOr>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
BitVector b = node[1].getConst<BitVector>();
BitVector res = a | b;
@@ -75,7 +75,7 @@ bool RewriteRule<EvalXor>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalXor>::apply(TNode node) {
Unreachable();
- BVDebug("bv-rewrite") << "RewriteRule<EvalXor>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalXor>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
BitVector b = node[1].getConst<BitVector>();
BitVector res = a ^ b;
@@ -91,7 +91,7 @@ Node RewriteRule<EvalXor>::apply(TNode node) {
// template<> inline
// Node RewriteRule<EvalXnor>::apply(TNode node) {
-// BVDebug("bv-rewrite") << "RewriteRule<EvalXnor>(" << node << ")" << std::endl;
+// Debug("bv-rewrite") << "RewriteRule<EvalXnor>(" << node << ")" << std::endl;
// BitVector a = node[0].getConst<BitVector>();
// BitVector b = node[1].getConst<BitVector>();
// BitVector res = ~ (a ^ b);
@@ -106,7 +106,7 @@ bool RewriteRule<EvalNot>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalNot>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalNot>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalNot>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
BitVector res = ~ a;
return utils::mkConst(res);
@@ -120,7 +120,7 @@ Node RewriteRule<EvalNot>::apply(TNode node) {
// template<> inline
// Node RewriteRule<EvalComp>::apply(TNode node) {
-// BVDebug("bv-rewrite") << "RewriteRule<EvalComp>(" << node << ")" << std::endl;
+// Debug("bv-rewrite") << "RewriteRule<EvalComp>(" << node << ")" << std::endl;
// BitVector a = node[0].getConst<BitVector>();
// BitVector b = node[1].getConst<BitVector>();
// BitVector res;
@@ -141,7 +141,7 @@ bool RewriteRule<EvalMult>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalMult>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalMult>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalMult>(" << node << ")" << std::endl;
TNode::iterator child_it = node.begin();
BitVector res = (*child_it).getConst<BitVector>();
for(++child_it; child_it != node.end(); ++child_it) {
@@ -158,7 +158,7 @@ bool RewriteRule<EvalPlus>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalPlus>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalPlus>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalPlus>(" << node << ")" << std::endl;
TNode::iterator child_it = node.begin();
BitVector res = (*child_it).getConst<BitVector>();
for(++child_it; child_it != node.end(); ++child_it) {
@@ -175,7 +175,7 @@ Node RewriteRule<EvalPlus>::apply(TNode node) {
// template<> inline
// Node RewriteRule<EvalSub>::apply(TNode node) {
-// BVDebug("bv-rewrite") << "RewriteRule<EvalSub>(" << node << ")" << std::endl;
+// Debug("bv-rewrite") << "RewriteRule<EvalSub>(" << node << ")" << std::endl;
// BitVector a = node[0].getConst<BitVector>();
// BitVector b = node[1].getConst<BitVector>();
// BitVector res = a - b;
@@ -190,7 +190,7 @@ bool RewriteRule<EvalNeg>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalNeg>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalNeg>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalNeg>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
BitVector res = - a;
@@ -204,7 +204,7 @@ bool RewriteRule<EvalUdiv>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalUdiv>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalUdiv>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalUdiv>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
BitVector b = node[1].getConst<BitVector>();
BitVector res = a.unsignedDivTotal(b);
@@ -219,7 +219,7 @@ bool RewriteRule<EvalUrem>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalUrem>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalUrem>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalUrem>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
BitVector b = node[1].getConst<BitVector>();
BitVector res = a.unsignedRemTotal(b);
@@ -234,7 +234,7 @@ bool RewriteRule<EvalShl>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalShl>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalShl>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalShl>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
BitVector b = node[1].getConst<BitVector>();
@@ -250,7 +250,7 @@ bool RewriteRule<EvalLshr>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalLshr>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalLshr>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalLshr>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
BitVector b = node[1].getConst<BitVector>();
@@ -266,7 +266,7 @@ bool RewriteRule<EvalAshr>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalAshr>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalAshr>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalAshr>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
BitVector b = node[1].getConst<BitVector>();
@@ -282,7 +282,7 @@ bool RewriteRule<EvalUlt>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalUlt>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalUlt>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalUlt>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
BitVector b = node[1].getConst<BitVector>();
@@ -300,7 +300,7 @@ bool RewriteRule<EvalSlt>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalSlt>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalSlt>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalSlt>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
BitVector b = node[1].getConst<BitVector>();
@@ -319,7 +319,7 @@ bool RewriteRule<EvalUle>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalUle>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalUle>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalUle>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
BitVector b = node[1].getConst<BitVector>();
@@ -337,7 +337,7 @@ bool RewriteRule<EvalSle>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalSle>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalSle>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalSle>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
BitVector b = node[1].getConst<BitVector>();
@@ -355,7 +355,7 @@ bool RewriteRule<EvalExtract>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalExtract>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalExtract>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalExtract>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
unsigned lo = utils::getExtractLow(node);
unsigned hi = utils::getExtractHigh(node);
@@ -373,7 +373,7 @@ bool RewriteRule<EvalConcat>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalConcat>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalConcat>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalConcat>(" << node << ")" << std::endl;
unsigned num = node.getNumChildren();
BitVector res = node[0].getConst<BitVector>();
for(unsigned i = 1; i < num; ++i ) {
@@ -391,7 +391,7 @@ bool RewriteRule<EvalSignExtend>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalSignExtend>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalSignExtend>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalSignExtend>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
unsigned amount = node.getOperator().getConst<BitVectorSignExtend>().signExtendAmount;
BitVector res = a.signExtend(amount);
@@ -407,7 +407,7 @@ bool RewriteRule<EvalEquals>::applies(TNode node) {
template<> inline
Node RewriteRule<EvalEquals>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<EvalEquals>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<EvalEquals>(" << node << ")" << std::endl;
BitVector a = node[0].getConst<BitVector>();
BitVector b = node[1].getConst<BitVector>();
if (a == b) {
diff --git a/src/theory/bv/theory_bv_rewrite_rules_core.h b/src/theory/bv/theory_bv_rewrite_rules_core.h
index b44c72f74..ade345d1c 100644
--- a/src/theory/bv/theory_bv_rewrite_rules_core.h
+++ b/src/theory/bv/theory_bv_rewrite_rules_core.h
@@ -33,7 +33,7 @@ bool RewriteRule<ConcatFlatten>::applies(TNode node) {
template<> inline
Node RewriteRule<ConcatFlatten>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<ConcatFlatten>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ConcatFlatten>(" << node << ")" << std::endl;
NodeBuilder<> result(kind::BITVECTOR_CONCAT);
std::vector<Node> processing_stack;
processing_stack.push_back(node);
@@ -48,7 +48,7 @@ Node RewriteRule<ConcatFlatten>::apply(TNode node) {
}
}
Node resultNode = result;
- BVDebug("bv-rewrite") << "RewriteRule<ConcatFlatten>(" << resultNode << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ConcatFlatten>(" << resultNode << ")" << std::endl;
return resultNode;
}
@@ -60,7 +60,7 @@ bool RewriteRule<ConcatExtractMerge>::applies(TNode node) {
template<> inline
Node RewriteRule<ConcatExtractMerge>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<ConcatExtractMerge>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ConcatExtractMerge>(" << node << ")" << std::endl;
std::vector<Node> mergedExtracts;
@@ -121,7 +121,7 @@ bool RewriteRule<ConcatConstantMerge>::applies(TNode node) {
template<> inline
Node RewriteRule<ConcatConstantMerge>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<ConcatConstantMerge>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ConcatConstantMerge>(" << node << ")" << std::endl;
std::vector<Node> mergedConstants;
for (unsigned i = 0, end = node.getNumChildren(); i < end;) {
@@ -150,7 +150,7 @@ Node RewriteRule<ConcatConstantMerge>::apply(TNode node) {
}
}
- BVDebug("bv-rewrite") << "RewriteRule<ConcatConstantMerge>(" << node << ") => " << utils::mkConcat(mergedConstants) << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ConcatConstantMerge>(" << node << ") => " << utils::mkConcat(mergedConstants) << std::endl;
return utils::mkConcat(mergedConstants);
}
@@ -168,7 +168,7 @@ bool RewriteRule<ExtractWhole>::applies(TNode node) {
template<> inline
Node RewriteRule<ExtractWhole>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<ExtractWhole>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ExtractWhole>(" << node << ")" << std::endl;
return node[0];
}
@@ -181,7 +181,7 @@ bool RewriteRule<ExtractConstant>::applies(TNode node) {
template<> inline
Node RewriteRule<ExtractConstant>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<ExtractConstant>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ExtractConstant>(" << node << ")" << std::endl;
Node child = node[0];
BitVector childValue = child.getConst<BitVector>();
return utils::mkConst(childValue.extract(utils::getExtractHigh(node), utils::getExtractLow(node)));
@@ -189,7 +189,7 @@ Node RewriteRule<ExtractConstant>::apply(TNode node) {
template<> inline
bool RewriteRule<ExtractConcat>::applies(TNode node) {
- //BVDebug("bv-rewrite") << "RewriteRule<ExtractConcat>(" << node << ")" << std::endl;
+ //Debug("bv-rewrite") << "RewriteRule<ExtractConcat>(" << node << ")" << std::endl;
if (node.getKind() != kind::BITVECTOR_EXTRACT) return false;
if (node[0].getKind() != kind::BITVECTOR_CONCAT) return false;
return true;
@@ -197,7 +197,7 @@ bool RewriteRule<ExtractConcat>::applies(TNode node) {
template<> inline
Node RewriteRule<ExtractConcat>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<ExtractConcat>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ExtractConcat>(" << node << ")" << std::endl;
int extract_high = utils::getExtractHigh(node);
int extract_low = utils::getExtractLow(node);
@@ -230,7 +230,7 @@ bool RewriteRule<ExtractExtract>::applies(TNode node) {
template<> inline
Node RewriteRule<ExtractExtract>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<ExtractExtract>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ExtractExtract>(" << node << ")" << std::endl;
// x[i:j][k:l] ~> x[k+j:l+j]
Node child = node[0];
@@ -244,7 +244,7 @@ Node RewriteRule<ExtractExtract>::apply(TNode node) {
template<> inline
bool RewriteRule<FailEq>::applies(TNode node) {
- //BVDebug("bv-rewrite") << "RewriteRule<FailEq>(" << node << ")" << std::endl;
+ //Debug("bv-rewrite") << "RewriteRule<FailEq>(" << node << ")" << std::endl;
if (node.getKind() != kind::EQUAL) return false;
if (node[0].getKind() != kind::CONST_BITVECTOR) return false;
if (node[1].getKind() != kind::CONST_BITVECTOR) return false;
@@ -264,7 +264,7 @@ bool RewriteRule<SimplifyEq>::applies(TNode node) {
template<> inline
Node RewriteRule<SimplifyEq>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<SimplifyEq>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<SimplifyEq>(" << node << ")" << std::endl;
return utils::mkTrue();
}
@@ -275,7 +275,7 @@ bool RewriteRule<ReflexivityEq>::applies(TNode node) {
template<> inline
Node RewriteRule<ReflexivityEq>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<ReflexivityEq>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ReflexivityEq>(" << node << ")" << std::endl;
return node[1].eqNode(node[0]);
}
diff --git a/src/theory/bv/theory_bv_rewrite_rules_normalization.h b/src/theory/bv/theory_bv_rewrite_rules_normalization.h
index 6b3d0f770..39f55f26c 100644
--- a/src/theory/bv/theory_bv_rewrite_rules_normalization.h
+++ b/src/theory/bv/theory_bv_rewrite_rules_normalization.h
@@ -41,7 +41,7 @@ bool RewriteRule<ExtractBitwise>::applies(TNode node) {
template<> inline
Node RewriteRule<ExtractBitwise>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<ExtractBitwise>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ExtractBitwise>(" << node << ")" << std::endl;
unsigned high = utils::getExtractHigh(node);
unsigned low = utils::getExtractLow(node);
std::vector<Node> children;
@@ -65,7 +65,7 @@ bool RewriteRule<ExtractNot>::applies(TNode node) {
template<> inline
Node RewriteRule<ExtractNot>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<ExtractNot>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ExtractNot>(" << node << ")" << std::endl;
unsigned low = utils::getExtractLow(node);
unsigned high = utils::getExtractHigh(node);
Node a = utils::mkExtract(node[0][0], high, low);
@@ -88,7 +88,7 @@ bool RewriteRule<ExtractArith>::applies(TNode node) {
template<> inline
Node RewriteRule<ExtractArith>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<ExtractArith>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ExtractArith>(" << node << ")" << std::endl;
unsigned low = utils::getExtractLow(node);
Assert (low == 0);
unsigned high = utils::getExtractHigh(node);
@@ -117,7 +117,7 @@ bool RewriteRule<ExtractArith2>::applies(TNode node) {
template<> inline
Node RewriteRule<ExtractArith2>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<ExtractArith2>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ExtractArith2>(" << node << ")" << std::endl;
unsigned low = utils::getExtractLow(node);
unsigned high = utils::getExtractHigh(node);
std::vector<Node> children;
@@ -151,7 +151,7 @@ bool RewriteRule<FlattenAssocCommut>::applies(TNode node) {
template<> inline
Node RewriteRule<FlattenAssocCommut>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<FlattenAssocCommut>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<FlattenAssocCommut>(" << node << ")" << std::endl;
std::vector<Node> processingStack;
processingStack.push_back(node);
std::vector<Node> children;
@@ -291,7 +291,7 @@ bool RewriteRule<PlusCombineLikeTerms>::applies(TNode node) {
template<> inline
Node RewriteRule<PlusCombineLikeTerms>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<PlusCombineLikeTerms>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<PlusCombineLikeTerms>(" << node << ")" << std::endl;
unsigned size = utils::getSize(node);
BitVector constSum(size, (unsigned)0);
std::map<Node, BitVector> factorToCoefficient;
@@ -348,7 +348,7 @@ bool RewriteRule<MultSimplify>::applies(TNode node) {
template<> inline
Node RewriteRule<MultSimplify>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<MultSimplify>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<MultSimplify>(" << node << ")" << std::endl;
unsigned size = utils::getSize(node);
BitVector constant(size, Integer(1));
@@ -397,7 +397,7 @@ bool RewriteRule<MultDistribConst>::applies(TNode node) {
template<> inline
Node RewriteRule<MultDistribConst>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<MultDistribConst>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<MultDistribConst>(" << node << ")" << std::endl;
TNode constant = node[1];
TNode factor = node[0];
@@ -434,7 +434,7 @@ bool RewriteRule<SolveEq>::applies(TNode node) {
// Doesn't do full solving (yet), instead, if a term appears both on lhs and rhs, it subtracts from both sides so that one side's coeff is zero
template<> inline
Node RewriteRule<SolveEq>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<SolveEq>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<SolveEq>(" << node << ")" << std::endl;
TNode left = node[0];
TNode right = node[1];
@@ -662,7 +662,7 @@ static inline Node mkNodeKind(Kind k, TNode node, TNode c) {
template<> inline
Node RewriteRule<BitwiseEq>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<BitwiseEq>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<BitwiseEq>(" << node << ")" << std::endl;
TNode term;
BitVector c;
@@ -745,7 +745,7 @@ bool RewriteRule<NegMult>::applies(TNode node) {
template<> inline
Node RewriteRule<NegMult>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<NegMult>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<NegMult>(" << node << ")" << std::endl;
TNode mult = node[0];
NodeBuilder<> nb(kind::BITVECTOR_MULT);
BitVector bv(utils::getSize(node), (unsigned)1);
@@ -767,7 +767,7 @@ bool RewriteRule<NegSub>::applies(TNode node) {
template<> inline
Node RewriteRule<NegSub>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<NegSub>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<NegSub>(" << node << ")" << std::endl;
return utils::mkNode(kind::BITVECTOR_SUB, node[0][1], node[0][0]);
}
@@ -779,7 +779,7 @@ bool RewriteRule<NegPlus>::applies(TNode node) {
template<> inline
Node RewriteRule<NegPlus>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<NegPlus>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<NegPlus>(" << node << ")" << std::endl;
std::vector<Node> children;
for (unsigned i = 0; i < node[0].getNumChildren(); ++i) {
children.push_back(utils::mkNode(kind::BITVECTOR_NEG, node[0][i]));
@@ -820,7 +820,7 @@ bool RewriteRule<AndSimplify>::applies(TNode node) {
template<> inline
Node RewriteRule<AndSimplify>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<AndSimplify>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<AndSimplify>(" << node << ")" << std::endl;
// this will remove duplicates
std::hash_map<TNode, Count, TNodeHashFunction> subterms;
@@ -883,7 +883,7 @@ bool RewriteRule<OrSimplify>::applies(TNode node) {
template<> inline
Node RewriteRule<OrSimplify>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<OrSimplify>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<OrSimplify>(" << node << ")" << std::endl;
// this will remove duplicates
std::hash_map<TNode, Count, TNodeHashFunction> subterms;
@@ -946,7 +946,7 @@ bool RewriteRule<XorSimplify>::applies(TNode node) {
template<> inline
Node RewriteRule<XorSimplify>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<XorSimplify>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<XorSimplify>(" << node << ")" << std::endl;
std::hash_map<TNode, Count, TNodeHashFunction> subterms;
@@ -1041,7 +1041,7 @@ Node RewriteRule<XorSimplify>::apply(TNode node) {
// template<> inline
// Node RewriteRule<AndSimplify>::apply(TNode node) {
-// BVDebug("bv-rewrite") << "RewriteRule<AndSimplify>(" << node << ")" << std::endl;
+// Debug("bv-rewrite") << "RewriteRule<AndSimplify>(" << node << ")" << std::endl;
// return resultNode;
// }
@@ -1053,7 +1053,7 @@ Node RewriteRule<XorSimplify>::apply(TNode node) {
// template<> inline
// Node RewriteRule<>::apply(TNode node) {
-// BVDebug("bv-rewrite") << "RewriteRule<>(" << node << ")" << std::endl;
+// Debug("bv-rewrite") << "RewriteRule<>(" << node << ")" << std::endl;
// return resultNode;
// }
diff --git a/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h b/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h
index 94983e03a..4202f8c2e 100644
--- a/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h
+++ b/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h
@@ -33,7 +33,7 @@ bool RewriteRule<UgtEliminate>::applies(TNode node) {
template<>
Node RewriteRule<UgtEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<UgtEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<UgtEliminate>(" << node << ")" << std::endl;
TNode a = node[0];
TNode b = node[1];
Node result = utils::mkNode(kind::BITVECTOR_ULT, b, a);
@@ -48,7 +48,7 @@ bool RewriteRule<UgeEliminate>::applies(TNode node) {
template<>
Node RewriteRule<UgeEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<UgeEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<UgeEliminate>(" << node << ")" << std::endl;
TNode a = node[0];
TNode b = node[1];
Node result = utils::mkNode(kind::BITVECTOR_ULE, b, a);
@@ -63,7 +63,7 @@ bool RewriteRule<SgtEliminate>::applies(TNode node) {
template<>
Node RewriteRule<SgtEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<SgtEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<SgtEliminate>(" << node << ")" << std::endl;
TNode a = node[0];
TNode b = node[1];
Node result = utils::mkNode(kind::BITVECTOR_SLT, b, a);
@@ -78,7 +78,7 @@ bool RewriteRule<SgeEliminate>::applies(TNode node) {
template<>
Node RewriteRule<SgeEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<SgeEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<SgeEliminate>(" << node << ")" << std::endl;
TNode a = node[0];
TNode b = node[1];
Node result = utils::mkNode(kind::BITVECTOR_SLE, b, a);
@@ -92,7 +92,7 @@ bool RewriteRule<SltEliminate>::applies(TNode node) {
template <>
Node RewriteRule<SltEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<SltEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<SltEliminate>(" << node << ")" << std::endl;
unsigned size = utils::getSize(node[0]);
Node pow_two = utils::mkConst(BitVector(size, Integer(1).multiplyByPow2(size - 1)));
@@ -110,7 +110,7 @@ bool RewriteRule<SleEliminate>::applies(TNode node) {
template <>
Node RewriteRule<SleEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<SleEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<SleEliminate>(" << node << ")" << std::endl;
unsigned size = utils::getSize(node[0]);
Node pow_two = utils::mkConst(BitVector(size, Integer(1).multiplyByPow2(size - 1)));
@@ -128,7 +128,7 @@ bool RewriteRule<CompEliminate>::applies(TNode node) {
template <>
Node RewriteRule<CompEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<CompEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<CompEliminate>(" << node << ")" << std::endl;
Node comp = utils::mkNode(kind::EQUAL, node[0], node[1]);
Node one = utils::mkConst(1, 1);
Node zero = utils::mkConst(1, 0);
@@ -143,7 +143,7 @@ bool RewriteRule<SubEliminate>::applies(TNode node) {
template <>
Node RewriteRule<SubEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<SubEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<SubEliminate>(" << node << ")" << std::endl;
Node negb = utils::mkNode(kind::BITVECTOR_NEG, node[1]);
Node a = node[0];
@@ -158,7 +158,7 @@ bool RewriteRule<RepeatEliminate>::applies(TNode node) {
template<>
Node RewriteRule<RepeatEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<RepeatEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<RepeatEliminate>(" << node << ")" << std::endl;
TNode a = node[0];
unsigned amount = node.getOperator().getConst<BitVectorRepeat>().repeatAmount;
Assert(amount >= 1);
@@ -180,7 +180,7 @@ bool RewriteRule<RotateLeftEliminate>::applies(TNode node) {
template<>
Node RewriteRule<RotateLeftEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<RotateLeftEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<RotateLeftEliminate>(" << node << ")" << std::endl;
TNode a = node[0];
unsigned amount = node.getOperator().getConst<BitVectorRotateLeft>().rotateLeftAmount;
amount = amount % utils::getSize(a);
@@ -202,7 +202,7 @@ bool RewriteRule<RotateRightEliminate>::applies(TNode node) {
template<>
Node RewriteRule<RotateRightEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<RotateRightEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<RotateRightEliminate>(" << node << ")" << std::endl;
TNode a = node[0];
unsigned amount = node.getOperator().getConst<BitVectorRotateRight>().rotateRightAmount;
amount = amount % utils::getSize(a);
@@ -225,7 +225,7 @@ bool RewriteRule<NandEliminate>::applies(TNode node) {
template<>
Node RewriteRule<NandEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<NandEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<NandEliminate>(" << node << ")" << std::endl;
TNode a = node[0];
TNode b = node[1];
Node andNode = utils::mkNode(kind::BITVECTOR_AND, a, b);
@@ -241,7 +241,7 @@ bool RewriteRule<NorEliminate>::applies(TNode node) {
template<>
Node RewriteRule<NorEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<NorEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<NorEliminate>(" << node << ")" << std::endl;
TNode a = node[0];
TNode b = node[1];
Node orNode = utils::mkNode(kind::BITVECTOR_OR, a, b);
@@ -257,7 +257,7 @@ bool RewriteRule<XnorEliminate>::applies(TNode node) {
template<>
Node RewriteRule<XnorEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<XnorEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<XnorEliminate>(" << node << ")" << std::endl;
TNode a = node[0];
TNode b = node[1];
Node xorNode = utils::mkNode(kind::BITVECTOR_XOR, a, b);
@@ -272,7 +272,7 @@ bool RewriteRule<SdivEliminate>::applies(TNode node) {
template<>
Node RewriteRule<SdivEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<SdivEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<SdivEliminate>(" << node << ")" << std::endl;
TNode a = node[0];
TNode b = node[1];
@@ -301,7 +301,7 @@ bool RewriteRule<SremEliminate>::applies(TNode node) {
template<>
Node RewriteRule<SremEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<SremEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<SremEliminate>(" << node << ")" << std::endl;
TNode a = node[0];
TNode b = node[1];
unsigned size = utils::getSize(a);
@@ -327,7 +327,7 @@ bool RewriteRule<SmodEliminate>::applies(TNode node) {
template<>
Node RewriteRule<SmodEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<SmodEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<SmodEliminate>(" << node << ")" << std::endl;
TNode s = node[0];
TNode t = node[1];
unsigned size = utils::getSize(s);
@@ -382,7 +382,7 @@ bool RewriteRule<ZeroExtendEliminate>::applies(TNode node) {
template<>
Node RewriteRule<ZeroExtendEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<ZeroExtendEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ZeroExtendEliminate>(" << node << ")" << std::endl;
TNode bv = node[0];
unsigned amount = node.getOperator().getConst<BitVectorZeroExtend>().zeroExtendAmount;
@@ -402,7 +402,7 @@ bool RewriteRule<SignExtendEliminate>::applies(TNode node) {
template<>
Node RewriteRule<SignExtendEliminate>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<SignExtendEliminate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<SignExtendEliminate>(" << node << ")" << std::endl;
unsigned amount = node.getOperator().getConst<BitVectorSignExtend>().signExtendAmount;
if(amount == 0) {
diff --git a/src/theory/bv/theory_bv_rewrite_rules_simplification.h b/src/theory/bv/theory_bv_rewrite_rules_simplification.h
index 8bcc64414..9d1cafab9 100644
--- a/src/theory/bv/theory_bv_rewrite_rules_simplification.h
+++ b/src/theory/bv/theory_bv_rewrite_rules_simplification.h
@@ -43,7 +43,7 @@ bool RewriteRule<ShlByConst>::applies(TNode node) {
template<> inline
Node RewriteRule<ShlByConst>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<ShlByConst>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ShlByConst>(" << node << ")" << std::endl;
Integer amount = node[1].getConst<BitVector>().toInteger();
Node a = node[0];
@@ -79,7 +79,7 @@ bool RewriteRule<LshrByConst>::applies(TNode node) {
template<> inline
Node RewriteRule<LshrByConst>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<LshrByConst>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<LshrByConst>(" << node << ")" << std::endl;
Integer amount = node[1].getConst<BitVector>().toInteger();
Node a = node[0];
@@ -115,7 +115,7 @@ bool RewriteRule<AshrByConst>::applies(TNode node) {
template<> inline
Node RewriteRule<AshrByConst>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<AshrByConst>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<AshrByConst>(" << node << ")" << std::endl;
Integer amount = node[1].getConst<BitVector>().toInteger();
Node a = node[0];
@@ -160,7 +160,7 @@ bool RewriteRule<BitwiseIdemp>::applies(TNode node) {
template<> inline
Node RewriteRule<BitwiseIdemp>::apply(TNode node) {
Unreachable();
- BVDebug("bv-rewrite") << "RewriteRule<BitwiseIdemp>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<BitwiseIdemp>(" << node << ")" << std::endl;
return node[0];
}
@@ -183,7 +183,7 @@ bool RewriteRule<AndZero>::applies(TNode node) {
template<> inline
Node RewriteRule<AndZero>::apply(TNode node) {
Unreachable();
- BVDebug("bv-rewrite") << "RewriteRule<AndZero>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<AndZero>(" << node << ")" << std::endl;
return utils::mkConst(utils::getSize(node), 0);
}
@@ -207,7 +207,7 @@ bool RewriteRule<AndOne>::applies(TNode node) {
template<> inline
Node RewriteRule<AndOne>::apply(TNode node) {
Unreachable();
- BVDebug("bv-rewrite") << "RewriteRule<AndOne>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<AndOne>(" << node << ")" << std::endl;
unsigned size = utils::getSize(node);
if (node[0] == utils::mkOnes(size)) {
@@ -237,7 +237,7 @@ bool RewriteRule<OrZero>::applies(TNode node) {
template<> inline
Node RewriteRule<OrZero>::apply(TNode node) {
Unreachable();
- BVDebug("bv-rewrite") << "RewriteRule<OrZero>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<OrZero>(" << node << ")" << std::endl;
unsigned size = utils::getSize(node);
if (node[0] == utils::mkConst(size, 0)) {
@@ -268,7 +268,7 @@ bool RewriteRule<OrOne>::applies(TNode node) {
template<> inline
Node RewriteRule<OrOne>::apply(TNode node) {
Unreachable();
- BVDebug("bv-rewrite") << "RewriteRule<OrOne>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<OrOne>(" << node << ")" << std::endl;
return utils::mkOnes(utils::getSize(node));
}
@@ -290,7 +290,7 @@ bool RewriteRule<XorDuplicate>::applies(TNode node) {
template<> inline
Node RewriteRule<XorDuplicate>::apply(TNode node) {
Unreachable();
- BVDebug("bv-rewrite") << "RewriteRule<XorDuplicate>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<XorDuplicate>(" << node << ")" << std::endl;
return utils::mkConst(BitVector(utils::getSize(node), Integer(0)));
}
@@ -316,7 +316,7 @@ bool RewriteRule<XorOne>::applies(TNode node) {
template<> inline
Node RewriteRule<XorOne>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<XorOne>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<XorOne>(" << node << ")" << std::endl;
Node ones = utils::mkOnes(utils::getSize(node));
std::vector<Node> children;
bool found_ones = false;
@@ -360,7 +360,7 @@ bool RewriteRule<XorZero>::applies(TNode node) {
template<> inline
Node RewriteRule<XorZero>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<XorZero>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<XorZero>(" << node << ")" << std::endl;
std::vector<Node> children;
Node zero = utils::mkConst(utils::getSize(node), 0);
@@ -393,7 +393,7 @@ bool RewriteRule<BitwiseNotAnd>::applies(TNode node) {
template<> inline
Node RewriteRule<BitwiseNotAnd>::apply(TNode node) {
Unreachable();
- BVDebug("bv-rewrite") << "RewriteRule<BitwiseNegAnd>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<BitwiseNegAnd>(" << node << ")" << std::endl;
return utils::mkConst(BitVector(utils::getSize(node), Integer(0)));
}
@@ -415,7 +415,7 @@ bool RewriteRule<BitwiseNotOr>::applies(TNode node) {
template<> inline
Node RewriteRule<BitwiseNotOr>::apply(TNode node) {
Unreachable();
- BVDebug("bv-rewrite") << "RewriteRule<BitwiseNotOr>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<BitwiseNotOr>(" << node << ")" << std::endl;
uint32_t size = utils::getSize(node);
Integer ones = Integer(1).multiplyByPow2(size) - 1;
return utils::mkConst(BitVector(size, ones));
@@ -435,7 +435,7 @@ bool RewriteRule<XorNot>::applies(TNode node) {
template<> inline
Node RewriteRule<XorNot>::apply(TNode node) {
Unreachable();
- BVDebug("bv-rewrite") << "RewriteRule<XorNot>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<XorNot>(" << node << ")" << std::endl;
Node a = node[0][0];
Node b = node[1][0];
return utils::mkNode(kind::BITVECTOR_XOR, a, b);
@@ -455,7 +455,7 @@ bool RewriteRule<NotXor>::applies(TNode node) {
template<> inline
Node RewriteRule<NotXor>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<NotXor>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<NotXor>(" << node << ")" << std::endl;
std::vector<Node> children;
TNode::iterator child_it = node[0].begin();
children.push_back(utils::mkNode(kind::BITVECTOR_NOT, *child_it));
@@ -479,7 +479,7 @@ bool RewriteRule<NotIdemp>::applies(TNode node) {
template<> inline
Node RewriteRule<NotIdemp>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<XorIdemp>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<XorIdemp>(" << node << ")" << std::endl;
return node[0][0];
}
@@ -500,7 +500,7 @@ bool RewriteRule<LtSelf>::applies(TNode node) {
template<> inline
Node RewriteRule<LtSelf>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<LtSelf>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<LtSelf>(" << node << ")" << std::endl;
return utils::mkFalse();
}
@@ -519,7 +519,7 @@ bool RewriteRule<LteSelf>::applies(TNode node) {
template<> inline
Node RewriteRule<LteSelf>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<LteSelf>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<LteSelf>(" << node << ")" << std::endl;
return utils::mkTrue();
}
@@ -537,7 +537,7 @@ bool RewriteRule<UltZero>::applies(TNode node) {
template<> inline
Node RewriteRule<UltZero>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<UltZero>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<UltZero>(" << node << ")" << std::endl;
return utils::mkFalse();
}
@@ -555,7 +555,7 @@ bool RewriteRule<UltSelf>::applies(TNode node) {
template<> inline
Node RewriteRule<UltSelf>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<UltSelf>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<UltSelf>(" << node << ")" << std::endl;
return utils::mkFalse();
}
@@ -574,7 +574,7 @@ bool RewriteRule<UleZero>::applies(TNode node) {
template<> inline
Node RewriteRule<UleZero>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<UleZero>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<UleZero>(" << node << ")" << std::endl;
return utils::mkNode(kind::EQUAL, node[0], node[1]);
}
@@ -592,7 +592,7 @@ bool RewriteRule<UleSelf>::applies(TNode node) {
template<> inline
Node RewriteRule<UleSelf>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<UleSelf>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<UleSelf>(" << node << ")" << std::endl;
return utils::mkTrue();
}
@@ -611,7 +611,7 @@ bool RewriteRule<ZeroUle>::applies(TNode node) {
template<> inline
Node RewriteRule<ZeroUle>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<ZeroUle>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ZeroUle>(" << node << ")" << std::endl;
return utils::mkTrue();
}
@@ -634,7 +634,7 @@ bool RewriteRule<UleMax>::applies(TNode node) {
template<> inline
Node RewriteRule<UleMax>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<UleMax>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<UleMax>(" << node << ")" << std::endl;
return utils::mkTrue();
}
@@ -652,7 +652,7 @@ bool RewriteRule<NotUlt>::applies(TNode node) {
template<> inline
Node RewriteRule<NotUlt>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<NotUlt>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<NotUlt>(" << node << ")" << std::endl;
Node ult = node[0];
Node a = ult[0];
Node b = ult[1];
@@ -673,7 +673,7 @@ bool RewriteRule<NotUle>::applies(TNode node) {
template<> inline
Node RewriteRule<NotUle>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<NotUle>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<NotUle>(" << node << ")" << std::endl;
Node ult = node[0];
Node a = ult[0];
Node b = ult[1];
@@ -701,7 +701,7 @@ bool RewriteRule<MultPow2>::applies(TNode node) {
template<> inline
Node RewriteRule<MultPow2>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<MultPow2>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<MultPow2>(" << node << ")" << std::endl;
std::vector<Node> children;
unsigned exponent = 0;
@@ -736,7 +736,7 @@ bool RewriteRule<NegIdemp>::applies(TNode node) {
template<> inline
Node RewriteRule<NegIdemp>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<NegIdemp>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<NegIdemp>(" << node << ")" << std::endl;
return node[0][0];
}
@@ -754,7 +754,7 @@ bool RewriteRule<UdivPow2>::applies(TNode node) {
template<> inline
Node RewriteRule<UdivPow2>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<UdivPow2>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<UdivPow2>(" << node << ")" << std::endl;
Node a = node[0];
unsigned power = utils::isPow2Const(node[1]) -1;
@@ -778,7 +778,7 @@ bool RewriteRule<UdivOne>::applies(TNode node) {
template<> inline
Node RewriteRule<UdivOne>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<UdivOne>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<UdivOne>(" << node << ")" << std::endl;
return node[0];
}
@@ -796,7 +796,7 @@ bool RewriteRule<UdivSelf>::applies(TNode node) {
template<> inline
Node RewriteRule<UdivSelf>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<UdivSelf>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<UdivSelf>(" << node << ")" << std::endl;
return utils::mkConst(utils::getSize(node), 1);
}
@@ -814,7 +814,7 @@ bool RewriteRule<UremPow2>::applies(TNode node) {
template<> inline
Node RewriteRule<UremPow2>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<UremPow2>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<UremPow2>(" << node << ")" << std::endl;
TNode a = node[0];
unsigned power = utils::isPow2Const(node[1]) - 1;
if (power == 0) {
@@ -839,7 +839,7 @@ bool RewriteRule<UremOne>::applies(TNode node) {
template<> inline
Node RewriteRule<UremOne>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<UremOne>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<UremOne>(" << node << ")" << std::endl;
return utils::mkConst(utils::getSize(node), 0);
}
@@ -857,7 +857,7 @@ bool RewriteRule<UremSelf>::applies(TNode node) {
template<> inline
Node RewriteRule<UremSelf>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<UremSelf>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<UremSelf>(" << node << ")" << std::endl;
return utils::mkConst(utils::getSize(node), 0);
}
@@ -877,7 +877,7 @@ bool RewriteRule<ShiftZero>::applies(TNode node) {
template<> inline
Node RewriteRule<ShiftZero>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<ShiftZero>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<ShiftZero>(" << node << ")" << std::endl;
return node[0];
}
@@ -905,7 +905,7 @@ bool RewriteRule<BBPlusNeg>::applies(TNode node) {
template<> inline
Node RewriteRule<BBPlusNeg>::apply(TNode node) {
- BVDebug("bv-rewrite") << "RewriteRule<BBPlusNeg>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<BBPlusNeg>(" << node << ")" << std::endl;
std::vector<Node> children;
unsigned neg_count = 0;
@@ -944,7 +944,7 @@ Node RewriteRule<BBPlusNeg>::apply(TNode node) {
// template<> inline
// Node RewriteRule<BBFactorOut>::apply(TNode node) {
-// BVDebug("bv-rewrite") << "RewriteRule<BBFactorOut>(" << node << ")" << std::endl;
+// Debug("bv-rewrite") << "RewriteRule<BBFactorOut>(" << node << ")" << std::endl;
// std::hash_set<TNode, TNodeHashFunction> factors;
// for (unsigned i = 0; i < node.getNumChildren(); ++i) {
@@ -980,7 +980,7 @@ Node RewriteRule<BBPlusNeg>::apply(TNode node) {
// template<> inline
// Node RewriteRule<>::apply(TNode node) {
-// BVDebug("bv-rewrite") << "RewriteRule<>(" << node << ")" << std::endl;
+// Debug("bv-rewrite") << "RewriteRule<>(" << node << ")" << std::endl;
// return ;
// }
diff --git a/src/theory/bv/theory_bv_utils.h b/src/theory/bv/theory_bv_utils.h
index f87163e37..e5a7bbb84 100644
--- a/src/theory/bv/theory_bv_utils.h
+++ b/src/theory/bv/theory_bv_utils.h
@@ -24,12 +24,6 @@
#include <sstream>
#include "expr/node_manager.h"
-#ifdef CVC4_DEBUG
-#define BVDebug(x) Debug(x)
-#else
-#define BVDebug(x) if (false) Debug(x)
-#endif
-
namespace CVC4 {
diff --git a/src/theory/datatypes/theory_datatypes_type_rules.h b/src/theory/datatypes/theory_datatypes_type_rules.h
index ade9ffc26..9b4f24566 100644
--- a/src/theory/datatypes/theory_datatypes_type_rules.h
+++ b/src/theory/datatypes/theory_datatypes_type_rules.h
@@ -285,7 +285,7 @@ struct TupleSelectTypeRule {
const TupleSelect& ts = n.getOperator().getConst<TupleSelect>();
TypeNode tupleType = n[0].getType(check);
if(!tupleType.isTuple()) {
- if(!tupleType.hasAttribute(expr::DatatypeRecordAttr())) {
+ if(!tupleType.hasAttribute(expr::DatatypeTupleAttr())) {
throw TypeCheckingExceptionPrivate(n, "Tuple-select expression formed over non-tuple");
}
tupleType = tupleType.getAttribute(expr::DatatypeTupleAttr());
@@ -309,7 +309,7 @@ struct TupleUpdateTypeRule {
TypeNode newValue = n[1].getType(check);
if(check) {
if(!tupleType.isTuple()) {
- if(!tupleType.hasAttribute(expr::DatatypeRecordAttr())) {
+ if(!tupleType.hasAttribute(expr::DatatypeTupleAttr())) {
throw TypeCheckingExceptionPrivate(n, "Tuple-update expression formed over non-tuple");
}
tupleType = tupleType.getAttribute(expr::DatatypeTupleAttr());
diff --git a/src/theory/datatypes/type_enumerator.h b/src/theory/datatypes/type_enumerator.h
index 2a14d7fba..2a74f6d15 100644
--- a/src/theory/datatypes/type_enumerator.h
+++ b/src/theory/datatypes/type_enumerator.h
@@ -92,23 +92,21 @@ public:
newEnumerators();
}
- DatatypesEnumerator(const DatatypesEnumerator& other) :
- TypeEnumeratorBase<DatatypesEnumerator>(other.getType()),
- d_datatype(other.d_datatype),
- d_ctor(other.d_ctor),
- d_zeroCtor(other.d_zeroCtor),
+ DatatypesEnumerator(const DatatypesEnumerator& de) throw() :
+ TypeEnumeratorBase<DatatypesEnumerator>(de.getType()),
+ d_datatype(de.d_datatype),
+ d_ctor(de.d_ctor),
+ d_zeroCtor(de.d_zeroCtor),
d_argEnumerators(NULL) {
-
- if (other.d_argEnumerators != NULL) {
- d_argEnumerators = new TypeEnumerator*[d_datatype[d_ctor].getNumArgs()];
+
+ if(de.d_argEnumerators != NULL) {
+ newEnumerators();
for(size_t a = 0; a < d_datatype[d_ctor].getNumArgs(); ++a) {
- if (other.d_argEnumerators[a] != NULL) {
- d_argEnumerators[a] = new TypeEnumerator(*other.d_argEnumerators[a]);
- } else {
- d_argEnumerators[a] = NULL;
+ if(de.d_argEnumerators[a] != NULL) {
+ d_argEnumerators[a] = new TypeEnumerator(*de.d_argEnumerators[a]);
}
- }
- }
+ }
+ }
}
~DatatypesEnumerator() throw() {
@@ -139,11 +137,10 @@ public:
DatatypesEnumerator& operator++() throw() {
if(d_ctor < d_datatype.getNumConstructors()) {
for(size_t a = d_datatype[d_ctor].getNumArgs(); a > 0; --a) {
- try {
- *++*d_argEnumerators[a - 1];
- return *this;
- } catch(NoMoreValuesException&) {
+ if((++*d_argEnumerators[a - 1]).isFinished()) {
*d_argEnumerators[a - 1] = TypeEnumerator(Node::fromExpr(d_datatype[d_ctor][a - 1].getSelector()).getType()[1]);
+ } else {
+ return *this;
}
}
@@ -175,6 +172,14 @@ public:
class TupleEnumerator : public TypeEnumeratorBase<TupleEnumerator> {
TypeEnumerator** d_enumerators;
+ /** Allocate and initialize the delegate enumerators */
+ void newEnumerators() {
+ d_enumerators = new TypeEnumerator*[getType().getNumChildren()];
+ for(size_t i = 0; i < getType().getNumChildren(); ++i) {
+ d_enumerators[i] = NULL;
+ }
+ }
+
void deleteEnumerators() throw() {
if(d_enumerators != NULL) {
for(size_t i = 0; i < getType().getNumChildren(); ++i) {
@@ -190,9 +195,20 @@ public:
TupleEnumerator(TypeNode type) throw() :
TypeEnumeratorBase<TupleEnumerator>(type) {
Assert(type.isTuple());
- d_enumerators = new TypeEnumerator*[type.getNumChildren()];
- for(size_t i = 0; i < type.getNumChildren(); ++i) {
- d_enumerators[i] = new TypeEnumerator(type[i]);
+ newEnumerators();
+ }
+
+ TupleEnumerator(const TupleEnumerator& te) throw() :
+ TypeEnumeratorBase<TupleEnumerator>(te.getType()),
+ d_enumerators(NULL) {
+
+ if(te.d_enumerators != NULL) {
+ newEnumerators();
+ for(size_t i = 0; i < getType().getNumChildren(); ++i) {
+ if(te.d_enumerators[i] != NULL) {
+ d_enumerators[i] = new TypeEnumerator(*te.d_enumerators[i]);
+ }
+ }
}
}
@@ -241,9 +257,19 @@ public:
class RecordEnumerator : public TypeEnumeratorBase<RecordEnumerator> {
TypeEnumerator** d_enumerators;
+ /** Allocate and initialize the delegate enumerators */
+ void newEnumerators() {
+ const Record& rec = getType().getConst<Record>();
+ d_enumerators = new TypeEnumerator*[rec.getNumFields()];
+ for(size_t i = 0; i < rec.getNumFields(); ++i) {
+ d_enumerators[i] = new TypeEnumerator(TypeNode::fromType(rec[i].second));
+ }
+ }
+
void deleteEnumerators() throw() {
if(d_enumerators != NULL) {
- for(size_t i = 0; i < getType().getNumChildren(); ++i) {
+ const Record& rec = getType().getConst<Record>();
+ for(size_t i = 0; i < rec.getNumFields(); ++i) {
delete d_enumerators[i];
}
delete [] d_enumerators;
@@ -256,12 +282,20 @@ public:
RecordEnumerator(TypeNode type) throw() :
TypeEnumeratorBase<RecordEnumerator>(type) {
Assert(type.isRecord());
- const Record& rec = getType().getConst<Record>();
- Debug("te") << "creating record enumerator for " << type << std::endl;
- d_enumerators = new TypeEnumerator*[rec.getNumFields()];
- for(size_t i = 0; i < rec.getNumFields(); ++i) {
- Debug("te") << " - sub-enumerator for " << rec[i].second << std::endl;
- d_enumerators[i] = new TypeEnumerator(TypeNode::fromType(rec[i].second));
+ newEnumerators();
+ }
+
+ RecordEnumerator(const RecordEnumerator& re) throw() :
+ TypeEnumeratorBase<RecordEnumerator>(re.getType()),
+ d_enumerators(NULL) {
+
+ if(re.d_enumerators != NULL) {
+ newEnumerators();
+ for(size_t i = 0; i < getType().getNumChildren(); ++i) {
+ if(re.d_enumerators[i] != NULL) {
+ d_enumerators[i] = new TypeEnumerator(*re.d_enumerators[i]);
+ }
+ }
}
}
diff --git a/src/theory/mkrewriter b/src/theory/mkrewriter
index 88ac5b9fb..2d8012bfb 100755
--- a/src/theory/mkrewriter
+++ b/src/theory/mkrewriter
@@ -2,7 +2,7 @@
#
# mkrewriter
# Morgan Deters <mdeters@cs.nyu.edu> for CVC4
-# Copyright (c) 2010-2012 The CVC4 Project
+# Copyright (c) 2010-2013 The CVC4 Project
#
# The purpose of this script is to create rewriter_tables.h from a template
# and a list of theory kinds.
@@ -14,13 +14,14 @@
# Output is to standard out.
#
-copyright=2010-2012
+copyright=2010-2013
cat <<EOF
/********************* */
/** rewriter_tables.h
**
- ** Copyright $copyright The AcSys Group, New York University, and as below.
+ ** Copyright $copyright New York University and The University of Iowa,
+ ** and as below.
**
** This header file automatically generated by:
**
diff --git a/src/theory/mktheorytraits b/src/theory/mktheorytraits
index a44d8e9c3..3edc7c140 100755
--- a/src/theory/mktheorytraits
+++ b/src/theory/mktheorytraits
@@ -2,7 +2,7 @@
#
# mktheorytraits
# Morgan Deters <mdeters@cs.nyu.edu> for CVC4
-# Copyright (c) 2010-2012 The CVC4 Project
+# Copyright (c) 2010-2013 The CVC4 Project
#
# The purpose of this script is to create theory_traits.h from a template
# and a list of theory kinds.
@@ -14,7 +14,7 @@
# Output is to standard out.
#
-copyright=2010-2012
+copyright=2010-2013
filename=`basename "$1" | sed 's,_template,,'`
@@ -22,7 +22,8 @@ cat <<EOF
/********************* */
/** $filename
**
- ** Copyright $copyright The AcSys Group, New York University, and as below.
+ ** Copyright $copyright New York University and The University of Iowa,
+ ** and as below.
**
** This header file automatically generated by:
**
diff --git a/src/theory/model.cpp b/src/theory/model.cpp
index 713587be2..bbc51c9e0 100644
--- a/src/theory/model.cpp
+++ b/src/theory/model.cpp
@@ -395,6 +395,9 @@ bool TheoryEngineModelBuilder::isAssignable(TNode n)
void TheoryEngineModelBuilder::checkTerms(TNode n, TheoryModel* tm, NodeSet& cache)
{
+ if (n.getKind()==FORALL || n.getKind()==EXISTS) {
+ return;
+ }
if (cache.find(n) != cache.end()) {
return;
}
diff --git a/src/theory/model.h b/src/theory/model.h
index e283ee183..98eeda97a 100644
--- a/src/theory/model.h
+++ b/src/theory/model.h
@@ -87,7 +87,7 @@ public:
void addSubstitution(TNode x, TNode t, bool invalidateCache = true);
/** add term function
* addTerm( n ) will do any model-specific processing necessary for n,
- * such as contraining the interpretation of uninterpretted functions,
+ * such as constraining the interpretation of uninterpreted functions,
* and adding n to the equality engine of this model
*/
virtual void addTerm(TNode n);
diff --git a/src/theory/quantifiers/inst_gen.cpp b/src/theory/quantifiers/inst_gen.cpp
index d3bd6ad03..dea371e9c 100755..100644
--- a/src/theory/quantifiers/inst_gen.cpp
+++ b/src/theory/quantifiers/inst_gen.cpp
@@ -1,298 +1,296 @@
-/********************* */
-/*! \file inst_gen.cpp
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Implementation of inst gen classes
- **/
-
-#include "theory/quantifiers/inst_gen.h"
-#include "theory/quantifiers/model_engine.h"
-#include "theory/quantifiers/model_builder.h"
-#include "theory/quantifiers/first_order_model.h"
-
-//#define CHILD_USE_CONSIDER
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::quantifiers;
-
-
-
-InstGenProcess::InstGenProcess( Node n ) : d_node( n ){
- Assert( n.hasAttribute(InstConstantAttribute()) );
- int count = 0;
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- if( n[i].getKind()!=INST_CONSTANT && n[i].hasAttribute(InstConstantAttribute()) ){
- d_children.push_back( InstGenProcess( n[i] ) );
- d_children_index.push_back( i );
- d_children_map[ i ] = count;
- count++;
- }
- }
-}
-
-void InstGenProcess::addMatchValue( QuantifiersEngine* qe, Node f, Node val, InstMatch& m ){
- if( !qe->existsInstantiation( f, m, true ) ){
- //make sure no duplicates are produced
- if( d_inst_trie[val].addInstMatch( qe, f, m, true ) ){
- d_match_values.push_back( val );
- d_matches.push_back( InstMatch( &m ) );
- qe->getModelEngine()->getModelBuilder()->d_instGenMatches++;
- }
- }
-}
-
-void InstGenProcess::calculateMatches( QuantifiersEngine* qe, Node f, std::vector< Node >& considerVal, bool useConsider ){
- Trace("inst-gen-cm") << "* Calculate matches " << d_node << std::endl;
- //whether we are doing a product or sum or matches
- bool doProduct = true;
- //get the model
- FirstOrderModel* fm = qe->getModel();
-
- //calculate terms we will consider
- std::vector< Node > considerTerms;
- std::vector< std::vector< Node > > newConsiderVal;
- std::vector< bool > newUseConsider;
- std::map< Node, InstMatch > considerTermsMatch[2];
- std::map< Node, bool > considerTermsSuccess[2];
- newConsiderVal.resize( d_children.size() );
- newUseConsider.resize( d_children.size(), useConsider );
- if( d_node.getKind()==APPLY_UF ){
- Node op = d_node.getOperator();
- if( useConsider ){
-#ifndef CHILD_USE_CONSIDER
- for( size_t i=0; i<newUseConsider.size(); i++ ){
- newUseConsider[i] = false;
- }
-#endif
- for( size_t i=0; i<considerVal.size(); i++ ){
- eq::EqClassIterator eqc( qe->getEqualityQuery()->getEngine()->getRepresentative( considerVal[i] ),
- qe->getEqualityQuery()->getEngine() );
- while( !eqc.isFinished() ){
- Node en = (*eqc);
- if( en.getKind()==APPLY_UF && en.getOperator()==op ){
- considerTerms.push_back( en );
- }
- ++eqc;
- }
- }
- }else{
- considerTerms.insert( considerTerms.begin(), fm->d_uf_terms[op].begin(), fm->d_uf_terms[op].end() );
- }
- //for each term we consider, calculate a current match
- for( size_t i=0; i<considerTerms.size(); i++ ){
- Node n = considerTerms[i];
- bool isSelected = qe->getModelEngine()->getModelBuilder()->isTermSelected( n );
- bool hadSuccess CVC4_UNUSED = false;
- for( int t=(isSelected ? 0 : 1); t<2; t++ ){
- if( t==0 || !n.getAttribute(NoMatchAttribute()) ){
- considerTermsMatch[t][n] = InstMatch();
- considerTermsSuccess[t][n] = true;
- for( size_t j=0; j<d_node.getNumChildren(); j++ ){
- if( d_children_map.find( j )==d_children_map.end() ){
- if( t!=0 || !n[j].getAttribute(ModelBasisAttribute()) ){
- if( d_node[j].getKind()==INST_CONSTANT ){
- if( !considerTermsMatch[t][n].setMatch( qe->getEqualityQuery(), d_node[j], n[j] ) ){
- Trace("inst-gen-cm") << "fail match: " << n[j] << " is not equal to ";
- Trace("inst-gen-cm") << considerTermsMatch[t][n].getValue( d_node[j] ) << std::endl;
- considerTermsSuccess[t][n] = false;
- break;
- }
- }else if( !qe->getEqualityQuery()->areEqual( d_node[j], n[j] ) ){
- Trace("inst-gen-cm") << "fail arg: " << n[j] << " is not equal to " << d_node[j] << std::endl;
- considerTermsSuccess[t][n] = false;
- break;
- }
- }
- }
- }
- //if successful, store it
- if( considerTermsSuccess[t][n] ){
-#ifdef CHILD_USE_CONSIDER
- if( !hadSuccess ){
- hadSuccess = true;
- for( size_t k=0; k<d_children.size(); k++ ){
- if( newUseConsider[k] ){
- int childIndex = d_children_index[k];
- //determine if we are restricted or not
- if( t!=0 || !n[childIndex].getAttribute(ModelBasisAttribute()) ){
- Node r = qe->getModel()->getRepresentative( n[childIndex] );
- if( std::find( newConsiderVal[k].begin(), newConsiderVal[k].end(), r )==newConsiderVal[k].end() ){
- newConsiderVal[k].push_back( r );
- //check if we now need to consider the entire domain
- TypeNode tn = r.getType();
- if( qe->getModel()->d_rep_set.hasType( tn ) ){
- if( (int)newConsiderVal[k].size()>=qe->getModel()->d_rep_set.getNumRepresentatives( tn ) ){
- newConsiderVal[k].clear();
- newUseConsider[k] = false;
- }
- }
- }
- }else{
- //matching against selected term, will need to consider all values
- newConsiderVal[k].clear();
- newUseConsider[k] = false;
- }
- }
- }
- }
-#endif
- }
- }
- }
- }
- }else{
- //the interpretted case
- if( d_node.getType().isBoolean() ){
- if( useConsider ){
- //if( considerVal.size()!=1 ) { std::cout << "consider val = " << considerVal.size() << std::endl; }
- Assert( considerVal.size()==1 );
- bool reqPol = considerVal[0]==fm->d_true;
- Node ncv = considerVal[0];
- if( d_node.getKind()==NOT ){
- ncv = reqPol ? fm->d_false : fm->d_true;
- }
- if( d_node.getKind()==NOT || d_node.getKind()==AND || d_node.getKind()==OR ){
- for( size_t i=0; i<newConsiderVal.size(); i++ ){
- newConsiderVal[i].push_back( ncv );
- }
- //instead we will do a sum
- if( ( d_node.getKind()==AND && !reqPol ) || ( d_node.getKind()==OR && reqPol ) ){
- doProduct = false;
- }
- }else{
- //do not use consider
- for( size_t i=0; i<newUseConsider.size(); i++ ){
- newUseConsider[i] = false;
- }
- }
- }
- }
- }
-
- //calculate all matches for children
- for( int i=0; i<(int)d_children.size(); i++ ){
- d_children[i].calculateMatches( qe, f, newConsiderVal[i], newUseConsider[i] );
- if( doProduct && d_children[i].getNumMatches()==0 ){
- return;
- }
- }
- if( d_node.getKind()==APPLY_UF ){
- //if this is an uninterpreted function
- Node op = d_node.getOperator();
- //process all values
- for( size_t i=0; i<considerTerms.size(); i++ ){
- Node n = considerTerms[i];
- bool isSelected = qe->getModelEngine()->getModelBuilder()->isTermSelected( n );
- for( int t=(isSelected ? 0 : 1); t<2; t++ ){
- //do not consider ground case if it is already congruent to another ground term
- if( t==0 || !n.getAttribute(NoMatchAttribute()) ){
- Trace("inst-gen-cm") << "calculate for " << n << ", selected = " << (t==0) << std::endl;
- if( considerTermsSuccess[t][n] ){
- //try to find unifier for d_node = n
- calculateMatchesUninterpreted( qe, f, considerTermsMatch[t][n], n, 0, t==0 );
- }
- }
- }
- }
- }else{
- //if this is an interpreted function
- if( doProduct ){
- //combining children matches
- InstMatch curr;
- std::vector< Node > terms;
- calculateMatchesInterpreted( qe, f, curr, terms, 0 );
- }else{
- //summing children matches
- Assert( considerVal.size()==1 );
- for( int i=0; i<(int)d_children.size(); i++ ){
- for( int j=0; j<(int)d_children[ i ].getNumMatches(); j++ ){
- InstMatch m;
- if( d_children[ i ].getMatch( qe->getEqualityQuery(), j, m ) ){
- addMatchValue( qe, f, considerVal[0], m );
- }
- }
- }
- }
- }
- Trace("inst-gen-cm") << "done calculate matches" << std::endl;
- //can clear information used for finding duplicates
- d_inst_trie.clear();
-}
-
-bool InstGenProcess::getMatch( EqualityQuery* q, int i, InstMatch& m ){
- //FIXME: is this correct? (query may not be accurate)
- return m.merge( q, d_matches[i] );
-}
-
-void InstGenProcess::calculateMatchesUninterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, Node n, int childIndex, bool isSelected ){
- if( childIndex==(int)d_children.size() ){
- Node val = qe->getModel()->getRepresentative( n ); //FIXME: is this correct?
- Trace("inst-gen-cm") << " - u-match : " << val << std::endl;
- Trace("inst-gen-cm") << " : " << curr << std::endl;
- addMatchValue( qe, f, val, curr );
- }else{
- Trace("inst-gen-cm") << "Consider child index = " << childIndex << ", against ground term argument " << d_children_index[childIndex] << " ... " << n[d_children_index[childIndex]] << std::endl;
- bool sel = ( isSelected && n[d_children_index[childIndex]].getAttribute(ModelBasisAttribute()) );
- for( int i=0; i<(int)d_children[ childIndex ].getNumMatches(); i++ ){
- //FIXME: is this correct?
- if( sel || qe->getEqualityQuery()->areEqual( d_children[ childIndex ].getMatchValue( i ), n[d_children_index[childIndex]] ) ){
- InstMatch next( &curr );
- if( d_children[ childIndex ].getMatch( qe->getEqualityQuery(), i, next ) ){
- calculateMatchesUninterpreted( qe, f, next, n, childIndex+1, isSelected );
- }else{
- Trace("inst-gen-cm") << curr << " not equal to " << d_children[ childIndex ].d_matches[i] << std::endl;
- Trace("inst-gen-cm") << childIndex << " match " << i << " not equal subs." << std::endl;
- }
- }else{
- Trace("inst-gen-cm") << childIndex << " match " << i << " not equal value." << std::endl;
- }
- }
- }
-}
-
-void InstGenProcess::calculateMatchesInterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, std::vector< Node >& terms, int argIndex ){
- FirstOrderModel* fm = qe->getModel();
- if( argIndex==(int)d_node.getNumChildren() ){
- Node val;
- if( d_node.getNumChildren()==0 ){
- val = d_node;
- }else if( d_node.getKind()==EQUAL ){
- val = qe->getEqualityQuery()->areEqual( terms[0], terms[1] ) ? fm->d_true : fm->d_false;
- }else{
- val = NodeManager::currentNM()->mkNode( d_node.getKind(), terms );
- val = Rewriter::rewrite( val );
- }
- Trace("inst-gen-cm") << " - i-match : " << d_node << std::endl;
- Trace("inst-gen-cm") << " : " << val << std::endl;
- Trace("inst-gen-cm") << " : " << curr << std::endl;
- addMatchValue( qe, f, val, curr );
- }else{
- if( d_children_map.find( argIndex )==d_children_map.end() ){
- terms.push_back( fm->getRepresentative( d_node[argIndex] ) );
- calculateMatchesInterpreted( qe, f, curr, terms, argIndex+1 );
- terms.pop_back();
- }else{
- for( int i=0; i<(int)d_children[ d_children_map[argIndex] ].getNumMatches(); i++ ){
- InstMatch next( &curr );
- if( d_children[ d_children_map[argIndex] ].getMatch( qe->getEqualityQuery(), i, next ) ){
- terms.push_back( d_children[ d_children_map[argIndex] ].getMatchValue( i ) );
- calculateMatchesInterpreted( qe, f, next, terms, argIndex+1 );
- terms.pop_back();
- }
- }
- }
- }
-}
+/********************* */
+/*! \file inst_gen.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Implementation of inst gen classes
+ **/
+
+#include "theory/quantifiers/inst_gen.h"
+#include "theory/quantifiers/model_engine.h"
+#include "theory/quantifiers/model_builder.h"
+#include "theory/quantifiers/first_order_model.h"
+
+//#define CHILD_USE_CONSIDER
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+
+
+
+InstGenProcess::InstGenProcess( Node n ) : d_node( n ){
+ Assert( n.hasAttribute(InstConstantAttribute()) );
+ int count = 0;
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ if( n[i].getKind()!=INST_CONSTANT && n[i].hasAttribute(InstConstantAttribute()) ){
+ d_children.push_back( InstGenProcess( n[i] ) );
+ d_children_index.push_back( i );
+ d_children_map[ i ] = count;
+ count++;
+ }
+ }
+}
+
+void InstGenProcess::addMatchValue( QuantifiersEngine* qe, Node f, Node val, InstMatch& m ){
+ if( !qe->existsInstantiation( f, m, true ) ){
+ //make sure no duplicates are produced
+ if( d_inst_trie[val].addInstMatch( qe, f, m, true ) ){
+ d_match_values.push_back( val );
+ d_matches.push_back( InstMatch( &m ) );
+ qe->getModelEngine()->getModelBuilder()->d_instGenMatches++;
+ }
+ }
+}
+
+void InstGenProcess::calculateMatches( QuantifiersEngine* qe, Node f, std::vector< Node >& considerVal, bool useConsider ){
+ Trace("inst-gen-cm") << "* Calculate matches " << d_node << std::endl;
+ //whether we are doing a product or sum or matches
+ bool doProduct = true;
+ //get the model
+ FirstOrderModel* fm = qe->getModel();
+
+ //calculate terms we will consider
+ std::vector< Node > considerTerms;
+ std::vector< std::vector< Node > > newConsiderVal;
+ std::vector< bool > newUseConsider;
+ std::map< Node, InstMatch > considerTermsMatch[2];
+ std::map< Node, bool > considerTermsSuccess[2];
+ newConsiderVal.resize( d_children.size() );
+ newUseConsider.resize( d_children.size(), useConsider );
+ if( d_node.getKind()==APPLY_UF ){
+ Node op = d_node.getOperator();
+ if( useConsider ){
+#ifndef CHILD_USE_CONSIDER
+ for( size_t i=0; i<newUseConsider.size(); i++ ){
+ newUseConsider[i] = false;
+ }
+#endif
+ for( size_t i=0; i<considerVal.size(); i++ ){
+ eq::EqClassIterator eqc( qe->getEqualityQuery()->getEngine()->getRepresentative( considerVal[i] ),
+ qe->getEqualityQuery()->getEngine() );
+ while( !eqc.isFinished() ){
+ Node en = (*eqc);
+ if( en.getKind()==APPLY_UF && en.getOperator()==op ){
+ considerTerms.push_back( en );
+ }
+ ++eqc;
+ }
+ }
+ }else{
+ considerTerms.insert( considerTerms.begin(), fm->d_uf_terms[op].begin(), fm->d_uf_terms[op].end() );
+ }
+ //for each term we consider, calculate a current match
+ for( size_t i=0; i<considerTerms.size(); i++ ){
+ Node n = considerTerms[i];
+ bool isSelected = qe->getModelEngine()->getModelBuilder()->isTermSelected( n );
+ bool hadSuccess CVC4_UNUSED = false;
+ for( int t=(isSelected ? 0 : 1); t<2; t++ ){
+ if( t==0 || !n.getAttribute(NoMatchAttribute()) ){
+ considerTermsMatch[t][n] = InstMatch();
+ considerTermsSuccess[t][n] = true;
+ for( size_t j=0; j<d_node.getNumChildren(); j++ ){
+ if( d_children_map.find( j )==d_children_map.end() ){
+ if( t!=0 || !n[j].getAttribute(ModelBasisAttribute()) ){
+ if( d_node[j].getKind()==INST_CONSTANT ){
+ if( !considerTermsMatch[t][n].setMatch( qe->getEqualityQuery(), d_node[j], n[j] ) ){
+ Trace("inst-gen-cm") << "fail match: " << n[j] << " is not equal to ";
+ Trace("inst-gen-cm") << considerTermsMatch[t][n].getValue( d_node[j] ) << std::endl;
+ considerTermsSuccess[t][n] = false;
+ break;
+ }
+ }else if( !qe->getEqualityQuery()->areEqual( d_node[j], n[j] ) ){
+ Trace("inst-gen-cm") << "fail arg: " << n[j] << " is not equal to " << d_node[j] << std::endl;
+ considerTermsSuccess[t][n] = false;
+ break;
+ }
+ }
+ }
+ }
+ //if successful, store it
+ if( considerTermsSuccess[t][n] ){
+#ifdef CHILD_USE_CONSIDER
+ if( !hadSuccess ){
+ hadSuccess = true;
+ for( size_t k=0; k<d_children.size(); k++ ){
+ if( newUseConsider[k] ){
+ int childIndex = d_children_index[k];
+ //determine if we are restricted or not
+ if( t!=0 || !n[childIndex].getAttribute(ModelBasisAttribute()) ){
+ Node r = qe->getModel()->getRepresentative( n[childIndex] );
+ if( std::find( newConsiderVal[k].begin(), newConsiderVal[k].end(), r )==newConsiderVal[k].end() ){
+ newConsiderVal[k].push_back( r );
+ //check if we now need to consider the entire domain
+ TypeNode tn = r.getType();
+ if( qe->getModel()->d_rep_set.hasType( tn ) ){
+ if( (int)newConsiderVal[k].size()>=qe->getModel()->d_rep_set.getNumRepresentatives( tn ) ){
+ newConsiderVal[k].clear();
+ newUseConsider[k] = false;
+ }
+ }
+ }
+ }else{
+ //matching against selected term, will need to consider all values
+ newConsiderVal[k].clear();
+ newUseConsider[k] = false;
+ }
+ }
+ }
+ }
+#endif
+ }
+ }
+ }
+ }
+ }else{
+ //the interpretted case
+ if( d_node.getType().isBoolean() ){
+ if( useConsider ){
+ //if( considerVal.size()!=1 ) { std::cout << "consider val = " << considerVal.size() << std::endl; }
+ Assert( considerVal.size()==1 );
+ bool reqPol = considerVal[0]==fm->d_true;
+ Node ncv = considerVal[0];
+ if( d_node.getKind()==NOT ){
+ ncv = reqPol ? fm->d_false : fm->d_true;
+ }
+ if( d_node.getKind()==NOT || d_node.getKind()==AND || d_node.getKind()==OR ){
+ for( size_t i=0; i<newConsiderVal.size(); i++ ){
+ newConsiderVal[i].push_back( ncv );
+ }
+ //instead we will do a sum
+ if( ( d_node.getKind()==AND && !reqPol ) || ( d_node.getKind()==OR && reqPol ) ){
+ doProduct = false;
+ }
+ }else{
+ //do not use consider
+ for( size_t i=0; i<newUseConsider.size(); i++ ){
+ newUseConsider[i] = false;
+ }
+ }
+ }
+ }
+ }
+
+ //calculate all matches for children
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ d_children[i].calculateMatches( qe, f, newConsiderVal[i], newUseConsider[i] );
+ if( doProduct && d_children[i].getNumMatches()==0 ){
+ return;
+ }
+ }
+ if( d_node.getKind()==APPLY_UF ){
+ //if this is an uninterpreted function
+ Node op = d_node.getOperator();
+ //process all values
+ for( size_t i=0; i<considerTerms.size(); i++ ){
+ Node n = considerTerms[i];
+ bool isSelected = qe->getModelEngine()->getModelBuilder()->isTermSelected( n );
+ for( int t=(isSelected ? 0 : 1); t<2; t++ ){
+ //do not consider ground case if it is already congruent to another ground term
+ if( t==0 || !n.getAttribute(NoMatchAttribute()) ){
+ Trace("inst-gen-cm") << "calculate for " << n << ", selected = " << (t==0) << std::endl;
+ if( considerTermsSuccess[t][n] ){
+ //try to find unifier for d_node = n
+ calculateMatchesUninterpreted( qe, f, considerTermsMatch[t][n], n, 0, t==0 );
+ }
+ }
+ }
+ }
+ }else{
+ //if this is an interpreted function
+ if( doProduct ){
+ //combining children matches
+ InstMatch curr;
+ std::vector< Node > terms;
+ calculateMatchesInterpreted( qe, f, curr, terms, 0 );
+ }else{
+ //summing children matches
+ Assert( considerVal.size()==1 );
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ for( int j=0; j<(int)d_children[ i ].getNumMatches(); j++ ){
+ InstMatch m;
+ if( d_children[ i ].getMatch( qe->getEqualityQuery(), j, m ) ){
+ addMatchValue( qe, f, considerVal[0], m );
+ }
+ }
+ }
+ }
+ }
+ Trace("inst-gen-cm") << "done calculate matches" << std::endl;
+ //can clear information used for finding duplicates
+ d_inst_trie.clear();
+}
+
+bool InstGenProcess::getMatch( EqualityQuery* q, int i, InstMatch& m ){
+ //FIXME: is this correct? (query may not be accurate)
+ return m.merge( q, d_matches[i] );
+}
+
+void InstGenProcess::calculateMatchesUninterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, Node n, int childIndex, bool isSelected ){
+ if( childIndex==(int)d_children.size() ){
+ Node val = qe->getModel()->getRepresentative( n ); //FIXME: is this correct?
+ Trace("inst-gen-cm") << " - u-match : " << val << std::endl;
+ Trace("inst-gen-cm") << " : " << curr << std::endl;
+ addMatchValue( qe, f, val, curr );
+ }else{
+ Trace("inst-gen-cm") << "Consider child index = " << childIndex << ", against ground term argument " << d_children_index[childIndex] << " ... " << n[d_children_index[childIndex]] << std::endl;
+ bool sel = ( isSelected && n[d_children_index[childIndex]].getAttribute(ModelBasisAttribute()) );
+ for( int i=0; i<(int)d_children[ childIndex ].getNumMatches(); i++ ){
+ //FIXME: is this correct?
+ if( sel || qe->getEqualityQuery()->areEqual( d_children[ childIndex ].getMatchValue( i ), n[d_children_index[childIndex]] ) ){
+ InstMatch next( &curr );
+ if( d_children[ childIndex ].getMatch( qe->getEqualityQuery(), i, next ) ){
+ calculateMatchesUninterpreted( qe, f, next, n, childIndex+1, isSelected );
+ }else{
+ Trace("inst-gen-cm") << curr << " not equal to " << d_children[ childIndex ].d_matches[i] << std::endl;
+ Trace("inst-gen-cm") << childIndex << " match " << i << " not equal subs." << std::endl;
+ }
+ }else{
+ Trace("inst-gen-cm") << childIndex << " match " << i << " not equal value." << std::endl;
+ }
+ }
+ }
+}
+
+void InstGenProcess::calculateMatchesInterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, std::vector< Node >& terms, int argIndex ){
+ FirstOrderModel* fm = qe->getModel();
+ if( argIndex==(int)d_node.getNumChildren() ){
+ Node val;
+ if( d_node.getNumChildren()==0 ){
+ val = d_node;
+ }else if( d_node.getKind()==EQUAL ){
+ val = qe->getEqualityQuery()->areEqual( terms[0], terms[1] ) ? fm->d_true : fm->d_false;
+ }else{
+ val = NodeManager::currentNM()->mkNode( d_node.getKind(), terms );
+ val = Rewriter::rewrite( val );
+ }
+ Trace("inst-gen-cm") << " - i-match : " << d_node << std::endl;
+ Trace("inst-gen-cm") << " : " << val << std::endl;
+ Trace("inst-gen-cm") << " : " << curr << std::endl;
+ addMatchValue( qe, f, val, curr );
+ }else{
+ if( d_children_map.find( argIndex )==d_children_map.end() ){
+ terms.push_back( fm->getRepresentative( d_node[argIndex] ) );
+ calculateMatchesInterpreted( qe, f, curr, terms, argIndex+1 );
+ terms.pop_back();
+ }else{
+ for( int i=0; i<(int)d_children[ d_children_map[argIndex] ].getNumMatches(); i++ ){
+ InstMatch next( &curr );
+ if( d_children[ d_children_map[argIndex] ].getMatch( qe->getEqualityQuery(), i, next ) ){
+ terms.push_back( d_children[ d_children_map[argIndex] ].getMatchValue( i ) );
+ calculateMatchesInterpreted( qe, f, next, terms, argIndex+1 );
+ terms.pop_back();
+ }
+ }
+ }
+ }
+}
diff --git a/src/theory/quantifiers/inst_gen.h b/src/theory/quantifiers/inst_gen.h
index f6e6a372e..930133954 100755..100644
--- a/src/theory/quantifiers/inst_gen.h
+++ b/src/theory/quantifiers/inst_gen.h
@@ -1,61 +1,59 @@
-/********************* */
-/*! \file inst_gen.h
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Inst Gen classes
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__THEORY__QUANTIFIERS__INST_GEN_H
-#define __CVC4__THEORY__QUANTIFIERS__INST_GEN_H
-
-#include "theory/quantifiers_engine.h"
-#include "theory/quantifiers/inst_match.h"
-
-namespace CVC4 {
-namespace theory {
-namespace quantifiers {
-
-class InstGenProcess
-{
-private:
- //the node we are processing
- Node d_node;
- //the sub children for this node
- std::vector< InstGenProcess > d_children;
- std::vector< int > d_children_index;
- std::map< int, int > d_children_map;
- //the matches we have produced
- std::vector< InstMatch > d_matches;
- std::vector< Node > d_match_values;
- //add match value
- std::map< Node, inst::InstMatchTrie > d_inst_trie;
- void addMatchValue( QuantifiersEngine* qe, Node f, Node val, InstMatch& m );
-private:
- void calculateMatchesUninterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, Node n, int childIndex, bool isSelected );
- void calculateMatchesInterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, std::vector< Node >& terms, int argIndex );
-public:
- InstGenProcess( Node n );
- virtual ~InstGenProcess(){}
-
- void calculateMatches( QuantifiersEngine* qe, Node f, std::vector< Node >& considerVal, bool useConsider );
- int getNumMatches() { return d_matches.size(); }
- bool getMatch( EqualityQuery* q, int i, InstMatch& m );
- Node getMatchValue( int i ) { return d_match_values[i]; }
-};
-
-}
-}
-}
-
-#endif
+/********************* */
+/*! \file inst_gen.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Inst Gen classes
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANTIFIERS__INST_GEN_H
+#define __CVC4__THEORY__QUANTIFIERS__INST_GEN_H
+
+#include "theory/quantifiers_engine.h"
+#include "theory/quantifiers/inst_match.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+class InstGenProcess
+{
+private:
+ //the node we are processing
+ Node d_node;
+ //the sub children for this node
+ std::vector< InstGenProcess > d_children;
+ std::vector< int > d_children_index;
+ std::map< int, int > d_children_map;
+ //the matches we have produced
+ std::vector< InstMatch > d_matches;
+ std::vector< Node > d_match_values;
+ //add match value
+ std::map< Node, inst::InstMatchTrie > d_inst_trie;
+ void addMatchValue( QuantifiersEngine* qe, Node f, Node val, InstMatch& m );
+private:
+ void calculateMatchesUninterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, Node n, int childIndex, bool isSelected );
+ void calculateMatchesInterpreted( QuantifiersEngine* qe, Node f, InstMatch& curr, std::vector< Node >& terms, int argIndex );
+public:
+ InstGenProcess( Node n );
+ virtual ~InstGenProcess(){}
+
+ void calculateMatches( QuantifiersEngine* qe, Node f, std::vector< Node >& considerVal, bool useConsider );
+ int getNumMatches() { return d_matches.size(); }
+ bool getMatch( EqualityQuery* q, int i, InstMatch& m );
+ Node getMatchValue( int i ) { return d_match_values[i]; }
+};/* 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.cpp b/src/theory/quantifiers/inst_match.cpp
index dcd7a1b79..85a96f90a 100644
--- a/src/theory/quantifiers/inst_match.cpp
+++ b/src/theory/quantifiers/inst_match.cpp
@@ -103,12 +103,12 @@ void InstMatch::makeComplete( Node f, QuantifiersEngine* qe ){
}
}
-void InstMatch::makeInternalRepresentative( QuantifiersEngine* qe ){
- EqualityQueryQuantifiersEngine* eqqe = (EqualityQueryQuantifiersEngine*)qe->getEqualityQuery();
- for( std::map< Node, Node >::iterator it = d_map.begin(); it != d_map.end(); ++it ){
- d_map[ it->first ] = eqqe->getInternalRepresentative( it->second );
- }
-}
+//void InstMatch::makeInternalRepresentative( QuantifiersEngine* qe ){
+// EqualityQueryQuantifiersEngine* eqqe = (EqualityQueryQuantifiersEngine*)qe->getEqualityQuery();
+// for( std::map< Node, Node >::iterator it = d_map.begin(); it != d_map.end(); ++it ){
+// d_map[ it->first ] = eqqe->getInternalRepresentative( it->second );
+// }
+//}
void InstMatch::makeRepresentative( QuantifiersEngine* qe ){
for( std::map< Node, Node >::iterator it = d_map.begin(); it != d_map.end(); ++it ){
diff --git a/src/theory/quantifiers/inst_match.h b/src/theory/quantifiers/inst_match.h
index 8b2d9726b..b9e61be20 100644
--- a/src/theory/quantifiers/inst_match.h
+++ b/src/theory/quantifiers/inst_match.h
@@ -58,7 +58,7 @@ public:
/** make complete */
void makeComplete( Node f, QuantifiersEngine* qe );
/** make internal representative */
- void makeInternalRepresentative( QuantifiersEngine* qe );
+ //void makeInternalRepresentative( QuantifiersEngine* qe );
/** make representative */
void makeRepresentative( QuantifiersEngine* qe );
/** get value */
diff --git a/src/theory/quantifiers/inst_match_generator.cpp b/src/theory/quantifiers/inst_match_generator.cpp
index 3b5e594fb..5484e25e9 100755..100644
--- a/src/theory/quantifiers/inst_match_generator.cpp
+++ b/src/theory/quantifiers/inst_match_generator.cpp
@@ -1,664 +1,658 @@
-/********************* */
-/*! \file inst_match_generator.cpp
-** \verbatim
-** Original author: ajreynol
-** Major contributors: bobot
-** Minor contributors (to current version): barrett, mdeters
-** This file is part of the CVC4 prototype.
-** Copyright (c) 2009-2012 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 match generator class
-**/
-
-#include "theory/quantifiers/inst_match_generator.h"
-#include "theory/quantifiers/trigger.h"
-#include "theory/quantifiers/term_database.h"
-#include "theory/quantifiers/candidate_generator.h"
-#include "theory/quantifiers_engine.h"
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-
-namespace CVC4 {
-namespace theory {
-namespace inst {
-
-
-InstMatchGenerator::InstMatchGenerator( Node pat, QuantifiersEngine* qe, int matchPolicy ) : d_matchPolicy( matchPolicy ){
- initializePattern( pat, qe );
-}
-
-InstMatchGenerator::InstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe, int matchPolicy ) : d_matchPolicy( matchPolicy ){
- if( pats.size()==1 ){
- initializePattern( pats[0], qe );
- }else{
- initializePatterns( pats, qe );
- }
-}
-
-void InstMatchGenerator::initializePatterns( std::vector< Node >& pats, QuantifiersEngine* qe ){
- int childMatchPolicy = d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ? 0 : d_matchPolicy;
- for( int i=0; i<(int)pats.size(); i++ ){
- d_children.push_back( new InstMatchGenerator( pats[i], qe, childMatchPolicy ) );
- }
- d_pattern = Node::null();
- d_match_pattern = Node::null();
- d_cg = NULL;
-}
-
-void InstMatchGenerator::initializePattern( Node pat, QuantifiersEngine* qe ){
- Debug("inst-match-gen") << "Pattern term is " << pat << std::endl;
- Assert( pat.hasAttribute(InstConstantAttribute()) );
- d_pattern = pat;
- d_match_pattern = pat;
- if( d_match_pattern.getKind()==NOT ){
- //we want to add the children of the NOT
- d_match_pattern = d_pattern[0];
- }
- if( d_match_pattern.getKind()==IFF || d_match_pattern.getKind()==EQUAL ){
- if( !d_match_pattern[0].hasAttribute(InstConstantAttribute()) ){
- Assert( d_match_pattern[1].hasAttribute(InstConstantAttribute()) );
- //swap sides
- d_pattern = NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), d_match_pattern[1], d_match_pattern[0] );
- d_pattern = pat.getKind()==NOT ? d_pattern.notNode() : d_pattern;
- if( pat.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching
- d_match_pattern = d_match_pattern[1];
- }else{
- d_match_pattern = d_pattern[0][0];
- }
- }else if( !d_match_pattern[1].hasAttribute(InstConstantAttribute()) ){
- Assert( d_match_pattern[0].hasAttribute(InstConstantAttribute()) );
- if( pat.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching
- d_match_pattern = d_match_pattern[0];
- }
- }
- }
- int childMatchPolicy = MATCH_GEN_DEFAULT;
- for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
- if( d_match_pattern[i].hasAttribute(InstConstantAttribute()) ){
- if( d_match_pattern[i].getKind()!=INST_CONSTANT ){
- d_children.push_back( new InstMatchGenerator( d_match_pattern[i], qe, childMatchPolicy ) );
- d_children_index.push_back( i );
- }
- }
- }
-
- Debug("inst-match-gen") << "Pattern is " << d_pattern << ", match pattern is " << d_match_pattern << std::endl;
-
- //create candidate generator
- if( d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==IFF ){
- Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
- //we will be producing candidates via literal matching heuristics
- if( d_pattern.getKind()!=NOT ){
- //candidates will be all equalities
- d_cg = new inst::CandidateGeneratorQELitEq( qe, d_match_pattern );
- }else{
- //candidates will be all disequalities
- d_cg = new inst::CandidateGeneratorQELitDeq( qe, d_match_pattern );
- }
- }else if( d_pattern.getKind()==EQUAL || d_pattern.getKind()==IFF || d_pattern.getKind()==NOT ){
- Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
- if( d_pattern.getKind()==NOT ){
- Unimplemented("Disequal generator unimplemented");
- }else{
- Assert( Trigger::isAtomicTrigger( d_match_pattern ) );
- //we are matching only in a particular equivalence class
- d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
- //store the equivalence class that we will call d_cg->reset( ... ) on
- d_eq_class = d_pattern[1];
- }
- }else if( Trigger::isAtomicTrigger( d_match_pattern ) ){
- //if( d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ){
- //Warning() << "Currently efficient e matching is not taken into account for quantifiers: " << d_pattern << std::endl;
- //}
- //we will be scanning lists trying to find d_match_pattern.getOperator()
- d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
- }else{
- d_cg = new CandidateGeneratorQueue;
- if( !Trigger::getPatternArithmetic( d_match_pattern.getAttribute(InstConstantAttribute()), d_match_pattern, d_arith_coeffs ) ){
- Debug("inst-match-gen") << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
- //Warning() << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
- d_matchPolicy = MATCH_GEN_INTERNAL_ERROR;
- }else{
- Debug("matching-arith") << "Generated arithmetic pattern for " << d_match_pattern << ": " << std::endl;
- for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
- Debug("matching-arith") << " " << it->first << " -> " << it->second << std::endl;
- }
- //we will treat this as match gen internal arithmetic
- d_matchPolicy = MATCH_GEN_INTERNAL_ARITHMETIC;
- }
- }
-}
-
-/** get match (not modulo equality) */
-bool InstMatchGenerator::getMatch( Node t, InstMatch& m, QuantifiersEngine* qe ){
- Debug("matching") << "Matching " << t << " against pattern " << d_match_pattern << " ("
- << m.size() << ")" << ", " << d_children.size() << std::endl;
- Assert( !d_match_pattern.isNull() );
- if( qe->d_optMatchIgnoreModelBasis && t.getAttribute(ModelBasisAttribute()) ){
- return true;
- }else if( d_matchPolicy==MATCH_GEN_INTERNAL_ARITHMETIC ){
- return getMatchArithmetic( t, m, qe );
- }else if( d_matchPolicy==MATCH_GEN_INTERNAL_ERROR ){
- return false;
- }else{
- EqualityQuery* q = qe->getEqualityQuery();
- //add m to partial match vector
- std::vector< InstMatch > partial;
- partial.push_back( InstMatch( &m ) );
- //if t is null
- Assert( !t.isNull() );
- Assert( !t.hasAttribute(InstConstantAttribute()) );
- Assert( t.getKind()==d_match_pattern.getKind() );
- Assert( !Trigger::isAtomicTrigger( d_match_pattern ) || t.getOperator()==d_match_pattern.getOperator() );
- //first, check if ground arguments are not equal, or a match is in conflict
- for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
- if( d_match_pattern[i].hasAttribute(InstConstantAttribute()) ){
- if( d_match_pattern[i].getKind()==INST_CONSTANT ){
- if( !partial[0].setMatch( q, d_match_pattern[i], t[i] ) ){
- //match is in conflict
- Debug("matching-debug") << "Match in conflict " << t[i] << " and "
- << d_match_pattern[i] << " because "
- << partial[0].get(d_match_pattern[i])
- << std::endl;
- Debug("matching-fail") << "Match fail: " << partial[0].get(d_match_pattern[i]) << " and " << t[i] << std::endl;
- return false;
- }
- }
- }else{
- if( !q->areEqual( d_match_pattern[i], t[i] ) ){
- Debug("matching-fail") << "Match fail arg: " << d_match_pattern[i] << " and " << t[i] << std::endl;
- //ground arguments are not equal
- return false;
- }
- }
- }
- //now, fit children into match
- //we will be requesting candidates for matching terms for each child
- std::vector< Node > reps;
- for( int i=0; i<(int)d_children.size(); i++ ){
- Node rep = q->getRepresentative( t[ d_children_index[i] ] );
- reps.push_back( rep );
- d_children[i]->d_cg->reset( rep );
- }
-
- //combine child matches
- int index = 0;
- while( index>=0 && index<(int)d_children.size() ){
- partial.push_back( InstMatch( &partial[index] ) );
- if( d_children[index]->getNextMatch2( partial[index+1], qe ) ){
- index++;
- }else{
- d_children[index]->d_cg->reset( reps[index] );
- partial.pop_back();
- if( !partial.empty() ){
- partial.pop_back();
- }
- index--;
- }
- }
- if( index>=0 ){
- m = partial.back();
- return true;
- }else{
- return false;
- }
- }
-}
-
-bool InstMatchGenerator::getNextMatch2( InstMatch& m, QuantifiersEngine* qe, bool saveMatched ){
- bool success = false;
- Node t;
- do{
- //get the next candidate term t
- t = d_cg->getNextCandidate();
- //if t not null, try to fit it into match m
- if( !t.isNull() && t.getType()==d_match_pattern.getType() ){
- success = getMatch( t, m, qe );
- }
- }while( !success && !t.isNull() );
- if (saveMatched) m.d_matched = t;
- return success;
-}
-
-bool InstMatchGenerator::getMatchArithmetic( Node t, InstMatch& m, QuantifiersEngine* qe ){
- Debug("matching-arith") << "Matching " << t << " " << d_match_pattern << std::endl;
- if( !d_arith_coeffs.empty() ){
- NodeBuilder<> tb(kind::PLUS);
- Node ic = Node::null();
- for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
- Debug("matching-arith") << it->first << " -> " << it->second << std::endl;
- if( !it->first.isNull() ){
- if( m.find( it->first )==m.end() ){
- //see if we can choose this to set
- if( ic.isNull() && ( it->second.isNull() || !it->first.getType().isInteger() ) ){
- ic = it->first;
- }
- }else{
- Debug("matching-arith") << "already set " << m.get( it->first ) << std::endl;
- Node tm = m.get( it->first );
- if( !it->second.isNull() ){
- tm = NodeManager::currentNM()->mkNode( MULT, it->second, tm );
- }
- tb << tm;
- }
- }else{
- tb << it->second;
- }
- }
- if( !ic.isNull() ){
- Node tm;
- if( tb.getNumChildren()==0 ){
- tm = t;
- }else{
- tm = tb.getNumChildren()==1 ? tb.getChild( 0 ) : tb;
- tm = NodeManager::currentNM()->mkNode( MINUS, t, tm );
- }
- if( !d_arith_coeffs[ ic ].isNull() ){
- Assert( !ic.getType().isInteger() );
- Node coeff = NodeManager::currentNM()->mkConst( Rational(1) / d_arith_coeffs[ ic ].getConst<Rational>() );
- tm = NodeManager::currentNM()->mkNode( MULT, coeff, tm );
- }
- m.set( ic, Rewriter::rewrite( tm ));
- //set the rest to zeros
- for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
- if( !it->first.isNull() ){
- if( m.find( it->first )==m.end() ){
- m.set( it->first, NodeManager::currentNM()->mkConst( Rational(0) ) );
- }
- }
- }
- Debug("matching-arith") << "Setting " << ic << " to " << tm << std::endl;
- return true;
- }else{
- return false;
- }
- }else{
- return false;
- }
-}
-
-
-/** reset instantiation round */
-void InstMatchGenerator::resetInstantiationRound( QuantifiersEngine* qe ){
- if( d_match_pattern.isNull() ){
- for( int i=0; i<(int)d_children.size(); i++ ){
- d_children[i]->resetInstantiationRound( qe );
- }
- }else{
- if( d_cg ){
- d_cg->resetInstantiationRound();
- }
- }
-}
-
-void InstMatchGenerator::reset( Node eqc, QuantifiersEngine* qe ){
- if( d_match_pattern.isNull() ){
- for( int i=0; i<(int)d_children.size(); i++ ){
- d_children[i]->reset( eqc, qe );
- }
- d_partial.clear();
- }else{
- if( !d_eq_class.isNull() ){
- //we have a specific equivalence class in mind
- //we are producing matches for f(E) ~ t, where E is a non-ground vector of terms, and t is a ground term
- //just look in equivalence class of the RHS
- d_cg->reset( d_eq_class );
- }else{
- d_cg->reset( eqc );
- }
- }
-}
-
-bool InstMatchGenerator::getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
- m.d_matched = Node::null();
- if( d_match_pattern.isNull() ){
- int index = (int)d_partial.size();
- while( index>=0 && index<(int)d_children.size() ){
- if( index>0 ){
- d_partial.push_back( InstMatch( &d_partial[index-1] ) );
- }else{
- d_partial.push_back( InstMatch() );
- }
- if( d_children[index]->getNextMatch( d_partial[index], qe ) ){
- index++;
- }else{
- d_children[index]->reset( Node::null(), qe );
- d_partial.pop_back();
- if( !d_partial.empty() ){
- d_partial.pop_back();
- }
- index--;
- }
- }
- if( index>=0 ){
- m = d_partial.back();
- d_partial.pop_back();
- return true;
- }else{
- return false;
- }
- }else{
- bool res = getNextMatch2( m, qe, true );
- Assert(!res || !m.d_matched.isNull());
- return res;
- }
-}
-
-
-
-int InstMatchGenerator::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
- //now, try to add instantiation for each match produced
- int addedLemmas = 0;
- InstMatch m;
- while( getNextMatch( m, qe ) ){
- //m.makeInternal( d_quantEngine->getEqualityQuery() );
- m.add( baseMatch );
- if( qe->addInstantiation( f, m ) ){
- addedLemmas++;
- if( qe->d_optInstLimitActive && qe->d_optInstLimit<=0 ){
- return addedLemmas;
- }
- }
- m.clear();
- }
- //return number of lemmas added
- return addedLemmas;
-}
-
-int InstMatchGenerator::addTerm( Node f, Node t, QuantifiersEngine* qe ){
- Assert( options::eagerInstQuant() );
- if( !d_match_pattern.isNull() ){
- InstMatch m;
- if( getMatch( t, m, qe ) ){
- if( qe->addInstantiation( f, m ) ){
- return 1;
- }
- }
- }else{
- for( int i=0; i<(int)d_children.size(); i++ ){
- d_children[i]->addTerm( f, t, qe );
- }
- }
- return 0;
-}
-
-/** constructors */
-InstMatchGeneratorMulti::InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption ) :
-d_f( f ){
- Debug("smart-multi-trigger") << "Making smart multi-trigger for " << f << std::endl;
- std::map< Node, std::vector< Node > > var_contains;
- qe->getTermDatabase()->getVarContains( f, pats, var_contains );
- //convert to indicies
- for( std::map< Node, std::vector< Node > >::iterator it = var_contains.begin(); it != var_contains.end(); ++it ){
- Debug("smart-multi-trigger") << "Pattern " << it->first << " contains: ";
- for( int i=0; i<(int)it->second.size(); i++ ){
- Debug("smart-multi-trigger") << it->second[i] << " ";
- int index = it->second[i].getAttribute(InstVarNumAttribute());
- d_var_contains[ it->first ].push_back( index );
- d_var_to_node[ index ].push_back( it->first );
- }
- Debug("smart-multi-trigger") << std::endl;
- }
- for( int i=0; i<(int)pats.size(); i++ ){
- Node n = pats[i];
- //make the match generator
- d_children.push_back( new InstMatchGenerator( n, qe, matchOption ) );
- //compute unique/shared variables
- std::vector< int > unique_vars;
- std::map< int, bool > shared_vars;
- int numSharedVars = 0;
- for( int j=0; j<(int)d_var_contains[n].size(); j++ ){
- if( d_var_to_node[ d_var_contains[n][j] ].size()==1 ){
- Debug("smart-multi-trigger") << "Var " << d_var_contains[n][j] << " is unique to " << pats[i] << std::endl;
- unique_vars.push_back( d_var_contains[n][j] );
- }else{
- shared_vars[ d_var_contains[n][j] ] = true;
- numSharedVars++;
- }
- }
- //we use the latest shared variables, then unique variables
- std::vector< int > vars;
- int index = i==0 ? (int)(pats.size()-1) : (i-1);
- while( numSharedVars>0 && index!=i ){
- for( std::map< int, bool >::iterator it = shared_vars.begin(); it != shared_vars.end(); ++it ){
- if( it->second ){
- if( std::find( d_var_contains[ pats[index] ].begin(), d_var_contains[ pats[index] ].end(), it->first )!=
- d_var_contains[ pats[index] ].end() ){
- vars.push_back( it->first );
- shared_vars[ it->first ] = false;
- numSharedVars--;
- }
- }
- }
- index = index==0 ? (int)(pats.size()-1) : (index-1);
- }
- vars.insert( vars.end(), unique_vars.begin(), unique_vars.end() );
- Debug("smart-multi-trigger") << " Index[" << i << "]: ";
- for( int i=0; i<(int)vars.size(); i++ ){
- Debug("smart-multi-trigger") << vars[i] << " ";
- }
- Debug("smart-multi-trigger") << std::endl;
- //make ordered inst match trie
- InstMatchTrie::ImtIndexOrder* imtio = new InstMatchTrie::ImtIndexOrder;
- imtio->d_order.insert( imtio->d_order.begin(), vars.begin(), vars.end() );
- d_children_trie.push_back( InstMatchTrieOrdered( imtio ) );
- }
-
-}
-
-/** reset instantiation round (call this whenever equivalence classes have changed) */
-void InstMatchGeneratorMulti::resetInstantiationRound( QuantifiersEngine* qe ){
- for( int i=0; i<(int)d_children.size(); i++ ){
- d_children[i]->resetInstantiationRound( qe );
- }
-}
-
-/** reset, eqc is the equivalence class to search in (any if eqc=null) */
-void InstMatchGeneratorMulti::reset( Node eqc, QuantifiersEngine* qe ){
- for( int i=0; i<(int)d_children.size(); i++ ){
- d_children[i]->reset( eqc, qe );
- }
-}
-
-int InstMatchGeneratorMulti::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
- int addedLemmas = 0;
- Debug("smart-multi-trigger") << "Process smart multi trigger" << std::endl;
- for( int i=0; i<(int)d_children.size(); i++ ){
- Debug("smart-multi-trigger") << "Calculate matches " << i << std::endl;
- std::vector< InstMatch > newMatches;
- InstMatch m;
- while( d_children[i]->getNextMatch( m, qe ) ){
- m.makeRepresentative( qe );
- newMatches.push_back( InstMatch( &m ) );
- m.clear();
- }
- for( int j=0; j<(int)newMatches.size(); j++ ){
- processNewMatch( qe, newMatches[j], i, addedLemmas );
- }
- }
- return addedLemmas;
-}
-
-void InstMatchGeneratorMulti::processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas ){
- //see if these produce new matches
- d_children_trie[fromChildIndex].addInstMatch( qe, d_f, m, true );
- //possibly only do the following if we know that new matches will be produced?
- //the issue is that instantiations are filtered in quantifiers engine, and so there is no guarentee that
- // we can safely skip the following lines, even when we have already produced this match.
- Debug("smart-multi-trigger") << "Child " << fromChildIndex << " produced match " << m << std::endl;
- //process new instantiations
- int childIndex = (fromChildIndex+1)%(int)d_children.size();
- std::vector< IndexedTrie > unique_var_tries;
- processNewInstantiations( qe, m, addedLemmas, d_children_trie[childIndex].getTrie(),
- unique_var_tries, 0, childIndex, fromChildIndex, true );
-}
-
-void InstMatchGeneratorMulti::processNewInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
- std::vector< IndexedTrie >& unique_var_tries,
- int trieIndex, int childIndex, int endChildIndex, bool modEq ){
- if( childIndex==endChildIndex ){
- //now, process unique variables
- processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, 0 );
- }else if( trieIndex<(int)d_children_trie[childIndex].getOrdering()->d_order.size() ){
- int curr_index = d_children_trie[childIndex].getOrdering()->d_order[trieIndex];
- Node curr_ic = qe->getTermDatabase()->getInstantiationConstant( d_f, curr_index );
- if( m.find( curr_ic )==m.end() ){
- //if( d_var_to_node[ curr_index ].size()==1 ){ //FIXME
- // //unique variable(s), defer calculation
- // unique_var_tries.push_back( IndexedTrie( std::pair< int, int >( childIndex, trieIndex ), tr ) );
- // int newChildIndex = (childIndex+1)%(int)d_children.size();
- // processNewInstantiations( qe, m, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
- // 0, newChildIndex, endChildIndex, modEq );
- //}else{
- //shared and non-set variable, add to InstMatch
- for( std::map< Node, InstMatchTrie >::iterator it = tr->d_data.begin(); it != tr->d_data.end(); ++it ){
- InstMatch mn( &m );
- mn.set( curr_ic, it->first);
- processNewInstantiations( qe, mn, addedLemmas, &(it->second), unique_var_tries,
- trieIndex+1, childIndex, endChildIndex, modEq );
- }
- //}
- }else{
- //shared and set variable, try to merge
- Node n = m.get( curr_ic );
- std::map< Node, InstMatchTrie >::iterator it = tr->d_data.find( n );
- if( it!=tr->d_data.end() ){
- processNewInstantiations( qe, m, addedLemmas, &(it->second), unique_var_tries,
- trieIndex+1, childIndex, endChildIndex, modEq );
- }
- if( modEq ){
- //check modulo equality for other possible instantiations
- if( qe->getEqualityQuery()->getEngine()->hasTerm( n ) ){
- eq::EqClassIterator eqc( qe->getEqualityQuery()->getEngine()->getRepresentative( n ),
- qe->getEqualityQuery()->getEngine() );
- while( !eqc.isFinished() ){
- Node en = (*eqc);
- if( en!=n ){
- std::map< Node, InstMatchTrie >::iterator itc = tr->d_data.find( en );
- if( itc!=tr->d_data.end() ){
- processNewInstantiations( qe, m, addedLemmas, &(itc->second), unique_var_tries,
- trieIndex+1, childIndex, endChildIndex, modEq );
- }
- }
- ++eqc;
- }
- }
- }
- }
- }else{
- int newChildIndex = (childIndex+1)%(int)d_children.size();
- processNewInstantiations( qe, m, addedLemmas, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
- 0, newChildIndex, endChildIndex, modEq );
- }
-}
-
-void InstMatchGeneratorMulti::processNewInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
- std::vector< IndexedTrie >& unique_var_tries,
- int uvtIndex, InstMatchTrie* tr, int trieIndex ){
- if( uvtIndex<(int)unique_var_tries.size() ){
- int childIndex = unique_var_tries[uvtIndex].first.first;
- if( !tr ){
- tr = unique_var_tries[uvtIndex].second;
- trieIndex = unique_var_tries[uvtIndex].first.second;
- }
- if( trieIndex<(int)d_children_trie[childIndex].getOrdering()->d_order.size() ){
- int curr_index = d_children_trie[childIndex].getOrdering()->d_order[trieIndex];
- Node curr_ic = qe->getTermDatabase()->getInstantiationConstant( d_f, curr_index );
- //unique non-set variable, add to InstMatch
- for( std::map< Node, InstMatchTrie >::iterator it = tr->d_data.begin(); it != tr->d_data.end(); ++it ){
- InstMatch mn( &m );
- mn.set( curr_ic, it->first);
- processNewInstantiations2( qe, mn, addedLemmas, unique_var_tries, uvtIndex, &(it->second), trieIndex+1 );
- }
- }else{
- processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, uvtIndex+1 );
- }
- }else{
- //m is an instantiation
- if( qe->addInstantiation( d_f, m ) ){
- addedLemmas++;
- Debug("smart-multi-trigger") << "-> Produced instantiation " << m << std::endl;
- }
- }
-}
-
-int InstMatchGeneratorMulti::addTerm( Node f, Node t, QuantifiersEngine* qe ){
- Assert( options::eagerInstQuant() );
- int addedLemmas = 0;
- for( int i=0; i<(int)d_children.size(); i++ ){
- if( ((InstMatchGenerator*)d_children[i])->d_match_pattern.getOperator()==t.getOperator() ){
- InstMatch m;
- //if it produces a match, then process it with the rest
- if( ((InstMatchGenerator*)d_children[i])->getMatch( t, m, qe ) ){
- processNewMatch( qe, m, i, addedLemmas );
- }
- }
- }
- return addedLemmas;
-}
-
-int InstMatchGeneratorSimple::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
- InstMatch m;
- m.add( baseMatch );
- int addedLemmas = 0;
- if( d_match_pattern.getType()==NodeManager::currentNM()->booleanType() ){
- for( int i=0; i<2; i++ ){
- addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_pred_map_trie[i][ d_match_pattern.getOperator() ]) );
- }
- }else{
- addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_func_map_trie[ d_match_pattern.getOperator() ]) );
- }
- return addedLemmas;
-}
-
-void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex, quantifiers::TermArgTrie* tat ){
- if( argIndex==(int)d_match_pattern.getNumChildren() ){
- //m is an instantiation
- if( qe->addInstantiation( d_f, m ) ){
- addedLemmas++;
- Debug("simple-multi-trigger") << "-> Produced instantiation " << m << std::endl;
- }
- }else{
- if( d_match_pattern[argIndex].getKind()==INST_CONSTANT ){
- Node ic = d_match_pattern[argIndex];
- for( std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
- Node t = it->first;
- if( ( m.get( ic ).isNull() || m.get( ic )==t ) && ic.getType()==t.getType() ){
- Node prev = m.get( ic );
- m.set( ic, t);
- addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
- m.set( ic, prev);
- }
- }
- }else{
- Node r = qe->getEqualityQuery()->getRepresentative( d_match_pattern[argIndex] );
- std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.find( r );
- if( it!=tat->d_data.end() ){
- addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
- }
- }
- }
-}
-
-int InstMatchGeneratorSimple::addTerm( Node f, Node t, QuantifiersEngine* qe ){
- Assert( options::eagerInstQuant() );
- InstMatch m;
- for( int i=0; i<(int)t.getNumChildren(); i++ ){
- if( d_match_pattern[i].getKind()==INST_CONSTANT ){
- m.set(d_match_pattern[i], t[i]);
- }else if( !qe->getEqualityQuery()->areEqual( d_match_pattern[i], t[i] ) ){
- return 0;
- }
- }
- return qe->addInstantiation( f, m ) ? 1 : 0;
-}
-
-}/* CVC4::theory::inst namespace */
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
+/********************* */
+/*! \file inst_match_generator.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** [[ Add lengthier description here ]]
+ ** \todo document this file
+**/
+
+#include "theory/quantifiers/inst_match_generator.h"
+#include "theory/quantifiers/trigger.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/candidate_generator.h"
+#include "theory/quantifiers_engine.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+
+namespace CVC4 {
+namespace theory {
+namespace inst {
+
+
+InstMatchGenerator::InstMatchGenerator( Node pat, int matchPolicy ) : d_matchPolicy( matchPolicy ){
+ d_active_add = false;
+ Assert( pat.hasAttribute(InstConstantAttribute()) );
+ d_pattern = pat;
+ d_match_pattern = pat;
+ d_next = NULL;
+}
+
+void InstMatchGenerator::setActiveAdd(){
+ d_active_add = true;
+ if( d_next!=NULL ){
+ d_next->setActiveAdd();
+ }
+}
+
+void InstMatchGenerator::initialize( QuantifiersEngine* qe, std::vector< InstMatchGenerator * > & gens ){
+ if( !d_pattern.isNull() ){
+ Debug("inst-match-gen") << "Pattern term is " << d_pattern << std::endl;
+ if( d_match_pattern.getKind()==NOT ){
+ //we want to add the children of the NOT
+ d_match_pattern = d_pattern[0];
+ }
+ if( d_match_pattern.getKind()==IFF || d_match_pattern.getKind()==EQUAL ){
+ if( !d_match_pattern[0].hasAttribute(InstConstantAttribute()) ){
+ Assert( d_match_pattern[1].hasAttribute(InstConstantAttribute()) );
+ //swap sides
+ Node pat = d_pattern;
+ d_pattern = NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), d_match_pattern[1], d_match_pattern[0] );
+ d_pattern = pat.getKind()==NOT ? d_pattern.notNode() : d_pattern;
+ if( pat.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching
+ d_match_pattern = d_match_pattern[1];
+ }else{
+ d_match_pattern = d_pattern[0][0];
+ }
+ }else if( !d_match_pattern[1].hasAttribute(InstConstantAttribute()) ){
+ Assert( d_match_pattern[0].hasAttribute(InstConstantAttribute()) );
+ if( d_pattern.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching
+ d_match_pattern = d_match_pattern[0];
+ }
+ }
+ }
+ int childMatchPolicy = MATCH_GEN_DEFAULT;
+ for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
+ if( d_match_pattern[i].hasAttribute(InstConstantAttribute()) ){
+ if( d_match_pattern[i].getKind()!=INST_CONSTANT ){
+ InstMatchGenerator * cimg = new InstMatchGenerator( d_match_pattern[i], childMatchPolicy );
+ d_children.push_back( cimg );
+ d_children_index.push_back( i );
+ gens.push_back( cimg );
+ }
+ }
+ }
+
+ Debug("inst-match-gen") << "Pattern is " << d_pattern << ", match pattern is " << d_match_pattern << std::endl;
+
+ //create candidate generator
+ if( d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==IFF ){
+ Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
+ //we will be producing candidates via literal matching heuristics
+ if( d_pattern.getKind()!=NOT ){
+ //candidates will be all equalities
+ d_cg = new inst::CandidateGeneratorQELitEq( qe, d_match_pattern );
+ }else{
+ //candidates will be all disequalities
+ d_cg = new inst::CandidateGeneratorQELitDeq( qe, d_match_pattern );
+ }
+ }else if( d_pattern.getKind()==EQUAL || d_pattern.getKind()==IFF || d_pattern.getKind()==NOT ){
+ Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
+ if( d_pattern.getKind()==NOT ){
+ Unimplemented("Disequal generator unimplemented");
+ }else{
+ Assert( Trigger::isAtomicTrigger( d_match_pattern ) );
+ //we are matching only in a particular equivalence class
+ d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
+ //store the equivalence class that we will call d_cg->reset( ... ) on
+ d_eq_class = d_pattern[1];
+ }
+ }else if( Trigger::isAtomicTrigger( d_match_pattern ) ){
+ //if( d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ){
+ //Warning() << "Currently efficient e matching is not taken into account for quantifiers: " << d_pattern << std::endl;
+ //}
+ //we will be scanning lists trying to find d_match_pattern.getOperator()
+ d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
+ }else{
+ d_cg = new CandidateGeneratorQueue;
+ if( !Trigger::getPatternArithmetic( d_match_pattern.getAttribute(InstConstantAttribute()), d_match_pattern, d_arith_coeffs ) ){
+ Debug("inst-match-gen") << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
+ //Warning() << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
+ d_matchPolicy = MATCH_GEN_INTERNAL_ERROR;
+ }else{
+ Debug("matching-arith") << "Generated arithmetic pattern for " << d_match_pattern << ": " << std::endl;
+ for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+ Debug("matching-arith") << " " << it->first << " -> " << it->second << std::endl;
+ }
+ //we will treat this as match gen internal arithmetic
+ d_matchPolicy = MATCH_GEN_INTERNAL_ARITHMETIC;
+ }
+ }
+ }
+}
+
+/** get match (not modulo equality) */
+bool InstMatchGenerator::getMatch( Node f, Node t, InstMatch& m, QuantifiersEngine* qe ){
+ Debug("matching") << "Matching " << t << " against pattern " << d_match_pattern << " ("
+ << m << ")" << ", " << d_children.size() << std::endl;
+ Assert( !d_match_pattern.isNull() );
+ if( qe->d_optMatchIgnoreModelBasis && t.getAttribute(ModelBasisAttribute()) ){
+ return true;
+ }else if( d_matchPolicy==MATCH_GEN_INTERNAL_ARITHMETIC ){
+ return getMatchArithmetic( t, m, qe );
+ }else if( d_matchPolicy==MATCH_GEN_INTERNAL_ERROR ){
+ return false;
+ }else{
+ EqualityQuery* q = qe->getEqualityQuery();
+ bool success = true;
+ //save previous match
+ InstMatch prev( &m );
+ //if t is null
+ Assert( !t.isNull() );
+ Assert( !t.hasAttribute(InstConstantAttribute()) );
+ Assert( t.getKind()==d_match_pattern.getKind() );
+ Assert( !Trigger::isAtomicTrigger( d_match_pattern ) || t.getOperator()==d_match_pattern.getOperator() );
+ //first, check if ground arguments are not equal, or a match is in conflict
+ for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
+ if( d_match_pattern[i].hasAttribute(InstConstantAttribute()) ){
+ if( d_match_pattern[i].getKind()==INST_CONSTANT ){
+ if( !m.setMatch( q, d_match_pattern[i], t[i] ) ){
+ //match is in conflict
+ Debug("matching-debug") << "Match in conflict " << t[i] << " and "
+ << d_match_pattern[i] << " because "
+ << m.get(d_match_pattern[i])
+ << std::endl;
+ Debug("matching-fail") << "Match fail: " << m.get(d_match_pattern[i]) << " and " << t[i] << std::endl;
+ success = false;
+ break;
+ }
+ }
+ }else{
+ if( !q->areEqual( d_match_pattern[i], t[i] ) ){
+ Debug("matching-fail") << "Match fail arg: " << d_match_pattern[i] << " and " << t[i] << std::endl;
+ //ground arguments are not equal
+ success = false;
+ break;
+ }
+ }
+ }
+ if( success ){
+ //now, fit children into match
+ //we will be requesting candidates for matching terms for each child
+ std::vector< Node > reps;
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ Node rep = q->getRepresentative( t[ d_children_index[i] ] );
+ reps.push_back( rep );
+ d_children[i]->reset( rep, qe );
+ }
+ if( d_next!=NULL ){
+ success = d_next->getNextMatch( f, m, qe );
+ }else{
+ if( d_active_add ){
+ Trace("active-add") << "Active Adding instantiation " << m << std::endl;
+ success = qe->addInstantiation( f, m );
+ Trace("active-add") << "Success = " << success << std::endl;
+ }
+ }
+ }
+ if( !success ){
+ m = InstMatch( &prev );
+ }
+ return success;
+ }
+}
+
+bool InstMatchGenerator::getMatchArithmetic( Node t, InstMatch& m, QuantifiersEngine* qe ){
+ Debug("matching-arith") << "Matching " << t << " " << d_match_pattern << std::endl;
+ if( !d_arith_coeffs.empty() ){
+ NodeBuilder<> tb(kind::PLUS);
+ Node ic = Node::null();
+ for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+ Debug("matching-arith") << it->first << " -> " << it->second << std::endl;
+ if( !it->first.isNull() ){
+ if( m.find( it->first )==m.end() ){
+ //see if we can choose this to set
+ if( ic.isNull() && ( it->second.isNull() || !it->first.getType().isInteger() ) ){
+ ic = it->first;
+ }
+ }else{
+ Debug("matching-arith") << "already set " << m.get( it->first ) << std::endl;
+ Node tm = m.get( it->first );
+ if( !it->second.isNull() ){
+ tm = NodeManager::currentNM()->mkNode( MULT, it->second, tm );
+ }
+ tb << tm;
+ }
+ }else{
+ tb << it->second;
+ }
+ }
+ if( !ic.isNull() ){
+ Node tm;
+ if( tb.getNumChildren()==0 ){
+ tm = t;
+ }else{
+ tm = tb.getNumChildren()==1 ? tb.getChild( 0 ) : tb;
+ tm = NodeManager::currentNM()->mkNode( MINUS, t, tm );
+ }
+ if( !d_arith_coeffs[ ic ].isNull() ){
+ Assert( !ic.getType().isInteger() );
+ Node coeff = NodeManager::currentNM()->mkConst( Rational(1) / d_arith_coeffs[ ic ].getConst<Rational>() );
+ tm = NodeManager::currentNM()->mkNode( MULT, coeff, tm );
+ }
+ m.set( ic, Rewriter::rewrite( tm ));
+ //set the rest to zeros
+ for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+ if( !it->first.isNull() ){
+ if( m.find( it->first )==m.end() ){
+ m.set( it->first, NodeManager::currentNM()->mkConst( Rational(0) ) );
+ }
+ }
+ }
+ Debug("matching-arith") << "Setting " << ic << " to " << tm << std::endl;
+ return true;
+ }else{
+ return false;
+ }
+ }else{
+ return false;
+ }
+}
+
+
+/** reset instantiation round */
+void InstMatchGenerator::resetInstantiationRound( QuantifiersEngine* qe ){
+ if( d_match_pattern.isNull() ){
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ d_children[i]->resetInstantiationRound( qe );
+ }
+ }else{
+ if( d_cg ){
+ d_cg->resetInstantiationRound();
+ }
+ }
+}
+
+void InstMatchGenerator::reset( Node eqc, QuantifiersEngine* qe ){
+ if( !eqc.isNull() ){
+ d_eq_class = eqc;
+ }
+ //we have a specific equivalence class in mind
+ //we are producing matches for f(E) ~ t, where E is a non-ground vector of terms, and t is a ground term
+ //just look in equivalence class of the RHS
+ d_cg->reset( d_eq_class );
+}
+
+bool InstMatchGenerator::getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ){
+ m.d_matched = Node::null();
+ //Debug("matching") << this << " " << d_pattern << " get next match 2 " << m << " in eq class " << d_eq_class << std::endl;
+ bool success = false;
+ Node t;
+ do{
+ //get the next candidate term t
+ t = d_cg->getNextCandidate();
+ //if t not null, try to fit it into match m
+ if( !t.isNull() && t.getType()==d_match_pattern.getType() ){
+ success = getMatch( f, t, m, qe );
+ }
+ }while( !success && !t.isNull() );
+ m.d_matched = t;
+ if( !success ){
+ //Debug("matching") << this << " failed, reset " << d_eq_class << std::endl;
+ //we failed, must reset
+ reset( d_eq_class, qe );
+ }
+ return success;
+}
+
+
+
+int InstMatchGenerator::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
+ //try to add instantiation for each match produced
+ int addedLemmas = 0;
+ InstMatch m;
+ while( getNextMatch( f, m, qe ) ){
+ if( !d_active_add ){
+ //m.makeInternal( d_quantEngine->getEqualityQuery() );
+ m.add( baseMatch );
+ if( qe->addInstantiation( f, m ) ){
+ addedLemmas++;
+ if( qe->d_optInstLimitActive && qe->d_optInstLimit<=0 ){
+ return addedLemmas;
+ }
+ }
+ }else{
+ addedLemmas++;
+ }
+ m.clear();
+ }
+ //return number of lemmas added
+ return addedLemmas;
+}
+
+int InstMatchGenerator::addTerm( Node f, Node t, QuantifiersEngine* qe ){
+ Assert( options::eagerInstQuant() );
+ if( !d_match_pattern.isNull() ){
+ InstMatch m;
+ if( getMatch( f, t, m, qe ) ){
+ if( qe->addInstantiation( f, m ) ){
+ return 1;
+ }
+ }
+ }else{
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ d_children[i]->addTerm( f, t, qe );
+ }
+ }
+ return 0;
+}
+
+
+InstMatchGenerator* InstMatchGenerator::mkInstMatchGenerator( Node pat, QuantifiersEngine* qe ) {
+ std::vector< Node > pats;
+ pats.push_back( pat );
+ return mkInstMatchGenerator( pats, qe );
+}
+
+InstMatchGenerator* InstMatchGenerator::mkInstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe ) {
+ size_t pCounter = 0;
+ InstMatchGenerator* prev = NULL;
+ InstMatchGenerator* oinit = NULL;
+ while( pCounter<pats.size() ){
+ size_t counter = 0;
+ std::vector< InstMatchGenerator* > gens;
+ InstMatchGenerator* init = new InstMatchGenerator(pats[pCounter]);
+ if(pCounter==0){
+ oinit = init;
+ }
+ gens.push_back(init);
+ //chain the resulting match generators together
+ while (counter<gens.size()) {
+ InstMatchGenerator* curr = gens[counter];
+ if( prev ){
+ prev->d_next = curr;
+ }
+ curr->initialize(qe, gens);
+ prev = curr;
+ counter++;
+ }
+ pCounter++;
+ }
+ return oinit;
+}
+
+/** constructors */
+InstMatchGeneratorMulti::InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption ) :
+d_f( f ){
+ Debug("smart-multi-trigger") << "Making smart multi-trigger for " << f << std::endl;
+ std::map< Node, std::vector< Node > > var_contains;
+ qe->getTermDatabase()->getVarContains( f, pats, var_contains );
+ //convert to indicies
+ for( std::map< Node, std::vector< Node > >::iterator it = var_contains.begin(); it != var_contains.end(); ++it ){
+ Debug("smart-multi-trigger") << "Pattern " << it->first << " contains: ";
+ for( int i=0; i<(int)it->second.size(); i++ ){
+ Debug("smart-multi-trigger") << it->second[i] << " ";
+ int index = it->second[i].getAttribute(InstVarNumAttribute());
+ d_var_contains[ it->first ].push_back( index );
+ d_var_to_node[ index ].push_back( it->first );
+ }
+ Debug("smart-multi-trigger") << std::endl;
+ }
+ for( int i=0; i<(int)pats.size(); i++ ){
+ Node n = pats[i];
+ //make the match generator
+ d_children.push_back( InstMatchGenerator::mkInstMatchGenerator( n, qe ) );
+ //compute unique/shared variables
+ std::vector< int > unique_vars;
+ std::map< int, bool > shared_vars;
+ int numSharedVars = 0;
+ for( int j=0; j<(int)d_var_contains[n].size(); j++ ){
+ if( d_var_to_node[ d_var_contains[n][j] ].size()==1 ){
+ Debug("smart-multi-trigger") << "Var " << d_var_contains[n][j] << " is unique to " << pats[i] << std::endl;
+ unique_vars.push_back( d_var_contains[n][j] );
+ }else{
+ shared_vars[ d_var_contains[n][j] ] = true;
+ numSharedVars++;
+ }
+ }
+ //we use the latest shared variables, then unique variables
+ std::vector< int > vars;
+ int index = i==0 ? (int)(pats.size()-1) : (i-1);
+ while( numSharedVars>0 && index!=i ){
+ for( std::map< int, bool >::iterator it = shared_vars.begin(); it != shared_vars.end(); ++it ){
+ if( it->second ){
+ if( std::find( d_var_contains[ pats[index] ].begin(), d_var_contains[ pats[index] ].end(), it->first )!=
+ d_var_contains[ pats[index] ].end() ){
+ vars.push_back( it->first );
+ shared_vars[ it->first ] = false;
+ numSharedVars--;
+ }
+ }
+ }
+ index = index==0 ? (int)(pats.size()-1) : (index-1);
+ }
+ vars.insert( vars.end(), unique_vars.begin(), unique_vars.end() );
+ Debug("smart-multi-trigger") << " Index[" << i << "]: ";
+ for( int i=0; i<(int)vars.size(); i++ ){
+ Debug("smart-multi-trigger") << vars[i] << " ";
+ }
+ Debug("smart-multi-trigger") << std::endl;
+ //make ordered inst match trie
+ InstMatchTrie::ImtIndexOrder* imtio = new InstMatchTrie::ImtIndexOrder;
+ imtio->d_order.insert( imtio->d_order.begin(), vars.begin(), vars.end() );
+ d_children_trie.push_back( InstMatchTrieOrdered( imtio ) );
+ }
+
+}
+
+/** reset instantiation round (call this whenever equivalence classes have changed) */
+void InstMatchGeneratorMulti::resetInstantiationRound( QuantifiersEngine* qe ){
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ d_children[i]->resetInstantiationRound( qe );
+ }
+}
+
+/** reset, eqc is the equivalence class to search in (any if eqc=null) */
+void InstMatchGeneratorMulti::reset( Node eqc, QuantifiersEngine* qe ){
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ d_children[i]->reset( eqc, qe );
+ }
+}
+
+int InstMatchGeneratorMulti::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
+ int addedLemmas = 0;
+ Debug("smart-multi-trigger") << "Process smart multi trigger" << std::endl;
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ Debug("smart-multi-trigger") << "Calculate matches " << i << std::endl;
+ std::vector< InstMatch > newMatches;
+ InstMatch m;
+ while( d_children[i]->getNextMatch( f, m, qe ) ){
+ //m.makeRepresentative( qe );
+ newMatches.push_back( InstMatch( &m ) );
+ m.clear();
+ }
+ Debug("smart-multi-trigger") << "Made " << newMatches.size() << " new matches for index " << i << std::endl;
+ for( int j=0; j<(int)newMatches.size(); j++ ){
+ processNewMatch( qe, newMatches[j], i, addedLemmas );
+ }
+ }
+ return addedLemmas;
+}
+
+void InstMatchGeneratorMulti::processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas ){
+ //see if these produce new matches
+ d_children_trie[fromChildIndex].addInstMatch( qe, d_f, m, true );
+ //possibly only do the following if we know that new matches will be produced?
+ //the issue is that instantiations are filtered in quantifiers engine, and so there is no guarentee that
+ // we can safely skip the following lines, even when we have already produced this match.
+ Debug("smart-multi-trigger") << "Child " << fromChildIndex << " produced match " << m << std::endl;
+ //process new instantiations
+ int childIndex = (fromChildIndex+1)%(int)d_children.size();
+ std::vector< IndexedTrie > unique_var_tries;
+ processNewInstantiations( qe, m, addedLemmas, d_children_trie[childIndex].getTrie(),
+ unique_var_tries, 0, childIndex, fromChildIndex, true );
+}
+
+void InstMatchGeneratorMulti::processNewInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
+ std::vector< IndexedTrie >& unique_var_tries,
+ int trieIndex, int childIndex, int endChildIndex, bool modEq ){
+ if( childIndex==endChildIndex ){
+ //now, process unique variables
+ processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, 0 );
+ }else if( trieIndex<(int)d_children_trie[childIndex].getOrdering()->d_order.size() ){
+ int curr_index = d_children_trie[childIndex].getOrdering()->d_order[trieIndex];
+ Node curr_ic = qe->getTermDatabase()->getInstantiationConstant( d_f, curr_index );
+ if( m.find( curr_ic )==m.end() ){
+ //if( d_var_to_node[ curr_index ].size()==1 ){ //FIXME
+ // //unique variable(s), defer calculation
+ // unique_var_tries.push_back( IndexedTrie( std::pair< int, int >( childIndex, trieIndex ), tr ) );
+ // int newChildIndex = (childIndex+1)%(int)d_children.size();
+ // processNewInstantiations( qe, m, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
+ // 0, newChildIndex, endChildIndex, modEq );
+ //}else{
+ //shared and non-set variable, add to InstMatch
+ for( std::map< Node, InstMatchTrie >::iterator it = tr->d_data.begin(); it != tr->d_data.end(); ++it ){
+ InstMatch mn( &m );
+ mn.set( curr_ic, it->first);
+ processNewInstantiations( qe, mn, addedLemmas, &(it->second), unique_var_tries,
+ trieIndex+1, childIndex, endChildIndex, modEq );
+ }
+ //}
+ }else{
+ //shared and set variable, try to merge
+ Node n = m.get( curr_ic );
+ std::map< Node, InstMatchTrie >::iterator it = tr->d_data.find( n );
+ if( it!=tr->d_data.end() ){
+ processNewInstantiations( qe, m, addedLemmas, &(it->second), unique_var_tries,
+ trieIndex+1, childIndex, endChildIndex, modEq );
+ }
+ if( modEq ){
+ //check modulo equality for other possible instantiations
+ if( qe->getEqualityQuery()->getEngine()->hasTerm( n ) ){
+ eq::EqClassIterator eqc( qe->getEqualityQuery()->getEngine()->getRepresentative( n ),
+ qe->getEqualityQuery()->getEngine() );
+ while( !eqc.isFinished() ){
+ Node en = (*eqc);
+ if( en!=n ){
+ std::map< Node, InstMatchTrie >::iterator itc = tr->d_data.find( en );
+ if( itc!=tr->d_data.end() ){
+ processNewInstantiations( qe, m, addedLemmas, &(itc->second), unique_var_tries,
+ trieIndex+1, childIndex, endChildIndex, modEq );
+ }
+ }
+ ++eqc;
+ }
+ }
+ }
+ }
+ }else{
+ int newChildIndex = (childIndex+1)%(int)d_children.size();
+ processNewInstantiations( qe, m, addedLemmas, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
+ 0, newChildIndex, endChildIndex, modEq );
+ }
+}
+
+void InstMatchGeneratorMulti::processNewInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
+ std::vector< IndexedTrie >& unique_var_tries,
+ int uvtIndex, InstMatchTrie* tr, int trieIndex ){
+ if( uvtIndex<(int)unique_var_tries.size() ){
+ int childIndex = unique_var_tries[uvtIndex].first.first;
+ if( !tr ){
+ tr = unique_var_tries[uvtIndex].second;
+ trieIndex = unique_var_tries[uvtIndex].first.second;
+ }
+ if( trieIndex<(int)d_children_trie[childIndex].getOrdering()->d_order.size() ){
+ int curr_index = d_children_trie[childIndex].getOrdering()->d_order[trieIndex];
+ Node curr_ic = qe->getTermDatabase()->getInstantiationConstant( d_f, curr_index );
+ //unique non-set variable, add to InstMatch
+ for( std::map< Node, InstMatchTrie >::iterator it = tr->d_data.begin(); it != tr->d_data.end(); ++it ){
+ InstMatch mn( &m );
+ mn.set( curr_ic, it->first);
+ processNewInstantiations2( qe, mn, addedLemmas, unique_var_tries, uvtIndex, &(it->second), trieIndex+1 );
+ }
+ }else{
+ processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, uvtIndex+1 );
+ }
+ }else{
+ //m is an instantiation
+ if( qe->addInstantiation( d_f, m ) ){
+ addedLemmas++;
+ Debug("smart-multi-trigger") << "-> Produced instantiation " << m << std::endl;
+ }
+ }
+}
+
+int InstMatchGeneratorMulti::addTerm( Node f, Node t, QuantifiersEngine* qe ){
+ Assert( options::eagerInstQuant() );
+ int addedLemmas = 0;
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ if( ((InstMatchGenerator*)d_children[i])->d_match_pattern.getOperator()==t.getOperator() ){
+ InstMatch m;
+ //if it produces a match, then process it with the rest
+ if( ((InstMatchGenerator*)d_children[i])->getMatch( f, t, m, qe ) ){
+ processNewMatch( qe, m, i, addedLemmas );
+ }
+ }
+ }
+ return addedLemmas;
+}
+
+int InstMatchGeneratorSimple::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
+ InstMatch m;
+ m.add( baseMatch );
+ int addedLemmas = 0;
+ if( d_match_pattern.getType()==NodeManager::currentNM()->booleanType() ){
+ for( int i=0; i<2; i++ ){
+ addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_pred_map_trie[i][ d_match_pattern.getOperator() ]) );
+ }
+ }else{
+ addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_func_map_trie[ d_match_pattern.getOperator() ]) );
+ }
+ return addedLemmas;
+}
+
+void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex, quantifiers::TermArgTrie* tat ){
+ if( argIndex==(int)d_match_pattern.getNumChildren() ){
+ //m is an instantiation
+ if( qe->addInstantiation( d_f, m ) ){
+ addedLemmas++;
+ Debug("simple-multi-trigger") << "-> Produced instantiation " << m << std::endl;
+ }
+ }else{
+ if( d_match_pattern[argIndex].getKind()==INST_CONSTANT ){
+ Node ic = d_match_pattern[argIndex];
+ for( std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
+ Node t = it->first;
+ if( ( m.get( ic ).isNull() || m.get( ic )==t ) && ic.getType()==t.getType() ){
+ Node prev = m.get( ic );
+ m.set( ic, t);
+ addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
+ m.set( ic, prev);
+ }
+ }
+ }else{
+ Node r = qe->getEqualityQuery()->getRepresentative( d_match_pattern[argIndex] );
+ std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.find( r );
+ if( it!=tat->d_data.end() ){
+ addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
+ }
+ }
+ }
+}
+
+int InstMatchGeneratorSimple::addTerm( Node f, Node t, QuantifiersEngine* qe ){
+ Assert( options::eagerInstQuant() );
+ InstMatch m;
+ for( int i=0; i<(int)t.getNumChildren(); i++ ){
+ if( d_match_pattern[i].getKind()==INST_CONSTANT ){
+ m.set(d_match_pattern[i], t[i]);
+ }else if( !qe->getEqualityQuery()->areEqual( d_match_pattern[i], t[i] ) ){
+ return 0;
+ }
+ }
+ return qe->addInstantiation( f, m ) ? 1 : 0;
+}
+
+}/* CVC4::theory::inst namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
diff --git a/src/theory/quantifiers/inst_match_generator.h b/src/theory/quantifiers/inst_match_generator.h
index af65e809b..b201fa60f 100755..100644
--- a/src/theory/quantifiers/inst_match_generator.h
+++ b/src/theory/quantifiers/inst_match_generator.h
@@ -1,192 +1,194 @@
-/********************* */
-/*! \file inst_match_generator.h
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: bobot
- ** Minor contributors (to current version): mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief inst match generator class
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__THEORY__QUANTIFIERS__INST_MATCH_GENERATOR_H
-#define __CVC4__THEORY__QUANTIFIERS__INST_MATCH_GENERATOR_H
-
-#include "theory/quantifiers/inst_match.h"
-#include <map>
-
-namespace CVC4 {
-namespace theory {
-
-class QuantifiersEngine;
-namespace quantifiers{
- class TermArgTrie;
-}
-
-namespace inst {
-
-/** base class for producing InstMatch objects */
-class IMGenerator {
-public:
- /** reset instantiation round (call this at beginning of instantiation round) */
- virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
- /** reset, eqc is the equivalence class to search in (any if eqc=null) */
- virtual void reset( Node eqc, QuantifiersEngine* qe ) = 0;
- /** get the next match. must call reset( eqc ) before this function. */
- virtual bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) = 0;
- /** add instantiations directly */
- virtual int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ) = 0;
- /** add ground term t, called when t is added to term db */
- virtual int addTerm( Node f, Node t, QuantifiersEngine* qe ) = 0;
-};/* class IMGenerator */
-
-class CandidateGenerator;
-
-class InstMatchGenerator : public IMGenerator {
-private:
- /** candidate generator */
- CandidateGenerator* d_cg;
- /** policy to use for matching */
- int d_matchPolicy;
- /** children generators */
- std::vector< InstMatchGenerator* > d_children;
- std::vector< int > d_children_index;
- /** partial vector */
- std::vector< InstMatch > d_partial;
- /** eq class */
- Node d_eq_class;
- /** for arithmetic matching */
- std::map< Node, Node > d_arith_coeffs;
- /** initialize pattern */
- void initializePatterns( std::vector< Node >& pats, QuantifiersEngine* qe );
- void initializePattern( Node pat, QuantifiersEngine* qe );
-public:
- enum {
- //options for producing matches
- MATCH_GEN_DEFAULT = 0,
- MATCH_GEN_EFFICIENT_E_MATCH, //generate matches via Efficient E-matching for SMT solvers
- //others (internally used)
- MATCH_GEN_INTERNAL_ARITHMETIC,
- MATCH_GEN_INTERNAL_ERROR,
- };
-private:
- /** get the next match. must call d_cg->reset( ... ) before using.
- only valid for use where !d_match_pattern.isNull().
- */
- bool getNextMatch2( InstMatch& m, QuantifiersEngine* qe, bool saveMatched = false );
- /** for arithmetic */
- bool getMatchArithmetic( Node t, InstMatch& m, QuantifiersEngine* qe );
-public:
- /** get the match against ground term or formula t.
- d_match_pattern and t should have the same shape.
- only valid for use where !d_match_pattern.isNull().
- */
- bool getMatch( Node t, InstMatch& m, QuantifiersEngine* qe );
-
- /** constructors */
- InstMatchGenerator( Node pat, QuantifiersEngine* qe, int matchOption = 0 );
- InstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption = 0 );
- /** destructor */
- ~InstMatchGenerator(){}
- /** The pattern we are producing matches for.
- If null, this is a multi trigger that is merging matches from d_children.
- */
- Node d_pattern;
- /** match pattern */
- Node d_match_pattern;
-public:
- /** reset instantiation round (call this whenever equivalence classes have changed) */
- void resetInstantiationRound( QuantifiersEngine* qe );
- /** reset, eqc is the equivalence class to search in (any if eqc=null) */
- void reset( Node eqc, QuantifiersEngine* qe );
- /** get the next match. must call reset( eqc ) before this function. */
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe );
- /** add instantiations */
- int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
- /** add ground term t */
- int addTerm( Node f, Node t, QuantifiersEngine* qe );
-};/* class InstMatchGenerator */
-
-/** smart multi-trigger implementation */
-class InstMatchGeneratorMulti : public IMGenerator {
-private:
- /** indexed trie */
- typedef std::pair< std::pair< int, int >, InstMatchTrie* > IndexedTrie;
- /** process new match */
- void processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas );
- /** process new instantiations */
- void processNewInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
- std::vector< IndexedTrie >& unique_var_tries,
- int trieIndex, int childIndex, int endChildIndex, bool modEq );
- /** process new instantiations 2 */
- void processNewInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
- std::vector< IndexedTrie >& unique_var_tries,
- int uvtIndex, InstMatchTrie* tr = NULL, int trieIndex = 0 );
-private:
- /** var contains (variable indices) for each pattern node */
- std::map< Node, std::vector< int > > d_var_contains;
- /** variable indices contained to pattern nodes */
- std::map< int, std::vector< Node > > d_var_to_node;
- /** quantifier to use */
- Node d_f;
- /** policy to use for matching */
- int d_matchPolicy;
- /** children generators */
- std::vector< InstMatchGenerator* > d_children;
- /** inst match tries for each child */
- std::vector< InstMatchTrieOrdered > d_children_trie;
- /** calculate matches */
- void calculateMatches( QuantifiersEngine* qe );
-public:
- /** constructors */
- InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption = 0 );
- /** destructor */
- ~InstMatchGeneratorMulti(){}
- /** reset instantiation round (call this whenever equivalence classes have changed) */
- void resetInstantiationRound( QuantifiersEngine* qe );
- /** reset, eqc is the equivalence class to search in (any if eqc=null) */
- void reset( Node eqc, QuantifiersEngine* qe );
- /** get the next match. must call reset( eqc ) before this function. (not implemented) */
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) { return false; }
- /** add instantiations */
- int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
- /** add ground term t */
- int addTerm( Node f, Node t, QuantifiersEngine* qe );
-};/* class InstMatchGeneratorMulti */
-
-/** smart (single)-trigger implementation */
-class InstMatchGeneratorSimple : public IMGenerator {
-private:
- /** quantifier for match term */
- Node d_f;
- /** match term */
- Node d_match_pattern;
- /** add instantiations */
- void addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex, quantifiers::TermArgTrie* tat );
-public:
- /** constructors */
- InstMatchGeneratorSimple( Node f, Node pat ) : d_f( f ), d_match_pattern( pat ){}
- /** destructor */
- ~InstMatchGeneratorSimple(){}
- /** reset instantiation round (call this whenever equivalence classes have changed) */
- void resetInstantiationRound( QuantifiersEngine* qe ) {}
- /** reset, eqc is the equivalence class to search in (any if eqc=null) */
- void reset( Node eqc, QuantifiersEngine* qe ) {}
- /** get the next match. must call reset( eqc ) before this function. (not implemented) */
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) { return false; }
- /** add instantiations */
- int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
- /** add ground term t, possibly add instantiations */
- int addTerm( Node f, Node t, QuantifiersEngine* qe );
-};/* class InstMatchGeneratorSimple */
-
-}
-}
-}
-
-#endif
+/********************* */
+/*! \file inst_match_generator.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief inst match generator class
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANTIFIERS__INST_MATCH_GENERATOR_H
+#define __CVC4__THEORY__QUANTIFIERS__INST_MATCH_GENERATOR_H
+
+#include "theory/quantifiers/inst_match.h"
+#include <map>
+
+namespace CVC4 {
+namespace theory {
+
+class QuantifiersEngine;
+namespace quantifiers{
+ class TermArgTrie;
+}
+
+namespace inst {
+
+/** base class for producing InstMatch objects */
+class IMGenerator {
+public:
+ /** reset instantiation round (call this at beginning of instantiation round) */
+ virtual void resetInstantiationRound( QuantifiersEngine* qe ) = 0;
+ /** reset, eqc is the equivalence class to search in (any if eqc=null) */
+ virtual void reset( Node eqc, QuantifiersEngine* qe ) = 0;
+ /** get the next match. must call reset( eqc ) before this function. */
+ virtual bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ) = 0;
+ /** add instantiations directly */
+ virtual int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ) = 0;
+ /** add ground term t, called when t is added to term db */
+ virtual int addTerm( Node f, Node t, QuantifiersEngine* qe ) = 0;
+ /** set active add */
+ virtual void setActiveAdd() {}
+};/* class IMGenerator */
+
+class CandidateGenerator;
+
+class InstMatchGenerator : public IMGenerator {
+private:
+ /** candidate generator */
+ CandidateGenerator* d_cg;
+ /** policy to use for matching */
+ int d_matchPolicy;
+ /** children generators */
+ std::vector< InstMatchGenerator* > d_children;
+ std::vector< int > d_children_index;
+ /** the next generator in order */
+ InstMatchGenerator* d_next;
+ /** eq class */
+ Node d_eq_class;
+ /** for arithmetic matching */
+ std::map< Node, Node > d_arith_coeffs;
+ /** initialize pattern */
+ void initialize( QuantifiersEngine* qe, std::vector< InstMatchGenerator * > & gens );
+public:
+ enum {
+ //options for producing matches
+ MATCH_GEN_DEFAULT = 0,
+ MATCH_GEN_EFFICIENT_E_MATCH, //generate matches via Efficient E-matching for SMT solvers
+ //others (internally used)
+ MATCH_GEN_INTERNAL_ARITHMETIC,
+ MATCH_GEN_INTERNAL_ERROR,
+ };
+private:
+ /** for arithmetic */
+ bool getMatchArithmetic( Node t, InstMatch& m, QuantifiersEngine* qe );
+public:
+ /** get the match against ground term or formula t.
+ d_match_pattern and t should have the same shape.
+ only valid for use where !d_match_pattern.isNull().
+ */
+ bool getMatch( Node f, Node t, InstMatch& m, QuantifiersEngine* qe );
+
+ /** constructors */
+ InstMatchGenerator( Node pat, int matchOption = 0 );
+ /** destructor */
+ ~InstMatchGenerator(){}
+ /** The pattern we are producing matches for.
+ If null, this is a multi trigger that is merging matches from d_children.
+ */
+ Node d_pattern;
+ /** match pattern */
+ Node d_match_pattern;
+public:
+ /** reset instantiation round (call this whenever equivalence classes have changed) */
+ void resetInstantiationRound( QuantifiersEngine* qe );
+ /** reset, eqc is the equivalence class to search in (any if eqc=null) */
+ void reset( Node eqc, QuantifiersEngine* qe );
+ /** get the next match. must call reset( eqc ) before this function. */
+ bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe );
+ /** add instantiations */
+ int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
+ /** add ground term t */
+ int addTerm( Node f, Node t, QuantifiersEngine* qe );
+
+ bool d_active_add;
+ void setActiveAdd();
+
+ static InstMatchGenerator* mkInstMatchGenerator( Node pat, QuantifiersEngine* qe );
+ static InstMatchGenerator* mkInstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe );
+};/* class InstMatchGenerator */
+
+/** smart multi-trigger implementation */
+class InstMatchGeneratorMulti : public IMGenerator {
+private:
+ /** indexed trie */
+ typedef std::pair< std::pair< int, int >, InstMatchTrie* > IndexedTrie;
+ /** process new match */
+ void processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas );
+ /** process new instantiations */
+ void processNewInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
+ std::vector< IndexedTrie >& unique_var_tries,
+ int trieIndex, int childIndex, int endChildIndex, bool modEq );
+ /** process new instantiations 2 */
+ void processNewInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
+ std::vector< IndexedTrie >& unique_var_tries,
+ int uvtIndex, InstMatchTrie* tr = NULL, int trieIndex = 0 );
+private:
+ /** var contains (variable indices) for each pattern node */
+ std::map< Node, std::vector< int > > d_var_contains;
+ /** variable indices contained to pattern nodes */
+ std::map< int, std::vector< Node > > d_var_to_node;
+ /** quantifier to use */
+ Node d_f;
+ /** policy to use for matching */
+ int d_matchPolicy;
+ /** children generators */
+ std::vector< InstMatchGenerator* > d_children;
+ /** inst match tries for each child */
+ std::vector< InstMatchTrieOrdered > d_children_trie;
+ /** calculate matches */
+ void calculateMatches( QuantifiersEngine* qe );
+public:
+ /** constructors */
+ InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption = 0 );
+ /** destructor */
+ ~InstMatchGeneratorMulti(){}
+ /** reset instantiation round (call this whenever equivalence classes have changed) */
+ void resetInstantiationRound( QuantifiersEngine* qe );
+ /** reset, eqc is the equivalence class to search in (any if eqc=null) */
+ void reset( Node eqc, QuantifiersEngine* qe );
+ /** get the next match. must call reset( eqc ) before this function. (not implemented) */
+ bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ) { return false; }
+ /** add instantiations */
+ int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
+ /** add ground term t */
+ int addTerm( Node f, Node t, QuantifiersEngine* qe );
+};/* class InstMatchGeneratorMulti */
+
+/** smart (single)-trigger implementation */
+class InstMatchGeneratorSimple : public IMGenerator {
+private:
+ /** quantifier for match term */
+ Node d_f;
+ /** match term */
+ Node d_match_pattern;
+ /** add instantiations */
+ void addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex, quantifiers::TermArgTrie* tat );
+public:
+ /** constructors */
+ InstMatchGeneratorSimple( Node f, Node pat ) : d_f( f ), d_match_pattern( pat ){}
+ /** destructor */
+ ~InstMatchGeneratorSimple(){}
+ /** reset instantiation round (call this whenever equivalence classes have changed) */
+ void resetInstantiationRound( QuantifiersEngine* qe ) {}
+ /** reset, eqc is the equivalence class to search in (any if eqc=null) */
+ void reset( Node eqc, QuantifiersEngine* qe ) {}
+ /** get the next match. must call reset( eqc ) before this function. (not implemented) */
+ bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ) { return false; }
+ /** add instantiations */
+ int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
+ /** add ground term t, possibly add instantiations */
+ int addTerm( Node f, Node t, QuantifiersEngine* qe );
+};/* class InstMatchGeneratorSimple */
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/inst_strategy_cbqi.cpp b/src/theory/quantifiers/inst_strategy_cbqi.cpp
index ddf763b73..b12fed619 100755..100644
--- a/src/theory/quantifiers/inst_strategy_cbqi.cpp
+++ b/src/theory/quantifiers/inst_strategy_cbqi.cpp
@@ -1,405 +1,405 @@
-/********************* */
-/*! \file inst_strategy_cbqi.cpp
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): bobot, mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Implementation of cbqi instantiation strategies
- **/
-
-#include "theory/quantifiers/inst_strategy_cbqi.h"
-#include "theory/arith/theory_arith.h"
-#include "theory/theory_engine.h"
-#include "theory/quantifiers/options.h"
-#include "theory/quantifiers/term_database.h"
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::quantifiers;
-using namespace CVC4::theory::arith;
-using namespace CVC4::theory::datatypes;
-
-#define ARITH_INSTANTIATOR_USE_MINUS_DELTA
-
-InstStrategySimplex::InstStrategySimplex( TheoryArith* th, QuantifiersEngine* ie ) :
- InstStrategy( ie ), d_th( th ), d_counter( 0 ){
- d_negOne = NodeManager::currentNM()->mkConst( Rational(-1) );
-}
-
-bool InstStrategySimplex::calculateShouldProcess( Node f ){
- //DO_THIS
- return false;
-}
-
-void InstStrategySimplex::processResetInstantiationRound( Theory::Effort effort ){
- Debug("quant-arith") << "Setting up simplex for instantiator... " << std::endl;
- d_instRows.clear();
- d_tableaux_term.clear();
- d_tableaux.clear();
- d_ceTableaux.clear();
- //search for instantiation rows in simplex tableaux
- ArithVarNodeMap& avnm = d_th->d_arithvarNodeMap;
- ArithVarNodeMap::var_iterator vi, vend;
- for(vi = avnm.var_begin(), vend = avnm.var_end(); vi != vend; ++vi ){
- ArithVar x = *vi;
- if( d_th->d_partialModel.hasEitherBound( x ) ){
- Node n = avnm.asNode(x);
- Node f;
- NodeBuilder<> t(kind::PLUS);
- if( n.getKind()==PLUS ){
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- addTermToRow( x, n[i], f, t );
- }
- }else{
- addTermToRow( x, n, f, t );
- }
- if( f!=Node::null() ){
- d_instRows[f].push_back( x );
- //this theory has constraints from f
- Debug("quant-arith") << "Has constraints from " << f << std::endl;
- //set that we should process it
- d_quantActive[ f ] = true;
- //set tableaux term
- if( t.getNumChildren()==0 ){
- d_tableaux_term[x] = NodeManager::currentNM()->mkConst( Rational(0) );
- }else if( t.getNumChildren()==1 ){
- d_tableaux_term[x] = t.getChild( 0 );
- }else{
- d_tableaux_term[x] = t;
- }
- }
- }
- }
- //print debug
- debugPrint( "quant-arith-debug" );
- d_counter++;
-}
-
-int InstStrategySimplex::process( Node f, Theory::Effort effort, int e ){
- if( e<2 ){
- return STATUS_UNFINISHED;
- }else if( e==2 ){
- //Notice() << f << std::endl;
- //Notice() << "Num inst rows = " << d_th->d_instRows[f].size() << std::endl;
- //Notice() << "Num inst constants = " << d_quantEngine->getNumInstantiationConstants( f ) << std::endl;
- Debug("quant-arith-simplex") << "InstStrategySimplex check " << f << ", rows = " << d_instRows[f].size() << std::endl;
- for( int j=0; j<(int)d_instRows[f].size(); j++ ){
- ArithVar x = d_instRows[f][j];
- if( !d_ceTableaux[x].empty() ){
- Debug("quant-arith-simplex") << "Check row " << x << std::endl;
- //instantiation row will be A*e + B*t = beta,
- // where e is a vector of terms , and t is vector of ground terms.
- // Say one term in A*e is coeff*e_i, where e_i is an instantiation constant
- // We will construct the term ( beta - B*t)/coeff to use for e_i.
- InstMatch m;
- //By default, choose the first instantiation constant to be e_i.
- Node var = d_ceTableaux[x].begin()->first;
- if( var.getType().isInteger() ){
- std::map< Node, Node >::iterator it = d_ceTableaux[x].begin();
- //try to find coefficent that is +/- 1
- while( !var.isNull() && !d_ceTableaux[x][var].isNull() && d_ceTableaux[x][var]!=d_negOne ){
- ++it;
- if( it==d_ceTableaux[x].end() ){
- var = Node::null();
- }else{
- var = it->first;
- }
- }
- //otherwise, try one that divides all ground term coefficients? DO_THIS
- }
- if( !var.isNull() ){
- Debug("quant-arith-simplex") << "Instantiate with var " << var << std::endl;
- doInstantiation( f, d_tableaux_term[x], x, m, var );
- }else{
- Debug("quant-arith-simplex") << "Could not find var." << std::endl;
- }
- ////choose a new variable based on alternation strategy
- //int index = d_counter%(int)d_th->d_ceTableaux[x].size();
- //Node var;
- //for( std::map< Node, Node >::iterator it = d_th->d_ceTableaux[x].begin(); it != d_th->d_ceTableaux[x].end(); ++it ){
- // if( index==0 ){
- // var = it->first;
- // break;
- // }
- // index--;
- //}
- //d_th->doInstantiation( f, d_th->d_tableaux_term[x], x, &m, var );
- }
- }
- }
- return STATUS_UNKNOWN;
-}
-
-
-void InstStrategySimplex::addTermToRow( ArithVar x, Node n, Node& f, NodeBuilder<>& t ){
- if( n.getKind()==MULT ){
- if( n[1].hasAttribute(InstConstantAttribute()) ){
- f = n[1].getAttribute(InstConstantAttribute());
- if( n[1].getKind()==INST_CONSTANT ){
- d_ceTableaux[x][ n[1] ] = n[0];
- }else{
- d_tableaux_ce_term[x][ n[1] ] = n[0];
- }
- }else{
- d_tableaux[x][ n[1] ] = n[0];
- t << n;
- }
- }else{
- if( n.hasAttribute(InstConstantAttribute()) ){
- f = n.getAttribute(InstConstantAttribute());
- if( n.getKind()==INST_CONSTANT ){
- d_ceTableaux[x][ n ] = Node::null();
- }else{
- d_tableaux_ce_term[x][ n ] = NodeManager::currentNM()->mkConst( Rational(1) );
- }
- }else{
- d_tableaux[x][ n ] = NodeManager::currentNM()->mkConst( Rational(1) );
- t << n;
- }
- }
-}
-
-void InstStrategySimplex::debugPrint( const char* c ){
- const ArithVarNodeMap& avnm = d_th->d_arithvarNodeMap;
- ArithVarNodeMap::var_iterator vi, vend;
- for(vi = avnm.var_begin(), vend = avnm.var_end(); vi != vend; ++vi ){
- ArithVar x = *vi;
- Node n = avnm.asNode(x);
- //if( ((TheoryArith*)getTheory())->d_partialModel.hasEitherBound( x ) ){
- Debug(c) << x << " : " << n << ", bounds = ";
- if( d_th->d_partialModel.hasLowerBound( x ) ){
- Debug(c) << d_th->d_partialModel.getLowerBound( x );
- }else{
- Debug(c) << "-infty";
- }
- Debug(c) << " <= ";
- Debug(c) << d_th->d_partialModel.getAssignment( x );
- Debug(c) << " <= ";
- if( d_th->d_partialModel.hasUpperBound( x ) ){
- Debug(c) << d_th->d_partialModel.getUpperBound( x );
- }else{
- Debug(c) << "+infty";
- }
- Debug(c) << std::endl;
- //Debug(c) << " Term = " << d_tableaux_term[x] << std::endl;
- //Debug(c) << " ";
- //for( std::map< Node, Node >::iterator it2 = d_tableaux[x].begin(); it2 != d_tableaux[x].end(); ++it2 ){
- // Debug(c) << "( " << it2->first << ", " << it2->second << " ) ";
- //}
- //for( std::map< Node, Node >::iterator it2 = d_ceTableaux[x].begin(); it2 != d_ceTableaux[x].end(); ++it2 ){
- // Debug(c) << "(CE)( " << it2->first << ", " << it2->second << " ) ";
- //}
- //for( std::map< Node, Node >::iterator it2 = d_tableaux_ce_term[x].begin(); it2 != d_tableaux_ce_term[x].end(); ++it2 ){
- // Debug(c) << "(CE-term)( " << it2->first << ", " << it2->second << " ) ";
- //}
- //Debug(c) << std::endl;
- //}
- }
- Debug(c) << std::endl;
-
- for( int q=0; q<d_quantEngine->getNumQuantifiers(); q++ ){
- Node f = d_quantEngine->getQuantifier( q );
- Debug(c) << f << std::endl;
- Debug(c) << " Inst constants: ";
- for( int i=0; i<(int)d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
- if( i>0 ){
- Debug( c ) << ", ";
- }
- Debug( c ) << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i );
- }
- Debug(c) << std::endl;
- Debug(c) << " Instantiation rows: ";
- for( int i=0; i<(int)d_instRows[f].size(); i++ ){
- if( i>0 ){
- Debug(c) << ", ";
- }
- Debug(c) << d_instRows[f][i];
- }
- Debug(c) << std::endl;
- }
-}
-
-//say instantiation row x for quantifier f is coeff*var + A*t[e] + term = beta,
-// where var is an instantiation constant from f,
-// t[e] is a vector of terms containing instantiation constants from f,
-// and term is a ground term (c1*t1 + ... + cn*tn).
-// We construct the term ( beta - term )/coeff to use as an instantiation for var.
-bool InstStrategySimplex::doInstantiation( Node f, Node term, ArithVar x, InstMatch& m, Node var ){
- //first try +delta
- if( doInstantiation2( f, term, x, m, var ) ){
- ++(d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_cbqi_arith);
- return true;
- }else{
-#ifdef ARITH_INSTANTIATOR_USE_MINUS_DELTA
- //otherwise try -delta
- if( doInstantiation2( f, term, x, m, var, true ) ){
- ++(d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_cbqi_arith_minus);
- return true;
- }else{
- return false;
- }
-#else
- return false;
-#endif
- }
-}
-
-bool InstStrategySimplex::doInstantiation2( Node f, Node term, ArithVar x, InstMatch& m, Node var, bool minus_delta ){
- // make term ( beta - term )/coeff
- Node beta = getTableauxValue( x, minus_delta );
- Node instVal = NodeManager::currentNM()->mkNode( MINUS, beta, term );
- if( !d_ceTableaux[x][var].isNull() ){
- if( var.getType().isInteger() ){
- Assert( d_ceTableaux[x][var]==NodeManager::currentNM()->mkConst( Rational(-1) ) );
- instVal = NodeManager::currentNM()->mkNode( MULT, d_ceTableaux[x][var], instVal );
- }else{
- Node coeff = NodeManager::currentNM()->mkConst( Rational(1) / d_ceTableaux[x][var].getConst<Rational>() );
- instVal = NodeManager::currentNM()->mkNode( MULT, coeff, instVal );
- }
- }
- instVal = Rewriter::rewrite( instVal );
- //use as instantiation value for var
- m.set(var, instVal);
- Debug("quant-arith") << "Add instantiation " << m << std::endl;
- return d_quantEngine->addInstantiation( f, m );
-}
-
-Node InstStrategySimplex::getTableauxValue( Node n, bool minus_delta ){
- if( d_th->d_arithvarNodeMap.hasArithVar(n) ){
- ArithVar v = d_th->d_arithvarNodeMap.asArithVar( n );
- return getTableauxValue( v, minus_delta );
- }else{
- return NodeManager::currentNM()->mkConst( Rational(0) );
- }
-}
-
-Node InstStrategySimplex::getTableauxValue( ArithVar v, bool minus_delta ){
- const Rational& delta = d_th->d_partialModel.getDelta();
- DeltaRational drv = d_th->d_partialModel.getAssignment( v );
- Rational qmodel = drv.substituteDelta( minus_delta ? -delta : delta );
- return mkRationalNode(qmodel);
-}
-
-
-InstStrategyDatatypesValue::InstStrategyDatatypesValue( TheoryDatatypes* th, QuantifiersEngine* qe ) :
- InstStrategy( qe ), d_th( th ){
-
-}
-
-bool InstStrategyDatatypesValue::calculateShouldProcess( Node f ){
- //DO_THIS
- return false;
-}
-
-void InstStrategyDatatypesValue::processResetInstantiationRound( Theory::Effort effort ){
-
-}
-
-int InstStrategyDatatypesValue::process( Node f, Theory::Effort effort, int e ){
- Debug("quant-datatypes") << "Datatypes: Try to solve (" << e << ") for " << f << "... " << std::endl;
- if( e<2 ){
- return InstStrategy::STATUS_UNFINISHED;
- }else if( e==2 ){
- InstMatch m;
- for( int j = 0; j<(int)d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); j++ ){
- Node i = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );
- if( i.getType().isDatatype() ){
- Node n = getValueFor( i );
- Debug("quant-datatypes-debug") << "Value for " << i << " is " << n << std::endl;
- m.set(i,n);
- }
- }
- //d_quantEngine->addInstantiation( f, m );
- }
- return InstStrategy::STATUS_UNKNOWN;
-}
-
-Node InstStrategyDatatypesValue::getValueFor( Node n ){
- //simply get the ground value for n in the current model, if it exists,
- // or return an arbitrary ground term otherwise
- if( !n.hasAttribute(InstConstantAttribute()) ){
- return n;
- }else{
- return n;
- }
- /* FIXME
-
- Debug("quant-datatypes-debug") << "get value for " << n << std::endl;
- if( !n.hasAttribute(InstConstantAttribute()) ){
- return n;
- }else{
- Assert( n.getType().isDatatype() );
- //check if in equivalence class with ground term
- Node rep = getRepresentative( n );
- Debug("quant-datatypes-debug") << "Rep is " << rep << std::endl;
- if( !rep.hasAttribute(InstConstantAttribute()) ){
- return rep;
- }else{
- if( !n.getType().isDatatype() ){
- return n.getType().mkGroundTerm();
- }else{
- if( n.getKind()==APPLY_CONSTRUCTOR ){
- std::vector< Node > children;
- children.push_back( n.getOperator() );
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- children.push_back( getValueFor( n[i] ) );
- }
- return NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, children );
- }else{
- const Datatype& dt = ((DatatypeType)(n.getType()).toType()).getDatatype();
- TheoryDatatypes::EqLists* labels = &((TheoryDatatypes*)d_th)->d_labels;
- //otherwise, use which constructor the inst constant is current chosen to be
- if( labels->find( n )!=labels->end() ){
- TheoryDatatypes::EqList* lbl = (*labels->find( n )).second;
- int tIndex = -1;
- if( !lbl->empty() && (*lbl)[ lbl->size()-1 ].getKind()==APPLY_TESTER ){
- Debug("quant-datatypes-debug") << n << " tester is " << (*lbl)[ lbl->size()-1 ] << std::endl;
- tIndex = Datatype::indexOf((*lbl)[ lbl->size()-1 ].getOperator().toExpr());
- }else{
- Debug("quant-datatypes-debug") << "find possible tester choice" << std::endl;
- //must find a possible choice
- vector< bool > possibleCons;
- possibleCons.resize( dt.getNumConstructors(), true );
- for( TheoryDatatypes::EqList::const_iterator j = lbl->begin(); j != lbl->end(); j++ ) {
- Node leqn = (*j);
- possibleCons[ Datatype::indexOf( leqn[0].getOperator().toExpr() ) ] = false;
- }
- for( unsigned int j=0; j<possibleCons.size(); j++ ) {
- if( possibleCons[j] ){
- tIndex = j;
- break;
- }
- }
- }
- Assert( tIndex!=-1 );
- Node cons = Node::fromExpr( dt[ tIndex ].getConstructor() );
- Debug("quant-datatypes-debug") << n << " cons is " << cons << std::endl;
- std::vector< Node > children;
- children.push_back( cons );
- for( int i=0; i<(int)dt[ tIndex ].getNumArgs(); i++ ) {
- Node sn = NodeManager::currentNM()->mkNode( APPLY_SELECTOR, Node::fromExpr( dt[tIndex][i].getSelector() ), n );
- if( n.hasAttribute(InstConstantAttribute()) ){
- InstConstantAttribute ica;
- sn.setAttribute(ica,n.getAttribute(InstConstantAttribute()) );
- }
- Node snn = getValueFor( sn );
- children.push_back( snn );
- }
- return NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, children );
- }else{
- return n.getType().mkGroundTerm();
- }
- }
- }
- }
- }
- */
-}
+/********************* */
+/*! \file inst_strategy_cbqi.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Implementation of cbqi instantiation strategies
+ **/
+
+#include "theory/quantifiers/inst_strategy_cbqi.h"
+#include "theory/arith/theory_arith.h"
+#include "theory/theory_engine.h"
+#include "theory/quantifiers/options.h"
+#include "theory/quantifiers/term_database.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+using namespace CVC4::theory::arith;
+using namespace CVC4::theory::datatypes;
+
+#define ARITH_INSTANTIATOR_USE_MINUS_DELTA
+
+InstStrategySimplex::InstStrategySimplex( TheoryArith* th, QuantifiersEngine* ie ) :
+ InstStrategy( ie ), d_th( th ), d_counter( 0 ){
+ d_negOne = NodeManager::currentNM()->mkConst( Rational(-1) );
+}
+
+bool InstStrategySimplex::calculateShouldProcess( Node f ){
+ //DO_THIS
+ return false;
+}
+
+void InstStrategySimplex::processResetInstantiationRound( Theory::Effort effort ){
+ Debug("quant-arith") << "Setting up simplex for instantiator... " << std::endl;
+ d_instRows.clear();
+ d_tableaux_term.clear();
+ d_tableaux.clear();
+ d_ceTableaux.clear();
+ //search for instantiation rows in simplex tableaux
+ ArithVarNodeMap& avnm = d_th->d_arithvarNodeMap;
+ ArithVarNodeMap::var_iterator vi, vend;
+ for(vi = avnm.var_begin(), vend = avnm.var_end(); vi != vend; ++vi ){
+ ArithVar x = *vi;
+ if( d_th->d_partialModel.hasEitherBound( x ) ){
+ Node n = avnm.asNode(x);
+ Node f;
+ NodeBuilder<> t(kind::PLUS);
+ if( n.getKind()==PLUS ){
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ addTermToRow( x, n[i], f, t );
+ }
+ }else{
+ addTermToRow( x, n, f, t );
+ }
+ if( f!=Node::null() ){
+ d_instRows[f].push_back( x );
+ //this theory has constraints from f
+ Debug("quant-arith") << "Has constraints from " << f << std::endl;
+ //set that we should process it
+ d_quantActive[ f ] = true;
+ //set tableaux term
+ if( t.getNumChildren()==0 ){
+ d_tableaux_term[x] = NodeManager::currentNM()->mkConst( Rational(0) );
+ }else if( t.getNumChildren()==1 ){
+ d_tableaux_term[x] = t.getChild( 0 );
+ }else{
+ d_tableaux_term[x] = t;
+ }
+ }
+ }
+ }
+ //print debug
+ debugPrint( "quant-arith-debug" );
+ d_counter++;
+}
+
+int InstStrategySimplex::process( Node f, Theory::Effort effort, int e ){
+ if( e<2 ){
+ return STATUS_UNFINISHED;
+ }else if( e==2 ){
+ //Notice() << f << std::endl;
+ //Notice() << "Num inst rows = " << d_th->d_instRows[f].size() << std::endl;
+ //Notice() << "Num inst constants = " << d_quantEngine->getNumInstantiationConstants( f ) << std::endl;
+ Debug("quant-arith-simplex") << "InstStrategySimplex check " << f << ", rows = " << d_instRows[f].size() << std::endl;
+ for( int j=0; j<(int)d_instRows[f].size(); j++ ){
+ ArithVar x = d_instRows[f][j];
+ if( !d_ceTableaux[x].empty() ){
+ Debug("quant-arith-simplex") << "Check row " << x << std::endl;
+ //instantiation row will be A*e + B*t = beta,
+ // where e is a vector of terms , and t is vector of ground terms.
+ // Say one term in A*e is coeff*e_i, where e_i is an instantiation constant
+ // We will construct the term ( beta - B*t)/coeff to use for e_i.
+ InstMatch m;
+ //By default, choose the first instantiation constant to be e_i.
+ Node var = d_ceTableaux[x].begin()->first;
+ if( var.getType().isInteger() ){
+ std::map< Node, Node >::iterator it = d_ceTableaux[x].begin();
+ //try to find coefficent that is +/- 1
+ while( !var.isNull() && !d_ceTableaux[x][var].isNull() && d_ceTableaux[x][var]!=d_negOne ){
+ ++it;
+ if( it==d_ceTableaux[x].end() ){
+ var = Node::null();
+ }else{
+ var = it->first;
+ }
+ }
+ //otherwise, try one that divides all ground term coefficients? DO_THIS
+ }
+ if( !var.isNull() ){
+ Debug("quant-arith-simplex") << "Instantiate with var " << var << std::endl;
+ doInstantiation( f, d_tableaux_term[x], x, m, var );
+ }else{
+ Debug("quant-arith-simplex") << "Could not find var." << std::endl;
+ }
+ ////choose a new variable based on alternation strategy
+ //int index = d_counter%(int)d_th->d_ceTableaux[x].size();
+ //Node var;
+ //for( std::map< Node, Node >::iterator it = d_th->d_ceTableaux[x].begin(); it != d_th->d_ceTableaux[x].end(); ++it ){
+ // if( index==0 ){
+ // var = it->first;
+ // break;
+ // }
+ // index--;
+ //}
+ //d_th->doInstantiation( f, d_th->d_tableaux_term[x], x, &m, var );
+ }
+ }
+ }
+ return STATUS_UNKNOWN;
+}
+
+
+void InstStrategySimplex::addTermToRow( ArithVar x, Node n, Node& f, NodeBuilder<>& t ){
+ if( n.getKind()==MULT ){
+ if( n[1].hasAttribute(InstConstantAttribute()) ){
+ f = n[1].getAttribute(InstConstantAttribute());
+ if( n[1].getKind()==INST_CONSTANT ){
+ d_ceTableaux[x][ n[1] ] = n[0];
+ }else{
+ d_tableaux_ce_term[x][ n[1] ] = n[0];
+ }
+ }else{
+ d_tableaux[x][ n[1] ] = n[0];
+ t << n;
+ }
+ }else{
+ if( n.hasAttribute(InstConstantAttribute()) ){
+ f = n.getAttribute(InstConstantAttribute());
+ if( n.getKind()==INST_CONSTANT ){
+ d_ceTableaux[x][ n ] = Node::null();
+ }else{
+ d_tableaux_ce_term[x][ n ] = NodeManager::currentNM()->mkConst( Rational(1) );
+ }
+ }else{
+ d_tableaux[x][ n ] = NodeManager::currentNM()->mkConst( Rational(1) );
+ t << n;
+ }
+ }
+}
+
+void InstStrategySimplex::debugPrint( const char* c ){
+ const ArithVarNodeMap& avnm = d_th->d_arithvarNodeMap;
+ ArithVarNodeMap::var_iterator vi, vend;
+ for(vi = avnm.var_begin(), vend = avnm.var_end(); vi != vend; ++vi ){
+ ArithVar x = *vi;
+ Node n = avnm.asNode(x);
+ //if( ((TheoryArith*)getTheory())->d_partialModel.hasEitherBound( x ) ){
+ Debug(c) << x << " : " << n << ", bounds = ";
+ if( d_th->d_partialModel.hasLowerBound( x ) ){
+ Debug(c) << d_th->d_partialModel.getLowerBound( x );
+ }else{
+ Debug(c) << "-infty";
+ }
+ Debug(c) << " <= ";
+ Debug(c) << d_th->d_partialModel.getAssignment( x );
+ Debug(c) << " <= ";
+ if( d_th->d_partialModel.hasUpperBound( x ) ){
+ Debug(c) << d_th->d_partialModel.getUpperBound( x );
+ }else{
+ Debug(c) << "+infty";
+ }
+ Debug(c) << std::endl;
+ //Debug(c) << " Term = " << d_tableaux_term[x] << std::endl;
+ //Debug(c) << " ";
+ //for( std::map< Node, Node >::iterator it2 = d_tableaux[x].begin(); it2 != d_tableaux[x].end(); ++it2 ){
+ // Debug(c) << "( " << it2->first << ", " << it2->second << " ) ";
+ //}
+ //for( std::map< Node, Node >::iterator it2 = d_ceTableaux[x].begin(); it2 != d_ceTableaux[x].end(); ++it2 ){
+ // Debug(c) << "(CE)( " << it2->first << ", " << it2->second << " ) ";
+ //}
+ //for( std::map< Node, Node >::iterator it2 = d_tableaux_ce_term[x].begin(); it2 != d_tableaux_ce_term[x].end(); ++it2 ){
+ // Debug(c) << "(CE-term)( " << it2->first << ", " << it2->second << " ) ";
+ //}
+ //Debug(c) << std::endl;
+ //}
+ }
+ Debug(c) << std::endl;
+
+ for( int q=0; q<d_quantEngine->getNumQuantifiers(); q++ ){
+ Node f = d_quantEngine->getQuantifier( q );
+ Debug(c) << f << std::endl;
+ Debug(c) << " Inst constants: ";
+ for( int i=0; i<(int)d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
+ if( i>0 ){
+ Debug( c ) << ", ";
+ }
+ Debug( c ) << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i );
+ }
+ Debug(c) << std::endl;
+ Debug(c) << " Instantiation rows: ";
+ for( int i=0; i<(int)d_instRows[f].size(); i++ ){
+ if( i>0 ){
+ Debug(c) << ", ";
+ }
+ Debug(c) << d_instRows[f][i];
+ }
+ Debug(c) << std::endl;
+ }
+}
+
+//say instantiation row x for quantifier f is coeff*var + A*t[e] + term = beta,
+// where var is an instantiation constant from f,
+// t[e] is a vector of terms containing instantiation constants from f,
+// and term is a ground term (c1*t1 + ... + cn*tn).
+// We construct the term ( beta - term )/coeff to use as an instantiation for var.
+bool InstStrategySimplex::doInstantiation( Node f, Node term, ArithVar x, InstMatch& m, Node var ){
+ //first try +delta
+ if( doInstantiation2( f, term, x, m, var ) ){
+ ++(d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_cbqi_arith);
+ return true;
+ }else{
+#ifdef ARITH_INSTANTIATOR_USE_MINUS_DELTA
+ //otherwise try -delta
+ if( doInstantiation2( f, term, x, m, var, true ) ){
+ ++(d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_cbqi_arith_minus);
+ return true;
+ }else{
+ return false;
+ }
+#else
+ return false;
+#endif
+ }
+}
+
+bool InstStrategySimplex::doInstantiation2( Node f, Node term, ArithVar x, InstMatch& m, Node var, bool minus_delta ){
+ // make term ( beta - term )/coeff
+ Node beta = getTableauxValue( x, minus_delta );
+ Node instVal = NodeManager::currentNM()->mkNode( MINUS, beta, term );
+ if( !d_ceTableaux[x][var].isNull() ){
+ if( var.getType().isInteger() ){
+ Assert( d_ceTableaux[x][var]==NodeManager::currentNM()->mkConst( Rational(-1) ) );
+ instVal = NodeManager::currentNM()->mkNode( MULT, d_ceTableaux[x][var], instVal );
+ }else{
+ Node coeff = NodeManager::currentNM()->mkConst( Rational(1) / d_ceTableaux[x][var].getConst<Rational>() );
+ instVal = NodeManager::currentNM()->mkNode( MULT, coeff, instVal );
+ }
+ }
+ instVal = Rewriter::rewrite( instVal );
+ //use as instantiation value for var
+ m.set(var, instVal);
+ Debug("quant-arith") << "Add instantiation " << m << std::endl;
+ return d_quantEngine->addInstantiation( f, m );
+}
+
+Node InstStrategySimplex::getTableauxValue( Node n, bool minus_delta ){
+ if( d_th->d_arithvarNodeMap.hasArithVar(n) ){
+ ArithVar v = d_th->d_arithvarNodeMap.asArithVar( n );
+ return getTableauxValue( v, minus_delta );
+ }else{
+ return NodeManager::currentNM()->mkConst( Rational(0) );
+ }
+}
+
+Node InstStrategySimplex::getTableauxValue( ArithVar v, bool minus_delta ){
+ const Rational& delta = d_th->d_partialModel.getDelta();
+ DeltaRational drv = d_th->d_partialModel.getAssignment( v );
+ Rational qmodel = drv.substituteDelta( minus_delta ? -delta : delta );
+ return mkRationalNode(qmodel);
+}
+
+
+InstStrategyDatatypesValue::InstStrategyDatatypesValue( TheoryDatatypes* th, QuantifiersEngine* qe ) :
+ InstStrategy( qe ), d_th( th ){
+
+}
+
+bool InstStrategyDatatypesValue::calculateShouldProcess( Node f ){
+ //DO_THIS
+ return false;
+}
+
+void InstStrategyDatatypesValue::processResetInstantiationRound( Theory::Effort effort ){
+
+}
+
+int InstStrategyDatatypesValue::process( Node f, Theory::Effort effort, int e ){
+ Debug("quant-datatypes") << "Datatypes: Try to solve (" << e << ") for " << f << "... " << std::endl;
+ if( e<2 ){
+ return InstStrategy::STATUS_UNFINISHED;
+ }else if( e==2 ){
+ InstMatch m;
+ for( int j = 0; j<(int)d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); j++ ){
+ Node i = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );
+ if( i.getType().isDatatype() ){
+ Node n = getValueFor( i );
+ Debug("quant-datatypes-debug") << "Value for " << i << " is " << n << std::endl;
+ m.set(i,n);
+ }
+ }
+ //d_quantEngine->addInstantiation( f, m );
+ }
+ return InstStrategy::STATUS_UNKNOWN;
+}
+
+Node InstStrategyDatatypesValue::getValueFor( Node n ){
+ //simply get the ground value for n in the current model, if it exists,
+ // or return an arbitrary ground term otherwise
+ if( !n.hasAttribute(InstConstantAttribute()) ){
+ return n;
+ }else{
+ return n;
+ }
+ /* FIXME
+
+ Debug("quant-datatypes-debug") << "get value for " << n << std::endl;
+ if( !n.hasAttribute(InstConstantAttribute()) ){
+ return n;
+ }else{
+ Assert( n.getType().isDatatype() );
+ //check if in equivalence class with ground term
+ Node rep = getRepresentative( n );
+ Debug("quant-datatypes-debug") << "Rep is " << rep << std::endl;
+ if( !rep.hasAttribute(InstConstantAttribute()) ){
+ return rep;
+ }else{
+ if( !n.getType().isDatatype() ){
+ return n.getType().mkGroundTerm();
+ }else{
+ if( n.getKind()==APPLY_CONSTRUCTOR ){
+ std::vector< Node > children;
+ children.push_back( n.getOperator() );
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ children.push_back( getValueFor( n[i] ) );
+ }
+ return NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, children );
+ }else{
+ const Datatype& dt = ((DatatypeType)(n.getType()).toType()).getDatatype();
+ TheoryDatatypes::EqLists* labels = &((TheoryDatatypes*)d_th)->d_labels;
+ //otherwise, use which constructor the inst constant is current chosen to be
+ if( labels->find( n )!=labels->end() ){
+ TheoryDatatypes::EqList* lbl = (*labels->find( n )).second;
+ int tIndex = -1;
+ if( !lbl->empty() && (*lbl)[ lbl->size()-1 ].getKind()==APPLY_TESTER ){
+ Debug("quant-datatypes-debug") << n << " tester is " << (*lbl)[ lbl->size()-1 ] << std::endl;
+ tIndex = Datatype::indexOf((*lbl)[ lbl->size()-1 ].getOperator().toExpr());
+ }else{
+ Debug("quant-datatypes-debug") << "find possible tester choice" << std::endl;
+ //must find a possible choice
+ vector< bool > possibleCons;
+ possibleCons.resize( dt.getNumConstructors(), true );
+ for( TheoryDatatypes::EqList::const_iterator j = lbl->begin(); j != lbl->end(); j++ ) {
+ Node leqn = (*j);
+ possibleCons[ Datatype::indexOf( leqn[0].getOperator().toExpr() ) ] = false;
+ }
+ for( unsigned int j=0; j<possibleCons.size(); j++ ) {
+ if( possibleCons[j] ){
+ tIndex = j;
+ break;
+ }
+ }
+ }
+ Assert( tIndex!=-1 );
+ Node cons = Node::fromExpr( dt[ tIndex ].getConstructor() );
+ Debug("quant-datatypes-debug") << n << " cons is " << cons << std::endl;
+ std::vector< Node > children;
+ children.push_back( cons );
+ for( int i=0; i<(int)dt[ tIndex ].getNumArgs(); i++ ) {
+ Node sn = NodeManager::currentNM()->mkNode( APPLY_SELECTOR, Node::fromExpr( dt[tIndex][i].getSelector() ), n );
+ if( n.hasAttribute(InstConstantAttribute()) ){
+ InstConstantAttribute ica;
+ sn.setAttribute(ica,n.getAttribute(InstConstantAttribute()) );
+ }
+ Node snn = getValueFor( sn );
+ children.push_back( snn );
+ }
+ return NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, children );
+ }else{
+ return n.getType().mkGroundTerm();
+ }
+ }
+ }
+ }
+ }
+ */
+}
diff --git a/src/theory/quantifiers/inst_strategy_cbqi.h b/src/theory/quantifiers/inst_strategy_cbqi.h
index 3ee423fe7..de548ab14 100755..100644
--- a/src/theory/quantifiers/inst_strategy_cbqi.h
+++ b/src/theory/quantifiers/inst_strategy_cbqi.h
@@ -1,110 +1,110 @@
-/********************* */
-/*! \file inst_strategy_cbqi.h
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief instantiator_arith_instantiator
- **/
-
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__INST_STRATEGT_CBQI_H
-#define __CVC4__INST_STRATEGT_CBQI_H
-
-#include "theory/quantifiers/instantiation_engine.h"
-#include "theory/arith/arithvar_node_map.h"
-
-#include "util/statistics_registry.h"
-
-namespace CVC4 {
-namespace theory {
-
-namespace arith {
- class TheoryArith;
-}
-
-namespace datatypes {
- class TheoryDatatypes;
-}
-
-namespace quantifiers {
-
-
-class InstStrategySimplex : public InstStrategy{
-protected:
- /** calculate if we should process this quantifier */
- bool calculateShouldProcess( Node f );
-private:
- /** reference to theory arithmetic */
- arith::TheoryArith* d_th;
- /** delta */
- std::map< TypeNode, Node > d_deltas;
- /** for each quantifier, simplex rows */
- std::map< Node, std::vector< arith::ArithVar > > d_instRows;
- /** tableaux */
- std::map< arith::ArithVar, Node > d_tableaux_term;
- std::map< arith::ArithVar, std::map< Node, Node > > d_tableaux_ce_term;
- std::map< arith::ArithVar, std::map< Node, Node > > d_tableaux;
- /** ce tableaux */
- std::map< arith::ArithVar, std::map< Node, Node > > d_ceTableaux;
- /** get value */
- Node getTableauxValue( Node n, bool minus_delta = false );
- Node getTableauxValue( arith::ArithVar v, bool minus_delta = false );
- /** do instantiation */
- bool doInstantiation( Node f, Node term, arith::ArithVar x, InstMatch& m, Node var );
- bool doInstantiation2( Node f, Node term, arith::ArithVar x, InstMatch& m, Node var, bool minus_delta = false );
- /** add term to row */
- void addTermToRow( arith::ArithVar x, Node n, Node& f, NodeBuilder<>& t );
- /** print debug */
- void debugPrint( const char* c );
-private:
- /** */
- int d_counter;
- /** negative one */
- Node d_negOne;
- /** process functions */
- void processResetInstantiationRound( Theory::Effort effort );
- int process( Node f, Theory::Effort effort, int e );
-public:
- InstStrategySimplex( arith::TheoryArith* th, QuantifiersEngine* ie );
- ~InstStrategySimplex(){}
- /** identify */
- std::string identify() const { return std::string("Simplex"); }
-};
-
-
-class InstStrategyDatatypesValue : public InstStrategy
-{
-protected:
- /** calculate if we should process this quantifier */
- bool calculateShouldProcess( Node f );
-private:
- /** reference to theory datatypes */
- datatypes::TheoryDatatypes* d_th;
- /** get value function */
- Node getValueFor( Node n );
-public:
- //constructor
- InstStrategyDatatypesValue( datatypes::TheoryDatatypes* th, QuantifiersEngine* qe );
- ~InstStrategyDatatypesValue(){}
- /** reset instantiation */
- void processResetInstantiationRound( Theory::Effort effort );
- /** process method, returns a status */
- int process( Node f, Theory::Effort effort, int e );
- /** identify */
- std::string identify() const { return std::string("InstStrategyDatatypesValue"); }
-
-};/* class InstStrategy */
-
-}
-}
-}
-
+/********************* */
+/*! \file inst_strategy_cbqi.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief instantiator_arith_instantiator
+ **/
+
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__INST_STRATEGT_CBQI_H
+#define __CVC4__INST_STRATEGT_CBQI_H
+
+#include "theory/quantifiers/instantiation_engine.h"
+#include "theory/arith/arithvar_node_map.h"
+
+#include "util/statistics_registry.h"
+
+namespace CVC4 {
+namespace theory {
+
+namespace arith {
+ class TheoryArith;
+}
+
+namespace datatypes {
+ class TheoryDatatypes;
+}
+
+namespace quantifiers {
+
+
+class InstStrategySimplex : public InstStrategy{
+protected:
+ /** calculate if we should process this quantifier */
+ bool calculateShouldProcess( Node f );
+private:
+ /** reference to theory arithmetic */
+ arith::TheoryArith* d_th;
+ /** delta */
+ std::map< TypeNode, Node > d_deltas;
+ /** for each quantifier, simplex rows */
+ std::map< Node, std::vector< arith::ArithVar > > d_instRows;
+ /** tableaux */
+ std::map< arith::ArithVar, Node > d_tableaux_term;
+ std::map< arith::ArithVar, std::map< Node, Node > > d_tableaux_ce_term;
+ std::map< arith::ArithVar, std::map< Node, Node > > d_tableaux;
+ /** ce tableaux */
+ std::map< arith::ArithVar, std::map< Node, Node > > d_ceTableaux;
+ /** get value */
+ Node getTableauxValue( Node n, bool minus_delta = false );
+ Node getTableauxValue( arith::ArithVar v, bool minus_delta = false );
+ /** do instantiation */
+ bool doInstantiation( Node f, Node term, arith::ArithVar x, InstMatch& m, Node var );
+ bool doInstantiation2( Node f, Node term, arith::ArithVar x, InstMatch& m, Node var, bool minus_delta = false );
+ /** add term to row */
+ void addTermToRow( arith::ArithVar x, Node n, Node& f, NodeBuilder<>& t );
+ /** print debug */
+ void debugPrint( const char* c );
+private:
+ /** */
+ int d_counter;
+ /** negative one */
+ Node d_negOne;
+ /** process functions */
+ void processResetInstantiationRound( Theory::Effort effort );
+ int process( Node f, Theory::Effort effort, int e );
+public:
+ InstStrategySimplex( arith::TheoryArith* th, QuantifiersEngine* ie );
+ ~InstStrategySimplex(){}
+ /** identify */
+ std::string identify() const { return std::string("Simplex"); }
+};
+
+
+class InstStrategyDatatypesValue : public InstStrategy
+{
+protected:
+ /** calculate if we should process this quantifier */
+ bool calculateShouldProcess( Node f );
+private:
+ /** reference to theory datatypes */
+ datatypes::TheoryDatatypes* d_th;
+ /** get value function */
+ Node getValueFor( Node n );
+public:
+ //constructor
+ InstStrategyDatatypesValue( datatypes::TheoryDatatypes* th, QuantifiersEngine* qe );
+ ~InstStrategyDatatypesValue(){}
+ /** reset instantiation */
+ void processResetInstantiationRound( Theory::Effort effort );
+ /** process method, returns a status */
+ int process( Node f, Theory::Effort effort, int e );
+ /** identify */
+ std::string identify() const { return std::string("InstStrategyDatatypesValue"); }
+
+};/* class InstStrategy */
+
+}
+}
+}
+
#endif \ No newline at end of file
diff --git a/src/theory/quantifiers/inst_strategy_e_matching.cpp b/src/theory/quantifiers/inst_strategy_e_matching.cpp
index 48af334ff..3f5cc7666 100755..100644
--- a/src/theory/quantifiers/inst_strategy_e_matching.cpp
+++ b/src/theory/quantifiers/inst_strategy_e_matching.cpp
@@ -1,379 +1,375 @@
-/********************* */
-/*! \file inst_strategy_e_matching.cpp
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: mdeters
- ** Minor contributors (to current version): bobot
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Implementation of e matching instantiation strategies
- **/
-
-#include "theory/quantifiers/inst_strategy_e_matching.h"
-
-#include "theory/theory_engine.h"
-#include "theory/quantifiers/options.h"
-#include "theory/quantifiers/term_database.h"
-#include "theory/quantifiers/inst_match_generator.h"
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::inst;
-using namespace CVC4::theory::quantifiers;
-
-#define USE_SINGLE_TRIGGER_BEFORE_MULTI_TRIGGER
-//#define MULTI_TRIGGER_FULL_EFFORT_HALF
-#define MULTI_MULTI_TRIGGERS
-
-struct sortQuantifiersForSymbol {
- QuantifiersEngine* d_qe;
- bool operator() (Node i, Node j) {
- int nqfsi = d_qe->getQuantifierRelevance()->getNumQuantifiersForSymbol( i.getOperator() );
- int nqfsj = d_qe->getQuantifierRelevance()->getNumQuantifiersForSymbol( j.getOperator() );
- if( nqfsi<nqfsj ){
- return true;
- }else if( nqfsi>nqfsj ){
- return false;
- }else{
- return false;
- }
- }
-};
-
-void InstStrategyUserPatterns::processResetInstantiationRound( Theory::Effort effort ){
- //reset triggers
- for( std::map< Node, std::vector< Trigger* > >::iterator it = d_user_gen.begin(); it != d_user_gen.end(); ++it ){
- for( int i=0; i<(int)it->second.size(); i++ ){
- it->second[i]->resetInstantiationRound();
- it->second[i]->reset( Node::null() );
- }
- }
-}
-
-int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e ){
- if( e==0 ){
- return STATUS_UNFINISHED;
- }else if( e==1 ){
- d_counter[f]++;
- Debug("quant-uf-strategy") << "Try user-provided patterns..." << std::endl;
- //Notice() << "Try user-provided patterns..." << std::endl;
- for( int i=0; i<(int)d_user_gen[f].size(); i++ ){
- bool processTrigger = true;
- if( effort!=Theory::EFFORT_LAST_CALL && d_user_gen[f][i]->isMultiTrigger() ){
-//#ifdef MULTI_TRIGGER_FULL_EFFORT_HALF
-// processTrigger = d_counter[f]%2==0;
-//#endif
- }
- if( processTrigger ){
- //if( d_user_gen[f][i]->isMultiTrigger() )
- //Notice() << " Process (user) " << (*d_user_gen[f][i]) << " for " << f << "..." << std::endl;
- InstMatch baseMatch;
- int numInst = d_user_gen[f][i]->addInstantiations( baseMatch );
- //if( d_user_gen[f][i]->isMultiTrigger() )
- //Notice() << " Done, numInst = " << numInst << "." << std::endl;
- d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_user_patterns += numInst;
- if( d_user_gen[f][i]->isMultiTrigger() ){
- d_quantEngine->d_statistics.d_multi_trigger_instantiations += numInst;
- }
- //d_quantEngine->d_hasInstantiated[f] = true;
- }
- }
- Debug("quant-uf-strategy") << "done." << std::endl;
- //Notice() << "done" << std::endl;
- }
- return STATUS_UNKNOWN;
-}
-
-void InstStrategyUserPatterns::addUserPattern( Node f, Node pat ){
- //add to generators
- std::vector< Node > nodes;
- for( int i=0; i<(int)pat.getNumChildren(); i++ ){
- nodes.push_back( pat[i] );
- }
- if( Trigger::isUsableTrigger( nodes, f ) ){
- //extend to literal matching
- d_quantEngine->getPhaseReqTerms( f, nodes );
- //check match option
- int matchOption = options::efficientEMatching() ? InstMatchGenerator::MATCH_GEN_EFFICIENT_E_MATCH : 0;
- d_user_gen[f].push_back( Trigger::mkTrigger( d_quantEngine, f, nodes, matchOption, true, Trigger::TR_MAKE_NEW,
- options::smartTriggers() ) );
- }
-}
-/*
-InstStrategyUserPatterns::Statistics::Statistics():
- d_instantiations("InstStrategyUserPatterns::Instantiations", 0)
-{
- StatisticsRegistry::registerStat(&d_instantiations);
-}
-
-InstStrategyUserPatterns::Statistics::~Statistics(){
- StatisticsRegistry::unregisterStat(&d_instantiations);
-}
-*/
-
-void InstStrategyAutoGenTriggers::processResetInstantiationRound( Theory::Effort effort ){
- //reset triggers
- for( std::map< Node, std::map< Trigger*, bool > >::iterator it = d_auto_gen_trigger.begin(); it != d_auto_gen_trigger.end(); ++it ){
- for( std::map< Trigger*, bool >::iterator itt = it->second.begin(); itt != it->second.end(); ++itt ){
- itt->first->resetInstantiationRound();
- itt->first->reset( Node::null() );
- }
- }
-}
-
-int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e ){
- int peffort = f.getNumChildren()==3 ? 2 : 1;
- //int peffort = f.getNumChildren()==3 ? 2 : 1;
- //int peffort = 1;
- if( e<peffort ){
- return STATUS_UNFINISHED;
- }else{
- bool gen = false;
- if( e==peffort ){
- if( d_counter.find( f )==d_counter.end() ){
- d_counter[f] = 0;
- gen = true;
- }else{
- d_counter[f]++;
- gen = d_regenerate && d_counter[f]%d_regenerate_frequency==0;
- }
- }else{
- gen = true;
- }
- if( gen ){
- generateTriggers( f );
- }
- Debug("quant-uf-strategy") << "Try auto-generated triggers... " << d_tr_strategy << " " << e << std::endl;
- //Notice() << "Try auto-generated triggers..." << std::endl;
- for( std::map< Trigger*, bool >::iterator itt = d_auto_gen_trigger[f].begin(); itt != d_auto_gen_trigger[f].end(); ++itt ){
- Trigger* tr = itt->first;
- if( tr ){
- bool processTrigger = itt->second;
- if( effort!=Theory::EFFORT_LAST_CALL && tr->isMultiTrigger() ){
-#ifdef MULTI_TRIGGER_FULL_EFFORT_HALF
- processTrigger = d_counter[f]%2==0;
-#endif
- }
- if( processTrigger ){
- //if( tr->isMultiTrigger() )
- Debug("quant-uf-strategy-auto-gen-triggers") << " Process " << (*tr) << "..." << std::endl;
- InstMatch baseMatch;
- int numInst = tr->addInstantiations( baseMatch );
- //if( tr->isMultiTrigger() )
- Debug("quant-uf-strategy-auto-gen-triggers") << " Done, numInst = " << numInst << "." << std::endl;
- if( d_tr_strategy==Trigger::TS_MIN_TRIGGER ){
- d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_auto_gen_min += numInst;
- }else{
- d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_auto_gen += numInst;
- }
- if( tr->isMultiTrigger() ){
- d_quantEngine->d_statistics.d_multi_trigger_instantiations += numInst;
- }
- //d_quantEngine->d_hasInstantiated[f] = true;
- }
- }
- }
- Debug("quant-uf-strategy") << "done." << std::endl;
- //Notice() << "done" << std::endl;
- }
- return STATUS_UNKNOWN;
-}
-
-void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
- Debug("auto-gen-trigger") << "Generate trigger for " << f << std::endl;
- if( d_patTerms[0].find( f )==d_patTerms[0].end() ){
- //determine all possible pattern terms based on trigger term selection strategy d_tr_strategy
- d_patTerms[0][f].clear();
- d_patTerms[1][f].clear();
- std::vector< Node > patTermsF;
- Trigger::collectPatTerms( d_quantEngine, f, d_quantEngine->getTermDatabase()->getInstConstantBody( f ), patTermsF, d_tr_strategy, true );
- Debug("auto-gen-trigger") << "Collected pat terms for " << d_quantEngine->getTermDatabase()->getInstConstantBody( f ) << std::endl;
- Debug("auto-gen-trigger") << " ";
- for( int i=0; i<(int)patTermsF.size(); i++ ){
- Debug("auto-gen-trigger") << patTermsF[i] << " ";
- }
- Debug("auto-gen-trigger") << std::endl;
- //extend to literal matching (if applicable)
- d_quantEngine->getPhaseReqTerms( f, patTermsF );
- //sort into single/multi triggers
- std::map< Node, std::vector< Node > > varContains;
- d_quantEngine->getTermDatabase()->getVarContains( f, patTermsF, varContains );
- for( std::map< Node, std::vector< Node > >::iterator it = varContains.begin(); it != varContains.end(); ++it ){
- if( it->second.size()==f[0].getNumChildren() ){
- d_patTerms[0][f].push_back( it->first );
- d_is_single_trigger[ it->first ] = true;
- }else{
- d_patTerms[1][f].push_back( it->first );
- d_is_single_trigger[ it->first ] = false;
- }
- }
- d_made_multi_trigger[f] = false;
- Debug("auto-gen-trigger") << "Single triggers for " << f << " : " << std::endl;
- Debug("auto-gen-trigger") << " ";
- for( int i=0; i<(int)d_patTerms[0][f].size(); i++ ){
- Debug("auto-gen-trigger") << d_patTerms[0][f][i] << " ";
- }
- Debug("auto-gen-trigger") << std::endl;
- Debug("auto-gen-trigger") << "Multi-trigger term pool for " << f << " : " << std::endl;
- Debug("auto-gen-trigger") << " ";
- for( int i=0; i<(int)d_patTerms[1][f].size(); i++ ){
- Debug("auto-gen-trigger") << d_patTerms[1][f][i] << " ";
- }
- Debug("auto-gen-trigger") << std::endl;
- }
-
- //populate candidate pattern term vector for the current trigger
- std::vector< Node > patTerms;
-#ifdef USE_SINGLE_TRIGGER_BEFORE_MULTI_TRIGGER
- //try to add single triggers first
- for( int i=0; i<(int)d_patTerms[0][f].size(); i++ ){
- if( !d_single_trigger_gen[d_patTerms[0][f][i]] ){
- patTerms.push_back( d_patTerms[0][f][i] );
- }
- }
- //if no single triggers exist, add multi trigger terms
- if( patTerms.empty() ){
- patTerms.insert( patTerms.begin(), d_patTerms[1][f].begin(), d_patTerms[1][f].end() );
- }
-#else
- patTerms.insert( patTerms.begin(), d_patTerms[0][f].begin(), d_patTerms[0][f].end() );
- patTerms.insert( patTerms.begin(), d_patTerms[1][f].begin(), d_patTerms[1][f].end() );
-#endif
-
- if( !patTerms.empty() ){
- Debug("auto-gen-trigger") << "Generate trigger for " << f << std::endl;
- //sort terms based on relevance
- if( d_rlv_strategy==RELEVANCE_DEFAULT ){
- sortQuantifiersForSymbol sqfs;
- sqfs.d_qe = d_quantEngine;
- //sort based on # occurrences (this will cause Trigger to select rarer symbols)
- std::sort( patTerms.begin(), patTerms.end(), sqfs );
- Debug("relevant-trigger") << "Terms based on relevance: " << std::endl;
- for( int i=0; i<(int)patTerms.size(); i++ ){
- Debug("relevant-trigger") << " " << patTerms[i] << " (";
- Debug("relevant-trigger") << d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[i].getOperator() ) << ")" << std::endl;
- }
- //Notice() << "Terms based on relevance: " << std::endl;
- //for( int i=0; i<(int)patTerms.size(); i++ ){
- // Notice() << " " << patTerms[i] << " (";
- // Notice() << d_quantEngine->getNumQuantifiersForSymbol( patTerms[i].getOperator() ) << ")" << std::endl;
- //}
- }
- //now, generate the trigger...
- int matchOption = options::efficientEMatching() ? InstMatchGenerator::MATCH_GEN_EFFICIENT_E_MATCH : 0;
- Trigger* tr = NULL;
- if( d_is_single_trigger[ patTerms[0] ] ){
- tr = Trigger::mkTrigger( d_quantEngine, f, patTerms[0], matchOption, false, Trigger::TR_RETURN_NULL,
- options::smartTriggers() );
- d_single_trigger_gen[ patTerms[0] ] = true;
- }else{
- //if we are re-generating triggers, shuffle based on some method
- if( d_made_multi_trigger[f] ){
-#ifndef MULTI_MULTI_TRIGGERS
- return;
-#endif
- std::random_shuffle( patTerms.begin(), patTerms.end() ); //shuffle randomly
- }else{
- d_made_multi_trigger[f] = true;
- }
- //will possibly want to get an old trigger
- tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, false, Trigger::TR_GET_OLD,
- options::smartTriggers() );
- }
- if( tr ){
- if( tr->isMultiTrigger() ){
- //disable all other multi triggers
- for( std::map< Trigger*, bool >::iterator it = d_auto_gen_trigger[f].begin(); it != d_auto_gen_trigger[f].end(); ++it ){
- if( it->first->isMultiTrigger() ){
- d_auto_gen_trigger[f][ it->first ] = false;
- }
- }
- }
- //making it during an instantiation round, so must reset
- if( d_auto_gen_trigger[f].find( tr )==d_auto_gen_trigger[f].end() ){
- tr->resetInstantiationRound();
- tr->reset( Node::null() );
- }
- d_auto_gen_trigger[f][tr] = true;
- //if we are generating additional triggers...
- if( d_generate_additional && d_is_single_trigger[ patTerms[0] ] ){
- int index = 0;
- if( index<(int)patTerms.size() ){
- //Notice() << "check add additional" << std::endl;
- //check if similar patterns exist, and if so, add them additionally
- int nqfs_curr = d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[0].getOperator() );
- index++;
- bool success = true;
- while( success && index<(int)patTerms.size() && d_is_single_trigger[ patTerms[index] ] ){
- success = false;
- if( d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[index].getOperator() )<=nqfs_curr ){
- d_single_trigger_gen[ patTerms[index] ] = true;
- Trigger* tr2 = Trigger::mkTrigger( d_quantEngine, f, patTerms[index], matchOption, false, Trigger::TR_RETURN_NULL,
- options::smartTriggers() );
- if( tr2 ){
- //Notice() << "Add additional trigger " << patTerms[index] << std::endl;
- tr2->resetInstantiationRound();
- tr2->reset( Node::null() );
- d_auto_gen_trigger[f][tr2] = true;
- }
- success = true;
- }
- index++;
- }
- //Notice() << "done check add additional" << std::endl;
- }
- }
- }
- }
-}
-/*
-InstStrategyAutoGenTriggers::Statistics::Statistics():
- d_instantiations("InstStrategyAutoGenTriggers::Instantiations", 0),
- d_instantiations_min("InstStrategyAutoGenTriggers::Instantiations_min", 0)
-{
- StatisticsRegistry::registerStat(&d_instantiations);
- StatisticsRegistry::registerStat(&d_instantiations_min);
-}
-
-InstStrategyAutoGenTriggers::Statistics::~Statistics(){
- StatisticsRegistry::unregisterStat(&d_instantiations);
- StatisticsRegistry::unregisterStat(&d_instantiations_min);
-}
-*/
-
-void InstStrategyFreeVariable::processResetInstantiationRound( Theory::Effort effort ){
-}
-
-int InstStrategyFreeVariable::process( Node f, Theory::Effort effort, int e ){
- if( e<5 ){
- return STATUS_UNFINISHED;
- }else{
- if( d_guessed.find( f )==d_guessed.end() ){
- d_guessed[f] = true;
- Debug("quant-uf-alg") << "Add guessed instantiation" << std::endl;
- InstMatch m;
- if( d_quantEngine->addInstantiation( f, m ) ){
- ++(d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_guess);
- //d_quantEngine->d_hasInstantiated[f] = true;
- }
- }
- return STATUS_UNKNOWN;
- }
-}
-/*
-InstStrategyFreeVariable::Statistics::Statistics():
- d_instantiations("InstStrategyGuess::Instantiations", 0)
-{
- StatisticsRegistry::registerStat(&d_instantiations);
-}
-
-InstStrategyFreeVariable::Statistics::~Statistics(){
- StatisticsRegistry::unregisterStat(&d_instantiations);
-}
-*/
+/********************* */
+/*! \file inst_strategy_e_matching.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Implementation of e matching instantiation strategies
+ **/
+
+#include "theory/quantifiers/inst_strategy_e_matching.h"
+
+#include "theory/theory_engine.h"
+#include "theory/quantifiers/options.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/inst_match_generator.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::inst;
+using namespace CVC4::theory::quantifiers;
+
+//#define MULTI_TRIGGER_FULL_EFFORT_HALF
+#define MULTI_MULTI_TRIGGERS
+
+struct sortQuantifiersForSymbol {
+ QuantifiersEngine* d_qe;
+ bool operator() (Node i, Node j) {
+ int nqfsi = d_qe->getQuantifierRelevance()->getNumQuantifiersForSymbol( i.getOperator() );
+ int nqfsj = d_qe->getQuantifierRelevance()->getNumQuantifiersForSymbol( j.getOperator() );
+ if( nqfsi<nqfsj ){
+ return true;
+ }else if( nqfsi>nqfsj ){
+ return false;
+ }else{
+ return false;
+ }
+ }
+};
+
+void InstStrategyUserPatterns::processResetInstantiationRound( Theory::Effort effort ){
+ //reset triggers
+ for( std::map< Node, std::vector< Trigger* > >::iterator it = d_user_gen.begin(); it != d_user_gen.end(); ++it ){
+ for( int i=0; i<(int)it->second.size(); i++ ){
+ it->second[i]->resetInstantiationRound();
+ it->second[i]->reset( Node::null() );
+ }
+ }
+}
+
+int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e ){
+ if( e==0 ){
+ return STATUS_UNFINISHED;
+ }else if( e==1 ){
+ d_counter[f]++;
+ Debug("quant-uf-strategy") << "Try user-provided patterns..." << std::endl;
+ //Notice() << "Try user-provided patterns..." << std::endl;
+ for( int i=0; i<(int)d_user_gen[f].size(); i++ ){
+ bool processTrigger = true;
+ if( processTrigger ){
+ //if( d_user_gen[f][i]->isMultiTrigger() )
+ Trace("process-trigger") << " Process (user) " << (*d_user_gen[f][i]) << "..." << std::endl;
+ InstMatch baseMatch;
+ int numInst = d_user_gen[f][i]->addInstantiations( baseMatch );
+ //if( d_user_gen[f][i]->isMultiTrigger() )
+ Trace("process-trigger") << " Done, numInst = " << numInst << "." << std::endl;
+ d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_user_patterns += numInst;
+ if( d_user_gen[f][i]->isMultiTrigger() ){
+ d_quantEngine->d_statistics.d_multi_trigger_instantiations += numInst;
+ }
+ //d_quantEngine->d_hasInstantiated[f] = true;
+ }
+ }
+ Debug("quant-uf-strategy") << "done." << std::endl;
+ //Notice() << "done" << std::endl;
+ }
+ return STATUS_UNKNOWN;
+}
+
+void InstStrategyUserPatterns::addUserPattern( Node f, Node pat ){
+ //add to generators
+ std::vector< Node > nodes;
+ for( int i=0; i<(int)pat.getNumChildren(); i++ ){
+ nodes.push_back( pat[i] );
+ }
+ if( Trigger::isUsableTrigger( nodes, f ) ){
+ //extend to literal matching
+ d_quantEngine->getPhaseReqTerms( f, nodes );
+ //check match option
+ int matchOption = options::efficientEMatching() ? InstMatchGenerator::MATCH_GEN_EFFICIENT_E_MATCH : 0;
+ d_user_gen[f].push_back( Trigger::mkTrigger( d_quantEngine, f, nodes, matchOption, true, Trigger::TR_MAKE_NEW,
+ options::smartTriggers() ) );
+ }
+}
+/*
+InstStrategyUserPatterns::Statistics::Statistics():
+ d_instantiations("InstStrategyUserPatterns::Instantiations", 0)
+{
+ StatisticsRegistry::registerStat(&d_instantiations);
+}
+
+InstStrategyUserPatterns::Statistics::~Statistics(){
+ StatisticsRegistry::unregisterStat(&d_instantiations);
+}
+*/
+
+void InstStrategyAutoGenTriggers::processResetInstantiationRound( Theory::Effort effort ){
+ //reset triggers
+ for( std::map< Node, std::map< Trigger*, bool > >::iterator it = d_auto_gen_trigger.begin(); it != d_auto_gen_trigger.end(); ++it ){
+ for( std::map< Trigger*, bool >::iterator itt = it->second.begin(); itt != it->second.end(); ++itt ){
+ itt->first->resetInstantiationRound();
+ itt->first->reset( Node::null() );
+ }
+ }
+ d_processed_trigger.clear();
+}
+
+int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e ){
+ int peffort = f.getNumChildren()==3 ? 2 : 1;
+ //int peffort = f.getNumChildren()==3 ? 2 : 1;
+ //int peffort = 1;
+ if( e<peffort ){
+ return STATUS_UNFINISHED;
+ }else{
+ int status = STATUS_UNKNOWN;
+ bool gen = false;
+ if( e==peffort ){
+ if( d_counter.find( f )==d_counter.end() ){
+ d_counter[f] = 0;
+ gen = true;
+ }else{
+ d_counter[f]++;
+ gen = d_regenerate && d_counter[f]%d_regenerate_frequency==0;
+ }
+ }else{
+ gen = true;
+ }
+ if( gen ){
+ generateTriggers( f, effort, e, status );
+ }
+ Debug("quant-uf-strategy") << "Try auto-generated triggers... " << d_tr_strategy << " " << e << std::endl;
+ //Notice() << "Try auto-generated triggers..." << std::endl;
+ for( std::map< Trigger*, bool >::iterator itt = d_auto_gen_trigger[f].begin(); itt != d_auto_gen_trigger[f].end(); ++itt ){
+ Trigger* tr = itt->first;
+ if( tr ){
+ bool processTrigger = itt->second;
+ if( processTrigger && d_processed_trigger[f].find( tr )==d_processed_trigger[f].end() ){
+ d_processed_trigger[f][tr] = true;
+ //if( tr->isMultiTrigger() )
+ Trace("process-trigger") << " Process " << (*tr) << "..." << std::endl;
+ InstMatch baseMatch;
+ int numInst = tr->addInstantiations( baseMatch );
+ //if( tr->isMultiTrigger() )
+ Trace("process-trigger") << " Done, numInst = " << numInst << "." << std::endl;
+ if( d_tr_strategy==Trigger::TS_MIN_TRIGGER ){
+ d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_auto_gen_min += numInst;
+ }else{
+ d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_auto_gen += numInst;
+ }
+ if( tr->isMultiTrigger() ){
+ d_quantEngine->d_statistics.d_multi_trigger_instantiations += numInst;
+ }
+ //d_quantEngine->d_hasInstantiated[f] = true;
+ }
+ }
+ }
+ Debug("quant-uf-strategy") << "done." << std::endl;
+ //Notice() << "done" << std::endl;
+ return status;
+ }
+}
+
+void InstStrategyAutoGenTriggers::generateTriggers( Node f, Theory::Effort effort, int e, int & status ){
+ Trace("auto-gen-trigger-debug") << "Generate trigger for " << f << std::endl;
+ if( d_patTerms[0].find( f )==d_patTerms[0].end() ){
+ //determine all possible pattern terms based on trigger term selection strategy d_tr_strategy
+ d_patTerms[0][f].clear();
+ d_patTerms[1][f].clear();
+ std::vector< Node > patTermsF;
+ Trigger::collectPatTerms( d_quantEngine, f, d_quantEngine->getTermDatabase()->getInstConstantBody( f ), patTermsF, d_tr_strategy, true );
+ Trace("auto-gen-trigger") << "Collected pat terms for " << d_quantEngine->getTermDatabase()->getInstConstantBody( f ) << std::endl;
+ Trace("auto-gen-trigger") << " ";
+ for( int i=0; i<(int)patTermsF.size(); i++ ){
+ Trace("auto-gen-trigger") << patTermsF[i] << " ";
+ }
+ Trace("auto-gen-trigger") << std::endl;
+ //extend to literal matching (if applicable)
+ d_quantEngine->getPhaseReqTerms( f, patTermsF );
+ //sort into single/multi triggers
+ std::map< Node, std::vector< Node > > varContains;
+ d_quantEngine->getTermDatabase()->getVarContains( f, patTermsF, varContains );
+ for( std::map< Node, std::vector< Node > >::iterator it = varContains.begin(); it != varContains.end(); ++it ){
+ if( it->second.size()==f[0].getNumChildren() ){
+ d_patTerms[0][f].push_back( it->first );
+ d_is_single_trigger[ it->first ] = true;
+ }else{
+ d_patTerms[1][f].push_back( it->first );
+ d_is_single_trigger[ it->first ] = false;
+ }
+ }
+ d_made_multi_trigger[f] = false;
+ Trace("auto-gen-trigger") << "Single triggers for " << f << " : " << std::endl;
+ Trace("auto-gen-trigger") << " ";
+ for( int i=0; i<(int)d_patTerms[0][f].size(); i++ ){
+ Trace("auto-gen-trigger") << d_patTerms[0][f][i] << " ";
+ }
+ Trace("auto-gen-trigger") << std::endl;
+ Trace("auto-gen-trigger") << "Multi-trigger term pool for " << f << " : " << std::endl;
+ Trace("auto-gen-trigger") << " ";
+ for( int i=0; i<(int)d_patTerms[1][f].size(); i++ ){
+ Trace("auto-gen-trigger") << d_patTerms[1][f][i] << " ";
+ }
+ Trace("auto-gen-trigger") << std::endl;
+ }
+
+ //populate candidate pattern term vector for the current trigger
+ std::vector< Node > patTerms;
+ //try to add single triggers first
+ for( int i=0; i<(int)d_patTerms[0][f].size(); i++ ){
+ if( !d_single_trigger_gen[d_patTerms[0][f][i]] ){
+ patTerms.push_back( d_patTerms[0][f][i] );
+ }
+ }
+ //if no single triggers exist, add multi trigger terms
+ if( patTerms.empty() ){
+ patTerms.insert( patTerms.begin(), d_patTerms[1][f].begin(), d_patTerms[1][f].end() );
+ }
+
+ if( !patTerms.empty() ){
+ Trace("auto-gen-trigger") << "Generate trigger for " << f << std::endl;
+ //sort terms based on relevance
+ if( d_rlv_strategy==RELEVANCE_DEFAULT ){
+ sortQuantifiersForSymbol sqfs;
+ sqfs.d_qe = d_quantEngine;
+ //sort based on # occurrences (this will cause Trigger to select rarer symbols)
+ std::sort( patTerms.begin(), patTerms.end(), sqfs );
+ Debug("relevant-trigger") << "Terms based on relevance: " << std::endl;
+ for( int i=0; i<(int)patTerms.size(); i++ ){
+ Debug("relevant-trigger") << " " << patTerms[i] << " (";
+ Debug("relevant-trigger") << d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[i].getOperator() ) << ")" << std::endl;
+ }
+ //Notice() << "Terms based on relevance: " << std::endl;
+ //for( int i=0; i<(int)patTerms.size(); i++ ){
+ // Notice() << " " << patTerms[i] << " (";
+ // Notice() << d_quantEngine->getNumQuantifiersForSymbol( patTerms[i].getOperator() ) << ")" << std::endl;
+ //}
+ }
+ //now, generate the trigger...
+ int matchOption = options::efficientEMatching() ? InstMatchGenerator::MATCH_GEN_EFFICIENT_E_MATCH : 0;
+ Trigger* tr = NULL;
+ if( d_is_single_trigger[ patTerms[0] ] ){
+ tr = Trigger::mkTrigger( d_quantEngine, f, patTerms[0], matchOption, false, Trigger::TR_RETURN_NULL,
+ options::smartTriggers() );
+ d_single_trigger_gen[ patTerms[0] ] = true;
+ }else{
+ //only generate multi trigger if effort level > 5, or if no single triggers exist
+ if( !d_patTerms[0][f].empty() ){
+ if( e<=5 ){
+ status = STATUS_UNFINISHED;
+ return;
+ }else{
+ Trace("multi-trigger-debug") << "Resort to choosing multi-triggers..." << std::endl;
+ }
+ }
+ //if we are re-generating triggers, shuffle based on some method
+ if( d_made_multi_trigger[f] ){
+#ifndef MULTI_MULTI_TRIGGERS
+ return;
+#endif
+ std::random_shuffle( patTerms.begin(), patTerms.end() ); //shuffle randomly
+ }else{
+ d_made_multi_trigger[f] = true;
+ }
+ //will possibly want to get an old trigger
+ tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, false, Trigger::TR_GET_OLD,
+ options::smartTriggers() );
+ }
+ if( tr ){
+ if( tr->isMultiTrigger() ){
+ //disable all other multi triggers
+ for( std::map< Trigger*, bool >::iterator it = d_auto_gen_trigger[f].begin(); it != d_auto_gen_trigger[f].end(); ++it ){
+ if( it->first->isMultiTrigger() ){
+ d_auto_gen_trigger[f][ it->first ] = false;
+ }
+ }
+ }
+ //making it during an instantiation round, so must reset
+ if( d_auto_gen_trigger[f].find( tr )==d_auto_gen_trigger[f].end() ){
+ tr->resetInstantiationRound();
+ tr->reset( Node::null() );
+ }
+ d_auto_gen_trigger[f][tr] = true;
+ //if we are generating additional triggers...
+ if( d_generate_additional && d_is_single_trigger[ patTerms[0] ] ){
+ int index = 0;
+ if( index<(int)patTerms.size() ){
+ //Notice() << "check add additional" << std::endl;
+ //check if similar patterns exist, and if so, add them additionally
+ int nqfs_curr = d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[0].getOperator() );
+ index++;
+ bool success = true;
+ while( success && index<(int)patTerms.size() && d_is_single_trigger[ patTerms[index] ] ){
+ success = false;
+ if( d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[index].getOperator() )<=nqfs_curr ){
+ d_single_trigger_gen[ patTerms[index] ] = true;
+ Trigger* tr2 = Trigger::mkTrigger( d_quantEngine, f, patTerms[index], matchOption, false, Trigger::TR_RETURN_NULL,
+ options::smartTriggers() );
+ if( tr2 ){
+ //Notice() << "Add additional trigger " << patTerms[index] << std::endl;
+ tr2->resetInstantiationRound();
+ tr2->reset( Node::null() );
+ d_auto_gen_trigger[f][tr2] = true;
+ }
+ success = true;
+ }
+ index++;
+ }
+ //Notice() << "done check add additional" << std::endl;
+ }
+ }
+ }
+ }
+}
+/*
+InstStrategyAutoGenTriggers::Statistics::Statistics():
+ d_instantiations("InstStrategyAutoGenTriggers::Instantiations", 0),
+ d_instantiations_min("InstStrategyAutoGenTriggers::Instantiations_min", 0)
+{
+ StatisticsRegistry::registerStat(&d_instantiations);
+ StatisticsRegistry::registerStat(&d_instantiations_min);
+}
+
+InstStrategyAutoGenTriggers::Statistics::~Statistics(){
+ StatisticsRegistry::unregisterStat(&d_instantiations);
+ StatisticsRegistry::unregisterStat(&d_instantiations_min);
+}
+*/
+
+void InstStrategyFreeVariable::processResetInstantiationRound( Theory::Effort effort ){
+}
+
+int InstStrategyFreeVariable::process( Node f, Theory::Effort effort, int e ){
+ if( e<5 ){
+ return STATUS_UNFINISHED;
+ }else{
+ if( d_guessed.find( f )==d_guessed.end() ){
+ d_guessed[f] = true;
+ Debug("quant-uf-alg") << "Add guessed instantiation" << std::endl;
+ InstMatch m;
+ if( d_quantEngine->addInstantiation( f, m ) ){
+ ++(d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_guess);
+ //d_quantEngine->d_hasInstantiated[f] = true;
+ }
+ }
+ return STATUS_UNKNOWN;
+ }
+}
+/*
+InstStrategyFreeVariable::Statistics::Statistics():
+ d_instantiations("InstStrategyGuess::Instantiations", 0)
+{
+ StatisticsRegistry::registerStat(&d_instantiations);
+}
+
+InstStrategyFreeVariable::Statistics::~Statistics(){
+ StatisticsRegistry::unregisterStat(&d_instantiations);
+}
+*/
diff --git a/src/theory/quantifiers/inst_strategy_e_matching.h b/src/theory/quantifiers/inst_strategy_e_matching.h
index 23f0d8a54..13d443c6a 100755..100644
--- a/src/theory/quantifiers/inst_strategy_e_matching.h
+++ b/src/theory/quantifiers/inst_strategy_e_matching.h
@@ -1,135 +1,137 @@
-/********************* */
-/*! \file inst_strategy_e_matching.h
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): bobot, mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief E matching instantiation strategies
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__INST_STRATEGY_E_MATCHING_H
-#define __CVC4__INST_STRATEGY_E_MATCHING_H
-
-#include "theory/quantifiers_engine.h"
-#include "theory/quantifiers/trigger.h"
-
-#include "context/context.h"
-#include "context/context_mm.h"
-
-#include "util/statistics_registry.h"
-#include "theory/quantifiers/instantiation_engine.h"
-
-namespace CVC4 {
-namespace theory {
-namespace quantifiers {
-
-//instantiation strategies
-
-class InstStrategyUserPatterns : public InstStrategy{
-private:
- /** explicitly provided patterns */
- std::map< Node, std::vector< inst::Trigger* > > d_user_gen;
- /** counter for quantifiers */
- std::map< Node, int > d_counter;
- /** process functions */
- void processResetInstantiationRound( Theory::Effort effort );
- int process( Node f, Theory::Effort effort, int e );
-public:
- InstStrategyUserPatterns( QuantifiersEngine* ie ) :
- InstStrategy( ie ){}
- ~InstStrategyUserPatterns(){}
-public:
- /** add pattern */
- void addUserPattern( Node f, Node pat );
- /** get num patterns */
- int getNumUserGenerators( Node f ) { return (int)d_user_gen[f].size(); }
- /** get user pattern */
- inst::Trigger* getUserGenerator( Node f, int i ) { return d_user_gen[f][ i ]; }
- /** identify */
- std::string identify() const { return std::string("UserPatterns"); }
-};/* class InstStrategyUserPatterns */
-
-class InstStrategyAutoGenTriggers : public InstStrategy{
-public:
- enum {
- RELEVANCE_NONE,
- RELEVANCE_DEFAULT,
- };
-private:
- /** trigger generation strategy */
- int d_tr_strategy;
- /** relevance strategy */
- int d_rlv_strategy;
- /** regeneration */
- bool d_regenerate;
- int d_regenerate_frequency;
- /** generate additional triggers */
- bool d_generate_additional;
- /** triggers for each quantifier */
- std::map< Node, std::map< inst::Trigger*, bool > > d_auto_gen_trigger;
- std::map< Node, int > d_counter;
- /** single, multi triggers for each quantifier */
- std::map< Node, std::vector< Node > > d_patTerms[2];
- std::map< Node, bool > d_is_single_trigger;
- std::map< Node, bool > d_single_trigger_gen;
- std::map< Node, bool > d_made_multi_trigger;
-private:
- /** process functions */
- void processResetInstantiationRound( Theory::Effort effort );
- int process( Node f, Theory::Effort effort, int e );
- /** generate triggers */
- void generateTriggers( Node f );
-public:
- /** tstrt is the type of triggers to use (maximum depth, minimum depth, or all)
- rstrt is the relevance setting for trigger (use only relevant triggers vs. use all)
- rgfr is the frequency at which triggers are generated */
- InstStrategyAutoGenTriggers( QuantifiersEngine* qe, int tstrt, int rstrt, int rgfr = -1 ) :
- InstStrategy( qe ), d_tr_strategy( tstrt ), d_rlv_strategy( rstrt ), d_generate_additional( false ){
- setRegenerateFrequency( rgfr );
- }
- ~InstStrategyAutoGenTriggers(){}
-public:
- /** get auto-generated trigger */
- inst::Trigger* getAutoGenTrigger( Node f );
- /** identify */
- std::string identify() const { return std::string("AutoGenTriggers"); }
- /** set regenerate frequency, if fr<0, turn off regenerate */
- void setRegenerateFrequency( int fr ){
- if( fr<0 ){
- d_regenerate = false;
- }else{
- d_regenerate_frequency = fr;
- d_regenerate = true;
- }
- }
- /** set generate additional */
- void setGenerateAdditional( bool val ) { d_generate_additional = val; }
-};/* class InstStrategyAutoGenTriggers */
-
-class InstStrategyFreeVariable : public InstStrategy{
-private:
- /** guessed instantiations */
- std::map< Node, bool > d_guessed;
- /** process functions */
- void processResetInstantiationRound( Theory::Effort effort );
- int process( Node f, Theory::Effort effort, int e );
-public:
- InstStrategyFreeVariable( QuantifiersEngine* qe ) :
- InstStrategy( qe ){}
- ~InstStrategyFreeVariable(){}
- /** identify */
- std::string identify() const { return std::string("FreeVariable"); }
-};/* class InstStrategyFreeVariable */
-
-}
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
-
-#endif
+/********************* */
+/*! \file inst_strategy_e_matching.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief E matching instantiation strategies
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__INST_STRATEGY_E_MATCHING_H
+#define __CVC4__INST_STRATEGY_E_MATCHING_H
+
+#include "theory/quantifiers_engine.h"
+#include "theory/quantifiers/trigger.h"
+
+#include "context/context.h"
+#include "context/context_mm.h"
+
+#include "util/statistics_registry.h"
+#include "theory/quantifiers/instantiation_engine.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+//instantiation strategies
+
+class InstStrategyUserPatterns : public InstStrategy{
+private:
+ /** explicitly provided patterns */
+ std::map< Node, std::vector< inst::Trigger* > > d_user_gen;
+ /** counter for quantifiers */
+ std::map< Node, int > d_counter;
+ /** process functions */
+ void processResetInstantiationRound( Theory::Effort effort );
+ int process( Node f, Theory::Effort effort, int e );
+public:
+ InstStrategyUserPatterns( QuantifiersEngine* ie ) :
+ InstStrategy( ie ){}
+ ~InstStrategyUserPatterns(){}
+public:
+ /** add pattern */
+ void addUserPattern( Node f, Node pat );
+ /** get num patterns */
+ int getNumUserGenerators( Node f ) { return (int)d_user_gen[f].size(); }
+ /** get user pattern */
+ inst::Trigger* getUserGenerator( Node f, int i ) { return d_user_gen[f][ i ]; }
+ /** identify */
+ std::string identify() const { return std::string("UserPatterns"); }
+};/* class InstStrategyUserPatterns */
+
+class InstStrategyAutoGenTriggers : public InstStrategy{
+public:
+ enum {
+ RELEVANCE_NONE,
+ RELEVANCE_DEFAULT,
+ };
+private:
+ /** trigger generation strategy */
+ int d_tr_strategy;
+ /** relevance strategy */
+ int d_rlv_strategy;
+ /** regeneration */
+ bool d_regenerate;
+ int d_regenerate_frequency;
+ /** generate additional triggers */
+ bool d_generate_additional;
+ /** triggers for each quantifier */
+ std::map< Node, std::map< inst::Trigger*, bool > > d_auto_gen_trigger;
+ std::map< Node, int > d_counter;
+ /** single, multi triggers for each quantifier */
+ std::map< Node, std::vector< Node > > d_patTerms[2];
+ std::map< Node, bool > d_is_single_trigger;
+ std::map< Node, bool > d_single_trigger_gen;
+ std::map< Node, bool > d_made_multi_trigger;
+ //processed trigger this round
+ std::map< Node, std::map< inst::Trigger*, bool > > d_processed_trigger;
+private:
+ /** process functions */
+ void processResetInstantiationRound( Theory::Effort effort );
+ int process( Node f, Theory::Effort effort, int e );
+ /** generate triggers */
+ void generateTriggers( Node f, Theory::Effort effort, int e, int & status );
+public:
+ /** tstrt is the type of triggers to use (maximum depth, minimum depth, or all)
+ rstrt is the relevance setting for trigger (use only relevant triggers vs. use all)
+ rgfr is the frequency at which triggers are generated */
+ InstStrategyAutoGenTriggers( QuantifiersEngine* qe, int tstrt, int rstrt, int rgfr = -1 ) :
+ InstStrategy( qe ), d_tr_strategy( tstrt ), d_rlv_strategy( rstrt ), d_generate_additional( false ){
+ setRegenerateFrequency( rgfr );
+ }
+ ~InstStrategyAutoGenTriggers(){}
+public:
+ /** get auto-generated trigger */
+ inst::Trigger* getAutoGenTrigger( Node f );
+ /** identify */
+ std::string identify() const { return std::string("AutoGenTriggers"); }
+ /** set regenerate frequency, if fr<0, turn off regenerate */
+ void setRegenerateFrequency( int fr ){
+ if( fr<0 ){
+ d_regenerate = false;
+ }else{
+ d_regenerate_frequency = fr;
+ d_regenerate = true;
+ }
+ }
+ /** set generate additional */
+ void setGenerateAdditional( bool val ) { d_generate_additional = val; }
+};/* class InstStrategyAutoGenTriggers */
+
+class InstStrategyFreeVariable : public InstStrategy{
+private:
+ /** guessed instantiations */
+ std::map< Node, bool > d_guessed;
+ /** process functions */
+ void processResetInstantiationRound( Theory::Effort effort );
+ int process( Node f, Theory::Effort effort, int e );
+public:
+ InstStrategyFreeVariable( QuantifiersEngine* qe ) :
+ InstStrategy( qe ){}
+ ~InstStrategyFreeVariable(){}
+ /** identify */
+ std::string identify() const { return std::string("FreeVariable"); }
+};/* class InstStrategyFreeVariable */
+
+}
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
+
+#endif
diff --git a/src/theory/quantifiers/instantiation_engine.cpp b/src/theory/quantifiers/instantiation_engine.cpp
index 53977ee4f..75cc10615 100644
--- a/src/theory/quantifiers/instantiation_engine.cpp
+++ b/src/theory/quantifiers/instantiation_engine.cpp
@@ -84,16 +84,18 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
//add cbqi lemma
//get the counterexample literal
Node ceLit = d_quantEngine->getTermDatabase()->getCounterexampleLiteral( f );
- //require any decision on cel to be phase=true
- d_quantEngine->getOutputChannel().requirePhase( ceLit, true );
- Debug("cbqi-debug") << "Require phase " << ceLit << " = true." << std::endl;
- //add counterexample lemma
- NodeBuilder<> nb(kind::OR);
- nb << f << ceLit;
- Node lem = nb;
- Debug("cbqi-debug") << "Counterexample lemma : " << lem << std::endl;
- d_quantEngine->getOutputChannel().lemma( lem );
- addedLemma = true;
+ if( !ceLit.isNull() ){
+ //require any decision on cel to be phase=true
+ d_quantEngine->getOutputChannel().requirePhase( ceLit, true );
+ Debug("cbqi-debug") << "Require phase " << ceLit << " = true." << std::endl;
+ //add counterexample lemma
+ NodeBuilder<> nb(kind::OR);
+ nb << f << ceLit;
+ Node lem = nb;
+ Debug("cbqi-debug") << "Counterexample lemma : " << lem << std::endl;
+ d_quantEngine->getOutputChannel().lemma( lem );
+ addedLemma = true;
+ }
}
}
if( addedLemma ){
diff --git a/src/theory/quantifiers/macros.cpp b/src/theory/quantifiers/macros.cpp
index c116b73f5..bf67bdd25 100755..100644
--- a/src/theory/quantifiers/macros.cpp
+++ b/src/theory/quantifiers/macros.cpp
@@ -1,375 +1,375 @@
-/********************* */
-/*! \file macros.cpp
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Sort inference module
- **
- ** This class implements quantifiers macro definitions.
- **/
-
-#include <vector>
-
-#include "theory/quantifiers/macros.h"
-#include "theory/rewriter.h"
-
-using namespace CVC4;
-using namespace std;
-using namespace CVC4::theory;
-using namespace CVC4::theory::quantifiers;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-
-bool QuantifierMacros::simplify( std::vector< Node >& assertions, bool doRewrite ){
- //first, collect macro definitions
- for( size_t i=0; i<assertions.size(); i++ ){
- if( assertions[i].getKind()==FORALL ){
- std::vector< Node > args;
- for( size_t j=0; j<assertions[i][0].getNumChildren(); j++ ){
- args.push_back( assertions[i][0][j] );
- }
- //look at the body of the quantifier for macro definition
- process( assertions[i][1], true, args, assertions[i] );
- }
- }
- //create macro defs
- for( std::map< Node, std::vector< std::pair< Node, Node > > >::iterator it = d_macro_def_cases.begin();
- it != d_macro_def_cases.end(); ++it ){
- //create ite based on case definitions
- Node val;
- for( size_t i=0; i<it->second.size(); ++i ){
- if( it->second[i].first.isNull() ){
- Assert( i==0 );
- val = it->second[i].second;
- }else{
- //if value is null, must generate it
- if( val.isNull() ){
- std::stringstream ss;
- ss << "mdo_" << it->first << "_$$";
- Node op = NodeManager::currentNM()->mkSkolem( ss.str(), it->first.getType(), "op created during macro definitions" );
- //will be defined in terms of fresh operator
- std::vector< Node > children;
- children.push_back( op );
- children.insert( children.end(), d_macro_basis[ it->first ].begin(), d_macro_basis[ it->first ].end() );
- val = NodeManager::currentNM()->mkNode( APPLY_UF, children );
- }
- val = NodeManager::currentNM()->mkNode( ITE, it->second[i].first, it->second[i].second, val );
- }
- }
- d_macro_defs[ it->first ] = val;
- Trace("macros-def") << "* " << val << " is a macro for " << it->first << std::endl;
- }
- //now simplify bodies
- for( std::map< Node, Node >::iterator it = d_macro_defs.begin(); it != d_macro_defs.end(); ++it ){
- d_macro_defs[ it->first ] = Rewriter::rewrite( simplify( it->second ) );
- }
- bool retVal = false;
- if( doRewrite && !d_macro_defs.empty() ){
- //now, rewrite based on macro definitions
- for( size_t i=0; i<assertions.size(); i++ ){
- Node prev = assertions[i];
- assertions[i] = simplify( assertions[i] );
- if( prev!=assertions[i] ){
- assertions[i] = Rewriter::rewrite( assertions[i] );
- Trace("macros-rewrite") << "Rewrite " << prev << " to " << assertions[i] << std::endl;
- retVal = true;
- }
- }
- }
- return retVal;
-}
-
-bool QuantifierMacros::contains( Node n, Node n_s ){
- if( n==n_s ){
- return true;
- }else{
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- if( contains( n[i], n_s ) ){
- return true;
- }
- }
- return false;
- }
-}
-
-bool QuantifierMacros::containsBadOp( Node n, Node n_op ){
- if( n!=n_op ){
- if( n.getKind()==APPLY_UF ){
- Node op = n.getOperator();
- if( op==n_op.getOperator() ){
- return true;
- }
- if( d_macro_def_cases.find( op )!=d_macro_def_cases.end() && !d_macro_def_cases[op].empty() ){
- return true;
- }
- }
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- if( containsBadOp( n[i], n_op ) ){
- return true;
- }
- }
- }
- return false;
-}
-
-bool QuantifierMacros::isMacroLiteral( Node n, bool pol ){
- return pol && n.getKind()==EQUAL;//( n.getKind()==EQUAL || n.getKind()==IFF );
-}
-
-void QuantifierMacros::getMacroCandidates( Node n, std::vector< Node >& candidates ){
- if( n.getKind()==APPLY_UF ){
- candidates.push_back( n );
- }else if( n.getKind()==PLUS ){
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- getMacroCandidates( n[i], candidates );
- }
- }else if( n.getKind()==MULT ){
- //if the LHS is a constant
- if( n.getNumChildren()==2 && n[0].isConst() ){
- getMacroCandidates( n[1], candidates );
- }
- }
-}
-
-Node QuantifierMacros::solveInEquality( Node n, Node lit ){
- if( lit.getKind()==IFF || lit.getKind()==EQUAL ){
- //return the opposite side of the equality if defined that way
- for( int i=0; i<2; i++ ){
- if( lit[i]==n ){
- return lit[ i==0 ? 1 : 0];
- }
- }
- //must solve for term n in the literal lit
- if( lit[0].getType().isInteger() || lit[0].getType().isReal() ){
- Node coeff;
- Node term;
- //could be solved for on LHS
- if( lit[0].getKind()==MULT && lit[0][1]==n ){
- Assert( lit[0][0].isConst() );
- term = lit[1];
- coeff = lit[0][0];
- }else{
- Assert( lit[1].getKind()==PLUS );
- std::vector< Node > plus_children;
- //find monomial with n
- for( size_t j=0; j<lit[1].getNumChildren(); j++ ){
- if( lit[1][j]==n ){
- Assert( coeff.isNull() );
- coeff = NodeManager::currentNM()->mkConst( Rational(1) );
- }else if( lit[1][j].getKind()==MULT && lit[1][j][1]==n ){
- Assert( coeff.isNull() );
- Assert( lit[1][j][0].isConst() );
- coeff = lit[1][j][0];
- }else{
- plus_children.push_back( lit[1][j] );
- }
- }
- if( !coeff.isNull() ){
- term = NodeManager::currentNM()->mkNode( PLUS, plus_children );
- term = NodeManager::currentNM()->mkNode( MINUS, lit[0], term );
- }
- }
- if( !coeff.isNull() ){
- coeff = NodeManager::currentNM()->mkConst( Rational(1) / coeff.getConst<Rational>() );
- term = NodeManager::currentNM()->mkNode( MULT, coeff, term );
- term = Rewriter::rewrite( term );
- return term;
- }
- }
- }
- Trace("macros-debug") << "Cannot find for " << lit << " " << n << std::endl;
- return Node::null();
-}
-
-bool QuantifierMacros::isConsistentDefinition( Node op, Node cond, Node def ){
- if( d_macro_def_cases[op].empty() || ( cond.isNull() && !d_macro_def_cases[op][0].first.isNull() ) ){
- return true;
- }else{
- return false;
- }
-}
-
-bool QuantifierMacros::getFreeVariables( Node n, std::vector< Node >& v_quant, std::vector< Node >& vars, bool retOnly ){
- if( std::find( v_quant.begin(), v_quant.end(), n )!=v_quant.end() ){
- if( std::find( vars.begin(), vars.end(), n )==vars.end() ){
- if( retOnly ){
- return true;
- }else{
- vars.push_back( n );
- }
- }
- }
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- if( getFreeVariables( n[i], v_quant, vars, retOnly ) ){
- return true;
- }
- }
- return false;
-}
-
-bool QuantifierMacros::getSubstitution( std::vector< Node >& v_quant, std::map< Node, Node >& solved,
- std::vector< Node >& vars, std::vector< Node >& subs, bool reqComplete ){
- bool success = true;
- for( size_t a=0; a<v_quant.size(); a++ ){
- if( !solved[ v_quant[a] ].isNull() ){
- vars.push_back( v_quant[a] );
- subs.push_back( solved[ v_quant[a] ] );
- }else{
- if( reqComplete ){
- success = false;
- break;
- }
- }
- }
- return success;
-}
-
-void QuantifierMacros::process( Node n, bool pol, std::vector< Node >& args, Node f ){
- if( n.getKind()==NOT ){
- process( n[0], !pol, args, f );
- }else if( n.getKind()==AND || n.getKind()==OR || n.getKind()==IMPLIES ){
- //bool favorPol = (n.getKind()==AND)==pol;
- //conditional?
- }else if( n.getKind()==ITE ){
- //can not do anything
- }else{
- //literal case
- if( isMacroLiteral( n, pol ) ){
- std::vector< Node > candidates;
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- getMacroCandidates( n[i], candidates );
- }
- for( size_t i=0; i<candidates.size(); i++ ){
- Node m = candidates[i];
- Node op = m.getOperator();
- if( !containsBadOp( n, m ) ){
- std::vector< Node > fvs;
- getFreeVariables( m, args, fvs, false );
- //get definition and condition
- Node n_def = solveInEquality( m, n ); //definition for the macro
- //definition must exist and not contain any free variables apart from fvs
- if( !n_def.isNull() && !getFreeVariables( n_def, args, fvs, true ) ){
- Node n_cond; //condition when this definition holds
- //conditional must not contain any free variables apart from fvs
- if( n_cond.isNull() || !getFreeVariables( n_cond, args, fvs, true ) ){
- Trace("macros") << m << " is possible macro in " << f << std::endl;
- //now we must rewrite candidates[i] to a term of form g( x1, ..., xn ) where
- // x1 ... xn are distinct variables
- if( d_macro_basis[op].empty() ){
- for( size_t a=0; a<m.getNumChildren(); a++ ){
- std::stringstream ss;
- ss << "mda_" << op << "_$$";
- Node v = NodeManager::currentNM()->mkSkolem( ss.str(), m[a].getType(), "created during macro definition recognition" );
- d_macro_basis[op].push_back( v );
- }
- }
- std::vector< Node > eq;
- for( size_t a=0; a<m.getNumChildren(); a++ ){
- eq.push_back( m[a] );
- }
- //solve system of equations "d_macro_basis[op] = m" for variables in fvs
- std::map< Node, Node > solved;
- //solve obvious cases first
- for( size_t a=0; a<eq.size(); a++ ){
- if( std::find( fvs.begin(), fvs.end(), eq[a] )!=fvs.end() ){
- if( solved[ eq[a] ].isNull() ){
- solved[ eq[a] ] = d_macro_basis[op][a];
- }
- }
- }
- //now, apply substitution for obvious cases
- std::vector< Node > vars;
- std::vector< Node > subs;
- getSubstitution( fvs, solved, vars, subs, false );
- for( size_t a=0; a<eq.size(); a++ ){
- eq[a] = eq[a].substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
- }
-
- Trace("macros-eq") << "Solve system of equations : " << std::endl;
- for( size_t a=0; a<m.getNumChildren(); a++ ){
- if( d_macro_basis[op][a]!=eq[a] ){
- Trace("macros-eq") << " " << d_macro_basis[op][a] << " = " << eq[a] << std::endl;
- }
- }
- Trace("macros-eq") << " for ";
- for( size_t a=0; a<fvs.size(); a++ ){
- if( solved[ fvs[a] ].isNull() ){
- Trace("macros-eq") << fvs[a] << " ";
- }
- }
- Trace("macros-eq") << std::endl;
- //DO_THIS
-
-
- vars.clear();
- subs.clear();
- if( getSubstitution( fvs, solved, vars, subs, true ) ){
- //build condition
- std::vector< Node > conds;
- if( !n_cond.isNull() ){
- //must apply substitution obtained from solving system of equations to original condition
- n_cond = n_cond.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
- conds.push_back( n_cond );
- }
- for( size_t a=0; a<eq.size(); a++ ){
- //collect conditions based on solving argument's system of equations
- if( d_macro_basis[op][a]!=eq[a] ){
- conds.push_back( NodeManager::currentNM()->mkNode( eq[a].getType().isBoolean() ? IFF : EQUAL, d_macro_basis[op][a], eq[a] ) );
- }
- }
- //build the condition
- if( !conds.empty() ){
- n_cond = conds.size()==1 ? conds[0] : NodeManager::currentNM()->mkNode( AND, conds );
- }
- //apply the substitution to the
- n_def = n_def.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
- //now see if definition is consistent with others
- if( isConsistentDefinition( op, n_cond, n_def ) ){
- //must clear if it is a base definition
- if( n_cond.isNull() ){
- d_macro_def_cases[ op ].clear();
- }
- d_macro_def_cases[ op ].push_back( std::pair< Node, Node >( n_cond, n_def ) );
- }
- }
- }
- }
- }
- }
- }
- }
-}
-
-Node QuantifierMacros::simplify( Node n ){
- Trace("macros-debug") << "simplify " << n << std::endl;
- std::vector< Node > children;
- bool childChanged = false;
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- Node nn = simplify( n[i] );
- children.push_back( nn );
- childChanged = childChanged || nn!=n[i];
- }
- if( n.getKind()==APPLY_UF ){
- Node op = n.getOperator();
- if( d_macro_defs.find( op )!=d_macro_defs.end() && !d_macro_defs[op].isNull() ){
- //do subsitutition
- Node ret = d_macro_defs[op];
- ret = ret.substitute( d_macro_basis[op].begin(), d_macro_basis[op].end(), children.begin(), children.end() );
- return ret;
- }
- }
- if( childChanged ){
- if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
- children.insert( children.begin(), n.getOperator() );
- }
- return NodeManager::currentNM()->mkNode( n.getKind(), children );
- }else{
- return n;
- }
-}
+/********************* */
+/*! \file macros.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Sort inference module
+ **
+ ** This class implements quantifiers macro definitions.
+ **/
+
+#include <vector>
+
+#include "theory/quantifiers/macros.h"
+#include "theory/rewriter.h"
+
+using namespace CVC4;
+using namespace std;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+
+bool QuantifierMacros::simplify( std::vector< Node >& assertions, bool doRewrite ){
+ //first, collect macro definitions
+ for( size_t i=0; i<assertions.size(); i++ ){
+ if( assertions[i].getKind()==FORALL ){
+ std::vector< Node > args;
+ for( size_t j=0; j<assertions[i][0].getNumChildren(); j++ ){
+ args.push_back( assertions[i][0][j] );
+ }
+ //look at the body of the quantifier for macro definition
+ process( assertions[i][1], true, args, assertions[i] );
+ }
+ }
+ //create macro defs
+ for( std::map< Node, std::vector< std::pair< Node, Node > > >::iterator it = d_macro_def_cases.begin();
+ it != d_macro_def_cases.end(); ++it ){
+ //create ite based on case definitions
+ Node val;
+ for( size_t i=0; i<it->second.size(); ++i ){
+ if( it->second[i].first.isNull() ){
+ Assert( i==0 );
+ val = it->second[i].second;
+ }else{
+ //if value is null, must generate it
+ if( val.isNull() ){
+ std::stringstream ss;
+ ss << "mdo_" << it->first << "_$$";
+ Node op = NodeManager::currentNM()->mkSkolem( ss.str(), it->first.getType(), "op created during macro definitions" );
+ //will be defined in terms of fresh operator
+ std::vector< Node > children;
+ children.push_back( op );
+ children.insert( children.end(), d_macro_basis[ it->first ].begin(), d_macro_basis[ it->first ].end() );
+ val = NodeManager::currentNM()->mkNode( APPLY_UF, children );
+ }
+ val = NodeManager::currentNM()->mkNode( ITE, it->second[i].first, it->second[i].second, val );
+ }
+ }
+ d_macro_defs[ it->first ] = val;
+ Trace("macros-def") << "* " << val << " is a macro for " << it->first << std::endl;
+ }
+ //now simplify bodies
+ for( std::map< Node, Node >::iterator it = d_macro_defs.begin(); it != d_macro_defs.end(); ++it ){
+ d_macro_defs[ it->first ] = Rewriter::rewrite( simplify( it->second ) );
+ }
+ bool retVal = false;
+ if( doRewrite && !d_macro_defs.empty() ){
+ //now, rewrite based on macro definitions
+ for( size_t i=0; i<assertions.size(); i++ ){
+ Node prev = assertions[i];
+ assertions[i] = simplify( assertions[i] );
+ if( prev!=assertions[i] ){
+ assertions[i] = Rewriter::rewrite( assertions[i] );
+ Trace("macros-rewrite") << "Rewrite " << prev << " to " << assertions[i] << std::endl;
+ retVal = true;
+ }
+ }
+ }
+ return retVal;
+}
+
+bool QuantifierMacros::contains( Node n, Node n_s ){
+ if( n==n_s ){
+ return true;
+ }else{
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ if( contains( n[i], n_s ) ){
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+bool QuantifierMacros::containsBadOp( Node n, Node n_op ){
+ if( n!=n_op ){
+ if( n.getKind()==APPLY_UF ){
+ Node op = n.getOperator();
+ if( op==n_op.getOperator() ){
+ return true;
+ }
+ if( d_macro_def_cases.find( op )!=d_macro_def_cases.end() && !d_macro_def_cases[op].empty() ){
+ return true;
+ }
+ }
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ if( containsBadOp( n[i], n_op ) ){
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool QuantifierMacros::isMacroLiteral( Node n, bool pol ){
+ return pol && n.getKind()==EQUAL;//( n.getKind()==EQUAL || n.getKind()==IFF );
+}
+
+void QuantifierMacros::getMacroCandidates( Node n, std::vector< Node >& candidates ){
+ if( n.getKind()==APPLY_UF ){
+ candidates.push_back( n );
+ }else if( n.getKind()==PLUS ){
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ getMacroCandidates( n[i], candidates );
+ }
+ }else if( n.getKind()==MULT ){
+ //if the LHS is a constant
+ if( n.getNumChildren()==2 && n[0].isConst() ){
+ getMacroCandidates( n[1], candidates );
+ }
+ }
+}
+
+Node QuantifierMacros::solveInEquality( Node n, Node lit ){
+ if( lit.getKind()==IFF || lit.getKind()==EQUAL ){
+ //return the opposite side of the equality if defined that way
+ for( int i=0; i<2; i++ ){
+ if( lit[i]==n ){
+ return lit[ i==0 ? 1 : 0];
+ }
+ }
+ //must solve for term n in the literal lit
+ if( lit[0].getType().isInteger() || lit[0].getType().isReal() ){
+ Node coeff;
+ Node term;
+ //could be solved for on LHS
+ if( lit[0].getKind()==MULT && lit[0][1]==n ){
+ Assert( lit[0][0].isConst() );
+ term = lit[1];
+ coeff = lit[0][0];
+ }else{
+ Assert( lit[1].getKind()==PLUS );
+ std::vector< Node > plus_children;
+ //find monomial with n
+ for( size_t j=0; j<lit[1].getNumChildren(); j++ ){
+ if( lit[1][j]==n ){
+ Assert( coeff.isNull() );
+ coeff = NodeManager::currentNM()->mkConst( Rational(1) );
+ }else if( lit[1][j].getKind()==MULT && lit[1][j][1]==n ){
+ Assert( coeff.isNull() );
+ Assert( lit[1][j][0].isConst() );
+ coeff = lit[1][j][0];
+ }else{
+ plus_children.push_back( lit[1][j] );
+ }
+ }
+ if( !coeff.isNull() ){
+ term = NodeManager::currentNM()->mkNode( PLUS, plus_children );
+ term = NodeManager::currentNM()->mkNode( MINUS, lit[0], term );
+ }
+ }
+ if( !coeff.isNull() ){
+ coeff = NodeManager::currentNM()->mkConst( Rational(1) / coeff.getConst<Rational>() );
+ term = NodeManager::currentNM()->mkNode( MULT, coeff, term );
+ term = Rewriter::rewrite( term );
+ return term;
+ }
+ }
+ }
+ Trace("macros-debug") << "Cannot find for " << lit << " " << n << std::endl;
+ return Node::null();
+}
+
+bool QuantifierMacros::isConsistentDefinition( Node op, Node cond, Node def ){
+ if( d_macro_def_cases[op].empty() || ( cond.isNull() && !d_macro_def_cases[op][0].first.isNull() ) ){
+ return true;
+ }else{
+ return false;
+ }
+}
+
+bool QuantifierMacros::getFreeVariables( Node n, std::vector< Node >& v_quant, std::vector< Node >& vars, bool retOnly ){
+ if( std::find( v_quant.begin(), v_quant.end(), n )!=v_quant.end() ){
+ if( std::find( vars.begin(), vars.end(), n )==vars.end() ){
+ if( retOnly ){
+ return true;
+ }else{
+ vars.push_back( n );
+ }
+ }
+ }
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ if( getFreeVariables( n[i], v_quant, vars, retOnly ) ){
+ return true;
+ }
+ }
+ return false;
+}
+
+bool QuantifierMacros::getSubstitution( std::vector< Node >& v_quant, std::map< Node, Node >& solved,
+ std::vector< Node >& vars, std::vector< Node >& subs, bool reqComplete ){
+ bool success = true;
+ for( size_t a=0; a<v_quant.size(); a++ ){
+ if( !solved[ v_quant[a] ].isNull() ){
+ vars.push_back( v_quant[a] );
+ subs.push_back( solved[ v_quant[a] ] );
+ }else{
+ if( reqComplete ){
+ success = false;
+ break;
+ }
+ }
+ }
+ return success;
+}
+
+void QuantifierMacros::process( Node n, bool pol, std::vector< Node >& args, Node f ){
+ if( n.getKind()==NOT ){
+ process( n[0], !pol, args, f );
+ }else if( n.getKind()==AND || n.getKind()==OR || n.getKind()==IMPLIES ){
+ //bool favorPol = (n.getKind()==AND)==pol;
+ //conditional?
+ }else if( n.getKind()==ITE ){
+ //can not do anything
+ }else{
+ //literal case
+ if( isMacroLiteral( n, pol ) ){
+ std::vector< Node > candidates;
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ getMacroCandidates( n[i], candidates );
+ }
+ for( size_t i=0; i<candidates.size(); i++ ){
+ Node m = candidates[i];
+ Node op = m.getOperator();
+ if( !containsBadOp( n, m ) ){
+ std::vector< Node > fvs;
+ getFreeVariables( m, args, fvs, false );
+ //get definition and condition
+ Node n_def = solveInEquality( m, n ); //definition for the macro
+ //definition must exist and not contain any free variables apart from fvs
+ if( !n_def.isNull() && !getFreeVariables( n_def, args, fvs, true ) ){
+ Node n_cond; //condition when this definition holds
+ //conditional must not contain any free variables apart from fvs
+ if( n_cond.isNull() || !getFreeVariables( n_cond, args, fvs, true ) ){
+ Trace("macros") << m << " is possible macro in " << f << std::endl;
+ //now we must rewrite candidates[i] to a term of form g( x1, ..., xn ) where
+ // x1 ... xn are distinct variables
+ if( d_macro_basis[op].empty() ){
+ for( size_t a=0; a<m.getNumChildren(); a++ ){
+ std::stringstream ss;
+ ss << "mda_" << op << "_$$";
+ Node v = NodeManager::currentNM()->mkSkolem( ss.str(), m[a].getType(), "created during macro definition recognition" );
+ d_macro_basis[op].push_back( v );
+ }
+ }
+ std::vector< Node > eq;
+ for( size_t a=0; a<m.getNumChildren(); a++ ){
+ eq.push_back( m[a] );
+ }
+ //solve system of equations "d_macro_basis[op] = m" for variables in fvs
+ std::map< Node, Node > solved;
+ //solve obvious cases first
+ for( size_t a=0; a<eq.size(); a++ ){
+ if( std::find( fvs.begin(), fvs.end(), eq[a] )!=fvs.end() ){
+ if( solved[ eq[a] ].isNull() ){
+ solved[ eq[a] ] = d_macro_basis[op][a];
+ }
+ }
+ }
+ //now, apply substitution for obvious cases
+ std::vector< Node > vars;
+ std::vector< Node > subs;
+ getSubstitution( fvs, solved, vars, subs, false );
+ for( size_t a=0; a<eq.size(); a++ ){
+ eq[a] = eq[a].substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ }
+
+ Trace("macros-eq") << "Solve system of equations : " << std::endl;
+ for( size_t a=0; a<m.getNumChildren(); a++ ){
+ if( d_macro_basis[op][a]!=eq[a] ){
+ Trace("macros-eq") << " " << d_macro_basis[op][a] << " = " << eq[a] << std::endl;
+ }
+ }
+ Trace("macros-eq") << " for ";
+ for( size_t a=0; a<fvs.size(); a++ ){
+ if( solved[ fvs[a] ].isNull() ){
+ Trace("macros-eq") << fvs[a] << " ";
+ }
+ }
+ Trace("macros-eq") << std::endl;
+ //DO_THIS
+
+
+ vars.clear();
+ subs.clear();
+ if( getSubstitution( fvs, solved, vars, subs, true ) ){
+ //build condition
+ std::vector< Node > conds;
+ if( !n_cond.isNull() ){
+ //must apply substitution obtained from solving system of equations to original condition
+ n_cond = n_cond.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ conds.push_back( n_cond );
+ }
+ for( size_t a=0; a<eq.size(); a++ ){
+ //collect conditions based on solving argument's system of equations
+ if( d_macro_basis[op][a]!=eq[a] ){
+ conds.push_back( NodeManager::currentNM()->mkNode( eq[a].getType().isBoolean() ? IFF : EQUAL, d_macro_basis[op][a], eq[a] ) );
+ }
+ }
+ //build the condition
+ if( !conds.empty() ){
+ n_cond = conds.size()==1 ? conds[0] : NodeManager::currentNM()->mkNode( AND, conds );
+ }
+ //apply the substitution to the
+ n_def = n_def.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ //now see if definition is consistent with others
+ if( isConsistentDefinition( op, n_cond, n_def ) ){
+ //must clear if it is a base definition
+ if( n_cond.isNull() ){
+ d_macro_def_cases[ op ].clear();
+ }
+ d_macro_def_cases[ op ].push_back( std::pair< Node, Node >( n_cond, n_def ) );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+Node QuantifierMacros::simplify( Node n ){
+ Trace("macros-debug") << "simplify " << n << std::endl;
+ std::vector< Node > children;
+ bool childChanged = false;
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ Node nn = simplify( n[i] );
+ children.push_back( nn );
+ childChanged = childChanged || nn!=n[i];
+ }
+ if( n.getKind()==APPLY_UF ){
+ Node op = n.getOperator();
+ if( d_macro_defs.find( op )!=d_macro_defs.end() && !d_macro_defs[op].isNull() ){
+ //do substitution
+ Node ret = d_macro_defs[op];
+ ret = ret.substitute( d_macro_basis[op].begin(), d_macro_basis[op].end(), children.begin(), children.end() );
+ return ret;
+ }
+ }
+ if( childChanged ){
+ if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ children.insert( children.begin(), n.getOperator() );
+ }
+ return NodeManager::currentNM()->mkNode( n.getKind(), children );
+ }else{
+ return n;
+ }
+}
diff --git a/src/theory/quantifiers/macros.h b/src/theory/quantifiers/macros.h
index b1fbb3e68..140f02966 100755..100644
--- a/src/theory/quantifiers/macros.h
+++ b/src/theory/quantifiers/macros.h
@@ -1,62 +1,62 @@
-/********************* */
-/*! \file macros.h
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Pre-process step for detecting quantifier macro definitions
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__QUANTIFIERS_MACROS_H
-#define __CVC4__QUANTIFIERS_MACROS_H
-
-#include <iostream>
-#include <string>
-#include <vector>
-#include <map>
-#include "expr/node.h"
-#include "expr/type_node.h"
-
-namespace CVC4 {
-namespace theory {
-namespace quantifiers {
-
-class QuantifierMacros{
-private:
- void process( Node n, bool pol, std::vector< Node >& args, Node f );
- bool contains( Node n, Node n_s );
- bool containsBadOp( Node n, Node n_op );
- bool isMacroLiteral( Node n, bool pol );
- void getMacroCandidates( Node n, std::vector< Node >& candidates );
- Node solveInEquality( Node n, Node lit );
- bool isConsistentDefinition( Node op, Node cond, Node def );
- bool getFreeVariables( Node n, std::vector< Node >& v_quant, std::vector< Node >& vars, bool retOnly );
- bool getSubstitution( std::vector< Node >& v_quant, std::map< Node, Node >& solved,
- std::vector< Node >& vars, std::vector< Node >& subs, bool reqComplete );
- //map from operators to macro basis terms
- std::map< Node, std::vector< Node > > d_macro_basis;
- //map from operators to map from conditions to definition cases
- std::map< Node, std::vector< std::pair< Node, Node > > > d_macro_def_cases;
- //map from operators to macro definition
- std::map< Node, Node > d_macro_defs;
-private:
- Node simplify( Node n );
-public:
- QuantifierMacros(){}
- ~QuantifierMacros(){}
-
- bool simplify( std::vector< Node >& assertions, bool doRewrite = false );
-};
-
-}
-}
-}
-
-#endif
+/********************* */
+/*! \file macros.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Pre-process step for detecting quantifier macro definitions
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__QUANTIFIERS_MACROS_H
+#define __CVC4__QUANTIFIERS_MACROS_H
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <map>
+#include "expr/node.h"
+#include "expr/type_node.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+class QuantifierMacros{
+private:
+ void process( Node n, bool pol, std::vector< Node >& args, Node f );
+ bool contains( Node n, Node n_s );
+ bool containsBadOp( Node n, Node n_op );
+ bool isMacroLiteral( Node n, bool pol );
+ void getMacroCandidates( Node n, std::vector< Node >& candidates );
+ Node solveInEquality( Node n, Node lit );
+ bool isConsistentDefinition( Node op, Node cond, Node def );
+ bool getFreeVariables( Node n, std::vector< Node >& v_quant, std::vector< Node >& vars, bool retOnly );
+ bool getSubstitution( std::vector< Node >& v_quant, std::map< Node, Node >& solved,
+ std::vector< Node >& vars, std::vector< Node >& subs, bool reqComplete );
+ //map from operators to macro basis terms
+ std::map< Node, std::vector< Node > > d_macro_basis;
+ //map from operators to map from conditions to definition cases
+ std::map< Node, std::vector< std::pair< Node, Node > > > d_macro_def_cases;
+ //map from operators to macro definition
+ std::map< Node, Node > d_macro_defs;
+private:
+ Node simplify( Node n );
+public:
+ QuantifierMacros(){}
+ ~QuantifierMacros(){}
+
+ bool simplify( std::vector< Node >& assertions, bool doRewrite = false );
+};
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/model_builder.cpp b/src/theory/quantifiers/model_builder.cpp
index 2f44140c2..d8b154b95 100644
--- a/src/theory/quantifiers/model_builder.cpp
+++ b/src/theory/quantifiers/model_builder.cpp
@@ -368,15 +368,32 @@ void ModelEngineBuilderDefault::reset( FirstOrderModel* fm ){
d_op_selection_terms.clear();
}
+
+int ModelEngineBuilderDefault::getSelectionScore( std::vector< Node >& uf_terms ) {
+ /*
+ size_t maxChildren = 0;
+ for( size_t i=0; i<uf_terms.size(); i++ ){
+ if( uf_terms[i].getNumChildren()>maxChildren ){
+ maxChildren = uf_terms[i].getNumChildren();
+ }
+ }
+ //TODO: look at how many entries they have?
+ return (int)maxChildren;
+ */
+ return 0;
+}
+
void ModelEngineBuilderDefault::analyzeQuantifier( FirstOrderModel* fm, Node f ){
Debug("fmf-model-prefs") << "Analyze quantifier " << f << std::endl;
//the pro/con preferences for this quantifier
std::vector< Node > pro_con[2];
//the terms in the selection literal we choose
std::vector< Node > selectionLitTerms;
+ Trace("inst-gen-debug-quant") << "Inst-gen analyze " << f << std::endl;
//for each asserted quantifier f,
// - determine selection literals
// - check which function/predicates have good and bad definitions for satisfying f
+ int selectLitScore = -1;
QuantPhaseReq* qpr = d_qe->getPhaseRequirements( f );
for( std::map< Node, bool >::iterator it = qpr->d_phase_reqs.begin(); it != qpr->d_phase_reqs.end(); ++it ){
//the literal n is phase-required for quantifier f
@@ -433,10 +450,18 @@ void ModelEngineBuilderDefault::analyzeQuantifier( FirstOrderModel* fm, Node f )
selectLit = true;
}
}
+ //also check if it is naturally a better literal
+ if( !selectLit ){
+ int score = getSelectionScore( uf_terms );
+ //Trace("inst-gen-debug") << "Check " << score << " < " << selectLitScore << std::endl;
+ selectLit = score<selectLitScore;
+ }
//see if we wish to choose this as a selection literal
d_quant_selection_lit_candidates[f].push_back( value ? n : n.notNode() );
if( selectLit ){
+ selectLitScore = getSelectionScore( uf_terms );
Trace("inst-gen-debug") << "Choose selection literal " << gn << std::endl;
+ Trace("inst-gen-debug") << " flags: " << isConst << " " << selectLitConstraints << " " << selectLitScore << std::endl;
d_quant_selection_lit[f] = value ? n : n.notNode();
selectionLitTerms.clear();
selectionLitTerms.insert( selectionLitTerms.begin(), uf_terms.begin(), uf_terms.end() );
@@ -466,7 +491,7 @@ void ModelEngineBuilderDefault::analyzeQuantifier( FirstOrderModel* fm, Node f )
d_op_selection_terms[ selectionLitTerms[i].getOperator() ].push_back( selectionLitTerms[i] );
}
}else{
- Trace("inst-gen-warn") << "WARNING: " << f << " has no selection literals (is the body of f clausified?)" << std::endl;
+ Trace("inst-gen-warn") << "WARNING: " << f << " has no selection literals" << std::endl;
}
//process information about requirements and preferences of quantifier f
if( d_quant_sat.find( f )!=d_quant_sat.end() ){
@@ -526,7 +551,7 @@ int ModelEngineBuilderDefault::doInstGen( FirstOrderModel* fm, Node f ){
//if applicable, try to add exceptions here
if( !tr_terms.empty() ){
//make a trigger for these terms, add instantiations
- inst::Trigger* tr = inst::Trigger::mkTrigger( d_qe, f, tr_terms );
+ inst::Trigger* tr = inst::Trigger::mkTrigger( d_qe, f, tr_terms, 0, true, inst::Trigger::TR_MAKE_NEW, options::smartTriggers() );
//Notice() << "Trigger = " << (*tr) << std::endl;
tr->resetInstantiationRound();
tr->reset( Node::null() );
diff --git a/src/theory/quantifiers/model_builder.h b/src/theory/quantifiers/model_builder.h
index 908cfca2b..5490d17dd 100644
--- a/src/theory/quantifiers/model_builder.h
+++ b/src/theory/quantifiers/model_builder.h
@@ -155,6 +155,8 @@ private: ///information for (old) InstGen
std::map< Node, Node > d_term_selection_lit;
//map from operators to terms that appear in selection literals
std::map< Node, std::vector< Node > > d_op_selection_terms;
+ //get selection score
+ int getSelectionScore( std::vector< Node >& uf_terms );
protected:
//reset
void reset( FirstOrderModel* fm );
diff --git a/src/theory/quantifiers/model_engine.cpp b/src/theory/quantifiers/model_engine.cpp
index bf6ea11f0..1522d0828 100644
--- a/src/theory/quantifiers/model_engine.cpp
+++ b/src/theory/quantifiers/model_engine.cpp
@@ -73,9 +73,8 @@ void ModelEngine::check( Theory::Effort e ){
if( addedLemmas==0 ){
Trace("model-engine-debug") << "Verify uf ss is minimal..." << std::endl;
//let the strong solver verify that the model is minimal
- uf::StrongSolverTheoryUf* uf_ss = ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->theoryOf( THEORY_UF ))->getStrongSolver();
//for debugging, this will if there are terms in the model that the strong solver was not notified of
- uf_ss->debugModel( fm );
+ ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->theoryOf( THEORY_UF ))->getStrongSolver()->debugModel( fm );
Trace("model-engine-debug") << "Check model..." << std::endl;
d_incomplete_check = false;
//print debug
@@ -164,7 +163,7 @@ int ModelEngine::checkModel( int checkOption ){
Trace("model-engine-debug") << " ";
for( size_t i=0; i<it->second.size(); i++ ){
//Trace("model-engine-debug") << it->second[i] << " ";
- Node r = ((EqualityQueryQuantifiersEngine*)d_quantEngine->getEqualityQuery())->getInternalRepresentative( it->second[i] );
+ Node r = ((EqualityQueryQuantifiersEngine*)d_quantEngine->getEqualityQuery())->getRepresentative( it->second[i] );
Trace("model-engine-debug") << r << " ";
}
Trace("model-engine-debug") << std::endl;
@@ -225,7 +224,7 @@ int ModelEngine::checkModel( int checkOption ){
int ModelEngine::exhaustiveInstantiate( Node f, bool useRelInstDomain ){
int addedLemmas = 0;
- Debug("inst-fmf-ei") << "Exhaustive instantiate " << f << "..." << std::endl;
+ Trace("inst-fmf-ei") << "Exhaustive instantiate " << f << "..." << std::endl;
Debug("inst-fmf-ei") << " Instantiation Constants: ";
for( size_t i=0; i<f[0].getNumChildren(); i++ ){
Debug("inst-fmf-ei") << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i ) << " ";
@@ -299,12 +298,12 @@ int ModelEngine::exhaustiveInstantiate( Node f, bool useRelInstDomain ){
relevantInst = relevantInst * (int)riter.d_domain[i].size();
}
d_relevantLemmas += relevantInst;
- Debug("inst-fmf-ei") << "Finished: " << std::endl;
+ Trace("inst-fmf-ei") << "Finished: " << std::endl;
//Debug("inst-fmf-ei") << " Inst Total: " << totalInst << std::endl;
- Debug("inst-fmf-ei") << " Inst Relevant: " << relevantInst << std::endl;
- Debug("inst-fmf-ei") << " Inst Tried: " << triedLemmas << std::endl;
- Debug("inst-fmf-ei") << " Inst Added: " << addedLemmas << std::endl;
- Debug("inst-fmf-ei") << " # Tests: " << tests << std::endl;
+ Trace("inst-fmf-ei") << " Inst Relevant: " << relevantInst << std::endl;
+ Trace("inst-fmf-ei") << " Inst Tried: " << triedLemmas << std::endl;
+ Trace("inst-fmf-ei") << " Inst Added: " << addedLemmas << std::endl;
+ Trace("inst-fmf-ei") << " # Tests: " << tests << std::endl;
if( addedLemmas>1000 ){
Trace("model-engine-warn") << "WARNING: many instantiations produced for " << f << ": " << std::endl;
//Trace("model-engine-warn") << " Inst Total: " << totalInst << std::endl;
diff --git a/src/theory/quantifiers/options b/src/theory/quantifiers/options
index bc45e6051..7a3687dd5 100644
--- a/src/theory/quantifiers/options
+++ b/src/theory/quantifiers/options
@@ -37,6 +37,9 @@ option cnfQuant --cnf-quant bool :default false
option preSkolemQuant --pre-skolem-quant bool :default false
apply skolemization eagerly to bodies of quantified formulas
+# Whether to perform agressive miniscoping
+option aggressiveMiniscopeQuant --ag-miniscope-quant bool :default false
+ perform aggressive miniscoping for quantifiers
# Whether to perform quantifier macro expansion
option macrosQuant --macros-quant bool :default false
perform quantifiers macro expansions
@@ -45,8 +48,8 @@ option macrosQuant --macros-quant bool :default false
option smartTriggers /--disable-smart-triggers bool :default true
disable smart triggers
# Whether to use relevent triggers
-option relevantTriggers /--relevant-triggers bool :default true
- prefer triggers that are more relevant based on SInE style method
+option relevantTriggers --relevant-triggers bool :default true
+ prefer triggers that are more relevant based on SInE style analysis
# Whether to consider terms in the bodies of quantifiers for matching
option registerQuantBodyTerms --register-quant-body-terms bool :default false
@@ -65,13 +68,14 @@ option cbqi --enable-cbqi/--disable-cbqi bool :default false
turns on counterexample-based quantifier instantiation [off by default]
/turns off counterexample-based quantifier instantiation
+
option userPatternsQuant /--ignore-user-patterns bool :default true
ignore user-provided patterns for quantifier instantiation
option flipDecision --flip-decision/ bool :default false
turns on flip decision heuristic
-option internalReps --disable-quant-internal-reps/ bool :default true
+option internalReps /--disable-quant-internal-reps bool :default true
disables instantiating with representatives chosen by quantifiers engine
option finiteModelFind --finite-model-find bool :default false
@@ -94,6 +98,8 @@ option fmfInstGen /--disable-fmf-inst-gen bool :default true
disable Inst-Gen instantiation techniques for finite model finding
option fmfInstGenOneQuantPerRound --fmf-inst-gen-one-quant-per-round bool :default false
only perform Inst-Gen instantiation techniques on one quantifier per round
+option fmfFreshDistConst --fmf-fresh-dc bool :default false
+ use fresh distinguished representative when applying Inst-Gen techniques
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
diff --git a/src/theory/quantifiers/quant_util.cpp b/src/theory/quantifiers/quant_util.cpp
index d1b0e0fea..9e4a2a14a 100755..100644
--- a/src/theory/quantifiers/quant_util.cpp
+++ b/src/theory/quantifiers/quant_util.cpp
@@ -1,145 +1,145 @@
-/********************* */
-/*! \file quant_util.cpp
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: bobot, mdeters
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Implementation of quantifier utilities
- **/
-
-#include "theory/quantifiers/quant_util.h"
-#include "theory/quantifiers/inst_match.h"
-#include "theory/quantifiers/term_database.h"
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-
-void QuantRelevance::registerQuantifier( Node f ){
- //compute symbols in f
- std::vector< Node > syms;
- computeSymbols( f[1], syms );
- d_syms[f].insert( d_syms[f].begin(), syms.begin(), syms.end() );
- //set initial relevance
- int minRelevance = -1;
- for( int i=0; i<(int)syms.size(); i++ ){
- d_syms_quants[ syms[i] ].push_back( f );
- int r = getRelevance( syms[i] );
- if( r!=-1 && ( minRelevance==-1 || r<minRelevance ) ){
- minRelevance = r;
- }
- }
- if( minRelevance!=-1 ){
- setRelevance( f, minRelevance+1 );
- }
-}
-
-
-/** compute symbols */
-void QuantRelevance::computeSymbols( Node n, std::vector< Node >& syms ){
- if( n.getKind()==APPLY_UF ){
- Node op = n.getOperator();
- if( std::find( syms.begin(), syms.end(), op )==syms.end() ){
- syms.push_back( op );
- }
- }
- if( n.getKind()!=FORALL ){
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- computeSymbols( n[i], syms );
- }
- }
-}
-
-/** set relevance */
-void QuantRelevance::setRelevance( Node s, int r ){
- if( d_computeRel ){
- int rOld = getRelevance( s );
- if( rOld==-1 || r<rOld ){
- d_relevance[s] = r;
- if( s.getKind()==FORALL ){
- for( int i=0; i<(int)d_syms[s].size(); i++ ){
- setRelevance( d_syms[s][i], r );
- }
- }else{
- for( int i=0; i<(int)d_syms_quants[s].size(); i++ ){
- setRelevance( d_syms_quants[s][i], r+1 );
- }
- }
- }
- }
-}
-
-
-QuantPhaseReq::QuantPhaseReq( Node n, bool computeEq ){
- std::map< Node, int > phaseReqs2;
- computePhaseReqs( n, false, phaseReqs2 );
- for( std::map< Node, int >::iterator it = phaseReqs2.begin(); it != phaseReqs2.end(); ++it ){
- if( it->second==1 ){
- d_phase_reqs[ it->first ] = true;
- }else if( it->second==-1 ){
- d_phase_reqs[ it->first ] = false;
- }
- }
- Debug("inst-engine-phase-req") << "Phase requirements for " << n << ":" << std::endl;
- //now, compute if any patterns are equality required
- if( computeEq ){
- for( std::map< Node, bool >::iterator it = d_phase_reqs.begin(); it != d_phase_reqs.end(); ++it ){
- Debug("inst-engine-phase-req") << " " << it->first << " -> " << it->second << std::endl;
- if( it->first.getKind()==EQUAL ){
- if( it->first[0].hasAttribute(InstConstantAttribute()) ){
- if( !it->first[1].hasAttribute(InstConstantAttribute()) ){
- d_phase_reqs_equality_term[ it->first[0] ] = it->first[1];
- d_phase_reqs_equality[ it->first[0] ] = it->second;
- Debug("inst-engine-phase-req") << " " << it->first[0] << ( it->second ? " == " : " != " ) << it->first[1] << std::endl;
- }
- }else if( it->first[1].hasAttribute(InstConstantAttribute()) ){
- d_phase_reqs_equality_term[ it->first[1] ] = it->first[0];
- d_phase_reqs_equality[ it->first[1] ] = it->second;
- Debug("inst-engine-phase-req") << " " << it->first[1] << ( it->second ? " == " : " != " ) << it->first[0] << std::endl;
- }
- }
- }
- }
-}
-
-void QuantPhaseReq::computePhaseReqs( Node n, bool polarity, std::map< Node, int >& phaseReqs ){
- bool newReqPol = false;
- bool newPolarity;
- if( n.getKind()==NOT ){
- newReqPol = true;
- newPolarity = !polarity;
- }else if( n.getKind()==OR || n.getKind()==IMPLIES ){
- if( !polarity ){
- newReqPol = true;
- newPolarity = false;
- }
- }else if( n.getKind()==AND ){
- if( polarity ){
- newReqPol = true;
- newPolarity = true;
- }
- }else{
- int val = polarity ? 1 : -1;
- if( phaseReqs.find( n )==phaseReqs.end() ){
- phaseReqs[n] = val;
- }else if( val!=phaseReqs[n] ){
- phaseReqs[n] = 0;
- }
- }
- if( newReqPol ){
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( n.getKind()==IMPLIES && i==0 ){
- computePhaseReqs( n[i], !newPolarity, phaseReqs );
- }else{
- computePhaseReqs( n[i], newPolarity, phaseReqs );
- }
- }
- }
-}
+/********************* */
+/*! \file quant_util.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Implementation of quantifier utilities
+ **/
+
+#include "theory/quantifiers/quant_util.h"
+#include "theory/quantifiers/inst_match.h"
+#include "theory/quantifiers/term_database.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+
+void QuantRelevance::registerQuantifier( Node f ){
+ //compute symbols in f
+ std::vector< Node > syms;
+ computeSymbols( f[1], syms );
+ d_syms[f].insert( d_syms[f].begin(), syms.begin(), syms.end() );
+ //set initial relevance
+ int minRelevance = -1;
+ for( int i=0; i<(int)syms.size(); i++ ){
+ d_syms_quants[ syms[i] ].push_back( f );
+ int r = getRelevance( syms[i] );
+ if( r!=-1 && ( minRelevance==-1 || r<minRelevance ) ){
+ minRelevance = r;
+ }
+ }
+ if( minRelevance!=-1 ){
+ setRelevance( f, minRelevance+1 );
+ }
+}
+
+
+/** compute symbols */
+void QuantRelevance::computeSymbols( Node n, std::vector< Node >& syms ){
+ if( n.getKind()==APPLY_UF ){
+ Node op = n.getOperator();
+ if( std::find( syms.begin(), syms.end(), op )==syms.end() ){
+ syms.push_back( op );
+ }
+ }
+ if( n.getKind()!=FORALL ){
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ computeSymbols( n[i], syms );
+ }
+ }
+}
+
+/** set relevance */
+void QuantRelevance::setRelevance( Node s, int r ){
+ if( d_computeRel ){
+ int rOld = getRelevance( s );
+ if( rOld==-1 || r<rOld ){
+ d_relevance[s] = r;
+ if( s.getKind()==FORALL ){
+ for( int i=0; i<(int)d_syms[s].size(); i++ ){
+ setRelevance( d_syms[s][i], r );
+ }
+ }else{
+ for( int i=0; i<(int)d_syms_quants[s].size(); i++ ){
+ setRelevance( d_syms_quants[s][i], r+1 );
+ }
+ }
+ }
+ }
+}
+
+
+QuantPhaseReq::QuantPhaseReq( Node n, bool computeEq ){
+ std::map< Node, int > phaseReqs2;
+ computePhaseReqs( n, false, phaseReqs2 );
+ for( std::map< Node, int >::iterator it = phaseReqs2.begin(); it != phaseReqs2.end(); ++it ){
+ if( it->second==1 ){
+ d_phase_reqs[ it->first ] = true;
+ }else if( it->second==-1 ){
+ d_phase_reqs[ it->first ] = false;
+ }
+ }
+ Debug("inst-engine-phase-req") << "Phase requirements for " << n << ":" << std::endl;
+ //now, compute if any patterns are equality required
+ if( computeEq ){
+ for( std::map< Node, bool >::iterator it = d_phase_reqs.begin(); it != d_phase_reqs.end(); ++it ){
+ Debug("inst-engine-phase-req") << " " << it->first << " -> " << it->second << std::endl;
+ if( it->first.getKind()==EQUAL ){
+ if( it->first[0].hasAttribute(InstConstantAttribute()) ){
+ if( !it->first[1].hasAttribute(InstConstantAttribute()) ){
+ d_phase_reqs_equality_term[ it->first[0] ] = it->first[1];
+ d_phase_reqs_equality[ it->first[0] ] = it->second;
+ Debug("inst-engine-phase-req") << " " << it->first[0] << ( it->second ? " == " : " != " ) << it->first[1] << std::endl;
+ }
+ }else if( it->first[1].hasAttribute(InstConstantAttribute()) ){
+ d_phase_reqs_equality_term[ it->first[1] ] = it->first[0];
+ d_phase_reqs_equality[ it->first[1] ] = it->second;
+ Debug("inst-engine-phase-req") << " " << it->first[1] << ( it->second ? " == " : " != " ) << it->first[0] << std::endl;
+ }
+ }
+ }
+ }
+}
+
+void QuantPhaseReq::computePhaseReqs( Node n, bool polarity, std::map< Node, int >& phaseReqs ){
+ bool newReqPol = false;
+ bool newPolarity;
+ if( n.getKind()==NOT ){
+ newReqPol = true;
+ newPolarity = !polarity;
+ }else if( n.getKind()==OR || n.getKind()==IMPLIES ){
+ if( !polarity ){
+ newReqPol = true;
+ newPolarity = false;
+ }
+ }else if( n.getKind()==AND ){
+ if( polarity ){
+ newReqPol = true;
+ newPolarity = true;
+ }
+ }else{
+ int val = polarity ? 1 : -1;
+ if( phaseReqs.find( n )==phaseReqs.end() ){
+ phaseReqs[n] = val;
+ }else if( val!=phaseReqs[n] ){
+ phaseReqs[n] = 0;
+ }
+ }
+ if( newReqPol ){
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ if( n.getKind()==IMPLIES && i==0 ){
+ computePhaseReqs( n[i], !newPolarity, phaseReqs );
+ }else{
+ computePhaseReqs( n[i], newPolarity, phaseReqs );
+ }
+ }
+ }
+}
diff --git a/src/theory/quantifiers/quant_util.h b/src/theory/quantifiers/quant_util.h
index bb6855c47..85602dbab 100755..100644
--- a/src/theory/quantifiers/quant_util.h
+++ b/src/theory/quantifiers/quant_util.h
@@ -1,99 +1,99 @@
-/********************* */
-/*! \file quant_util.h
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): mdeters, bobot
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief quantifier util
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__THEORY__QUANT_UTIL_H
-#define __CVC4__THEORY__QUANT_UTIL_H
-
-#include "theory/theory.h"
-#include "theory/uf/equality_engine.h"
-
-#include <ext/hash_set>
-#include <iostream>
-#include <map>
-
-namespace CVC4 {
-namespace theory {
-
-
-class QuantRelevance
-{
-private:
- /** for computing relavance */
- bool d_computeRel;
- /** map from quantifiers to symbols they contain */
- std::map< Node, std::vector< Node > > d_syms;
- /** map from symbols to quantifiers */
- std::map< Node, std::vector< Node > > d_syms_quants;
- /** relevance for quantifiers and symbols */
- std::map< Node, int > d_relevance;
- /** compute symbols */
- void computeSymbols( Node n, std::vector< Node >& syms );
-public:
- QuantRelevance( bool cr ) : d_computeRel( cr ){}
- ~QuantRelevance(){}
- /** register quantifier */
- void registerQuantifier( Node f );
- /** set relevance */
- void setRelevance( Node s, int r );
- /** get relevance */
- int getRelevance( Node s ) { return d_relevance.find( s )==d_relevance.end() ? -1 : d_relevance[s]; }
- /** get number of quantifiers for symbol s */
- int getNumQuantifiersForSymbol( Node s ) { return (int)d_syms_quants[s].size(); }
-};
-
-class QuantPhaseReq
-{
-private:
- /** helper functions compute phase requirements */
- void computePhaseReqs( Node n, bool polarity, std::map< Node, int >& phaseReqs );
-public:
- QuantPhaseReq( Node n, bool computeEq = false );
- ~QuantPhaseReq(){}
- /** is phase required */
- bool isPhaseReq( Node lit ) { return d_phase_reqs.find( lit )!=d_phase_reqs.end(); }
- /** get phase requirement */
- bool getPhaseReq( Node lit ) { return d_phase_reqs.find( lit )==d_phase_reqs.end() ? false : d_phase_reqs[ lit ]; }
- /** phase requirements for each quantifier for each instantiation literal */
- std::map< Node, bool > d_phase_reqs;
- std::map< Node, bool > d_phase_reqs_equality;
- std::map< Node, Node > d_phase_reqs_equality_term;
-};
-
-
-class EqualityQuery {
-public:
- EqualityQuery(){}
- virtual ~EqualityQuery(){};
- /** reset */
- virtual void reset() = 0;
- /** contains term */
- virtual bool hasTerm( Node a ) = 0;
- /** get the representative of the equivalence class of a */
- virtual Node getRepresentative( Node a ) = 0;
- /** returns true if a and b are equal in the current context */
- virtual bool areEqual( Node a, Node b ) = 0;
- /** returns true is a and b are disequal in the current context */
- virtual bool areDisequal( Node a, Node b ) = 0;
- /** get the equality engine associated with this query */
- virtual eq::EqualityEngine* getEngine() = 0;
- /** get the equivalence class of a */
- virtual void getEquivalenceClass( Node a, std::vector< Node >& eqc ) = 0;
-};/* class EqualityQuery */
-
-}
-}
-
-#endif
+/********************* */
+/*! \file quant_util.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief quantifier util
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANT_UTIL_H
+#define __CVC4__THEORY__QUANT_UTIL_H
+
+#include "theory/theory.h"
+#include "theory/uf/equality_engine.h"
+
+#include <ext/hash_set>
+#include <iostream>
+#include <map>
+
+namespace CVC4 {
+namespace theory {
+
+
+class QuantRelevance
+{
+private:
+ /** for computing relavance */
+ bool d_computeRel;
+ /** map from quantifiers to symbols they contain */
+ std::map< Node, std::vector< Node > > d_syms;
+ /** map from symbols to quantifiers */
+ std::map< Node, std::vector< Node > > d_syms_quants;
+ /** relevance for quantifiers and symbols */
+ std::map< Node, int > d_relevance;
+ /** compute symbols */
+ void computeSymbols( Node n, std::vector< Node >& syms );
+public:
+ QuantRelevance( bool cr ) : d_computeRel( cr ){}
+ ~QuantRelevance(){}
+ /** register quantifier */
+ void registerQuantifier( Node f );
+ /** set relevance */
+ void setRelevance( Node s, int r );
+ /** get relevance */
+ int getRelevance( Node s ) { return d_relevance.find( s )==d_relevance.end() ? -1 : d_relevance[s]; }
+ /** get number of quantifiers for symbol s */
+ int getNumQuantifiersForSymbol( Node s ) { return (int)d_syms_quants[s].size(); }
+};
+
+class QuantPhaseReq
+{
+private:
+ /** helper functions compute phase requirements */
+ void computePhaseReqs( Node n, bool polarity, std::map< Node, int >& phaseReqs );
+public:
+ QuantPhaseReq( Node n, bool computeEq = false );
+ ~QuantPhaseReq(){}
+ /** is phase required */
+ bool isPhaseReq( Node lit ) { return d_phase_reqs.find( lit )!=d_phase_reqs.end(); }
+ /** get phase requirement */
+ bool getPhaseReq( Node lit ) { return d_phase_reqs.find( lit )==d_phase_reqs.end() ? false : d_phase_reqs[ lit ]; }
+ /** phase requirements for each quantifier for each instantiation literal */
+ std::map< Node, bool > d_phase_reqs;
+ std::map< Node, bool > d_phase_reqs_equality;
+ std::map< Node, Node > d_phase_reqs_equality_term;
+};
+
+
+class EqualityQuery {
+public:
+ EqualityQuery(){}
+ virtual ~EqualityQuery(){};
+ /** reset */
+ virtual void reset() = 0;
+ /** contains term */
+ virtual bool hasTerm( Node a ) = 0;
+ /** get the representative of the equivalence class of a */
+ virtual Node getRepresentative( Node a ) = 0;
+ /** returns true if a and b are equal in the current context */
+ virtual bool areEqual( Node a, Node b ) = 0;
+ /** returns true is a and b are disequal in the current context */
+ virtual bool areDisequal( Node a, Node b ) = 0;
+ /** get the equality engine associated with this query */
+ virtual eq::EqualityEngine* getEngine() = 0;
+ /** get the equivalence class of a */
+ virtual void getEquivalenceClass( Node a, std::vector< Node >& eqc ) = 0;
+};/* class EqualityQuery */
+
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/quantifiers_attributes.cpp b/src/theory/quantifiers/quantifiers_attributes.cpp
index 2f6dc47db..b00fe45f4 100644
--- a/src/theory/quantifiers/quantifiers_attributes.cpp
+++ b/src/theory/quantifiers/quantifiers_attributes.cpp
@@ -1,41 +1,41 @@
/********************* */
/*! \file quantifiers_attributes.cpp
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
- ** \brief Implementation of QuantifiersAttributes class
- **/
-
-#include "theory/quantifiers/quantifiers_attributes.h"
-#include "theory/quantifiers/options.h"
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::quantifiers;
-
-void QuantifiersAttributes::setUserAttribute( const std::string& attr, Node n ){
- if( n.getKind()==FORALL ){
- if( attr=="axiom" ){
- Trace("quant-attr") << "Set axiom " << n << std::endl;
- AxiomAttribute aa;
- n.setAttribute( aa, true );
- }else if( attr=="conjecture" ){
- Trace("quant-attr") << "Set conjecture " << n << std::endl;
- ConjectureAttribute ca;
- n.setAttribute( ca, true );
- }
- }else{
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- setUserAttribute( attr, n[i] );
- }
- }
-}
+ ** \brief Implementation of QuantifiersAttributes class
+ **/
+
+#include "theory/quantifiers/quantifiers_attributes.h"
+#include "theory/quantifiers/options.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+
+void QuantifiersAttributes::setUserAttribute( const std::string& attr, Node n ){
+ if( n.getKind()==FORALL ){
+ if( attr=="axiom" ){
+ Trace("quant-attr") << "Set axiom " << n << std::endl;
+ AxiomAttribute aa;
+ n.setAttribute( aa, true );
+ }else if( attr=="conjecture" ){
+ Trace("quant-attr") << "Set conjecture " << n << std::endl;
+ ConjectureAttribute ca;
+ n.setAttribute( ca, true );
+ }
+ }else{
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ setUserAttribute( attr, n[i] );
+ }
+ }
+}
diff --git a/src/theory/quantifiers/quantifiers_attributes.h b/src/theory/quantifiers/quantifiers_attributes.h
index 88bac8bc9..8e8ebe97a 100644
--- a/src/theory/quantifiers/quantifiers_attributes.h
+++ b/src/theory/quantifiers/quantifiers_attributes.h
@@ -1,51 +1,51 @@
/********************* */
/*! \file quantifiers_attributes.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
- ** \brief Attributes for the theory quantifiers
- **
- ** Attributes for the theory quantifiers.
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__THEORY__QUANTIFIERS__QUANTIFIERS_REWRITER_H
-#define __CVC4__THEORY__QUANTIFIERS__QUANTIFIERS_REWRITER_H
-
-#include "theory/rewriter.h"
-#include "theory/quantifiers_engine.h"
-
-namespace CVC4 {
-namespace theory {
-namespace quantifiers {
-
-/** Attribute true for quantifiers that are axioms */
-struct AxiomAttributeId {};
-typedef expr::Attribute< AxiomAttributeId, bool > AxiomAttribute;
-
-/** Attribute true for quantifiers that are conjecture */
-struct ConjectureAttributeId {};
-typedef expr::Attribute< ConjectureAttributeId, bool > ConjectureAttribute;
-
-struct QuantifiersAttributes
-{
- /** set user attribute
- * This function will apply a custom set of attributes to all top-level universal
- * quantifiers contained in n
- */
- static void setUserAttribute( const std::string& attr, Node n );
-};
-
-
-}
-}
-}
-
-#endif
+ ** \brief Attributes for the theory quantifiers
+ **
+ ** Attributes for the theory quantifiers.
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANTIFIERS__QUANTIFIERS_REWRITER_H
+#define __CVC4__THEORY__QUANTIFIERS__QUANTIFIERS_REWRITER_H
+
+#include "theory/rewriter.h"
+#include "theory/quantifiers_engine.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+/** Attribute true for quantifiers that are axioms */
+struct AxiomAttributeId {};
+typedef expr::Attribute< AxiomAttributeId, bool > AxiomAttribute;
+
+/** Attribute true for quantifiers that are conjecture */
+struct ConjectureAttributeId {};
+typedef expr::Attribute< ConjectureAttributeId, bool > ConjectureAttribute;
+
+struct QuantifiersAttributes
+{
+ /** set user attribute
+ * This function will apply a custom set of attributes to all top-level universal
+ * quantifiers contained in n
+ */
+ static void setUserAttribute( const std::string& attr, Node n );
+};
+
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/quantifiers_rewriter.cpp b/src/theory/quantifiers/quantifiers_rewriter.cpp
index dabaa2188..bf6a025f8 100644
--- a/src/theory/quantifiers/quantifiers_rewriter.cpp
+++ b/src/theory/quantifiers/quantifiers_rewriter.cpp
@@ -90,29 +90,15 @@ void QuantifiersRewriter::addNodeToOrBuilder( Node n, NodeBuilder<>& t ){
}
}
-void QuantifiersRewriter::computeArgs( std::map< Node, bool >& active, Node n ){
- if( active.find( n )!=active.end() ){
- active[n] = true;
+void QuantifiersRewriter::computeArgs( std::vector< Node >& args, std::vector< Node >& activeArgs, Node n ){
+ if( n.getKind()==BOUND_VARIABLE ){
+ if( std::find( args.begin(), args.end(), n )!=args.end() &&
+ std::find( activeArgs.begin(), activeArgs.end(), n )==activeArgs.end() ){
+ activeArgs.push_back( n );
+ }
}else{
for( int i=0; i<(int)n.getNumChildren(); i++ ){
- computeArgs( active, n[i] );
- }
- }
-}
-
-void QuantifiersRewriter::computeArgs( std::vector< Node >& args, std::vector< Node >& activeArgs, Node n ){
- std::map< Node, bool > active;
- for( int i=0; i<(int)args.size(); i++ ){
- active[ args[i] ] = false;
- }
- //Notice() << "For " << n << " : " << std::endl;
- computeArgs( active, n );
- activeArgs.clear();
- for( std::map< Node, bool >::iterator it = active.begin(); it != active.end(); ++it ){
- Node n = it->first;
- //Notice() << " " << it->first << " is " << it->second << std::endl;
- if( it->second ){ //only add bound variables that occur in body
- activeArgs.push_back( it->first );
+ computeArgs( args, activeArgs, n[i] );
}
}
}
@@ -468,37 +454,19 @@ Node QuantifiersRewriter::computeCNF( Node n, std::vector< Node >& args, NodeBui
}
}
-Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, bool pol, bool polReq ){
+Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, bool pol ){
if( body.getKind()==FORALL ){
- if( pol==polReq ){
+ if( pol ){
std::vector< Node > terms;
std::vector< Node > subs;
- if( polReq ){
- //for doing prenexing of same-signed quantifiers
- //must rename each variable that already exists
- for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
- //if( std::find( args.begin(), args.end(), body[0][i] )!=args.end() ){
- terms.push_back( body[0][i] );
- subs.push_back( NodeManager::currentNM()->mkBoundVar( body[0][i].getType() ) );
- }
- args.insert( args.end(), subs.begin(), subs.end() );
- }else{
- std::vector< TypeNode > argTypes;
- for( int i=0; i<(int)args.size(); i++ ){
- argTypes.push_back( args[i].getType() );
- }
- //for doing pre-skolemization of opposite-signed quantifiers
- for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
- terms.push_back( body[0][i] );
- //make the new function symbol
- TypeNode typ = NodeManager::currentNM()->mkFunctionType( argTypes, body[0][i].getType() );
- Node op = NodeManager::currentNM()->mkSkolem( "op_$$", typ, "was created by the quantifiers rewriter" );
- std::vector< Node > funcArgs;
- funcArgs.push_back( op );
- funcArgs.insert( funcArgs.end(), args.begin(), args.end() );
- subs.push_back( NodeManager::currentNM()->mkNode( APPLY_UF, funcArgs ) );
- }
+ //for doing prenexing of same-signed quantifiers
+ //must rename each variable that already exists
+ for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
+ //if( std::find( args.begin(), args.end(), body[0][i] )!=args.end() ){
+ terms.push_back( body[0][i] );
+ subs.push_back( NodeManager::currentNM()->mkBoundVar( body[0][i].getType() ) );
}
+ args.insert( args.end(), subs.begin(), subs.end() );
Node newBody = body[1];
newBody = newBody.substitute( terms.begin(), terms.end(), subs.begin(), subs.end() );
Debug("quantifiers-substitute-debug") << "Did substitute have an effect" << (body[1] != newBody) << body[1] << " became " << newBody << endl;
@@ -514,7 +482,7 @@ Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, b
std::vector< Node > newChildren;
for( int i=0; i<(int)body.getNumChildren(); i++ ){
bool newPol = ( body.getKind()==NOT || ( body.getKind()==IMPLIES && i==0 ) ) ? !pol : pol;
- Node n = computePrenex( body[i], args, newPol, polReq );
+ Node n = computePrenex( body[i], args, newPol );
newChildren.push_back( n );
if( n!=body[i] ){
childrenChanged = true;
@@ -549,10 +517,12 @@ Node QuantifiersRewriter::computeOperation( Node f, int computeOption ){
if( computeOption==COMPUTE_MINISCOPING ){
//return directly
return computeMiniscoping( args, n, ipl, f.hasAttribute(NestedQuantAttribute()) );
+ }else if( computeOption==COMPUTE_AGGRESSIVE_MINISCOPING ){
+ return computeAggressiveMiniscoping( args, n, f.hasAttribute(NestedQuantAttribute()) );
}else if( computeOption==COMPUTE_NNF ){
n = computeNNF( n );
- }else if( computeOption==COMPUTE_PRENEX || computeOption==COMPUTE_PRE_SKOLEM ){
- n = computePrenex( n, args, true, computeOption==COMPUTE_PRENEX );
+ }else if( computeOption==COMPUTE_PRENEX ){
+ n = computePrenex( n, args, true );
}else if( computeOption==COMPUTE_VAR_ELIMINATION ){
Node prev;
do{
@@ -670,42 +640,113 @@ Node QuantifiersRewriter::computeMiniscoping( std::vector< Node >& args, Node bo
}
return mkForAll( args, body, ipl );
}
-/*
-Node QuantifiersRewriter::rewriteQuants( Node n, bool isNested ){
- if( n.getKind()==FORALL ){
- return rewriteQuant( n, isNested );
- }else if( isLiteral( n ) ){
- return n;
- }else{
- NodeBuilder<> tt(n.getKind());
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- tt << rewriteQuants( n[i], isNested );
- }
- return tt.constructNode();
- }
-}
-Node QuantifiersRewriter::rewriteQuant( Node n, bool isNested ){
- Node prev = n;
- for( int op=0; op<COMPUTE_LAST; op++ ){
- if( doOperation( n, isNested, op ) ){
- Node prev2 = n;
- n = computeOperation( n, op );
- if( prev2!=n ){
- Trace("quantifiers-rewrite-op") << "Rewrite op " << op << ": rewrite " << prev2 << std::endl;
- Trace("quantifiers-rewrite-op") << " to " << std::endl;
- Trace("quantifiers-rewrite-op") << n << std::endl;
+Node QuantifiersRewriter::computeAggressiveMiniscoping( std::vector< Node >& args, Node body, bool isNested ){
+ if( !isNested ){
+ std::map< Node, std::vector< Node > > varLits;
+ std::map< Node, std::vector< Node > > litVars;
+ if( body.getKind()==OR ){
+ Trace("ag-miniscope") << "compute aggressive miniscoping on " << body << std::endl;
+ for( size_t i=0; i<body.getNumChildren(); i++ ){
+ std::vector< Node > activeArgs;
+ computeArgs( args, activeArgs, body[i] );
+ for (unsigned j=0; j<activeArgs.size(); j++ ){
+ varLits[activeArgs[j]].push_back( body[i] );
+ }
+ litVars[body[i]].insert( litVars[body[i]].begin(), activeArgs.begin(), activeArgs.end() );
+ }
+ //find the variable in the least number of literals
+ Node bestVar;
+ for( std::map< Node, std::vector< Node > >::iterator it = varLits.begin(); it != varLits.end(); ++it ){
+ if( bestVar.isNull() || varLits[bestVar].size()>it->second.size() ){
+ bestVar = it->first;
+ }
+ }
+ Trace("ag-miniscope-debug") << "Best variable " << bestVar << " occurs in " << varLits[bestVar].size() << "/ " << body.getNumChildren() << " literals." << std::endl;
+ if( !bestVar.isNull() && varLits[bestVar].size()<body.getNumChildren() ){
+ //we can miniscope
+ Trace("ag-miniscope") << "Miniscope on " << bestVar << std::endl;
+ //make the bodies
+ std::vector< Node > qlit1;
+ qlit1.insert( qlit1.begin(), varLits[bestVar].begin(), varLits[bestVar].end() );
+ std::vector< Node > qlitt;
+ //for all literals not containing bestVar
+ for( size_t i=0; i<body.getNumChildren(); i++ ){
+ if( std::find( qlit1.begin(), qlit1.end(), body[i] )==qlit1.end() ){
+ qlitt.push_back( body[i] );
+ }
+ }
+ //make the variable lists
+ std::vector< Node > qvl1;
+ std::vector< Node > qvl2;
+ std::vector< Node > qvsh;
+ for( unsigned i=0; i<args.size(); i++ ){
+ bool found1 = false;
+ bool found2 = false;
+ for( size_t j=0; j<varLits[args[i]].size(); j++ ){
+ if( !found1 && std::find( qlit1.begin(), qlit1.end(), varLits[args[i]][j] )!=qlit1.end() ){
+ found1 = true;
+ }else if( !found2 && std::find( qlitt.begin(), qlitt.end(), varLits[args[i]][j] )!=qlitt.end() ){
+ found2 = true;
+ }
+ if( found1 && found2 ){
+ break;
+ }
+ }
+ if( found1 ){
+ if( found2 ){
+ qvsh.push_back( args[i] );
+ }else{
+ qvl1.push_back( args[i] );
+ }
+ }else{
+ Assert(found2);
+ qvl2.push_back( args[i] );
+ }
+ }
+ Assert( !qvl1.empty() );
+ Assert( !qvl2.empty() || !qvsh.empty() );
+ //check for literals that only contain shared variables
+ std::vector< Node > qlitsh;
+ std::vector< Node > qlit2;
+ for( size_t i=0; i<qlitt.size(); i++ ){
+ bool hasVar2 = false;
+ for( size_t j=0; j<litVars[qlitt[i]].size(); j++ ){
+ if( std::find( qvl2.begin(), qvl2.end(), litVars[qlitt[i]][j] )!=qvl2.end() ){
+ hasVar2 = true;
+ break;
+ }
+ }
+ if( hasVar2 ){
+ qlit2.push_back( qlitt[i] );
+ }else{
+ qlitsh.push_back( qlitt[i] );
+ }
+ }
+ varLits.clear();
+ litVars.clear();
+ Trace("ag-miniscope-debug") << "Split into literals : " << qlit1.size() << " / " << qlit2.size() << " / " << qlitsh.size();
+ Trace("ag-miniscope-debug") << ", variables : " << qvl1.size() << " / " << qvl2.size() << " / " << qvsh.size() << std::endl;
+ Node n1 = qlit1.size()==1 ? qlit1[0] : NodeManager::currentNM()->mkNode( OR, qlit1 );
+ n1 = computeAggressiveMiniscoping( qvl1, n1 );
+ qlitsh.push_back( n1 );
+ if( !qlit2.empty() ){
+ Node n2 = qlit2.size()==1 ? qlit2[0] : NodeManager::currentNM()->mkNode( OR, qlit2 );
+ n2 = computeAggressiveMiniscoping( qvl2, n2 );
+ qlitsh.push_back( n2 );
+ }
+ Node n = NodeManager::currentNM()->mkNode( OR, qlitsh );
+ if( !qvsh.empty() ){
+ Node bvl = NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, qvsh);
+ n = NodeManager::currentNM()->mkNode( FORALL, bvl, n );
+ }
+ Trace("ag-miniscope") << "Return " << n << " for " << body << std::endl;
+ return n;
}
}
}
- if( prev==n ){
- return n;
- }else{
- //rewrite again until fix point is reached
- return rewriteQuant( n, isNested );
- }
+ return mkForAll( args, body, Node::null() );
}
-*/
bool QuantifiersRewriter::doMiniscopingNoFreeVar(){
return options::miniscopeQuantFreeVar();
@@ -726,12 +767,12 @@ bool QuantifiersRewriter::doMiniscopingAnd(){
bool QuantifiersRewriter::doOperation( Node f, bool isNested, int computeOption ){
if( computeOption==COMPUTE_MINISCOPING ){
return true;
+ }else if( computeOption==COMPUTE_AGGRESSIVE_MINISCOPING ){
+ return options::aggressiveMiniscopeQuant();
}else if( computeOption==COMPUTE_NNF ){
return false;//TODO: compute NNF (current bad idea since arithmetic rewrites equalities)
- }else if( computeOption==COMPUTE_PRE_SKOLEM ){
- return false;//options::preSkolemQuant();
}else if( computeOption==COMPUTE_PRENEX ){
- return options::prenexQuant();
+ return options::prenexQuant() && !options::aggressiveMiniscopeQuant();
}else if( computeOption==COMPUTE_VAR_ELIMINATION ){
return options::varElimQuant();
}else if( computeOption==COMPUTE_CNF ){
diff --git a/src/theory/quantifiers/quantifiers_rewriter.h b/src/theory/quantifiers/quantifiers_rewriter.h
index 00301c610..75b392e15 100644
--- a/src/theory/quantifiers/quantifiers_rewriter.h
+++ b/src/theory/quantifiers/quantifiers_rewriter.h
@@ -41,19 +41,19 @@ private:
static void computeArgs( std::vector< Node >& args, std::vector< Node >& activeArgs, Node n );
static bool hasArg( std::vector< Node >& args, Node n );
static void setNestedQuantifiers( Node n, Node q );
- static void computeArgs( std::map< Node, bool >& active, Node n );
static Node computeClause( Node n );
private:
static Node computeMiniscoping( 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 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, bool polReq );
+ static Node computePrenex( Node body, std::vector< Node >& args, bool pol );
private:
enum{
COMPUTE_MINISCOPING = 0,
+ COMPUTE_AGGRESSIVE_MINISCOPING,
COMPUTE_NNF,
- COMPUTE_PRE_SKOLEM,
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 d60aa2ef4..f6518cfd3 100644
--- a/src/theory/quantifiers/term_database.cpp
+++ b/src/theory/quantifiers/term_database.cpp
@@ -75,7 +75,7 @@ void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant ){
//Call the children?
if( inst::Trigger::isAtomicTrigger( n ) ){
if( !n.hasAttribute(InstConstantAttribute()) ){
- Debug("term-db") << "register trigger term " << n << std::endl;
+ Trace("term-db") << "register term in db " << n << std::endl;
//std::cout << "register trigger term " << n << std::endl;
Node op = n.getOperator();
d_op_map[op].push_back( n );
@@ -194,7 +194,7 @@ void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant ){
Node TermDb::getModelBasisTerm( TypeNode tn, int i ){
if( d_model_basis_term.find( tn )==d_model_basis_term.end() ){
Node mbt;
- if( d_type_map[ tn ].empty() ){
+ if( options::fmfFreshDistConst() || d_type_map[ tn ].empty() ){
std::stringstream ss;
ss << Expr::setlanguage(options::outputLanguage());
ss << "e_" << tn;
@@ -206,6 +206,7 @@ Node TermDb::getModelBasisTerm( TypeNode tn, int i ){
ModelBasisAttribute mba;
mbt.setAttribute(mba,true);
d_model_basis_term[tn] = mbt;
+ Trace("model-basis-term") << "Choose " << mbt << " as model basis term for " << tn << std::endl;
}
return d_model_basis_term[tn];
}
@@ -337,6 +338,14 @@ Node TermDb::getInstConstantBody( Node f ){
Node TermDb::getCounterexampleLiteral( Node f ){
if( d_ce_lit.find( f )==d_ce_lit.end() ){
Node ceBody = getInstConstantBody( f );
+ //check if any variable are of bad types, and fail if so
+ for( size_t i=0; i<d_inst_constants[f].size(); i++ ){
+ if( d_inst_constants[f][i].getType().isBoolean() ){
+ d_ce_lit[ f ] = Node::null();
+ return Node::null();
+ }
+ }
+ //otherwise, ensure literal
Node ceLit = d_quantEngine->getValuation().ensureLiteral( ceBody.notNode() );
d_ce_lit[ f ] = ceLit;
setInstantiationConstantAttr( ceLit, f );
@@ -367,6 +376,10 @@ Node TermDb::getSkolemizedBody( Node f ){
Node skv = NodeManager::currentNM()->mkSkolem( "skv_$$", f[0][i].getType(), "is a termdb-created skolemized body" );
d_skolem_constants[ f ].push_back( skv );
vars.push_back( f[0][i] );
+ //carry information for sort inference
+ if( options::sortInference() ){
+ d_quantEngine->getTheoryEngine()->getSortInference()->setSkolemVar( f, f[0][i], skv );
+ }
}
d_skolem_body[ f ] = f[ 1 ].substitute( vars.begin(), vars.end(),
d_skolem_constants[ f ].begin(), d_skolem_constants[ f ].end() );
@@ -515,6 +528,34 @@ int TermDb::isInstanceOf( Node n1, Node n2 ){
return 0;
}
+bool TermDb::isUnifiableInstanceOf( Node n1, Node n2, std::map< Node, Node >& subs ){
+ if( n1==n2 ){
+ return true;
+ }else if( n2.getKind()==INST_CONSTANT ){
+ //if( !node_contains( n1, n2 ) ){
+ // return false;
+ //}
+ if( subs.find( n2 )==subs.end() ){
+ subs[n2] = n1;
+ }else if( subs[n2]!=n1 ){
+ return false;
+ }
+ return true;
+ }else if( n1.getKind()==n2.getKind() && n1.getMetaKind()==kind::metakind::PARAMETERIZED ){
+ if( n1.getOperator()!=n2.getOperator() ){
+ return false;
+ }
+ for( int i=0; i<(int)n1.getNumChildren(); i++ ){
+ if( !isUnifiableInstanceOf( n1[i], n2[i], subs ) ){
+ return false;
+ }
+ }
+ return true;
+ }else{
+ return false;
+ }
+}
+
void TermDb::filterInstances( std::vector< Node >& nodes ){
std::vector< bool > active;
active.resize( nodes.size(), true );
@@ -523,8 +564,10 @@ void TermDb::filterInstances( std::vector< Node >& nodes ){
if( active[i] && active[j] ){
int result = isInstanceOf( nodes[i], nodes[j] );
if( result==1 ){
+ Trace("filter-instances") << nodes[j] << " is an instance of " << nodes[i] << std::endl;
active[j] = false;
}else if( result==-1 ){
+ Trace("filter-instances") << nodes[i] << " is an instance of " << nodes[j] << std::endl;
active[i] = false;
}
}
diff --git a/src/theory/quantifiers/term_database.h b/src/theory/quantifiers/term_database.h
index a1f1de1dc..6bfea5c44 100644
--- a/src/theory/quantifiers/term_database.h
+++ b/src/theory/quantifiers/term_database.h
@@ -167,7 +167,7 @@ public:
/** get counterexample literal (for cbqi) */
Node getCounterexampleLiteral( Node f );
/** returns node n with bound vars of f replaced by instantiation constants of f
- node n : is the futur pattern
+ node n : is the future pattern
node f : is the quantifier containing which bind the variable
return a pattern where the variable are replaced by variable for
instantiation.
@@ -212,6 +212,8 @@ private:
std::map< TNode, std::vector< TNode > > d_var_contains;
/** triggers for each operator */
std::map< Node, std::vector< inst::Trigger* > > d_op_triggers;
+ /** helper for is intance of */
+ bool isUnifiableInstanceOf( Node n1, Node n2, std::map< Node, Node >& subs );
public:
/** compute var contains */
void computeVarContains( Node n );
diff --git a/src/theory/quantifiers/theory_quantifiers.cpp b/src/theory/quantifiers/theory_quantifiers.cpp
index d1dbae90c..be6dd5b08 100644
--- a/src/theory/quantifiers/theory_quantifiers.cpp
+++ b/src/theory/quantifiers/theory_quantifiers.cpp
@@ -92,12 +92,14 @@ Node TheoryQuantifiers::getValue(TNode n) {
}
}
-void TheoryQuantifiers::collectModelInfo( TheoryModel* m, bool fullModel ){
- if( fullModel ){
+void TheoryQuantifiers::collectModelInfo(TheoryModel* m, bool fullModel) {
+ if(fullModel) {
for(assertions_iterator i = facts_begin(); i != facts_end(); ++i) {
if((*i).assertion.getKind() == kind::NOT) {
+ Debug("quantifiers::collectModelInfo") << "got quant FALSE: " << (*i).assertion[0] << endl;
m->assertPredicate((*i).assertion[0], false);
} else {
+ Debug("quantifiers::collectModelInfo") << "got quant TRUE : " << *i << endl;
m->assertPredicate(*i, true);
}
}
diff --git a/src/theory/quantifiers/trigger.cpp b/src/theory/quantifiers/trigger.cpp
index bc577fda6..cff28f243 100644
--- a/src/theory/quantifiers/trigger.cpp
+++ b/src/theory/quantifiers/trigger.cpp
@@ -34,24 +34,29 @@ using namespace CVC4::theory::inst;
Trigger::Trigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool smartTriggers ) :
d_quantEngine( qe ), d_f( f ){
d_nodes.insert( d_nodes.begin(), nodes.begin(), nodes.end() );
+ Trace("trigger") << "Trigger for " << f << ": " << std::endl;
+ for( int i=0; i<(int)d_nodes.size(); i++ ){
+ Trace("trigger") << " " << d_nodes[i] << std::endl;
+ }
+ Trace("trigger-debug") << ", smart triggers = " << smartTriggers;
+ Trace("trigger") << std::endl;
if( smartTriggers ){
if( d_nodes.size()==1 ){
if( isSimpleTrigger( d_nodes[0] ) ){
d_mg = new InstMatchGeneratorSimple( f, d_nodes[0] );
}else{
- d_mg = new InstMatchGenerator( d_nodes[0], qe, matchOption );
+ d_mg = InstMatchGenerator::mkInstMatchGenerator( d_nodes[0], qe );
+ d_mg->setActiveAdd();
}
}else{
d_mg = new InstMatchGeneratorMulti( f, d_nodes, qe, matchOption );
+ //d_mg = InstMatchGenerator::mkInstMatchGenerator( d_nodes, qe );
+ //d_mg->setActiveAdd();
}
}else{
- d_mg = new InstMatchGenerator( d_nodes, qe, matchOption );
- }
- Trace("trigger") << "Trigger for " << f << ": " << std::endl;
- for( int i=0; i<(int)d_nodes.size(); i++ ){
- Trace("trigger") << " " << d_nodes[i] << std::endl;
+ d_mg = InstMatchGenerator::mkInstMatchGenerator( d_nodes, qe );
+ d_mg->setActiveAdd();
}
- Trace("trigger") << std::endl;
if( d_nodes.size()==1 ){
if( isSimpleTrigger( d_nodes[0] ) ){
++(qe->d_statistics.d_triggers);
@@ -59,7 +64,7 @@ d_quantEngine( qe ), d_f( f ){
++(qe->d_statistics.d_simple_triggers);
}
}else{
- Debug("multi-trigger") << "Multi-trigger " << (*this) << std::endl;
+ Trace("multi-trigger") << "Multi-trigger " << (*this) << " for " << f << std::endl;
//Notice() << "Multi-trigger for " << f << " : " << std::endl;
//Notice() << " " << (*this) << std::endl;
++(qe->d_statistics.d_multi_triggers);
@@ -80,14 +85,14 @@ void Trigger::reset( Node eqc ){
d_mg->reset( eqc, d_quantEngine );
}
-bool Trigger::getNextMatch( InstMatch& m ){
- bool retVal = d_mg->getNextMatch( m, d_quantEngine );
+bool Trigger::getNextMatch( Node f, InstMatch& m ){
+ bool retVal = d_mg->getNextMatch( f, m, d_quantEngine );
return retVal;
}
-bool Trigger::getMatch( Node t, InstMatch& m ){
+bool Trigger::getMatch( Node f, Node t, InstMatch& m ){
//FIXME: this assumes d_mg is an inst match generator
- return ((InstMatchGenerator*)d_mg)->getMatch( t, m, d_quantEngine );
+ return ((InstMatchGenerator*)d_mg)->getMatch( f, t, m, d_quantEngine );
}
int Trigger::addTerm( Node t ){
@@ -115,6 +120,7 @@ Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >&
temp.insert( temp.begin(), nodes.begin(), nodes.end() );
std::map< Node, bool > vars;
std::map< Node, std::vector< Node > > patterns;
+ size_t varCount = 0;
for( int i=0; i<(int)temp.size(); i++ ){
bool foundVar = false;
qe->getTermDatabase()->computeVarContains( temp[i] );
@@ -122,6 +128,7 @@ Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >&
Node v = qe->getTermDatabase()->d_var_contains[ temp[i] ][j];
if( v.getAttribute(InstConstantAttribute())==f ){
if( vars.find( v )==vars.end() ){
+ varCount++;
vars[ v ] = true;
foundVar = true;
}
@@ -134,32 +141,40 @@ Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >&
patterns[ v ].push_back( temp[i] );
}
}
- }
- //now, minimalize the trigger
- for( int i=0; i<(int)trNodes.size(); i++ ){
- bool keepPattern = false;
- Node n = trNodes[i];
- for( int j=0; j<(int)qe->getTermDatabase()->d_var_contains[ n ].size(); j++ ){
- Node v = qe->getTermDatabase()->d_var_contains[ n ][j];
- if( patterns[v].size()==1 ){
- keepPattern = true;
- break;
- }
+ if( varCount==f[0].getNumChildren() ){
+ break;
}
- if( !keepPattern ){
- //remove from pattern vector
+ }
+ if( varCount<f[0].getNumChildren() ){
+ //do not generate multi-trigger if it does not contain all variables
+ return NULL;
+ }else{
+ //now, minimize the trigger
+ for( int i=0; i<(int)trNodes.size(); i++ ){
+ bool keepPattern = false;
+ Node n = trNodes[i];
for( int j=0; j<(int)qe->getTermDatabase()->d_var_contains[ n ].size(); j++ ){
Node v = qe->getTermDatabase()->d_var_contains[ n ][j];
- for( int k=0; k<(int)patterns[v].size(); k++ ){
- if( patterns[v][k]==n ){
- patterns[v].erase( patterns[v].begin() + k, patterns[v].begin() + k + 1 );
- break;
+ if( patterns[v].size()==1 ){
+ keepPattern = true;
+ break;
+ }
+ }
+ if( !keepPattern ){
+ //remove from pattern vector
+ for( int j=0; j<(int)qe->getTermDatabase()->d_var_contains[ n ].size(); j++ ){
+ Node v = qe->getTermDatabase()->d_var_contains[ n ][j];
+ for( int k=0; k<(int)patterns[v].size(); k++ ){
+ if( patterns[v][k]==n ){
+ patterns[v].erase( patterns[v].begin() + k, patterns[v].begin() + k + 1 );
+ break;
+ }
}
}
+ //remove from trigger nodes
+ trNodes.erase( trNodes.begin() + i, trNodes.begin() + i + 1 );
+ i--;
}
- //remove from trigger nodes
- trNodes.erase( trNodes.begin() + i, trNodes.begin() + i + 1 );
- i--;
}
}
}else{
@@ -322,16 +337,16 @@ void Trigger::collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vecto
temp.insert( temp.begin(), patTerms2.begin(), patTerms2.end() );
qe->getTermDatabase()->filterInstances( temp );
if( temp.size()!=patTerms2.size() ){
- Debug("trigger-filter-instance") << "Filtered an instance: " << std::endl;
- Debug("trigger-filter-instance") << "Old: ";
+ Trace("trigger-filter-instance") << "Filtered an instance: " << std::endl;
+ Trace("trigger-filter-instance") << "Old: ";
for( int i=0; i<(int)patTerms2.size(); i++ ){
- Debug("trigger-filter-instance") << patTerms2[i] << " ";
+ Trace("trigger-filter-instance") << patTerms2[i] << " ";
}
- Debug("trigger-filter-instance") << std::endl << "New: ";
+ Trace("trigger-filter-instance") << std::endl << "New: ";
for( int i=0; i<(int)temp.size(); i++ ){
- Debug("trigger-filter-instance") << temp[i] << " ";
+ Trace("trigger-filter-instance") << temp[i] << " ";
}
- Debug("trigger-filter-instance") << std::endl;
+ Trace("trigger-filter-instance") << std::endl;
}
if( tstrt==TS_ALL ){
patTerms.insert( patTerms.begin(), temp.begin(), temp.end() );
diff --git a/src/theory/quantifiers/trigger.h b/src/theory/quantifiers/trigger.h
index 6fcd316f4..93731283b 100644
--- a/src/theory/quantifiers/trigger.h
+++ b/src/theory/quantifiers/trigger.h
@@ -56,12 +56,12 @@ public:
/** reset, eqc is the equivalence class to search in (search in any if eqc=null) */
void reset( Node eqc );
/** get next match. must call reset( eqc ) once before this function. */
- bool getNextMatch( InstMatch& m );
+ bool getNextMatch( Node f, InstMatch& m );
/** get the match against ground term or formula t.
the trigger and t should have the same shape.
Currently the trigger should not be a multi-trigger.
*/
- bool getMatch( Node t, InstMatch& m);
+ bool getMatch( Node f, Node t, InstMatch& m);
/** add ground term t, called when t is added to the TermDb */
int addTerm( Node t );
/** return whether this is a multi-trigger */
diff --git a/src/theory/quantifiers_engine.cpp b/src/theory/quantifiers_engine.cpp
index 08bdd496b..a11cc85c0 100644
--- a/src/theory/quantifiers_engine.cpp
+++ b/src/theory/quantifiers_engine.cpp
@@ -71,6 +71,7 @@ d_lemmas_produced_c(u){
d_optMatchIgnoreModelBasis = false;
d_optInstLimitActive = false;
d_optInstLimit = 0;
+ d_total_inst_count_debug = 0;
}
QuantifiersEngine::~QuantifiersEngine(){
@@ -142,10 +143,23 @@ void QuantifiersEngine::check( Theory::Effort e ){
}
//build the model if not done so already
// this happens if no quantifiers are currently asserted and no model-building module is enabled
- if( options::produceModels() && e==Theory::EFFORT_LAST_CALL && !d_hasAddedLemma && !d_model->isModelSet() ){
- d_te->getModelBuilder()->buildModel( d_model, true );
+ if( e==Theory::EFFORT_LAST_CALL && !d_hasAddedLemma ){
+ if( options::produceModels() && !d_model->isModelSet() ){
+ d_te->getModelBuilder()->buildModel( d_model, true );
+ }
+ if( Trace.isOn("inst-per-quant") ){
+ for( std::map< Node, int >::iterator it = d_total_inst_debug.begin(); it != d_total_inst_debug.end(); ++it ){
+ Trace("inst-per-quant") << " * " << it->second << " for " << it->first << std::endl;
+ }
+ }
+ }else{
+ if( Trace.isOn("inst-per-quant-round") ){
+ for( std::map< Node, int >::iterator it = d_temp_inst_debug.begin(); it != d_temp_inst_debug.end(); ++it ){
+ Trace("inst-per-quant-round") << " * " << it->second << " for " << it->first << std::endl;
+ d_temp_inst_debug[it->first] = 0;
+ }
+ }
}
-
Trace("quant-engine") << "Finished quantifiers engine check." << std::endl;
}
}
@@ -242,6 +256,9 @@ bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& vars, std
Node lem = nb;
//check for duplication
if( addLemma( lem ) ){
+ d_total_inst_debug[f]++;
+ d_temp_inst_debug[f]++;
+ d_total_inst_count_debug++;
Trace("inst") << "*** Instantiate " << f << " with " << std::endl;
uint64_t maxInstLevel = 0;
for( int i=0; i<(int)terms.size(); i++ ){
@@ -354,7 +371,7 @@ bool QuantifiersEngine::addInstantiation( Node f, InstMatch& m, bool modEq, bool
//make it representative, this is helpful for recognizing duplication
if( mkRep ){
//pick the best possible representative for instantiation, based on past use and simplicity of term
- Node r = d_eq_query->getInternalRepresentative( val );
+ Node r = d_eq_query->getInternalRepresentative( val, f, i );
Trace("inst-add-debug") << "mkRep " << r << " " << val << std::endl;
m.set( ic, r );
}
@@ -460,56 +477,6 @@ void QuantifiersEngine::getPhaseReqTerms( Node f, std::vector< Node >& nodes ){
d_statistics.d_lit_phase_nreq += (int)nodes.size();
}
}
-/*
-EqualityQuery* QuantifiersEngine::getEqualityQuery(TypeNode t) {
- // Should use skeleton (in order to have the type and the kind
- // or any needed other information) instead of only the type
-
- // TheoryId id = Theory::theoryOf(t);
- // inst::EqualityQuery* eq = d_eq_query_arr[id];
- // if(eq == NULL) return d_eq_query_arr[theory::THEORY_UF];
- // else return eq;
-
- // hack because the generic one is too slow
- // TheoryId id = Theory::theoryOf(t);
- // if( true || id == theory::THEORY_UF){
- // uf::InstantiatorTheoryUf* ith = static_cast<uf::InstantiatorTheoryUf*>( getInstantiator( theory::THEORY_UF ));
- // return new uf::EqualityQueryInstantiatorTheoryUf(ith);
- // }
- // inst::EqualityQuery* eq = d_eq_query_arr[id];
- // if(eq == NULL) return d_eq_query_arr[theory::THEORY_UF];
- // else return eq;
-
-
- //Currently we use the generic EqualityQuery
- return getEqualityQuery();
-}
-
-
-rrinst::CandidateGenerator* QuantifiersEngine::getRRCanGenClasses() {
- return new GenericCandidateGeneratorClasses(this);
-}
-
-rrinst::CandidateGenerator* QuantifiersEngine::getRRCanGenClass() {
- return new GenericCandidateGeneratorClass(this);
-}
-
-rrinst::CandidateGenerator* QuantifiersEngine::getRRCanGenClasses(TypeNode t) {
- // TheoryId id = Theory::theoryOf(t);
- // rrinst::CandidateGenerator* eq = getInstantiator(id)->getRRCanGenClasses();
- // if(eq == NULL) return getInstantiator(id)->getRRCanGenClasses();
- // else return eq;
- return getRRCanGenClasses();
-}
-
-rrinst::CandidateGenerator* QuantifiersEngine::getRRCanGenClass(TypeNode t) {
- // TheoryId id = Theory::theoryOf(t);
- // rrinst::CandidateGenerator* eq = getInstantiator(id)->getRRCanGenClass();
- // if(eq == NULL) return getInstantiator(id)->getRRCanGenClass();
- // else return eq;
- return getRRCanGenClass();
-}
-*/
QuantifiersEngine::Statistics::Statistics():
d_num_quant("QuantifiersEngine::Num_Quantifiers", 0),
@@ -635,39 +602,57 @@ bool EqualityQueryQuantifiersEngine::areDisequal( Node a, Node b ){
return false;
}
-Node EqualityQueryQuantifiersEngine::getInternalRepresentative( Node a ){
+Node EqualityQueryQuantifiersEngine::getInternalRepresentative( Node a, Node f, int index ){
Node r = getRepresentative( a );
if( !options::internalReps() ){
return r;
}else{
- if( d_int_rep.find( r )==d_int_rep.end() ){
+ int sortId = 0;
+ if( optInternalRepSortInference() ){
+ sortId = d_qe->getTheoryEngine()->getSortInference()->getSortId( f, f[0][index] );
+ }
+ if( d_int_rep[sortId].find( r )==d_int_rep[sortId].end() ){
std::vector< Node > eqc;
getEquivalenceClass( r, eqc );
//find best selection for representative
- Node r_best = r;
- int r_best_score = getRepScore( r );
+ Node r_best;
+ int r_best_score = -1;
for( size_t i=0; i<eqc.size(); i++ ){
- int score = getRepScore( eqc[i] );
+ int score = getRepScore( eqc[i], f, index );
+ if( optInternalRepSortInference() ){
+ int e_sortId = d_qe->getTheoryEngine()->getSortInference()->getSortId( eqc[i]);
+ if( score>=0 && e_sortId!=sortId ){
+ score += 100;
+ }
+ }
//score prefers earliest use of this term as a representative
- if( score>=0 && ( r_best_score<0 || score<r_best_score ) ){
+ if( r_best.isNull() || ( score>=0 && ( r_best_score<0 || score<r_best_score ) ) ){
r_best = eqc[i];
r_best_score = score;
}
}
//now, make sure that no other member of the class is an instance
- r_best = getInstance( r_best, eqc );
+ if( !optInternalRepSortInference() ){
+ r_best = getInstance( r_best, eqc );
+ }
//store that this representative was chosen at this point
if( d_rep_score.find( r_best )==d_rep_score.end() ){
d_rep_score[ r_best ] = d_reset_count;
}
- d_int_rep[r] = r_best;
+ d_int_rep[sortId][r] = r_best;
if( r_best!=a ){
Trace("internal-rep-debug") << "rep( " << a << " ) = " << r << ", " << std::endl;
Trace("internal-rep-debug") << "int_rep( " << a << " ) = " << r_best << ", " << std::endl;
}
+ if( optInternalRepSortInference() ){
+ int sortIdBest = d_qe->getTheoryEngine()->getSortInference()->getSortId( r_best );
+ if( sortId!=sortIdBest ){
+ Trace("sort-inf-rep") << "Choosing representative with bad type " << r_best << " " << sortId << " " << sortIdBest << std::endl;
+ }
+ }
return r_best;
}else{
- return d_int_rep[r];
+ return d_int_rep[sortId][r];
}
}
}
@@ -723,7 +708,11 @@ int getDepth( Node n ){
}
}
-int EqualityQueryQuantifiersEngine::getRepScore( Node n ){
+int EqualityQueryQuantifiersEngine::getRepScore( Node n, Node f, int index ){
return d_rep_score.find( n )==d_rep_score.end() ? -1 : d_rep_score[n]; //initial
//return ( d_rep_score.find( n )==d_rep_score.end() ? 100 : 0 ) + getDepth( n ); //term depth
}
+
+bool EqualityQueryQuantifiersEngine::optInternalRepSortInference() {
+ return false; //shown to be not effective
+} \ No newline at end of file
diff --git a/src/theory/quantifiers_engine.h b/src/theory/quantifiers_engine.h
index 29381a309..9f520f420 100644
--- a/src/theory/quantifiers_engine.h
+++ b/src/theory/quantifiers_engine.h
@@ -119,6 +119,10 @@ private:
rrinst::TriggerTrie* d_rr_tr_trie;
/** extended model object */
quantifiers::FirstOrderModel* d_model;
+ /** statistics for debugging */
+ std::map< Node, int > d_total_inst_debug;
+ std::map< Node, int > d_temp_inst_debug;
+ int d_total_inst_count_debug;
private:
KEEP_STATISTIC(TimerStat, d_time, "theory::QuantifiersEngine::time");
public:
@@ -210,6 +214,7 @@ public:
rrinst::TriggerTrie* getRRTriggerDatabase() { return d_rr_tr_trie; }
/** add term to database */
void addTermToDatabase( Node n, bool withinQuant = false );
+ /** get the master equality engine */
eq::EqualityEngine* getMasterEqualityEngine() ;
public:
/** statistics class */
@@ -262,7 +267,7 @@ private:
/** pointer to theory engine */
QuantifiersEngine* d_qe;
/** internal representatives */
- std::map< Node, Node > d_int_rep;
+ std::map< int, std::map< Node, Node > > d_int_rep;
/** rep score */
std::map< Node, int > d_rep_score;
/** reset count */
@@ -271,7 +276,9 @@ private:
/** node contains */
Node getInstance( Node n, std::vector< Node >& eqc );
/** get score */
- int getRepScore( Node n );
+ int getRepScore( Node n, Node f, int index );
+ /** choose rep based on sort inference */
+ bool optInternalRepSortInference();
public:
EqualityQueryQuantifiersEngine( QuantifiersEngine* qe ) : d_qe( qe ), d_reset_count( 0 ){}
~EqualityQueryQuantifiersEngine(){}
@@ -288,7 +295,7 @@ public:
If cbqi is active, this will return a term in the equivalence class of "a" that does
not contain instantiation constants, if such a term exists.
*/
- Node getInternalRepresentative( Node a );
+ Node getInternalRepresentative( Node a, Node f, int index );
}; /* EqualityQueryQuantifiersEngine */
}/* CVC4::theory namespace */
diff --git a/src/theory/rep_set.cpp b/src/theory/rep_set.cpp
index b50878e70..2df0c3f61 100644
--- a/src/theory/rep_set.cpp
+++ b/src/theory/rep_set.cpp
@@ -1,231 +1,224 @@
/********************* */
/*! \file rep_set.cpp
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
- ** \brief Implementation of representative set
- **/
-
-#include "theory/rep_set.h"
-#include "theory/type_enumerator.h"
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-
-void RepSet::clear(){
- d_type_reps.clear();
- d_type_complete.clear();
- d_tmap.clear();
-}
-
-int RepSet::getNumRepresentatives( TypeNode tn ) const{
- std::map< TypeNode, std::vector< Node > >::const_iterator it = d_type_reps.find( tn );
- if( it!=d_type_reps.end() ){
- return (int)it->second.size();
- }else{
- return 0;
- }
-}
-
-void RepSet::add( Node n ){
- TypeNode t = n.getType();
- d_tmap[ n ] = (int)d_type_reps[t].size();
- d_type_reps[t].push_back( n );
-}
-
-int RepSet::getIndexFor( Node n ) const {
- std::map< Node, int >::const_iterator it = d_tmap.find( n );
- if( it!=d_tmap.end() ){
- return it->second;
- }else{
- return -1;
- }
-}
-
-void RepSet::complete( TypeNode t ){
- if( d_type_complete.find( t )==d_type_complete.end() ){
- d_type_complete[t] = true;
- TypeEnumerator te(t);
- while( !te.isFinished() ){
- Node n = *te;
- if( std::find( d_type_reps[t].begin(), d_type_reps[t].end(), n )==d_type_reps[t].end() ){
- add( n );
- }
- ++te;
- }
- for( size_t i=0; i<d_type_reps[t].size(); i++ ){
- Trace("reps-complete") << d_type_reps[t][i] << " ";
- }
- Trace("reps-complete") << std::endl;
- }
-}
-
-void RepSet::toStream(std::ostream& out){
-#if 0
- for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){
- out << it->first << " : " << std::endl;
- for( int i=0; i<(int)it->second.size(); i++ ){
- out << " " << i << ": " << it->second[i] << std::endl;
- }
- }
-#else
- for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){
- if( !it->first.isFunction() && !it->first.isPredicate() ){
- out << "(" << it->first << " " << it->second.size();
- out << " (";
- for( int i=0; i<(int)it->second.size(); i++ ){
- if( i>0 ){ out << " "; }
- out << it->second[i];
- }
- out << ")";
- out << ")" << std::endl;
- }
- }
-#endif
-}
-
-
-RepSetIterator::RepSetIterator( RepSet* rs ) : d_rep_set( rs ){
- d_incomplete = false;
-
-}
-
-bool RepSetIterator::setQuantifier( Node f ){
- Assert( d_types.empty() );
- //store indicies
- for( size_t i=0; i<f[0].getNumChildren(); i++ ){
- d_types.push_back( f[0][i].getType() );
- }
- return initialize();
-}
-
-bool RepSetIterator::setFunctionDomain( Node op ){
- Assert( d_types.empty() );
- TypeNode tn = op.getType();
- for( size_t i=0; i<tn.getNumChildren()-1; i++ ){
- d_types.push_back( tn[i] );
- }
- return initialize();
-}
-
-bool RepSetIterator::initialize(){
- for( size_t i=0; i<d_types.size(); i++ ){
- d_index.push_back( 0 );
- //store default index order
- d_index_order.push_back( i );
- d_var_order[i] = i;
- //store default domain
- d_domain.push_back( RepDomain() );
- TypeNode tn = d_types[i];
- if( tn.isSort() ){
- if( !d_rep_set->hasType( tn ) ){
- Node var = NodeManager::currentNM()->mkSkolem( "repSet_$$", tn, "is a variable created by the RepSetIterator" );
- Trace("mkVar") << "RepSetIterator:: Make variable " << var << " : " << tn << std::endl;
- d_rep_set->add( var );
- }
- }else if( tn.isInteger() || tn.isReal() ){
- Trace("fmf-incomplete") << "Incomplete because of infinite type " << tn << std::endl;
- d_incomplete = true;
- }else if( tn.isDatatype() ){
- const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
- //if finite, then complete all values of the domain
- if( dt.isFinite() ){
- d_rep_set->complete( tn );
- //d_incomplete = true;
- }else{
- Trace("fmf-incomplete") << "Incomplete because of infinite datatype " << tn << std::endl;
- d_incomplete = true;
- }
- }else{
- Trace("fmf-incomplete") << "Incomplete because of unknown type " << tn << std::endl;
- d_incomplete = true;
- }
- if( d_rep_set->hasType( tn ) ){
- for( size_t j=0; j<d_rep_set->d_type_reps[tn].size(); j++ ){
- d_domain[i].push_back( j );
- }
- }else{
- return false;
- }
- }
- return true;
-}
-
-void RepSetIterator::setIndexOrder( std::vector< int >& indexOrder ){
- d_index_order.clear();
- d_index_order.insert( d_index_order.begin(), indexOrder.begin(), indexOrder.end() );
- //make the d_var_order mapping
- for( int i=0; i<(int)d_index_order.size(); i++ ){
- d_var_order[d_index_order[i]] = i;
- }
-}
-
-void RepSetIterator::setDomain( std::vector< RepDomain >& domain ){
- d_domain.clear();
- d_domain.insert( d_domain.begin(), domain.begin(), domain.end() );
- //we are done if a domain is empty
- for( int i=0; i<(int)d_domain.size(); i++ ){
- if( d_domain[i].empty() ){
- d_index.clear();
- }
- }
-}
-
-void RepSetIterator::increment2( int counter ){
- Assert( !isFinished() );
-#ifdef DISABLE_EVAL_SKIP_MULTIPLE
- counter = (int)d_index.size()-1;
-#endif
- //increment d_index
- while( counter>=0 && d_index[counter]==(int)(d_domain[counter].size()-1) ){
- counter--;
- }
- if( counter==-1 ){
- d_index.clear();
- }else{
- for( int i=(int)d_index.size()-1; i>counter; i-- ){
- d_index[i] = 0;
- }
- d_index[counter]++;
- }
-}
-
-void RepSetIterator::increment(){
- if( !isFinished() ){
- increment2( (int)d_index.size()-1 );
- }
-}
-
-bool RepSetIterator::isFinished(){
- return d_index.empty();
-}
-
-Node RepSetIterator::getTerm( int i ){
- TypeNode tn = d_types[d_index_order[i]];
- Assert( d_rep_set->d_type_reps.find( tn )!=d_rep_set->d_type_reps.end() );
- int index = d_index_order[i];
- return d_rep_set->d_type_reps[tn][d_domain[index][d_index[index]]];
-}
-
-void RepSetIterator::debugPrint( const char* c ){
- for( int i=0; i<(int)d_index.size(); i++ ){
- Debug( c ) << i << " : " << d_index[i] << " : " << getTerm( i ) << std::endl;
- }
-}
-
-void RepSetIterator::debugPrintSmall( const char* c ){
- Debug( c ) << "RI: ";
- for( int i=0; i<(int)d_index.size(); i++ ){
- Debug( c ) << d_index[i] << ": " << getTerm( i ) << " ";
- }
- Debug( c ) << std::endl;
-}
+ ** \brief Implementation of representative set
+ **/
+
+#include "theory/rep_set.h"
+#include "theory/type_enumerator.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+
+void RepSet::clear(){
+ d_type_reps.clear();
+ d_type_complete.clear();
+ d_tmap.clear();
+}
+
+int RepSet::getNumRepresentatives( TypeNode tn ) const{
+ std::map< TypeNode, std::vector< Node > >::const_iterator it = d_type_reps.find( tn );
+ if( it!=d_type_reps.end() ){
+ return (int)it->second.size();
+ }else{
+ return 0;
+ }
+}
+
+void RepSet::add( Node n ){
+ TypeNode t = n.getType();
+ d_tmap[ n ] = (int)d_type_reps[t].size();
+ d_type_reps[t].push_back( n );
+}
+
+int RepSet::getIndexFor( Node n ) const {
+ std::map< Node, int >::const_iterator it = d_tmap.find( n );
+ if( it!=d_tmap.end() ){
+ return it->second;
+ }else{
+ return -1;
+ }
+}
+
+void RepSet::complete( TypeNode t ){
+ if( d_type_complete.find( t )==d_type_complete.end() ){
+ d_type_complete[t] = true;
+ TypeEnumerator te(t);
+ while( !te.isFinished() ){
+ Node n = *te;
+ if( std::find( d_type_reps[t].begin(), d_type_reps[t].end(), n )==d_type_reps[t].end() ){
+ add( n );
+ }
+ ++te;
+ }
+ for( size_t i=0; i<d_type_reps[t].size(); i++ ){
+ Trace("reps-complete") << d_type_reps[t][i] << " ";
+ }
+ Trace("reps-complete") << std::endl;
+ }
+}
+
+void RepSet::toStream(std::ostream& out){
+#if 0
+ for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){
+ out << it->first << " : " << std::endl;
+ for( int i=0; i<(int)it->second.size(); i++ ){
+ out << " " << i << ": " << it->second[i] << std::endl;
+ }
+ }
+#else
+ for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){
+ if( !it->first.isFunction() && !it->first.isPredicate() ){
+ out << "(" << it->first << " " << it->second.size();
+ out << " (";
+ for( int i=0; i<(int)it->second.size(); i++ ){
+ if( i>0 ){ out << " "; }
+ out << it->second[i];
+ }
+ out << ")";
+ out << ")" << std::endl;
+ }
+ }
+#endif
+}
+
+
+RepSetIterator::RepSetIterator( RepSet* rs ) : d_rep_set( rs ){
+ d_incomplete = false;
+
+}
+
+bool RepSetIterator::setQuantifier( Node f ){
+ Assert( d_types.empty() );
+ //store indicies
+ for( size_t i=0; i<f[0].getNumChildren(); i++ ){
+ d_types.push_back( f[0][i].getType() );
+ }
+ return initialize();
+}
+
+bool RepSetIterator::setFunctionDomain( Node op ){
+ Assert( d_types.empty() );
+ TypeNode tn = op.getType();
+ for( size_t i=0; i<tn.getNumChildren()-1; i++ ){
+ d_types.push_back( tn[i] );
+ }
+ return initialize();
+}
+
+bool RepSetIterator::initialize(){
+ for( size_t i=0; i<d_types.size(); i++ ){
+ d_index.push_back( 0 );
+ //store default index order
+ d_index_order.push_back( i );
+ d_var_order[i] = i;
+ //store default domain
+ d_domain.push_back( RepDomain() );
+ TypeNode tn = d_types[i];
+ if( tn.isSort() ){
+ if( !d_rep_set->hasType( tn ) ){
+ Node var = NodeManager::currentNM()->mkSkolem( "repSet_$$", tn, "is a variable created by the RepSetIterator" );
+ Trace("mkVar") << "RepSetIterator:: Make variable " << var << " : " << tn << std::endl;
+ d_rep_set->add( var );
+ }
+ }else if( tn.isInteger() || tn.isReal() ){
+ Trace("fmf-incomplete") << "Incomplete because of infinite type " << tn << std::endl;
+ d_incomplete = true;
+ //enumerate if the sort is reasonably small, the upper bound of 128 is chosen arbitrarily for now
+ }else if( tn.getCardinality().isFinite() && tn.getCardinality().getFiniteCardinality().toUnsignedInt()<=128 ){
+ d_rep_set->complete( tn );
+ }else{
+ Trace("fmf-incomplete") << "Incomplete because of unknown type " << tn << std::endl;
+ d_incomplete = true;
+ }
+ if( d_rep_set->hasType( tn ) ){
+ for( size_t j=0; j<d_rep_set->d_type_reps[tn].size(); j++ ){
+ d_domain[i].push_back( j );
+ }
+ }else{
+ return false;
+ }
+ }
+ return true;
+}
+
+void RepSetIterator::setIndexOrder( std::vector< int >& indexOrder ){
+ d_index_order.clear();
+ d_index_order.insert( d_index_order.begin(), indexOrder.begin(), indexOrder.end() );
+ //make the d_var_order mapping
+ for( int i=0; i<(int)d_index_order.size(); i++ ){
+ d_var_order[d_index_order[i]] = i;
+ }
+}
+
+void RepSetIterator::setDomain( std::vector< RepDomain >& domain ){
+ d_domain.clear();
+ d_domain.insert( d_domain.begin(), domain.begin(), domain.end() );
+ //we are done if a domain is empty
+ for( int i=0; i<(int)d_domain.size(); i++ ){
+ if( d_domain[i].empty() ){
+ d_index.clear();
+ }
+ }
+}
+
+void RepSetIterator::increment2( int counter ){
+ Assert( !isFinished() );
+#ifdef DISABLE_EVAL_SKIP_MULTIPLE
+ counter = (int)d_index.size()-1;
+#endif
+ //increment d_index
+ while( counter>=0 && d_index[counter]==(int)(d_domain[counter].size()-1) ){
+ counter--;
+ }
+ if( counter==-1 ){
+ d_index.clear();
+ }else{
+ for( int i=(int)d_index.size()-1; i>counter; i-- ){
+ d_index[i] = 0;
+ }
+ d_index[counter]++;
+ }
+}
+
+void RepSetIterator::increment(){
+ if( !isFinished() ){
+ increment2( (int)d_index.size()-1 );
+ }
+}
+
+bool RepSetIterator::isFinished(){
+ return d_index.empty();
+}
+
+Node RepSetIterator::getTerm( int i ){
+ TypeNode tn = d_types[d_index_order[i]];
+ Assert( d_rep_set->d_type_reps.find( tn )!=d_rep_set->d_type_reps.end() );
+ int index = d_index_order[i];
+ return d_rep_set->d_type_reps[tn][d_domain[index][d_index[index]]];
+}
+
+void RepSetIterator::debugPrint( const char* c ){
+ for( int i=0; i<(int)d_index.size(); i++ ){
+ Debug( c ) << i << " : " << d_index[i] << " : " << getTerm( i ) << std::endl;
+ }
+}
+
+void RepSetIterator::debugPrintSmall( const char* c ){
+ Debug( c ) << "RI: ";
+ for( int i=0; i<(int)d_index.size(); i++ ){
+ Debug( c ) << d_index[i] << ": " << getTerm( i ) << " ";
+ }
+ Debug( c ) << std::endl;
+}
diff --git a/src/theory/rep_set.h b/src/theory/rep_set.h
index 61b2ebf9f..019f69ec2 100644
--- a/src/theory/rep_set.h
+++ b/src/theory/rep_set.h
@@ -1,112 +1,112 @@
/********************* */
/*! \file rep_set.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
- ** \brief Representative set class and utilities
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__REP_SET_H
-#define __CVC4__REP_SET_H
-
-#include "expr/node.h"
-#include <map>
-
-namespace CVC4 {
-namespace theory {
-
-/** this class stores a representative set */
-class RepSet {
-public:
- RepSet(){}
- ~RepSet(){}
- std::map< TypeNode, std::vector< Node > > d_type_reps;
- std::map< TypeNode, bool > d_type_complete;
- std::map< Node, int > d_tmap;
- /** clear the set */
- void clear();
- /** has type */
- bool hasType( TypeNode tn ) const { return d_type_reps.find( tn )!=d_type_reps.end(); }
- /** get cardinality for type */
- int getNumRepresentatives( TypeNode tn ) const;
- /** add representative for type */
- void add( Node n );
- /** returns index in d_type_reps for node n */
- int getIndexFor( Node n ) const;
- /** complete all values */
- void complete( TypeNode t );
- /** debug print */
- void toStream(std::ostream& out);
-};
-
-//representative domain
-typedef std::vector< int > RepDomain;
-
-/** this class iterates over a RepSet */
-class RepSetIterator {
-private:
- //initialize function
- bool initialize();
-public:
- RepSetIterator( RepSet* rs );
- ~RepSetIterator(){}
- //set that this iterator will be iterating over instantiations for a quantifier
- bool setQuantifier( Node f );
- //set that this iterator will be iterating over the domain of a function
- bool setFunctionDomain( Node op );
-public:
- //pointer to model
- RepSet* d_rep_set;
- //index we are considering
- std::vector< int > d_index;
- //types we are considering
- std::vector< TypeNode > d_types;
- //domain we are considering
- std::vector< RepDomain > d_domain;
- //are we only considering a strict subset of the domain of the quantifier?
- bool d_incomplete;
- //ordering for variables we are indexing over
- // for example, given reps = { a, b } and quantifier forall( x, y, z ) P( x, y, z ) with d_index_order = { 2, 0, 1 },
- // then we consider instantiations in this order:
- // a/x a/y a/z
- // a/x b/y a/z
- // b/x a/y a/z
- // b/x b/y a/z
- // ...
- std::vector< int > d_index_order;
- //variables to index they are considered at
- // for example, if d_index_order = { 2, 0, 1 }
- // then d_var_order = { 0 -> 1, 1 -> 2, 2 -> 0 }
- std::map< int, int > d_var_order;
-public:
- /** set index order */
- void setIndexOrder( std::vector< int >& indexOrder );
- /** set domain */
- void setDomain( std::vector< RepDomain >& domain );
- /** increment the iterator at index=counter */
- void increment2( int counter );
- /** increment the iterator */
- void increment();
- /** is the iterator finished? */
- bool isFinished();
- /** get the i_th term we are considering */
- Node getTerm( int i );
- /** get the number of terms we are considering */
- int getNumTerms() { return (int)d_index_order.size(); }
- /** debug print */
- void debugPrint( const char* c );
- void debugPrintSmall( const char* c );
-};
-
-}
-}
-
-#endif \ No newline at end of file
+ ** \brief Representative set class and utilities
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__REP_SET_H
+#define __CVC4__THEORY__REP_SET_H
+
+#include "expr/node.h"
+#include <map>
+
+namespace CVC4 {
+namespace theory {
+
+/** this class stores a representative set */
+class RepSet {
+public:
+ RepSet(){}
+ ~RepSet(){}
+ std::map< TypeNode, std::vector< Node > > d_type_reps;
+ std::map< TypeNode, bool > d_type_complete;
+ std::map< Node, int > d_tmap;
+ /** clear the set */
+ void clear();
+ /** has type */
+ bool hasType( TypeNode tn ) const { return d_type_reps.find( tn )!=d_type_reps.end(); }
+ /** get cardinality for type */
+ int getNumRepresentatives( TypeNode tn ) const;
+ /** add representative for type */
+ void add( Node n );
+ /** returns index in d_type_reps for node n */
+ int getIndexFor( Node n ) const;
+ /** complete all values */
+ void complete( TypeNode t );
+ /** debug print */
+ void toStream(std::ostream& out);
+};/* class RepSet */
+
+//representative domain
+typedef std::vector< int > RepDomain;
+
+/** this class iterates over a RepSet */
+class RepSetIterator {
+private:
+ //initialize function
+ bool initialize();
+public:
+ RepSetIterator( RepSet* rs );
+ ~RepSetIterator(){}
+ //set that this iterator will be iterating over instantiations for a quantifier
+ bool setQuantifier( Node f );
+ //set that this iterator will be iterating over the domain of a function
+ bool setFunctionDomain( Node op );
+public:
+ //pointer to model
+ RepSet* d_rep_set;
+ //index we are considering
+ std::vector< int > d_index;
+ //types we are considering
+ std::vector< TypeNode > d_types;
+ //domain we are considering
+ std::vector< RepDomain > d_domain;
+ //are we only considering a strict subset of the domain of the quantifier?
+ bool d_incomplete;
+ //ordering for variables we are indexing over
+ // for example, given reps = { a, b } and quantifier forall( x, y, z ) P( x, y, z ) with d_index_order = { 2, 0, 1 },
+ // then we consider instantiations in this order:
+ // a/x a/y a/z
+ // a/x b/y a/z
+ // b/x a/y a/z
+ // b/x b/y a/z
+ // ...
+ std::vector< int > d_index_order;
+ //variables to index they are considered at
+ // for example, if d_index_order = { 2, 0, 1 }
+ // then d_var_order = { 0 -> 1, 1 -> 2, 2 -> 0 }
+ std::map< int, int > d_var_order;
+public:
+ /** set index order */
+ void setIndexOrder( std::vector< int >& indexOrder );
+ /** set domain */
+ void setDomain( std::vector< RepDomain >& domain );
+ /** increment the iterator at index=counter */
+ void increment2( int counter );
+ /** increment the iterator */
+ void increment();
+ /** is the iterator finished? */
+ bool isFinished();
+ /** get the i_th term we are considering */
+ Node getTerm( int i );
+ /** get the number of terms we are considering */
+ int getNumTerms() { return (int)d_index_order.size(); }
+ /** debug print */
+ void debugPrint( const char* c );
+ void debugPrintSmall( const char* c );
+};/* class RepSetIterator */
+
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
+
+#endif /* __CVC4__THEORY__REP_SET_H */
diff --git a/src/theory/rewriterules/efficient_e_matching.cpp b/src/theory/rewriterules/efficient_e_matching.cpp
index 2f39d8098..5ed34d46c 100755..100644
--- a/src/theory/rewriterules/efficient_e_matching.cpp
+++ b/src/theory/rewriterules/efficient_e_matching.cpp
@@ -1,686 +1,686 @@
-/********************* */
-/*! \file efficient_e_matching.cpp
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: bobot
- ** Minor contributors (to current version): mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Implementation of theory uf instantiator class
- **/
-
-#include "theory/rewriterules/efficient_e_matching.h"
-#include "theory/rewriterules/rr_candidate_generator.h"
-#include "theory/quantifiers/candidate_generator.h"
-#include "theory/quantifiers/options.h"
-#include "theory/rewriterules/options.h"
-#include "theory/quantifiers/term_database.h"
-
-#include "theory/theory_engine.h"
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::inst;
-
-namespace CVC4 {
-namespace theory {
-
-inline std::ostream& operator<<(std::ostream& out, const EfficientEMatcher::Ips& ips) {
- return out;
-};
-
-EqClassInfo::EqClassInfo( context::Context* c ) : d_funs( c ), d_pfuns( c ), d_disequal( c ){
-
-}
-
-//set member
-void EqClassInfo::setMember( Node n, quantifiers::TermDb* db ){
- if( n.hasOperator() ){
- d_funs.insertAtContextLevelZero(n.getOperator(),true);
- }
- //add parent functions
- for( std::hash_map< Node, std::hash_map< int, std::vector< Node > >, NodeHashFunction >::iterator it = db->d_parents[n].begin();
- it != db->d_parents[n].end(); ++it ){
- //TODO Is it true to do it at level 0? That depend when SetMember is called
- // At worst it is a good overapproximation
- d_pfuns.insertAtContextLevelZero( it->first, true);
- }
-}
-
-//get has function
-bool EqClassInfo::hasFunction( Node op ){
- return d_funs.find( op )!=d_funs.end();
-}
-
-bool EqClassInfo::hasParent( Node op ){
- return d_pfuns.find( op )!=d_pfuns.end();
-}
-
-//merge with another eq class info
-void EqClassInfo::merge( EqClassInfo* eci ){
- for( BoolMap::iterator it = eci->d_funs.begin(); it != eci->d_funs.end(); it++ ) {
- d_funs[ (*it).first ] = true;
- }
- for( BoolMap::iterator it = eci->d_pfuns.begin(); it != eci->d_pfuns.end(); it++ ) {
- d_pfuns[ (*it).first ] = true;
- }
-}
-
-inline void outputEqClassInfo( const char* c, const EqClassInfo* eci){
- Debug(c) << " funs:";
- for( EqClassInfo::BoolMap::iterator it = eci->d_funs.begin(); it != eci->d_funs.end(); it++ ) {
- Debug(c) << (*it).first << ",";
- }
- Debug(c) << std::endl << "pfuns:";
- for( EqClassInfo::BoolMap::iterator it = eci->d_pfuns.begin(); it != eci->d_pfuns.end(); it++ ) {
- Debug(c) << (*it).first << ",";
- }
- Debug(c) << std::endl;
-}
-
-
-
-EfficientEMatcher::EfficientEMatcher( CVC4::theory::QuantifiersEngine* qe ) : d_quantEngine( qe )
-{
-
-}
-
-eq::EqualityEngine* EfficientEMatcher::getEqualityEngine(){
- //return ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->theoryOf( THEORY_UF ))->getEqualityEngine();
- return d_quantEngine->getMasterEqualityEngine();
-}
-
-/** new node */
-void EfficientEMatcher::newEqClass( TNode n ){
-
-}
-
-void EfficientEMatcher::newTerms(SetNode& s){
- static NoMatchAttribute rewrittenNodeAttribute;
- /* op -> nodes (if the set is empty, the op is not interesting) */
- std::hash_map< TNode, SetNode, TNodeHashFunction > h;
- /* types -> nodes (if the set is empty, the type is not interesting) */
- std::hash_map< TypeNode, SetNode, TypeNodeHashFunction > tyh;
- for(SetNode::iterator i=s.begin(), end=s.end(); i != end; ++i){
- if (i->getAttribute(rewrittenNodeAttribute)) continue; /* skip it */
- if( !d_cand_gens.empty() ){
- // op
- TNode op = i->getOperator();
- std::hash_map< TNode, SetNode, TNodeHashFunction >::iterator
- is = h.find(op);
- if(is == h.end()){
- std::pair<std::hash_map< TNode, SetNode, TNodeHashFunction >::iterator,bool>
- p = h.insert(make_pair(op,SetNode()));
- is = p.first;
- if(d_cand_gens.find(op) != d_cand_gens.end()){
- is->second.insert(*i);
- } /* else we have inserted an empty set */
- }else if(!is->second.empty()){
- is->second.insert(*i);
- }
- }
- if( !d_cand_gen_types.empty() ){
- //type
- TypeNode ty = i->getType();
- std::hash_map< TypeNode, SetNode, TypeNodeHashFunction >::iterator
- is = tyh.find(ty);
- if(is == tyh.end()){
- std::pair<std::hash_map< TypeNode, SetNode, TypeNodeHashFunction >::iterator,bool>
- p = tyh.insert(make_pair(ty,SetNode()));
- is = p.first;
- if(d_cand_gen_types.find(ty) != d_cand_gen_types.end()){
- is->second.insert(*i);
- } /* else we have inserted an empty set */
- }else if(!is->second.empty()){
- is->second.insert(*i);
- }
- }
- }
- //op
- for(std::hash_map< TNode, SetNode, TNodeHashFunction >::iterator i=h.begin(), end=h.end();
- i != end; ++i){
- //new term, add n to candidate generators
- if(i->second.empty()) continue;
- std::map< Node, NodeNewTermDispatcher >::iterator
- inpc = d_cand_gens.find(i->first);
- //we know that this op exists
- Assert(inpc != d_cand_gens.end());
- inpc->second.send(i->second);
- }
- //type
- for(std::hash_map< TypeNode, SetNode, TypeNodeHashFunction >::iterator i=tyh.begin(), end=tyh.end();
- i != end; ++i){
- //new term, add n to candidate generators
- if(i->second.empty()) continue;
- std::map< TypeNode, NodeNewTermDispatcher >::iterator
- inpc = d_cand_gen_types.find(i->first);
- //we know that this op exists
- Assert(inpc != d_cand_gen_types.end());
- inpc->second.send(i->second);
- }
-
-}
-
-
-/** merge */
-void EfficientEMatcher::merge( TNode a, TNode b ){
- if( options::efficientEMatching() ){
- //merge eqc_ops of b into a
- EqClassInfo* eci_a = getOrCreateEquivalenceClassInfo( a );
- EqClassInfo* eci_b = getOrCreateEquivalenceClassInfo( b );
-
- if( a.getKind()!=IFF && a.getKind()!=EQUAL && b.getKind()!=IFF && b.getKind()!=EQUAL ){
- Debug("efficient-e-match") << "Merging " << a << " with " << b << std::endl;
-
- //determine new candidates for instantiation
- computeCandidatesPcPairs( a, eci_a, b, eci_b );
- computeCandidatesPcPairs( b, eci_b, a, eci_a );
- computeCandidatesPpPairs( a, eci_a, b, eci_b );
- computeCandidatesPpPairs( b, eci_b, a, eci_a );
- }
- computeCandidatesConstants( a, eci_a, b, eci_b);
- computeCandidatesConstants( b, eci_b, a, eci_a);
-
- eci_a->merge( eci_b );
- }
-}
-
-/** assert terms are disequal */
-void EfficientEMatcher::assertDisequal( TNode a, TNode b, TNode reason ){
-
-}
-
-EqClassInfo* EfficientEMatcher::getEquivalenceClassInfo( Node n ) {
- return d_eqc_ops.find( n )==d_eqc_ops.end() ? NULL : d_eqc_ops[n];
-}
-EqClassInfo* EfficientEMatcher::getOrCreateEquivalenceClassInfo( Node n ){
- Assert( n==getEqualityEngine()->getRepresentative( n ) );
- if( d_eqc_ops.find( n )==d_eqc_ops.end() ){
- EqClassInfo* eci = new EqClassInfo( d_quantEngine->getSatContext() );
- eci->setMember( n, d_quantEngine->getTermDatabase() );
- d_eqc_ops[n] = eci;
- }
- return d_eqc_ops[n];
-}
-
-void EfficientEMatcher::computeCandidatesPcPairs( Node a, EqClassInfo* eci_a, Node b, EqClassInfo* eci_b ){
- Debug("efficient-e-match") << "Compute candidates for pc pairs..." << std::endl;
- Debug("efficient-e-match") << " Eq class = [";
- outputEqClass( "efficient-e-match", a);
- Debug("efficient-e-match") << "]" << std::endl;
- outputEqClassInfo("efficient-e-match",eci_a);
- for( EqClassInfo::BoolMap::iterator it = eci_a->d_funs.begin(); it != eci_a->d_funs.end(); it++ ) {
- //the child function: a member of eq_class( a ) has top symbol g, in other words g is in funs( a )
- Node g = (*it).first;
- Debug("efficient-e-match") << " Checking application " << g << std::endl;
- //look at all parent/child pairs
- for( std::map< Node, std::vector< std::pair< NodePcDispatcher*, Ips > > >::iterator itf = d_pc_pairs[g].begin();
- itf != d_pc_pairs[g].end(); ++itf ){
- //f/g is a parent/child pair
- Node f = itf->first;
- if( eci_b->hasParent( f ) ){
- //DO_THIS: determine if f in pfuns( b ), only do the follow if so
- Debug("efficient-e-match") << " Checking parent application " << f << std::endl;
- //scan through the list of inverted path strings/candidate generators
- for( std::vector< std::pair< NodePcDispatcher*, Ips > >::iterator cit = itf->second.begin();
- cit != itf->second.end(); ++cit ){
-#ifdef CVC4_DEBUG
- Debug("efficient-e-match") << " Checking pattern " << cit->first->pat << std::endl;
-#endif
- Debug("efficient-e-match") << " Check inverted path string for pattern ";
- outputIps( "efficient-e-match", cit->second );
- Debug("efficient-e-match") << std::endl;
-
- //collect all new relevant terms
- SetNode terms;
- terms.insert( b );
- collectTermsIps( cit->second, terms );
- if( terms.empty() ) continue;
- Debug("efficient-e-match") << " -> Added terms (" << terms.size() << "): ";
- for( SetNode::const_iterator t=terms.begin(), end=terms.end();
- t!=end; ++t ){
- Debug("efficient-e-match") << (*t) << " ";
- }
- Debug("efficient-e-match") << std::endl;
- //add them as candidates to the candidate generator
- cit->first->send(terms);
- }
- }
- }
- }
-}
-
-void EfficientEMatcher::computeCandidatesPpPairs( Node a, EqClassInfo* eci_a, Node b, EqClassInfo* eci_b ){
- Debug("efficient-e-match") << "Compute candidates for pp pairs..." << std::endl;
- for( std::map< Node, std::map< Node, std::vector< triple< NodePpDispatcher*, Ips, Ips > > > >::iterator it = d_pp_pairs.begin();
- it != d_pp_pairs.end(); ++it ){
- Node f = it->first;
- if( eci_a->hasParent( f ) ){
- Debug("efficient-e-match") << " Checking parent application " << f << std::endl;
- for( std::map< Node, std::vector< triple<NodePpDispatcher*, Ips, Ips> > >::iterator it2 = it->second.begin();
- it2 != it->second.end(); ++it2 ){
- Node g = it2->first;
- if( eci_b->hasParent( g ) ){
- Debug("efficient-e-match") << " Checking parent application " << g << std::endl;
- //if f in pfuns( a ) and g is in pfuns( b ), only do the follow if so
- for( std::vector< triple<NodePpDispatcher*, Ips, Ips> > ::iterator cit = it2->second.begin();
- cit != it2->second.end(); ++cit ){
-#ifdef CVC4_DEBUG
- Debug("efficient-e-match") << " Checking pattern " << cit->first->pat1 << " and " << cit->first->pat2 << std::endl;
-#endif
- Debug("efficient-e-match") << " Check inverted path string ";
- outputIps( "efficient-e-match", cit->second );
- SetNode a_terms;
- a_terms.insert( a );
- collectTermsIps( cit->second, a_terms );
- if( a_terms.empty() ) continue;
- Debug("efficient-e-match") << " And check inverted path string ";
- outputIps( "efficient-e-match", cit->third );
- SetNode b_terms;
- b_terms.insert( b );
- collectTermsIps( cit->third, b_terms );
- if( b_terms.empty() ) continue;
- //Start debug
- Debug("efficient-e-match") << " -> Possibly Added termsA (" << a_terms.size() << "): ";
- for( SetNode::const_iterator t=a_terms.begin(), end=a_terms.end();
- t!=end; ++t ){
- Debug("efficient-e-match") << (*t) << " ";
- }
- Debug("efficient-e-match") << std::endl;
- Debug("efficient-e-match") << " -> Possibly Added termsB (" << b_terms.size() << "): ";
- for( SetNode::const_iterator t=b_terms.begin(), end=b_terms.end();
- t!=end; ++t ){
- Debug("efficient-e-match") << (*t) << " ";
- }
- Debug("efficient-e-match") << std::endl;
- //End debug
-
- cit->first->send(a_terms,b_terms);
- }
- }
- }
- }
- }
-}
-
-
-void EfficientEMatcher::computeCandidatesConstants( Node a, EqClassInfo* eci_a, Node b, EqClassInfo* eci_b ){
- Debug("efficient-e-match") << "Compute candidates constants for cc pairs..." << std::endl;
- Debug("efficient-e-match") << " Eq class = [";
- outputEqClass( "efficient-e-match", a);
- Debug("efficient-e-match") << "]" << std::endl;
- outputEqClassInfo("efficient-e-match",eci_a);
- for( std::map< Node, std::map< Node, NodePcDispatcher* > >::iterator
- it = d_cc_pairs.begin(), end = d_cc_pairs.end();
- it != end; ++it ) {
- Debug("efficient-e-match") << " Checking application " << it->first << std::endl;
- if( !eci_b->hasFunction(it->first) ) continue;
- for( std::map< Node, NodePcDispatcher* >::iterator
- itc = it->second.begin(), end = it->second.end();
- itc != end; ++itc ) {
- //The constant
- Debug("efficient-e-match") << " Checking constant " << a << std::endl;
- if(getEqualityEngine()->getRepresentative(itc->first) != a) continue;
- SetNode s;
- eq::EqClassIterator eqc_iter( b, getEqualityEngine() );
- while( !eqc_iter.isFinished() ){
- Debug("efficient-e-match-debug") << "> look at " << (*eqc_iter)
- << std::endl;
- if( (*eqc_iter).hasOperator() && (*eqc_iter).getOperator() == it->first ) s.insert(*eqc_iter);
- eqc_iter++;
- }
-
- if( s.empty() ) continue;
- Debug("efficient-e-match") << " -> Added terms (" << s.size() << "): ";
- for( SetNode::const_iterator t=s.begin(), end=s.end();
- t!=end; ++t ){
- Debug("efficient-e-match") << (*t) << " ";
- }
- Debug("efficient-e-match") << std::endl;
- itc->second->send(s);
- }
- }
-}
-
-void EfficientEMatcher::collectTermsIps( Ips& ips, SetNode & terms ){
- Assert( ips.size() > 0);
- return collectTermsIps( ips, terms, ips.size() - 1);
-}
-
-void EfficientEMatcher::collectTermsIps( Ips& ips, SetNode& terms, int index ){
- if( !terms.empty() ){
- Debug("efficient-e-match-debug") << "> Process " << index << std::endl;
- Node f = ips[index].first;
- int arg = ips[index].second;
-
- //for each term in terms, determine if any term (modulo equality) has parent "f" from position "arg"
- bool addRep = ( index!=0 ); // We want to keep the top symbol for the last
- SetNode newTerms;
- for( SetNode::const_iterator t=terms.begin(), end=terms.end();
- t!=end; ++t ){
- collectParentsTermsIps( *t, f, arg, newTerms, addRep );
- }
- terms.swap(newTerms);
-
- Debug("efficient-e-match-debug") << "> Terms are now: ";
- for( SetNode::const_iterator t=terms.begin(), end=terms.end();
- t!=end; ++t ){
- Debug("efficient-e-match-debug") << *t << " ";
- }
- Debug("efficient-e-match-debug") << std::endl;
-
- if(index!=0) collectTermsIps( ips, terms, index-1 );
- }
-}
-
-bool EfficientEMatcher::collectParentsTermsIps( Node n, Node f, int arg, SetNode & terms, bool addRep, bool modEq ){ //modEq default true
- bool addedTerm = false;
-
- if( modEq && getEqualityEngine()->hasTerm( n )){
- Assert( getEqualityEngine()->getRepresentative( n )==n );
- //collect modulo equality
- //DO_THIS: this should (if necessary) compute a current set of (f, arg) parents for n and cache it
- eq::EqClassIterator eqc_iter( n, getEqualityEngine() );
- while( !eqc_iter.isFinished() ){
- Debug("efficient-e-match-debug") << "> look at " << (*eqc_iter)
- << std::endl;
- if( collectParentsTermsIps( (*eqc_iter), f, arg, terms, addRep, false ) ){
- //if only one argument, we know we can stop (since all others added will be congruent)
- if( f.getType().getNumChildren()==2 ){
- return true;
- }
- addedTerm = true;
- }
- eqc_iter++;
- }
- }else{
- quantifiers::TermDb* db = d_quantEngine->getTermDatabase();
- //see if parent f exists from argument arg
- const std::vector<Node> & parents = db->getParents(n,f,arg);
- for( size_t i=0; i<parents.size(); ++i ){
- TNode t = parents[i];
- if(!CandidateGenerator::isLegalCandidate(t)) continue;
- if( addRep ) t = getEqualityEngine()->getRepresentative( t );
- terms.insert(t);
- addedTerm = true;
- }
- }
- return addedTerm;
-}
-
-void EfficientEMatcher::registerPatternElementPairs2( Node pat, Ips& ips, PpIpsMap & pp_ips_map, NodePcDispatcher* npc ){
- Assert( pat.hasOperator() );
- //add information for possible pp-pair
- ips.push_back( std::pair< Node, int >( pat.getOperator(), 0 ) ); //0 is just a dumb value
-
- for( int i=0; i<(int)pat.getNumChildren(); i++ ){
- if( pat[i].getKind()==INST_CONSTANT ){
- ips.back().second = i;
- pp_ips_map[ pat[i] ].push_back( make_pair( pat.getOperator(), Ips( ips ) ) );
- }
- }
-
- for( int i=0; i<(int)pat.getNumChildren(); i++ ){
- if( pat[i].getKind()==APPLY_UF ){
- ips.back().second = i;
- registerPatternElementPairs2( pat[i], ips, pp_ips_map, npc );
- Debug("pattern-element-opt") << "Found pc-pair ( " << pat.getOperator() << ", " << pat[i].getOperator() << " )" << std::endl;
- Debug("pattern-element-opt") << " Path = ";
- outputIps( "pattern-element-opt", ips );
- Debug("pattern-element-opt") << std::endl;
- //pat.getOperator() and pat[i].getOperator() are a pc-pair
- d_pc_pairs[ pat[i].getOperator() ][ pat.getOperator() ]
- .push_back( make_pair(npc,Ips(ips)) );
- }
- }
- ips.pop_back();
-}
-
-void EfficientEMatcher::registerPatternElementPairs( Node pat, PpIpsMap & pp_ips_map,
- NodePcDispatcher* npc,
- NodePpDispatcher* npp){
- Ips ips;
- registerPatternElementPairs2( pat, ips, pp_ips_map, npc );
- for( PpIpsMap::iterator it = pp_ips_map.begin(); it != pp_ips_map.end(); ++it ){
- // for each variable construct all the pp-pair
- for( size_t j=0; j<it->second.size(); j++ ){
- for( size_t k=j+1; k<it->second.size(); k++ ){
- //found a pp-pair
- Debug("pattern-element-opt") << "Found pp-pair ( " << it->second[j].first << ", " << it->second[k].first << " )" << std::endl;
- Debug("pattern-element-opt") << " Paths = ";
- outputIps( "pattern-element-opt", it->second[j].second );
- Debug("pattern-element-opt") << " and ";
- outputIps( "pattern-element-opt", it->second[k].second );
- Debug("pattern-element-opt") << std::endl;
- d_pp_pairs[ it->second[j].first ][ it->second[k].first ]
- .push_back( make_triple( npp, it->second[j].second, it->second[k].second ));
- }
- }
- }
-};
-
-void findPpSite(Node pat, EfficientEMatcher::Ips& ips, EfficientEMatcher::PpIpsMap & pp_ips_map){
- Assert( pat.getKind()==APPLY_UF );
- //add information for possible pp-pair
-
- ips.push_back( make_pair( pat.getOperator(), 0) );
- for( size_t i=0; i<pat.getNumChildren(); i++ ){
- if( pat[i].getKind()==INST_CONSTANT ){
- ips.back().second = i;
- pp_ips_map[ pat[i] ].push_back( make_pair( pat.getOperator(), EfficientEMatcher::Ips( ips ) ) );
- }
- }
-
- for( size_t i=0; i<pat.getNumChildren(); i++ ){
- if( pat[i].getKind()==APPLY_UF ){
- ips.back().second = i;
- findPpSite( pat[i], ips, pp_ips_map );
- }
- }
- ips.pop_back();
-}
-
-void EfficientEMatcher::combineMultiPpIpsMap(PpIpsMap & pp_ips_map, MultiPpIpsMap & multi_pp_ips_map,
- EfficientHandler& eh, size_t index2,const std::vector<Node> & pats){
- hash_map<size_t,NodePpDispatcher*> npps;
- for( PpIpsMap::iterator it = pp_ips_map.begin(); it != pp_ips_map.end(); ++it ){
- MultiPpIpsMap::iterator mit = multi_pp_ips_map.find(it->first);
- if(mit == multi_pp_ips_map.end()) continue;
- // for each variable construct all the pp-pair
- // j the last pattern treated
- for( std::vector< std::pair< Node, Ips > >::iterator j=it->second.begin(), jend = it->second.end() ;
- j != jend; ++j){
- // k one of the previous one
- for( std::vector< triple< size_t, Node, Ips > >::iterator k=mit->second.begin(), kend = mit->second.end() ;
- k != kend; ++k){
- //found a pp-pair
- Debug("pattern-element-opt") << "Found multi-pp-pair ( " << j->first
- << ", " << k->second << " in "<< k->first
- << " )" << std::endl;
- Debug("pattern-element-opt") << " Paths = ";
- outputIps( "pattern-element-opt", j->second );
- Debug("pattern-element-opt") << " and ";
- outputIps( "pattern-element-opt", k->third );
- Debug("pattern-element-opt") << std::endl;
- NodePpDispatcher* dispatcher;
- hash_map<size_t,NodePpDispatcher*>::iterator inpp = npps.find(k->first);
- if( inpp != npps.end() ) dispatcher = inpp->second;
- else{
- dispatcher = new NodePpDispatcher();
-#ifdef CVC4_DEBUG
- dispatcher->pat1 = pats[index2];
- dispatcher->pat2 = pats[k->first];
-#endif
- dispatcher->addPpDispatcher(&eh,index2,k->first);
- };
- d_pp_pairs[ j->first ][ k->second ].push_back( make_triple( dispatcher, j->second, k->third ));
- }
- }
- }
-
- /** Put pp_ips_map to multi_pp_ips_map */
- for( PpIpsMap::iterator it = pp_ips_map.begin(); it != pp_ips_map.end(); ++it ){
- for( std::vector< std::pair< Node, Ips > >::iterator j=it->second.begin(), jend = it->second.end() ;
- j != jend; ++j){
- multi_pp_ips_map[it->first].push_back(make_triple(index2, j->first, j->second));
- }
- }
-
-}
-
-
-void EfficientEMatcher::registerEfficientHandler( EfficientHandler& handler,
- const std::vector< Node > & pats ){
- Assert(pats.size() > 0);
-
- MultiPpIpsMap multi_pp_ips_map;
- PpIpsMap pp_ips_map;
- //In a multi-pattern Pattern that is only a variable are specials,
- //if the variable appears in another pattern, it can be discarded.
- //Otherwise new term of this term can be candidate. So we stock them
- //here before adding them.
- std::vector< size_t > patVars;
-
- Debug("pattern-element-opt") << "Register patterns" << pats << std::endl;
- for(size_t i = 0; i < pats.size(); ++i){
- if( pats[i].getKind() == kind::INST_CONSTANT){
- patVars.push_back(i);
- continue;
- }
- //to complete
- if( pats[i].getKind() == kind::NOT && pats[i][0].getKind() == kind::EQUAL){
- Node cst = NodeManager::currentNM()->mkConst<bool>(false);
- TNode op = pats[i][0].getOperator();
- if(d_cc_pairs[op][cst] == NULL){
- d_cc_pairs[op][cst] = new NodePcDispatcher();
- }
- d_cc_pairs[op][cst]->addPcDispatcher(&handler,i);
- continue;
- }
- //end to complete
- Debug("pattern-element-opt") << " Register candidate generator..." << pats[i] << std::endl;
- /* Has the pattern already been seen */
- if( d_pat_cand_gens.find( pats[i] )==d_pat_cand_gens.end() ){
- NodePcDispatcher* npc = new NodePcDispatcher();
- NodePpDispatcher* npp = new NodePpDispatcher();
-#ifdef CVC4_DEBUG
- npc->pat = pats[i];
- npp->pat1 = pats[i];
- npp->pat2 = pats[i];
-#endif
- d_pat_cand_gens[pats[i]] = make_pair(npc,npp);
- registerPatternElementPairs( pats[i], pp_ips_map, npc, npp );
- }else{
- Ips ips;
- findPpSite(pats[i],ips,pp_ips_map);
- }
- //Has the top operator already been seen */
- TNode op = pats[i].getOperator();
- d_pat_cand_gens[pats[i]].first->addPcDispatcher(&handler,i);
- d_pat_cand_gens[pats[i]].second->addPpDispatcher(&handler,i,i);
- d_cand_gens[op].addNewTermDispatcher(&handler,i);
-
- combineMultiPpIpsMap(pp_ips_map,multi_pp_ips_map,handler,i,pats);
-
- pp_ips_map.clear();
- }
-
- for(size_t i = 0; i < patVars.size(); ++i){
- TNode var = pats[patVars[i]];
- Assert( var.getKind() == kind::INST_CONSTANT );
- if( multi_pp_ips_map.find(var) != multi_pp_ips_map.end() ){
- //The variable appear in another pattern, skip it
- continue;
- };
- d_cand_gen_types[var.getType()].addNewTermDispatcher(&handler,patVars[i]);
- }
-
- //take all terms from the uf term db and add to candidate generator
- if( pats[0].getKind() == kind::INST_CONSTANT ){
- TypeNode ty = pats[0].getType();
- rrinst::CandidateGenerator* cg = new GenericCandidateGeneratorClasses(d_quantEngine);
- cg->reset(Node::null());
- TNode c;
- SetNode ele;
- while( !(c = cg->getNextCandidate()).isNull() ){
- if( c.getType() == ty ) ele.insert(c);
- }
- if( !ele.empty() ){
- // for(std::vector<Node>::iterator i = db->d_op_map[op].begin(), end = db->d_op_map[op].end(); i != end; ++i){
- // if(CandidateGenerator::isLegalCandidate(*i)) ele.insert(*i);
- // }
- if(Debug.isOn("efficient-e-match-stats")){
- Debug("efficient-e-match-stats") << "pattern " << pats << " initialized with " << ele.size() << " terms"<< std::endl;
- }
- handler.addMonoCandidate(ele, 0);
- }
-
- } else if( pats[0].getKind() == kind::NOT && pats[0][0].getKind() == kind::EQUAL){
- Node cst = NodeManager::currentNM()->mkConst<bool>(false);
- TNode op = pats[0][0].getOperator();
- cst = getEqualityEngine()->getRepresentative(cst);
- SetNode ele;
- eq::EqClassIterator eqc_iter( cst, getEqualityEngine() );
- while( !eqc_iter.isFinished() ){
- Debug("efficient-e-match-debug") << "> look at " << (*eqc_iter)
- << std::endl;
- if( (*eqc_iter).hasOperator() && (*eqc_iter).getOperator() == op ) ele.insert(*eqc_iter);
- eqc_iter++;
- }
- if( !ele.empty() ){
- if(Debug.isOn("efficient-e-match-stats")){
- Debug("efficient-e-match-stats") << "pattern " << pats << " initialized with " << ele.size() << " terms"<< std::endl;
- }
- handler.addMonoCandidate(ele, 0);
- }
-
- } else {
- Node op = pats[0].getOperator();
- TermDb* db = d_quantEngine->getTermDatabase();
- if(db->d_op_map[op].begin() != db->d_op_map[op].end()){
- SetNode ele;
- // for(std::vector<Node>::iterator i = db->d_op_map[op].begin(), end = db->d_op_map[op].end(); i != end; ++i){
- // if(CandidateGenerator::isLegalCandidate(*i)) ele.insert(*i);
- // }
- ele.insert(db->d_op_map[op].begin(), db->d_op_map[op].end());
- if(Debug.isOn("efficient-e-match-stats")){
- Debug("efficient-e-match-stats") << "pattern " << pats << " initialized with " << ele.size() << " terms"<< std::endl;
- }
- handler.addMonoCandidate(ele, 0);
- }
- }
- Debug("efficient-e-match") << "Done." << std::endl;
-}
-
-void EfficientEMatcher::outputEqClass( const char* c, Node n ){
- if( getEqualityEngine()->hasTerm( n ) ){
- eq::EqClassIterator eqc_iter( getEqualityEngine()->getRepresentative( n ),
- getEqualityEngine() );
- bool firstTime = true;
- while( !eqc_iter.isFinished() ){
- if( !firstTime ){ Debug(c) << ", "; }
- Debug(c) << (*eqc_iter);
- firstTime = false;
- eqc_iter++;
- }
- }else{
- Debug(c) << n;
- }
-}
-
-void EfficientEMatcher::outputIps( const char* c, Ips& ips ){
- for( int i=0; i<(int)ips.size(); i++ ){
- if( i>0 ){ Debug( c ) << "."; }
- Debug( c ) << ips[i].first << "." << ips[i].second;
- }
-}
-
-
-} /* namespace theory */
-} /* namespace cvc4 */
+/********************* */
+/*! \file efficient_e_matching.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Implementation of theory uf instantiator class
+ **/
+
+#include "theory/rewriterules/efficient_e_matching.h"
+#include "theory/rewriterules/rr_candidate_generator.h"
+#include "theory/quantifiers/candidate_generator.h"
+#include "theory/quantifiers/options.h"
+#include "theory/rewriterules/options.h"
+#include "theory/quantifiers/term_database.h"
+
+#include "theory/theory_engine.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::inst;
+
+namespace CVC4 {
+namespace theory {
+
+inline std::ostream& operator<<(std::ostream& out, const EfficientEMatcher::Ips& ips) {
+ return out;
+};
+
+EqClassInfo::EqClassInfo( context::Context* c ) : d_funs( c ), d_pfuns( c ), d_disequal( c ){
+
+}
+
+//set member
+void EqClassInfo::setMember( Node n, quantifiers::TermDb* db ){
+ if( n.hasOperator() ){
+ d_funs.insertAtContextLevelZero(n.getOperator(),true);
+ }
+ //add parent functions
+ for( std::hash_map< Node, std::hash_map< int, std::vector< Node > >, NodeHashFunction >::iterator it = db->d_parents[n].begin();
+ it != db->d_parents[n].end(); ++it ){
+ //TODO Is it true to do it at level 0? That depend when SetMember is called
+ // At worst it is a good overapproximation
+ d_pfuns.insertAtContextLevelZero( it->first, true);
+ }
+}
+
+//get has function
+bool EqClassInfo::hasFunction( Node op ){
+ return d_funs.find( op )!=d_funs.end();
+}
+
+bool EqClassInfo::hasParent( Node op ){
+ return d_pfuns.find( op )!=d_pfuns.end();
+}
+
+//merge with another eq class info
+void EqClassInfo::merge( EqClassInfo* eci ){
+ for( BoolMap::iterator it = eci->d_funs.begin(); it != eci->d_funs.end(); it++ ) {
+ d_funs[ (*it).first ] = true;
+ }
+ for( BoolMap::iterator it = eci->d_pfuns.begin(); it != eci->d_pfuns.end(); it++ ) {
+ d_pfuns[ (*it).first ] = true;
+ }
+}
+
+inline void outputEqClassInfo( const char* c, const EqClassInfo* eci){
+ Debug(c) << " funs:";
+ for( EqClassInfo::BoolMap::iterator it = eci->d_funs.begin(); it != eci->d_funs.end(); it++ ) {
+ Debug(c) << (*it).first << ",";
+ }
+ Debug(c) << std::endl << "pfuns:";
+ for( EqClassInfo::BoolMap::iterator it = eci->d_pfuns.begin(); it != eci->d_pfuns.end(); it++ ) {
+ Debug(c) << (*it).first << ",";
+ }
+ Debug(c) << std::endl;
+}
+
+
+
+EfficientEMatcher::EfficientEMatcher( CVC4::theory::QuantifiersEngine* qe ) : d_quantEngine( qe )
+{
+
+}
+
+eq::EqualityEngine* EfficientEMatcher::getEqualityEngine(){
+ //return ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->theoryOf( THEORY_UF ))->getEqualityEngine();
+ return d_quantEngine->getMasterEqualityEngine();
+}
+
+/** new node */
+void EfficientEMatcher::newEqClass( TNode n ){
+
+}
+
+void EfficientEMatcher::newTerms(SetNode& s){
+ static NoMatchAttribute rewrittenNodeAttribute;
+ /* op -> nodes (if the set is empty, the op is not interesting) */
+ std::hash_map< TNode, SetNode, TNodeHashFunction > h;
+ /* types -> nodes (if the set is empty, the type is not interesting) */
+ std::hash_map< TypeNode, SetNode, TypeNodeHashFunction > tyh;
+ for(SetNode::iterator i=s.begin(), end=s.end(); i != end; ++i){
+ if (i->getAttribute(rewrittenNodeAttribute)) continue; /* skip it */
+ if( !d_cand_gens.empty() ){
+ // op
+ TNode op = i->getOperator();
+ std::hash_map< TNode, SetNode, TNodeHashFunction >::iterator
+ is = h.find(op);
+ if(is == h.end()){
+ std::pair<std::hash_map< TNode, SetNode, TNodeHashFunction >::iterator,bool>
+ p = h.insert(make_pair(op,SetNode()));
+ is = p.first;
+ if(d_cand_gens.find(op) != d_cand_gens.end()){
+ is->second.insert(*i);
+ } /* else we have inserted an empty set */
+ }else if(!is->second.empty()){
+ is->second.insert(*i);
+ }
+ }
+ if( !d_cand_gen_types.empty() ){
+ //type
+ TypeNode ty = i->getType();
+ std::hash_map< TypeNode, SetNode, TypeNodeHashFunction >::iterator
+ is = tyh.find(ty);
+ if(is == tyh.end()){
+ std::pair<std::hash_map< TypeNode, SetNode, TypeNodeHashFunction >::iterator,bool>
+ p = tyh.insert(make_pair(ty,SetNode()));
+ is = p.first;
+ if(d_cand_gen_types.find(ty) != d_cand_gen_types.end()){
+ is->second.insert(*i);
+ } /* else we have inserted an empty set */
+ }else if(!is->second.empty()){
+ is->second.insert(*i);
+ }
+ }
+ }
+ //op
+ for(std::hash_map< TNode, SetNode, TNodeHashFunction >::iterator i=h.begin(), end=h.end();
+ i != end; ++i){
+ //new term, add n to candidate generators
+ if(i->second.empty()) continue;
+ std::map< Node, NodeNewTermDispatcher >::iterator
+ inpc = d_cand_gens.find(i->first);
+ //we know that this op exists
+ Assert(inpc != d_cand_gens.end());
+ inpc->second.send(i->second);
+ }
+ //type
+ for(std::hash_map< TypeNode, SetNode, TypeNodeHashFunction >::iterator i=tyh.begin(), end=tyh.end();
+ i != end; ++i){
+ //new term, add n to candidate generators
+ if(i->second.empty()) continue;
+ std::map< TypeNode, NodeNewTermDispatcher >::iterator
+ inpc = d_cand_gen_types.find(i->first);
+ //we know that this op exists
+ Assert(inpc != d_cand_gen_types.end());
+ inpc->second.send(i->second);
+ }
+
+}
+
+
+/** merge */
+void EfficientEMatcher::merge( TNode a, TNode b ){
+ if( options::efficientEMatching() ){
+ //merge eqc_ops of b into a
+ EqClassInfo* eci_a = getOrCreateEquivalenceClassInfo( a );
+ EqClassInfo* eci_b = getOrCreateEquivalenceClassInfo( b );
+
+ if( a.getKind()!=IFF && a.getKind()!=EQUAL && b.getKind()!=IFF && b.getKind()!=EQUAL ){
+ Debug("efficient-e-match") << "Merging " << a << " with " << b << std::endl;
+
+ //determine new candidates for instantiation
+ computeCandidatesPcPairs( a, eci_a, b, eci_b );
+ computeCandidatesPcPairs( b, eci_b, a, eci_a );
+ computeCandidatesPpPairs( a, eci_a, b, eci_b );
+ computeCandidatesPpPairs( b, eci_b, a, eci_a );
+ }
+ computeCandidatesConstants( a, eci_a, b, eci_b);
+ computeCandidatesConstants( b, eci_b, a, eci_a);
+
+ eci_a->merge( eci_b );
+ }
+}
+
+/** assert terms are disequal */
+void EfficientEMatcher::assertDisequal( TNode a, TNode b, TNode reason ){
+
+}
+
+EqClassInfo* EfficientEMatcher::getEquivalenceClassInfo( Node n ) {
+ return d_eqc_ops.find( n )==d_eqc_ops.end() ? NULL : d_eqc_ops[n];
+}
+EqClassInfo* EfficientEMatcher::getOrCreateEquivalenceClassInfo( Node n ){
+ Assert( n==getEqualityEngine()->getRepresentative( n ) );
+ if( d_eqc_ops.find( n )==d_eqc_ops.end() ){
+ EqClassInfo* eci = new EqClassInfo( d_quantEngine->getSatContext() );
+ eci->setMember( n, d_quantEngine->getTermDatabase() );
+ d_eqc_ops[n] = eci;
+ }
+ return d_eqc_ops[n];
+}
+
+void EfficientEMatcher::computeCandidatesPcPairs( Node a, EqClassInfo* eci_a, Node b, EqClassInfo* eci_b ){
+ Debug("efficient-e-match") << "Compute candidates for pc pairs..." << std::endl;
+ Debug("efficient-e-match") << " Eq class = [";
+ outputEqClass( "efficient-e-match", a);
+ Debug("efficient-e-match") << "]" << std::endl;
+ outputEqClassInfo("efficient-e-match",eci_a);
+ for( EqClassInfo::BoolMap::iterator it = eci_a->d_funs.begin(); it != eci_a->d_funs.end(); it++ ) {
+ //the child function: a member of eq_class( a ) has top symbol g, in other words g is in funs( a )
+ Node g = (*it).first;
+ Debug("efficient-e-match") << " Checking application " << g << std::endl;
+ //look at all parent/child pairs
+ for( std::map< Node, std::vector< std::pair< NodePcDispatcher*, Ips > > >::iterator itf = d_pc_pairs[g].begin();
+ itf != d_pc_pairs[g].end(); ++itf ){
+ //f/g is a parent/child pair
+ Node f = itf->first;
+ if( eci_b->hasParent( f ) ){
+ //DO_THIS: determine if f in pfuns( b ), only do the follow if so
+ Debug("efficient-e-match") << " Checking parent application " << f << std::endl;
+ //scan through the list of inverted path strings/candidate generators
+ for( std::vector< std::pair< NodePcDispatcher*, Ips > >::iterator cit = itf->second.begin();
+ cit != itf->second.end(); ++cit ){
+#ifdef CVC4_DEBUG
+ Debug("efficient-e-match") << " Checking pattern " << cit->first->pat << std::endl;
+#endif
+ Debug("efficient-e-match") << " Check inverted path string for pattern ";
+ outputIps( "efficient-e-match", cit->second );
+ Debug("efficient-e-match") << std::endl;
+
+ //collect all new relevant terms
+ SetNode terms;
+ terms.insert( b );
+ collectTermsIps( cit->second, terms );
+ if( terms.empty() ) continue;
+ Debug("efficient-e-match") << " -> Added terms (" << terms.size() << "): ";
+ for( SetNode::const_iterator t=terms.begin(), end=terms.end();
+ t!=end; ++t ){
+ Debug("efficient-e-match") << (*t) << " ";
+ }
+ Debug("efficient-e-match") << std::endl;
+ //add them as candidates to the candidate generator
+ cit->first->send(terms);
+ }
+ }
+ }
+ }
+}
+
+void EfficientEMatcher::computeCandidatesPpPairs( Node a, EqClassInfo* eci_a, Node b, EqClassInfo* eci_b ){
+ Debug("efficient-e-match") << "Compute candidates for pp pairs..." << std::endl;
+ for( std::map< Node, std::map< Node, std::vector< triple< NodePpDispatcher*, Ips, Ips > > > >::iterator it = d_pp_pairs.begin();
+ it != d_pp_pairs.end(); ++it ){
+ Node f = it->first;
+ if( eci_a->hasParent( f ) ){
+ Debug("efficient-e-match") << " Checking parent application " << f << std::endl;
+ for( std::map< Node, std::vector< triple<NodePpDispatcher*, Ips, Ips> > >::iterator it2 = it->second.begin();
+ it2 != it->second.end(); ++it2 ){
+ Node g = it2->first;
+ if( eci_b->hasParent( g ) ){
+ Debug("efficient-e-match") << " Checking parent application " << g << std::endl;
+ //if f in pfuns( a ) and g is in pfuns( b ), only do the follow if so
+ for( std::vector< triple<NodePpDispatcher*, Ips, Ips> > ::iterator cit = it2->second.begin();
+ cit != it2->second.end(); ++cit ){
+#ifdef CVC4_DEBUG
+ Debug("efficient-e-match") << " Checking pattern " << cit->first->pat1 << " and " << cit->first->pat2 << std::endl;
+#endif
+ Debug("efficient-e-match") << " Check inverted path string ";
+ outputIps( "efficient-e-match", cit->second );
+ SetNode a_terms;
+ a_terms.insert( a );
+ collectTermsIps( cit->second, a_terms );
+ if( a_terms.empty() ) continue;
+ Debug("efficient-e-match") << " And check inverted path string ";
+ outputIps( "efficient-e-match", cit->third );
+ SetNode b_terms;
+ b_terms.insert( b );
+ collectTermsIps( cit->third, b_terms );
+ if( b_terms.empty() ) continue;
+ //Start debug
+ Debug("efficient-e-match") << " -> Possibly Added termsA (" << a_terms.size() << "): ";
+ for( SetNode::const_iterator t=a_terms.begin(), end=a_terms.end();
+ t!=end; ++t ){
+ Debug("efficient-e-match") << (*t) << " ";
+ }
+ Debug("efficient-e-match") << std::endl;
+ Debug("efficient-e-match") << " -> Possibly Added termsB (" << b_terms.size() << "): ";
+ for( SetNode::const_iterator t=b_terms.begin(), end=b_terms.end();
+ t!=end; ++t ){
+ Debug("efficient-e-match") << (*t) << " ";
+ }
+ Debug("efficient-e-match") << std::endl;
+ //End debug
+
+ cit->first->send(a_terms,b_terms);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void EfficientEMatcher::computeCandidatesConstants( Node a, EqClassInfo* eci_a, Node b, EqClassInfo* eci_b ){
+ Debug("efficient-e-match") << "Compute candidates constants for cc pairs..." << std::endl;
+ Debug("efficient-e-match") << " Eq class = [";
+ outputEqClass( "efficient-e-match", a);
+ Debug("efficient-e-match") << "]" << std::endl;
+ outputEqClassInfo("efficient-e-match",eci_a);
+ for( std::map< Node, std::map< Node, NodePcDispatcher* > >::iterator
+ it = d_cc_pairs.begin(), end = d_cc_pairs.end();
+ it != end; ++it ) {
+ Debug("efficient-e-match") << " Checking application " << it->first << std::endl;
+ if( !eci_b->hasFunction(it->first) ) continue;
+ for( std::map< Node, NodePcDispatcher* >::iterator
+ itc = it->second.begin(), end = it->second.end();
+ itc != end; ++itc ) {
+ //The constant
+ Debug("efficient-e-match") << " Checking constant " << a << std::endl;
+ if(getEqualityEngine()->getRepresentative(itc->first) != a) continue;
+ SetNode s;
+ eq::EqClassIterator eqc_iter( b, getEqualityEngine() );
+ while( !eqc_iter.isFinished() ){
+ Debug("efficient-e-match-debug") << "> look at " << (*eqc_iter)
+ << std::endl;
+ if( (*eqc_iter).hasOperator() && (*eqc_iter).getOperator() == it->first ) s.insert(*eqc_iter);
+ eqc_iter++;
+ }
+
+ if( s.empty() ) continue;
+ Debug("efficient-e-match") << " -> Added terms (" << s.size() << "): ";
+ for( SetNode::const_iterator t=s.begin(), end=s.end();
+ t!=end; ++t ){
+ Debug("efficient-e-match") << (*t) << " ";
+ }
+ Debug("efficient-e-match") << std::endl;
+ itc->second->send(s);
+ }
+ }
+}
+
+void EfficientEMatcher::collectTermsIps( Ips& ips, SetNode & terms ){
+ Assert( ips.size() > 0);
+ return collectTermsIps( ips, terms, ips.size() - 1);
+}
+
+void EfficientEMatcher::collectTermsIps( Ips& ips, SetNode& terms, int index ){
+ if( !terms.empty() ){
+ Debug("efficient-e-match-debug") << "> Process " << index << std::endl;
+ Node f = ips[index].first;
+ int arg = ips[index].second;
+
+ //for each term in terms, determine if any term (modulo equality) has parent "f" from position "arg"
+ bool addRep = ( index!=0 ); // We want to keep the top symbol for the last
+ SetNode newTerms;
+ for( SetNode::const_iterator t=terms.begin(), end=terms.end();
+ t!=end; ++t ){
+ collectParentsTermsIps( *t, f, arg, newTerms, addRep );
+ }
+ terms.swap(newTerms);
+
+ Debug("efficient-e-match-debug") << "> Terms are now: ";
+ for( SetNode::const_iterator t=terms.begin(), end=terms.end();
+ t!=end; ++t ){
+ Debug("efficient-e-match-debug") << *t << " ";
+ }
+ Debug("efficient-e-match-debug") << std::endl;
+
+ if(index!=0) collectTermsIps( ips, terms, index-1 );
+ }
+}
+
+bool EfficientEMatcher::collectParentsTermsIps( Node n, Node f, int arg, SetNode & terms, bool addRep, bool modEq ){ //modEq default true
+ bool addedTerm = false;
+
+ if( modEq && getEqualityEngine()->hasTerm( n )){
+ Assert( getEqualityEngine()->getRepresentative( n )==n );
+ //collect modulo equality
+ //DO_THIS: this should (if necessary) compute a current set of (f, arg) parents for n and cache it
+ eq::EqClassIterator eqc_iter( n, getEqualityEngine() );
+ while( !eqc_iter.isFinished() ){
+ Debug("efficient-e-match-debug") << "> look at " << (*eqc_iter)
+ << std::endl;
+ if( collectParentsTermsIps( (*eqc_iter), f, arg, terms, addRep, false ) ){
+ //if only one argument, we know we can stop (since all others added will be congruent)
+ if( f.getType().getNumChildren()==2 ){
+ return true;
+ }
+ addedTerm = true;
+ }
+ eqc_iter++;
+ }
+ }else{
+ quantifiers::TermDb* db = d_quantEngine->getTermDatabase();
+ //see if parent f exists from argument arg
+ const std::vector<Node> & parents = db->getParents(n,f,arg);
+ for( size_t i=0; i<parents.size(); ++i ){
+ TNode t = parents[i];
+ if(!CandidateGenerator::isLegalCandidate(t)) continue;
+ if( addRep ) t = getEqualityEngine()->getRepresentative( t );
+ terms.insert(t);
+ addedTerm = true;
+ }
+ }
+ return addedTerm;
+}
+
+void EfficientEMatcher::registerPatternElementPairs2( Node pat, Ips& ips, PpIpsMap & pp_ips_map, NodePcDispatcher* npc ){
+ Assert( pat.hasOperator() );
+ //add information for possible pp-pair
+ ips.push_back( std::pair< Node, int >( pat.getOperator(), 0 ) ); //0 is just a dumb value
+
+ for( int i=0; i<(int)pat.getNumChildren(); i++ ){
+ if( pat[i].getKind()==INST_CONSTANT ){
+ ips.back().second = i;
+ pp_ips_map[ pat[i] ].push_back( make_pair( pat.getOperator(), Ips( ips ) ) );
+ }
+ }
+
+ for( int i=0; i<(int)pat.getNumChildren(); i++ ){
+ if( pat[i].getKind()==APPLY_UF ){
+ ips.back().second = i;
+ registerPatternElementPairs2( pat[i], ips, pp_ips_map, npc );
+ Debug("pattern-element-opt") << "Found pc-pair ( " << pat.getOperator() << ", " << pat[i].getOperator() << " )" << std::endl;
+ Debug("pattern-element-opt") << " Path = ";
+ outputIps( "pattern-element-opt", ips );
+ Debug("pattern-element-opt") << std::endl;
+ //pat.getOperator() and pat[i].getOperator() are a pc-pair
+ d_pc_pairs[ pat[i].getOperator() ][ pat.getOperator() ]
+ .push_back( make_pair(npc,Ips(ips)) );
+ }
+ }
+ ips.pop_back();
+}
+
+void EfficientEMatcher::registerPatternElementPairs( Node pat, PpIpsMap & pp_ips_map,
+ NodePcDispatcher* npc,
+ NodePpDispatcher* npp){
+ Ips ips;
+ registerPatternElementPairs2( pat, ips, pp_ips_map, npc );
+ for( PpIpsMap::iterator it = pp_ips_map.begin(); it != pp_ips_map.end(); ++it ){
+ // for each variable construct all the pp-pair
+ for( size_t j=0; j<it->second.size(); j++ ){
+ for( size_t k=j+1; k<it->second.size(); k++ ){
+ //found a pp-pair
+ Debug("pattern-element-opt") << "Found pp-pair ( " << it->second[j].first << ", " << it->second[k].first << " )" << std::endl;
+ Debug("pattern-element-opt") << " Paths = ";
+ outputIps( "pattern-element-opt", it->second[j].second );
+ Debug("pattern-element-opt") << " and ";
+ outputIps( "pattern-element-opt", it->second[k].second );
+ Debug("pattern-element-opt") << std::endl;
+ d_pp_pairs[ it->second[j].first ][ it->second[k].first ]
+ .push_back( make_triple( npp, it->second[j].second, it->second[k].second ));
+ }
+ }
+ }
+};
+
+void findPpSite(Node pat, EfficientEMatcher::Ips& ips, EfficientEMatcher::PpIpsMap & pp_ips_map){
+ Assert( pat.getKind()==APPLY_UF );
+ //add information for possible pp-pair
+
+ ips.push_back( make_pair( pat.getOperator(), 0) );
+ for( size_t i=0; i<pat.getNumChildren(); i++ ){
+ if( pat[i].getKind()==INST_CONSTANT ){
+ ips.back().second = i;
+ pp_ips_map[ pat[i] ].push_back( make_pair( pat.getOperator(), EfficientEMatcher::Ips( ips ) ) );
+ }
+ }
+
+ for( size_t i=0; i<pat.getNumChildren(); i++ ){
+ if( pat[i].getKind()==APPLY_UF ){
+ ips.back().second = i;
+ findPpSite( pat[i], ips, pp_ips_map );
+ }
+ }
+ ips.pop_back();
+}
+
+void EfficientEMatcher::combineMultiPpIpsMap(PpIpsMap & pp_ips_map, MultiPpIpsMap & multi_pp_ips_map,
+ EfficientHandler& eh, size_t index2,const std::vector<Node> & pats){
+ hash_map<size_t,NodePpDispatcher*> npps;
+ for( PpIpsMap::iterator it = pp_ips_map.begin(); it != pp_ips_map.end(); ++it ){
+ MultiPpIpsMap::iterator mit = multi_pp_ips_map.find(it->first);
+ if(mit == multi_pp_ips_map.end()) continue;
+ // for each variable construct all the pp-pair
+ // j the last pattern treated
+ for( std::vector< std::pair< Node, Ips > >::iterator j=it->second.begin(), jend = it->second.end() ;
+ j != jend; ++j){
+ // k one of the previous one
+ for( std::vector< triple< size_t, Node, Ips > >::iterator k=mit->second.begin(), kend = mit->second.end() ;
+ k != kend; ++k){
+ //found a pp-pair
+ Debug("pattern-element-opt") << "Found multi-pp-pair ( " << j->first
+ << ", " << k->second << " in "<< k->first
+ << " )" << std::endl;
+ Debug("pattern-element-opt") << " Paths = ";
+ outputIps( "pattern-element-opt", j->second );
+ Debug("pattern-element-opt") << " and ";
+ outputIps( "pattern-element-opt", k->third );
+ Debug("pattern-element-opt") << std::endl;
+ NodePpDispatcher* dispatcher;
+ hash_map<size_t,NodePpDispatcher*>::iterator inpp = npps.find(k->first);
+ if( inpp != npps.end() ) dispatcher = inpp->second;
+ else{
+ dispatcher = new NodePpDispatcher();
+#ifdef CVC4_DEBUG
+ dispatcher->pat1 = pats[index2];
+ dispatcher->pat2 = pats[k->first];
+#endif
+ dispatcher->addPpDispatcher(&eh,index2,k->first);
+ };
+ d_pp_pairs[ j->first ][ k->second ].push_back( make_triple( dispatcher, j->second, k->third ));
+ }
+ }
+ }
+
+ /** Put pp_ips_map to multi_pp_ips_map */
+ for( PpIpsMap::iterator it = pp_ips_map.begin(); it != pp_ips_map.end(); ++it ){
+ for( std::vector< std::pair< Node, Ips > >::iterator j=it->second.begin(), jend = it->second.end() ;
+ j != jend; ++j){
+ multi_pp_ips_map[it->first].push_back(make_triple(index2, j->first, j->second));
+ }
+ }
+
+}
+
+
+void EfficientEMatcher::registerEfficientHandler( EfficientHandler& handler,
+ const std::vector< Node > & pats ){
+ Assert(pats.size() > 0);
+
+ MultiPpIpsMap multi_pp_ips_map;
+ PpIpsMap pp_ips_map;
+ //In a multi-pattern Pattern that is only a variable are specials,
+ //if the variable appears in another pattern, it can be discarded.
+ //Otherwise new term of this term can be candidate. So we stock them
+ //here before adding them.
+ std::vector< size_t > patVars;
+
+ Debug("pattern-element-opt") << "Register patterns" << pats << std::endl;
+ for(size_t i = 0; i < pats.size(); ++i){
+ if( pats[i].getKind() == kind::INST_CONSTANT){
+ patVars.push_back(i);
+ continue;
+ }
+ //to complete
+ if( pats[i].getKind() == kind::NOT && pats[i][0].getKind() == kind::EQUAL){
+ Node cst = NodeManager::currentNM()->mkConst<bool>(false);
+ TNode op = pats[i][0].getOperator();
+ if(d_cc_pairs[op][cst] == NULL){
+ d_cc_pairs[op][cst] = new NodePcDispatcher();
+ }
+ d_cc_pairs[op][cst]->addPcDispatcher(&handler,i);
+ continue;
+ }
+ //end to complete
+ Debug("pattern-element-opt") << " Register candidate generator..." << pats[i] << std::endl;
+ /* Has the pattern already been seen */
+ if( d_pat_cand_gens.find( pats[i] )==d_pat_cand_gens.end() ){
+ NodePcDispatcher* npc = new NodePcDispatcher();
+ NodePpDispatcher* npp = new NodePpDispatcher();
+#ifdef CVC4_DEBUG
+ npc->pat = pats[i];
+ npp->pat1 = pats[i];
+ npp->pat2 = pats[i];
+#endif
+ d_pat_cand_gens[pats[i]] = make_pair(npc,npp);
+ registerPatternElementPairs( pats[i], pp_ips_map, npc, npp );
+ }else{
+ Ips ips;
+ findPpSite(pats[i],ips,pp_ips_map);
+ }
+ //Has the top operator already been seen */
+ TNode op = pats[i].getOperator();
+ d_pat_cand_gens[pats[i]].first->addPcDispatcher(&handler,i);
+ d_pat_cand_gens[pats[i]].second->addPpDispatcher(&handler,i,i);
+ d_cand_gens[op].addNewTermDispatcher(&handler,i);
+
+ combineMultiPpIpsMap(pp_ips_map,multi_pp_ips_map,handler,i,pats);
+
+ pp_ips_map.clear();
+ }
+
+ for(size_t i = 0; i < patVars.size(); ++i){
+ TNode var = pats[patVars[i]];
+ Assert( var.getKind() == kind::INST_CONSTANT );
+ if( multi_pp_ips_map.find(var) != multi_pp_ips_map.end() ){
+ //The variable appear in another pattern, skip it
+ continue;
+ };
+ d_cand_gen_types[var.getType()].addNewTermDispatcher(&handler,patVars[i]);
+ }
+
+ //take all terms from the uf term db and add to candidate generator
+ if( pats[0].getKind() == kind::INST_CONSTANT ){
+ TypeNode ty = pats[0].getType();
+ rrinst::CandidateGenerator* cg = new GenericCandidateGeneratorClasses(d_quantEngine);
+ cg->reset(Node::null());
+ TNode c;
+ SetNode ele;
+ while( !(c = cg->getNextCandidate()).isNull() ){
+ if( c.getType() == ty ) ele.insert(c);
+ }
+ if( !ele.empty() ){
+ // for(std::vector<Node>::iterator i = db->d_op_map[op].begin(), end = db->d_op_map[op].end(); i != end; ++i){
+ // if(CandidateGenerator::isLegalCandidate(*i)) ele.insert(*i);
+ // }
+ if(Debug.isOn("efficient-e-match-stats")){
+ Debug("efficient-e-match-stats") << "pattern " << pats << " initialized with " << ele.size() << " terms"<< std::endl;
+ }
+ handler.addMonoCandidate(ele, 0);
+ }
+
+ } else if( pats[0].getKind() == kind::NOT && pats[0][0].getKind() == kind::EQUAL){
+ Node cst = NodeManager::currentNM()->mkConst<bool>(false);
+ TNode op = pats[0][0].getOperator();
+ cst = getEqualityEngine()->getRepresentative(cst);
+ SetNode ele;
+ eq::EqClassIterator eqc_iter( cst, getEqualityEngine() );
+ while( !eqc_iter.isFinished() ){
+ Debug("efficient-e-match-debug") << "> look at " << (*eqc_iter)
+ << std::endl;
+ if( (*eqc_iter).hasOperator() && (*eqc_iter).getOperator() == op ) ele.insert(*eqc_iter);
+ eqc_iter++;
+ }
+ if( !ele.empty() ){
+ if(Debug.isOn("efficient-e-match-stats")){
+ Debug("efficient-e-match-stats") << "pattern " << pats << " initialized with " << ele.size() << " terms"<< std::endl;
+ }
+ handler.addMonoCandidate(ele, 0);
+ }
+
+ } else {
+ Node op = pats[0].getOperator();
+ TermDb* db = d_quantEngine->getTermDatabase();
+ if(db->d_op_map[op].begin() != db->d_op_map[op].end()){
+ SetNode ele;
+ // for(std::vector<Node>::iterator i = db->d_op_map[op].begin(), end = db->d_op_map[op].end(); i != end; ++i){
+ // if(CandidateGenerator::isLegalCandidate(*i)) ele.insert(*i);
+ // }
+ ele.insert(db->d_op_map[op].begin(), db->d_op_map[op].end());
+ if(Debug.isOn("efficient-e-match-stats")){
+ Debug("efficient-e-match-stats") << "pattern " << pats << " initialized with " << ele.size() << " terms"<< std::endl;
+ }
+ handler.addMonoCandidate(ele, 0);
+ }
+ }
+ Debug("efficient-e-match") << "Done." << std::endl;
+}
+
+void EfficientEMatcher::outputEqClass( const char* c, Node n ){
+ if( getEqualityEngine()->hasTerm( n ) ){
+ eq::EqClassIterator eqc_iter( getEqualityEngine()->getRepresentative( n ),
+ getEqualityEngine() );
+ bool firstTime = true;
+ while( !eqc_iter.isFinished() ){
+ if( !firstTime ){ Debug(c) << ", "; }
+ Debug(c) << (*eqc_iter);
+ firstTime = false;
+ eqc_iter++;
+ }
+ }else{
+ Debug(c) << n;
+ }
+}
+
+void EfficientEMatcher::outputIps( const char* c, Ips& ips ){
+ for( int i=0; i<(int)ips.size(); i++ ){
+ if( i>0 ){ Debug( c ) << "."; }
+ Debug( c ) << ips[i].first << "." << ips[i].second;
+ }
+}
+
+
+} /* namespace theory */
+} /* namespace cvc4 */
diff --git a/src/theory/rewriterules/efficient_e_matching.h b/src/theory/rewriterules/efficient_e_matching.h
index 2f0a07184..11c6b783e 100755..100644
--- a/src/theory/rewriterules/efficient_e_matching.h
+++ b/src/theory/rewriterules/efficient_e_matching.h
@@ -1,450 +1,450 @@
-/********************* */
-/*! \file efficient_e_matching.h
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: bobot
- ** Minor contributors (to current version): mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief efficient e-matching
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__EFFICIENT_E_MATCHING_H
-#define __CVC4__EFFICIENT_E_MATCHING_H
-
-#include "expr/node.h"
-#include "context/context.h"
-#include "context/context_mm.h"
-#include "context/cdchunk_list.h"
-
-#include "util/statistics_registry.h"
-#include "util/ntuple.h"
-#include "context/cdqueue.h"
-#include "context/cdo.h"
-
-#include "theory/uf/equality_engine.h"
-
-namespace CVC4 {
-namespace theory {
-
-class QuantifiersEngine;
-
-namespace quantifiers{
- class TermDb;
-}
-
-class EfficientEMatcher;
-class HandlerPcDispatcher;
-class HandlerPpDispatcher;
-
-typedef std::set<Node> SetNode;
-
-template<class T>
-class CleanUpPointer{
-public:
- inline void operator()(T** e){
- delete(*e);
- };
-};
-
-class EfficientHandler{
-public:
- typedef std::pair< Node, size_t > MonoCandidate;
- typedef std::pair< MonoCandidate, MonoCandidate > MultiCandidate;
- typedef std::pair< SetNode, size_t > MonoCandidates;
- typedef std::pair< MonoCandidates, MonoCandidates > MultiCandidates;
-private:
- /* Queue of candidates */
- typedef context::CDQueue< MonoCandidates *, CleanUpPointer<MonoCandidates> > MonoCandidatesQueue;
- typedef context::CDQueue< MultiCandidates *, CleanUpPointer<MultiCandidates> > MultiCandidatesQueue;
- MonoCandidatesQueue d_monoCandidates;
- typedef SetNode::iterator SetNodeIter;
- context::CDO<SetNodeIter> d_si;
- context::CDO<bool> d_mono_not_first;
-
- MonoCandidatesQueue d_monoCandidatesNewTerm;
- context::CDO<SetNodeIter> d_si_new_term;
- context::CDO<bool> d_mono_not_first_new_term;
-
-
- MultiCandidatesQueue d_multiCandidates;
- context::CDO<SetNodeIter> d_si1;
- context::CDO<SetNodeIter> d_si2;
- context::CDO<bool> d_multi_not_first;
-
-
- friend class EfficientEMatcher;
- friend class HandlerPcDispatcher;
- friend class HandlerPpDispatcher;
- friend class HandlerNewTermDispatcher;
-protected:
- void addMonoCandidate(SetNode & s, size_t index){
- Assert(!s.empty());
- d_monoCandidates.push(new MonoCandidates(s,index));
- }
- void addMonoCandidateNewTerm(SetNode & s, size_t index){
- Assert(!s.empty());
- d_monoCandidatesNewTerm.push(new MonoCandidates(s,index));
- }
- void addMultiCandidate(SetNode & s1, size_t index1, SetNode & s2, size_t index2){
- Assert(!s1.empty() && !s2.empty());
- d_multiCandidates.push(new MultiCandidates(MonoCandidates(s1,index1),
- MonoCandidates(s2,index2)));
- }
-public:
- EfficientHandler(context::Context * c):
- //false for d_mono_not_first beacause its the default constructor
- d_monoCandidates(c), d_si(c), d_mono_not_first(c,false),
- d_monoCandidatesNewTerm(c), d_si_new_term(c),
- d_mono_not_first_new_term(c,false),
- d_multiCandidates(c) , d_si1(c), d_si2(c), d_multi_not_first(c,false) {};
-
- bool getNextMonoCandidate(MonoCandidate & candidate){
- if(d_monoCandidates.empty()) return false;
- const MonoCandidates * front = d_monoCandidates.front();
- SetNodeIter si_tmp;
- if(!d_mono_not_first){
- Assert(front->first.begin() != front->first.end());
- d_mono_not_first = true;
- si_tmp=front->first.begin();
- }else{
- si_tmp = d_si;
- ++si_tmp;
- };
- if(si_tmp != front->first.end()){
- candidate.first = (*si_tmp);
- candidate.second = front->second;
- d_si = si_tmp;
- Debug("efficienthandler") << "Mono produces " << candidate.first << " for " << candidate.second << std::endl;
- return true;
- };
- d_monoCandidates.pop();
- d_mono_not_first = false;
- return getNextMonoCandidate(candidate);
- };
-
- bool getNextMonoCandidateNewTerm(MonoCandidate & candidate){
- if(d_monoCandidatesNewTerm.empty()) return false;
- const MonoCandidates * front = d_monoCandidatesNewTerm.front();
- SetNodeIter si_tmp;
- if(!d_mono_not_first_new_term){
- Assert(front->first.begin() != front->first.end());
- d_mono_not_first_new_term = true;
- si_tmp=front->first.begin();
- }else{
- si_tmp = d_si_new_term;
- ++si_tmp;
- };
- if(si_tmp != front->first.end()){
- candidate.first = (*si_tmp);
- candidate.second = front->second;
- d_si_new_term = si_tmp;
- Debug("efficienthandler") << "Mono produces " << candidate.first << " for " << candidate.second << std::endl;
- return true;
- };
- d_monoCandidatesNewTerm.pop();
- d_mono_not_first_new_term = false;
- return getNextMonoCandidateNewTerm(candidate);
- };
-
- bool getNextMultiCandidate(MultiCandidate & candidate){
- if(d_multiCandidates.empty()) return false;
- const MultiCandidates* front = d_multiCandidates.front();
- SetNodeIter si1_tmp;
- SetNodeIter si2_tmp;
- if(!d_multi_not_first){
- Assert(front->first.first.begin() != front->first.first.end());
- Assert(front->second.first.begin() != front->second.first.end());
- si1_tmp = front->first.first.begin();
- si2_tmp = front->second.first.begin();
- }else{
- si1_tmp = d_si1;
- si2_tmp = d_si2;
- ++si2_tmp;
- };
- if(si2_tmp != front->second.first.end()){
- candidate.first.first = *si1_tmp;
- candidate.first.second = front->first.second;
- candidate.second.first = *si2_tmp;
- candidate.second.second = front->second.second;
- if(!d_multi_not_first){d_si1 = si1_tmp; d_multi_not_first = true; };
- d_si2 = si2_tmp;
- Debug("efficienthandler") << "Multi1 produces "
- << candidate.first.first << " for "
- << candidate.first.second << " and "
- << candidate.second.first << " for "
- << candidate.second.second << " and "
- << std::endl;
- return true;
- }; // end of the second set
- si2_tmp = front->second.first.begin();
- ++si1_tmp;
- if(si1_tmp != front->first.first.end()){
- candidate.first.first = *si1_tmp;
- candidate.first.second = front->first.second;
- candidate.second.first = *si2_tmp;
- candidate.second.second = front->second.second;
- d_si1 = si1_tmp;
- d_si2 = si2_tmp;
- Debug("efficienthandler") << "Multi2 produces "
- << candidate.first.first << " for "
- << candidate.first.second << " and "
- << candidate.second.first << " for "
- << candidate.second.second << " and "
- << std::endl;
- return true;
- }; // end of the first set
- d_multiCandidates.pop();
- d_multi_not_first = false;
- return getNextMultiCandidate(candidate);
- }
-};
-
-class PcDispatcher{
-public:
- virtual ~PcDispatcher(){};
- /* Send the node to the dispatcher */
- virtual void send(SetNode & s) = 0;
-};
-
-
-class HandlerPcDispatcher: public PcDispatcher{
- EfficientHandler* d_handler;
- size_t d_index;
-public:
- HandlerPcDispatcher(EfficientHandler* handler, size_t index):
- d_handler(handler), d_index(index) {};
- void send(SetNode & s){
- d_handler->addMonoCandidate(s,d_index);
- }
-};
-
-
-/** All the dispatcher that correspond to this node */
-class NodePcDispatcher: public PcDispatcher{
-#ifdef CVC4_DEBUG
-public:
- Node pat;
-#endif/* CVC4_DEBUG*/
-private:
- std::vector<HandlerPcDispatcher> d_dis;
-public:
- void send(SetNode & s){
- Assert(!s.empty());
- for(std::vector<HandlerPcDispatcher>::iterator i = d_dis.begin(), end = d_dis.end();
- i != end; ++i){
- (*i).send(s);
- }
- }
- void addPcDispatcher(EfficientHandler* handler, size_t index){
- d_dis.push_back(HandlerPcDispatcher(handler,index));
- }
-};
-
-
-class HandlerNewTermDispatcher: public PcDispatcher{
- EfficientHandler* d_handler;
- size_t d_index;
-public:
- HandlerNewTermDispatcher(EfficientHandler* handler, size_t index):
- d_handler(handler), d_index(index) {};
- void send(SetNode & s){
- d_handler->addMonoCandidateNewTerm(s,d_index);
- }
-};
-
-/** All the dispatcher that correspond to this node */
-class NodeNewTermDispatcher: public PcDispatcher{
-#ifdef CVC4_DEBUG
-public:
- Node pat;
-#endif/* CVC4_DEBUG*/
-private:
- std::vector<HandlerNewTermDispatcher> d_dis;
-public:
- void send(SetNode & s){
- Assert(!s.empty());
- for(std::vector<HandlerNewTermDispatcher>::iterator i = d_dis.begin(), end = d_dis.end();
- i != end; ++i){
- (*i).send(s);
- }
- }
- void addNewTermDispatcher(EfficientHandler* handler, size_t index){
- d_dis.push_back(HandlerNewTermDispatcher(handler,index));
- }
-};
-
-class PpDispatcher{
-public:
- virtual ~PpDispatcher(){};
- /* Send the node to the dispatcher */
- virtual void send(SetNode & s1, SetNode & s2, SetNode & sinter) = 0;
-};
-
-
-class HandlerPpDispatcher: public PpDispatcher{
- EfficientHandler* d_handler;
- size_t d_index1;
- size_t d_index2;
-public:
- HandlerPpDispatcher(EfficientHandler* handler, size_t index1, size_t index2):
- d_handler(handler), d_index1(index1), d_index2(index2) {};
- void send(SetNode & s1, SetNode & s2, SetNode & sinter){
- if(d_index1 == d_index2){
- if(!sinter.empty())
- d_handler->addMonoCandidate(sinter,d_index1);
- }else{
- d_handler->addMultiCandidate(s1,d_index1,s2,d_index2);
- }
- }
-};
-
-
-/** All the dispatcher that correspond to this node */
-class NodePpDispatcher: public PpDispatcher{
-#ifdef CVC4_DEBUG
-public:
- Node pat1;
- Node pat2;
-#endif/* CVC4_DEBUG */
-private:
- std::vector<HandlerPpDispatcher> d_dis;
- void send(SetNode & s1, SetNode & s2, SetNode & inter){
- for(std::vector<HandlerPpDispatcher>::iterator i = d_dis.begin(), end = d_dis.end();
- i != end; ++i){
- (*i).send(s1,s2,inter);
- }
- }
-public:
- void send(SetNode & s1, SetNode & s2){
- // can be done in HandlerPpDispatcher lazily
- Assert(!s1.empty() && !s2.empty());
- SetNode inter;
- std::set_intersection( s1.begin(), s1.end(), s2.begin(), s2.end(),
- std::inserter( inter, inter.begin() ) );
- send(s1,s2,inter);
- }
- void addPpDispatcher(EfficientHandler* handler, size_t index1, size_t index2){
- d_dis.push_back(HandlerPpDispatcher(handler,index1,index2));
- }
-};
-
-//equivalence class info
-class EqClassInfo
-{
-public:
- typedef context::CDHashMap<Node, bool, NodeHashFunction> BoolMap;
- typedef context::CDChunkList<Node> NodeList;
-public:
- //a list of operators that occur as top symbols in this equivalence class
- // Efficient E-Matching for SMT Solvers: "funs"
- BoolMap d_funs;
- //a list of operators f for which a term of the form f( ... t ... ) exists
- // Efficient E-Matching for SMT Solvers: "pfuns"
- BoolMap d_pfuns;
- //a list of equivalence classes that are disequal
- BoolMap d_disequal;
-public:
- EqClassInfo( context::Context* c );
- ~EqClassInfo(){}
- //set member
- void setMember( Node n, quantifiers::TermDb* db );
- //has function "funs"
- bool hasFunction( Node op );
- //has parent "pfuns"
- bool hasParent( Node op );
- //merge with another eq class info
- void merge( EqClassInfo* eci );
-};
-
-class EfficientEMatcher{
-protected:
- /** reference to the quantifiers engine */
- QuantifiersEngine* d_quantEngine;
-public:
- EfficientEMatcher(CVC4::theory::QuantifiersEngine* qe);
- ~EfficientEMatcher() {
- for(std::map< Node, std::pair<NodePcDispatcher*, NodePpDispatcher*> >::iterator
- i = d_pat_cand_gens.begin(), end = d_pat_cand_gens.end();
- i != end; i++){
- delete(i->second.first);
- delete(i->second.second);
- }
- }
- /** get equality engine we are using */
- eq::EqualityEngine* getEqualityEngine();
-private:
- //information for each equivalence class
- std::map< Node, EqClassInfo* > d_eqc_ops;
-public:
- /** new node */
- void newEqClass( TNode n );
- /** merge */
- void merge( TNode a, TNode b );
- /** assert terms are disequal */
- void assertDisequal( TNode a, TNode b, TNode reason );
- /** get equivalence class info */
- EqClassInfo* getEquivalenceClassInfo( Node n );
- EqClassInfo* getOrCreateEquivalenceClassInfo( Node n );
- typedef std::vector< std::pair< Node, int > > Ips;
- typedef std::map< Node, std::vector< std::pair< Node, Ips > > > PpIpsMap;
- typedef std::map< Node, std::vector< triple< size_t, Node, Ips > > > MultiPpIpsMap;
-private:
- /** Parent/Child Pairs (for efficient E-matching)
- So, for example, if we have the pattern f( g( x ) ), then d_pc_pairs[g][f][f( g( x ) )] = { f.0 }.
- */
- std::map< Node, std::map< Node, std::vector< std::pair< NodePcDispatcher*, Ips > > > > d_pc_pairs;
- /** Parent/Parent Pairs (for efficient E-matching) */
- std::map< Node, std::map< Node, std::vector< triple< NodePpDispatcher*, Ips, Ips > > > > d_pp_pairs;
- /** Constants/Child Pairs
- So, for example, if we have the pattern f( x ) = c, then d_pc_pairs[f][c] = ..., pcdispatcher, ...
- */
- //TODO constant in pattern can use the same thing just add an Ips
- std::map< Node, std::map< Node, NodePcDispatcher* > > d_cc_pairs;
- /** list of all candidate generators for each operator */
- std::map< Node, NodeNewTermDispatcher > d_cand_gens;
- /** list of all candidate generators for each type */
- std::map< TypeNode, NodeNewTermDispatcher > d_cand_gen_types;
- /** map from patterns to candidate generators */
- std::map< Node, std::pair<NodePcDispatcher*, NodePpDispatcher*> > d_pat_cand_gens;
- /** helper functions */
- void registerPatternElementPairs2( Node pat, Ips& ips,
- PpIpsMap & pp_ips_map, NodePcDispatcher* npc);
- void registerPatternElementPairs( Node pat, PpIpsMap & pp_ips_map,
- NodePcDispatcher* npc, NodePpDispatcher* npp);
- /** find the pp-pair between pattern inside multi-pattern*/
- void combineMultiPpIpsMap(PpIpsMap & pp_ips_map, MultiPpIpsMap & multi_pp_ips_map,
- EfficientHandler& eh, size_t index2,
- const std::vector<Node> & pats); //pats for debug
- /** compute candidates for pc pairs */
- void computeCandidatesPcPairs( Node a, EqClassInfo*, Node b, EqClassInfo* );
- /** compute candidates for pp pairs */
- void computeCandidatesPpPairs( Node a, EqClassInfo*, Node b, EqClassInfo* );
- /** compute candidates for cc pairs */
- void computeCandidatesConstants( Node a, EqClassInfo*, Node b, EqClassInfo* );
- /** collect terms based on inverted path string */
- void collectTermsIps( Ips& ips, SetNode& terms, int index);
- bool collectParentsTermsIps( Node n, Node f, int arg, SetNode& terms, bool addRep, bool modEq = true );
-public:
- void collectTermsIps( Ips& ips, SetNode& terms);
-public:
- void registerEfficientHandler( EfficientHandler& eh, const std::vector<Node> & pat );
-public:
- void newTerms(SetNode& s);
-public:
- /** output eq class */
- void outputEqClass( const char* c, Node n );
- /** output inverted path string */
- void outputIps( const char* c, Ips& ips );
-};/* class EfficientEMatcher */
-
-
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
-
-#endif /* __CVC4__EFFICIENT_E_MATCHING_H */
+/********************* */
+/*! \file efficient_e_matching.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief efficient e-matching
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__EFFICIENT_E_MATCHING_H
+#define __CVC4__EFFICIENT_E_MATCHING_H
+
+#include "expr/node.h"
+#include "context/context.h"
+#include "context/context_mm.h"
+#include "context/cdchunk_list.h"
+
+#include "util/statistics_registry.h"
+#include "util/ntuple.h"
+#include "context/cdqueue.h"
+#include "context/cdo.h"
+
+#include "theory/uf/equality_engine.h"
+
+namespace CVC4 {
+namespace theory {
+
+class QuantifiersEngine;
+
+namespace quantifiers{
+ class TermDb;
+}
+
+class EfficientEMatcher;
+class HandlerPcDispatcher;
+class HandlerPpDispatcher;
+
+typedef std::set<Node> SetNode;
+
+template<class T>
+class CleanUpPointer{
+public:
+ inline void operator()(T** e){
+ delete(*e);
+ };
+};
+
+class EfficientHandler{
+public:
+ typedef std::pair< Node, size_t > MonoCandidate;
+ typedef std::pair< MonoCandidate, MonoCandidate > MultiCandidate;
+ typedef std::pair< SetNode, size_t > MonoCandidates;
+ typedef std::pair< MonoCandidates, MonoCandidates > MultiCandidates;
+private:
+ /* Queue of candidates */
+ typedef context::CDQueue< MonoCandidates *, CleanUpPointer<MonoCandidates> > MonoCandidatesQueue;
+ typedef context::CDQueue< MultiCandidates *, CleanUpPointer<MultiCandidates> > MultiCandidatesQueue;
+ MonoCandidatesQueue d_monoCandidates;
+ typedef SetNode::iterator SetNodeIter;
+ context::CDO<SetNodeIter> d_si;
+ context::CDO<bool> d_mono_not_first;
+
+ MonoCandidatesQueue d_monoCandidatesNewTerm;
+ context::CDO<SetNodeIter> d_si_new_term;
+ context::CDO<bool> d_mono_not_first_new_term;
+
+
+ MultiCandidatesQueue d_multiCandidates;
+ context::CDO<SetNodeIter> d_si1;
+ context::CDO<SetNodeIter> d_si2;
+ context::CDO<bool> d_multi_not_first;
+
+
+ friend class EfficientEMatcher;
+ friend class HandlerPcDispatcher;
+ friend class HandlerPpDispatcher;
+ friend class HandlerNewTermDispatcher;
+protected:
+ void addMonoCandidate(SetNode & s, size_t index){
+ Assert(!s.empty());
+ d_monoCandidates.push(new MonoCandidates(s,index));
+ }
+ void addMonoCandidateNewTerm(SetNode & s, size_t index){
+ Assert(!s.empty());
+ d_monoCandidatesNewTerm.push(new MonoCandidates(s,index));
+ }
+ void addMultiCandidate(SetNode & s1, size_t index1, SetNode & s2, size_t index2){
+ Assert(!s1.empty() && !s2.empty());
+ d_multiCandidates.push(new MultiCandidates(MonoCandidates(s1,index1),
+ MonoCandidates(s2,index2)));
+ }
+public:
+ EfficientHandler(context::Context * c):
+ //false for d_mono_not_first beacause its the default constructor
+ d_monoCandidates(c), d_si(c), d_mono_not_first(c,false),
+ d_monoCandidatesNewTerm(c), d_si_new_term(c),
+ d_mono_not_first_new_term(c,false),
+ d_multiCandidates(c) , d_si1(c), d_si2(c), d_multi_not_first(c,false) {};
+
+ bool getNextMonoCandidate(MonoCandidate & candidate){
+ if(d_monoCandidates.empty()) return false;
+ const MonoCandidates * front = d_monoCandidates.front();
+ SetNodeIter si_tmp;
+ if(!d_mono_not_first){
+ Assert(front->first.begin() != front->first.end());
+ d_mono_not_first = true;
+ si_tmp=front->first.begin();
+ }else{
+ si_tmp = d_si;
+ ++si_tmp;
+ };
+ if(si_tmp != front->first.end()){
+ candidate.first = (*si_tmp);
+ candidate.second = front->second;
+ d_si = si_tmp;
+ Debug("efficienthandler") << "Mono produces " << candidate.first << " for " << candidate.second << std::endl;
+ return true;
+ };
+ d_monoCandidates.pop();
+ d_mono_not_first = false;
+ return getNextMonoCandidate(candidate);
+ };
+
+ bool getNextMonoCandidateNewTerm(MonoCandidate & candidate){
+ if(d_monoCandidatesNewTerm.empty()) return false;
+ const MonoCandidates * front = d_monoCandidatesNewTerm.front();
+ SetNodeIter si_tmp;
+ if(!d_mono_not_first_new_term){
+ Assert(front->first.begin() != front->first.end());
+ d_mono_not_first_new_term = true;
+ si_tmp=front->first.begin();
+ }else{
+ si_tmp = d_si_new_term;
+ ++si_tmp;
+ };
+ if(si_tmp != front->first.end()){
+ candidate.first = (*si_tmp);
+ candidate.second = front->second;
+ d_si_new_term = si_tmp;
+ Debug("efficienthandler") << "Mono produces " << candidate.first << " for " << candidate.second << std::endl;
+ return true;
+ };
+ d_monoCandidatesNewTerm.pop();
+ d_mono_not_first_new_term = false;
+ return getNextMonoCandidateNewTerm(candidate);
+ };
+
+ bool getNextMultiCandidate(MultiCandidate & candidate){
+ if(d_multiCandidates.empty()) return false;
+ const MultiCandidates* front = d_multiCandidates.front();
+ SetNodeIter si1_tmp;
+ SetNodeIter si2_tmp;
+ if(!d_multi_not_first){
+ Assert(front->first.first.begin() != front->first.first.end());
+ Assert(front->second.first.begin() != front->second.first.end());
+ si1_tmp = front->first.first.begin();
+ si2_tmp = front->second.first.begin();
+ }else{
+ si1_tmp = d_si1;
+ si2_tmp = d_si2;
+ ++si2_tmp;
+ };
+ if(si2_tmp != front->second.first.end()){
+ candidate.first.first = *si1_tmp;
+ candidate.first.second = front->first.second;
+ candidate.second.first = *si2_tmp;
+ candidate.second.second = front->second.second;
+ if(!d_multi_not_first){d_si1 = si1_tmp; d_multi_not_first = true; };
+ d_si2 = si2_tmp;
+ Debug("efficienthandler") << "Multi1 produces "
+ << candidate.first.first << " for "
+ << candidate.first.second << " and "
+ << candidate.second.first << " for "
+ << candidate.second.second << " and "
+ << std::endl;
+ return true;
+ }; // end of the second set
+ si2_tmp = front->second.first.begin();
+ ++si1_tmp;
+ if(si1_tmp != front->first.first.end()){
+ candidate.first.first = *si1_tmp;
+ candidate.first.second = front->first.second;
+ candidate.second.first = *si2_tmp;
+ candidate.second.second = front->second.second;
+ d_si1 = si1_tmp;
+ d_si2 = si2_tmp;
+ Debug("efficienthandler") << "Multi2 produces "
+ << candidate.first.first << " for "
+ << candidate.first.second << " and "
+ << candidate.second.first << " for "
+ << candidate.second.second << " and "
+ << std::endl;
+ return true;
+ }; // end of the first set
+ d_multiCandidates.pop();
+ d_multi_not_first = false;
+ return getNextMultiCandidate(candidate);
+ }
+};
+
+class PcDispatcher{
+public:
+ virtual ~PcDispatcher(){};
+ /* Send the node to the dispatcher */
+ virtual void send(SetNode & s) = 0;
+};
+
+
+class HandlerPcDispatcher: public PcDispatcher{
+ EfficientHandler* d_handler;
+ size_t d_index;
+public:
+ HandlerPcDispatcher(EfficientHandler* handler, size_t index):
+ d_handler(handler), d_index(index) {};
+ void send(SetNode & s){
+ d_handler->addMonoCandidate(s,d_index);
+ }
+};
+
+
+/** All the dispatcher that correspond to this node */
+class NodePcDispatcher: public PcDispatcher{
+#ifdef CVC4_DEBUG
+public:
+ Node pat;
+#endif/* CVC4_DEBUG*/
+private:
+ std::vector<HandlerPcDispatcher> d_dis;
+public:
+ void send(SetNode & s){
+ Assert(!s.empty());
+ for(std::vector<HandlerPcDispatcher>::iterator i = d_dis.begin(), end = d_dis.end();
+ i != end; ++i){
+ (*i).send(s);
+ }
+ }
+ void addPcDispatcher(EfficientHandler* handler, size_t index){
+ d_dis.push_back(HandlerPcDispatcher(handler,index));
+ }
+};
+
+
+class HandlerNewTermDispatcher: public PcDispatcher{
+ EfficientHandler* d_handler;
+ size_t d_index;
+public:
+ HandlerNewTermDispatcher(EfficientHandler* handler, size_t index):
+ d_handler(handler), d_index(index) {};
+ void send(SetNode & s){
+ d_handler->addMonoCandidateNewTerm(s,d_index);
+ }
+};
+
+/** All the dispatcher that correspond to this node */
+class NodeNewTermDispatcher: public PcDispatcher{
+#ifdef CVC4_DEBUG
+public:
+ Node pat;
+#endif/* CVC4_DEBUG*/
+private:
+ std::vector<HandlerNewTermDispatcher> d_dis;
+public:
+ void send(SetNode & s){
+ Assert(!s.empty());
+ for(std::vector<HandlerNewTermDispatcher>::iterator i = d_dis.begin(), end = d_dis.end();
+ i != end; ++i){
+ (*i).send(s);
+ }
+ }
+ void addNewTermDispatcher(EfficientHandler* handler, size_t index){
+ d_dis.push_back(HandlerNewTermDispatcher(handler,index));
+ }
+};
+
+class PpDispatcher{
+public:
+ virtual ~PpDispatcher(){};
+ /* Send the node to the dispatcher */
+ virtual void send(SetNode & s1, SetNode & s2, SetNode & sinter) = 0;
+};
+
+
+class HandlerPpDispatcher: public PpDispatcher{
+ EfficientHandler* d_handler;
+ size_t d_index1;
+ size_t d_index2;
+public:
+ HandlerPpDispatcher(EfficientHandler* handler, size_t index1, size_t index2):
+ d_handler(handler), d_index1(index1), d_index2(index2) {};
+ void send(SetNode & s1, SetNode & s2, SetNode & sinter){
+ if(d_index1 == d_index2){
+ if(!sinter.empty())
+ d_handler->addMonoCandidate(sinter,d_index1);
+ }else{
+ d_handler->addMultiCandidate(s1,d_index1,s2,d_index2);
+ }
+ }
+};
+
+
+/** All the dispatcher that correspond to this node */
+class NodePpDispatcher: public PpDispatcher{
+#ifdef CVC4_DEBUG
+public:
+ Node pat1;
+ Node pat2;
+#endif/* CVC4_DEBUG */
+private:
+ std::vector<HandlerPpDispatcher> d_dis;
+ void send(SetNode & s1, SetNode & s2, SetNode & inter){
+ for(std::vector<HandlerPpDispatcher>::iterator i = d_dis.begin(), end = d_dis.end();
+ i != end; ++i){
+ (*i).send(s1,s2,inter);
+ }
+ }
+public:
+ void send(SetNode & s1, SetNode & s2){
+ // can be done in HandlerPpDispatcher lazily
+ Assert(!s1.empty() && !s2.empty());
+ SetNode inter;
+ std::set_intersection( s1.begin(), s1.end(), s2.begin(), s2.end(),
+ std::inserter( inter, inter.begin() ) );
+ send(s1,s2,inter);
+ }
+ void addPpDispatcher(EfficientHandler* handler, size_t index1, size_t index2){
+ d_dis.push_back(HandlerPpDispatcher(handler,index1,index2));
+ }
+};
+
+//equivalence class info
+class EqClassInfo
+{
+public:
+ typedef context::CDHashMap<Node, bool, NodeHashFunction> BoolMap;
+ typedef context::CDChunkList<Node> NodeList;
+public:
+ //a list of operators that occur as top symbols in this equivalence class
+ // Efficient E-Matching for SMT Solvers: "funs"
+ BoolMap d_funs;
+ //a list of operators f for which a term of the form f( ... t ... ) exists
+ // Efficient E-Matching for SMT Solvers: "pfuns"
+ BoolMap d_pfuns;
+ //a list of equivalence classes that are disequal
+ BoolMap d_disequal;
+public:
+ EqClassInfo( context::Context* c );
+ ~EqClassInfo(){}
+ //set member
+ void setMember( Node n, quantifiers::TermDb* db );
+ //has function "funs"
+ bool hasFunction( Node op );
+ //has parent "pfuns"
+ bool hasParent( Node op );
+ //merge with another eq class info
+ void merge( EqClassInfo* eci );
+};
+
+class EfficientEMatcher{
+protected:
+ /** reference to the quantifiers engine */
+ QuantifiersEngine* d_quantEngine;
+public:
+ EfficientEMatcher(CVC4::theory::QuantifiersEngine* qe);
+ ~EfficientEMatcher() {
+ for(std::map< Node, std::pair<NodePcDispatcher*, NodePpDispatcher*> >::iterator
+ i = d_pat_cand_gens.begin(), end = d_pat_cand_gens.end();
+ i != end; i++){
+ delete(i->second.first);
+ delete(i->second.second);
+ }
+ }
+ /** get equality engine we are using */
+ eq::EqualityEngine* getEqualityEngine();
+private:
+ //information for each equivalence class
+ std::map< Node, EqClassInfo* > d_eqc_ops;
+public:
+ /** new node */
+ void newEqClass( TNode n );
+ /** merge */
+ void merge( TNode a, TNode b );
+ /** assert terms are disequal */
+ void assertDisequal( TNode a, TNode b, TNode reason );
+ /** get equivalence class info */
+ EqClassInfo* getEquivalenceClassInfo( Node n );
+ EqClassInfo* getOrCreateEquivalenceClassInfo( Node n );
+ typedef std::vector< std::pair< Node, int > > Ips;
+ typedef std::map< Node, std::vector< std::pair< Node, Ips > > > PpIpsMap;
+ typedef std::map< Node, std::vector< triple< size_t, Node, Ips > > > MultiPpIpsMap;
+private:
+ /** Parent/Child Pairs (for efficient E-matching)
+ So, for example, if we have the pattern f( g( x ) ), then d_pc_pairs[g][f][f( g( x ) )] = { f.0 }.
+ */
+ std::map< Node, std::map< Node, std::vector< std::pair< NodePcDispatcher*, Ips > > > > d_pc_pairs;
+ /** Parent/Parent Pairs (for efficient E-matching) */
+ std::map< Node, std::map< Node, std::vector< triple< NodePpDispatcher*, Ips, Ips > > > > d_pp_pairs;
+ /** Constants/Child Pairs
+ So, for example, if we have the pattern f( x ) = c, then d_pc_pairs[f][c] = ..., pcdispatcher, ...
+ */
+ //TODO constant in pattern can use the same thing just add an Ips
+ std::map< Node, std::map< Node, NodePcDispatcher* > > d_cc_pairs;
+ /** list of all candidate generators for each operator */
+ std::map< Node, NodeNewTermDispatcher > d_cand_gens;
+ /** list of all candidate generators for each type */
+ std::map< TypeNode, NodeNewTermDispatcher > d_cand_gen_types;
+ /** map from patterns to candidate generators */
+ std::map< Node, std::pair<NodePcDispatcher*, NodePpDispatcher*> > d_pat_cand_gens;
+ /** helper functions */
+ void registerPatternElementPairs2( Node pat, Ips& ips,
+ PpIpsMap & pp_ips_map, NodePcDispatcher* npc);
+ void registerPatternElementPairs( Node pat, PpIpsMap & pp_ips_map,
+ NodePcDispatcher* npc, NodePpDispatcher* npp);
+ /** find the pp-pair between pattern inside multi-pattern*/
+ void combineMultiPpIpsMap(PpIpsMap & pp_ips_map, MultiPpIpsMap & multi_pp_ips_map,
+ EfficientHandler& eh, size_t index2,
+ const std::vector<Node> & pats); //pats for debug
+ /** compute candidates for pc pairs */
+ void computeCandidatesPcPairs( Node a, EqClassInfo*, Node b, EqClassInfo* );
+ /** compute candidates for pp pairs */
+ void computeCandidatesPpPairs( Node a, EqClassInfo*, Node b, EqClassInfo* );
+ /** compute candidates for cc pairs */
+ void computeCandidatesConstants( Node a, EqClassInfo*, Node b, EqClassInfo* );
+ /** collect terms based on inverted path string */
+ void collectTermsIps( Ips& ips, SetNode& terms, int index);
+ bool collectParentsTermsIps( Node n, Node f, int arg, SetNode& terms, bool addRep, bool modEq = true );
+public:
+ void collectTermsIps( Ips& ips, SetNode& terms);
+public:
+ void registerEfficientHandler( EfficientHandler& eh, const std::vector<Node> & pat );
+public:
+ void newTerms(SetNode& s);
+public:
+ /** output eq class */
+ void outputEqClass( const char* c, Node n );
+ /** output inverted path string */
+ void outputIps( const char* c, Ips& ips );
+};/* class EfficientEMatcher */
+
+
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
+
+#endif /* __CVC4__EFFICIENT_E_MATCHING_H */
diff --git a/src/theory/rewriterules/rr_candidate_generator.h b/src/theory/rewriterules/rr_candidate_generator.h
index 97c710219..d12c67f6a 100644
--- a/src/theory/rewriterules/rr_candidate_generator.h
+++ b/src/theory/rewriterules/rr_candidate_generator.h
@@ -32,7 +32,7 @@ typedef CVC4::theory::rrinst::CandidateGenerator CandidateGenerator;
//New CandidateGenerator. They have a simpler semantic than the old one
-// Just iterate amoung the equivalence classes
+// Just iterate among the equivalence classes
// node::Null() must be given to reset
class CandidateGeneratorTheoryEeClasses : public CandidateGenerator{
private:
@@ -54,7 +54,7 @@ public:
};
};
-// Just iterate amoung the equivalence class of the given node
+// Just iterate among the equivalence class of the given node
// node::Null() *can't* be given to reset
class CandidateGeneratorTheoryEeClass : public CandidateGenerator{
private:
diff --git a/src/theory/rewriterules/rr_inst_match.h b/src/theory/rewriterules/rr_inst_match.h
index 63728a95b..636a4dbc1 100644
--- a/src/theory/rewriterules/rr_inst_match.h
+++ b/src/theory/rewriterules/rr_inst_match.h
@@ -180,7 +180,7 @@ public:
/** If reset, or getNextMatch return false they remove from the
InstMatch the binding that they have previously created */
- /** virtual Matcher in order to have definned behavior */
+ /** virtual Matcher in order to have defined behavior */
virtual ~Matcher(){};
};
@@ -195,7 +195,7 @@ private:
std::vector< triple< Matcher*, size_t, EqualityQuery* > > d_childrens;
/** the variable that have been set by this matcher (during its own reset) */
std::vector< TNode > d_binded; /* TNode because the variable are already in d_pattern */
- /** the representant of the argument of the term given by the last reset */
+ /** the representative of the argument of the term given by the last reset */
std::vector< Node > d_reps;
public:
/** The pattern we are producing matches for */
@@ -250,7 +250,7 @@ public:
PatsMatcher* mkPatterns( std::vector< Node > pat, QuantifiersEngine* qe );
PatsMatcher* mkPatternsEfficient( std::vector< Node > pat, QuantifiersEngine* qe );
-/** return true if whatever Node is subsituted for the variables the
+/** return true if whatever Node is substituted for the variables the
given Node can't match the pattern */
bool nonunifiable( TNode t, TNode pat, const std::vector<Node> & vars);
diff --git a/src/theory/rewriterules/rr_trigger.h b/src/theory/rewriterules/rr_trigger.h
index 7be5d1507..f11d6ed66 100644
--- a/src/theory/rewriterules/rr_trigger.h
+++ b/src/theory/rewriterules/rr_trigger.h
@@ -100,6 +100,7 @@ public:
static inline bool isAtomicTrigger( TNode n ){
return
n.getKind()==kind::APPLY_UF ||
+ n.getKind() == kind::APPLY_CONSTRUCTOR ||
n.getKind()==kind::SELECT ||
n.getKind()==kind::STORE;
}
diff --git a/src/theory/substitutions.cpp b/src/theory/substitutions.cpp
index 0cc64e403..8858cc34b 100644
--- a/src/theory/substitutions.cpp
+++ b/src/theory/substitutions.cpp
@@ -27,12 +27,11 @@ struct substitution_stack_element {
bool children_added;
substitution_stack_element(TNode node)
: node(node), children_added(false) {}
-};
-
+};/* struct substitution_stack_element */
Node SubstitutionMap::internalSubstitute(TNode t) {
- Debug("substitution::internal") << "SubstitutionMap::internalSubstitute(" << t << ")" << std::endl;
+ Debug("substitution::internal") << "SubstitutionMap::internalSubstitute(" << t << ")" << endl;
if (d_substitutions.empty()) {
return t;
@@ -48,7 +47,7 @@ Node SubstitutionMap::internalSubstitute(TNode t) {
substitution_stack_element& stackHead = toVisit.back();
TNode current = stackHead.node;
- Debug("substitution::internal") << "SubstitutionMap::internalSubstitute(" << t << "): processing " << current << std::endl;
+ Debug("substitution::internal") << "SubstitutionMap::internalSubstitute(" << t << "): processing " << current << endl;
// If node already in the cache we're done, pop from the stack
NodeCache::iterator find = d_substitutionCache.find(current);
@@ -57,6 +56,14 @@ Node SubstitutionMap::internalSubstitute(TNode t) {
continue;
}
+ if (!d_substituteUnderQuantifiers &&
+ (current.getKind() == kind::FORALL || current.getKind() == kind::EXISTS)) {
+ Debug("substitution::internal") << "--not substituting under quantifier" << endl;
+ d_substitutionCache[current] = current;
+ toVisit.pop_back();
+ continue;
+ }
+
NodeMap::iterator find2 = d_substitutions.find(current);
if (find2 != d_substitutions.end()) {
Node rhs = (*find2).second;
@@ -98,7 +105,7 @@ Node SubstitutionMap::internalSubstitute(TNode t) {
}
}
}
- Debug("substitution::internal") << "SubstitutionMap::internalSubstitute(" << t << "): setting " << current << " -> " << result << std::endl;
+ Debug("substitution::internal") << "SubstitutionMap::internalSubstitute(" << t << "): setting " << current << " -> " << result << endl;
d_substitutionCache[current] = result;
toVisit.pop_back();
} else {
@@ -123,7 +130,7 @@ Node SubstitutionMap::internalSubstitute(TNode t) {
}
} else {
// No children, so we're done
- Debug("substitution::internal") << "SubstitutionMap::internalSubstitute(" << t << "): setting " << current << " -> " << current << std::endl;
+ Debug("substitution::internal") << "SubstitutionMap::internalSubstitute(" << t << "): setting " << current << " -> " << current << endl;
d_substitutionCache[current] = current;
toVisit.pop_back();
}
@@ -132,7 +139,7 @@ Node SubstitutionMap::internalSubstitute(TNode t) {
// Return the substituted version
return d_substitutionCache[t];
-}
+}/* SubstitutionMap::internalSubstitute() */
/*
@@ -258,7 +265,7 @@ void SubstitutionMap::processWorklist(vector<pair<Node, Node> >& equalities, boo
void SubstitutionMap::addSubstitution(TNode x, TNode t, bool invalidateCache)
{
- Debug("substitution") << "SubstitutionMap::addSubstitution(" << x << ", " << t << ")" << std::endl;
+ Debug("substitution") << "SubstitutionMap::addSubstitution(" << x << ", " << t << ")" << endl;
Assert(d_substitutions.find(x) == d_substitutions.end());
// this causes a later assert-fail (the rhs != current one, above) anyway
@@ -280,32 +287,32 @@ static bool check(TNode node, const SubstitutionMap::NodeMap& substitutions) CVC
static bool check(TNode node, const SubstitutionMap::NodeMap& substitutions) {
SubstitutionMap::NodeMap::const_iterator it = substitutions.begin();
SubstitutionMap::NodeMap::const_iterator it_end = substitutions.end();
- Debug("substitution") << "checking " << node << std::endl;
+ Debug("substitution") << "checking " << node << endl;
for (; it != it_end; ++ it) {
- Debug("substitution") << "-- hasSubterm( " << (*it).first << " ) ?" << std::endl;
+ Debug("substitution") << "-- hasSubterm( " << (*it).first << " ) ?" << endl;
if (node.hasSubterm((*it).first)) {
- Debug("substitution") << "-- FAIL" << std::endl;
+ Debug("substitution") << "-- FAIL" << endl;
return false;
}
}
- Debug("substitution") << "-- SUCCEED" << std::endl;
+ Debug("substitution") << "-- SUCCEED" << endl;
return true;
}
Node SubstitutionMap::apply(TNode t) {
- Debug("substitution") << "SubstitutionMap::apply(" << t << ")" << std::endl;
+ Debug("substitution") << "SubstitutionMap::apply(" << t << ")" << endl;
// Setup the cache
if (d_cacheInvalidated) {
d_substitutionCache.clear();
d_cacheInvalidated = false;
- Debug("substitution") << "-- reset the cache" << std::endl;
+ Debug("substitution") << "-- reset the cache" << endl;
}
// Perform the substitution
Node result = internalSubstitute(t);
- Debug("substitution") << "SubstitutionMap::apply(" << t << ") => " << result << std::endl;
+ Debug("substitution") << "SubstitutionMap::apply(" << t << ") => " << result << endl;
// Assert(check(result, d_substitutions));
diff --git a/src/theory/substitutions.h b/src/theory/substitutions.h
index 31a6b9141..a199256e7 100644
--- a/src/theory/substitutions.h
+++ b/src/theory/substitutions.h
@@ -62,6 +62,9 @@ private:
/** Cache of the already performed substitutions */
NodeCache d_substitutionCache;
+ /** Whether or not to substitute under quantifiers */
+ bool d_substituteUnderQuantifiers;
+
/** Has the cache been invalidated? */
bool d_cacheInvalidated;
@@ -95,10 +98,11 @@ private:
public:
- SubstitutionMap(context::Context* context) :
+ SubstitutionMap(context::Context* context, bool substituteUnderQuantifiers = true) :
d_context(context),
d_substitutions(context),
d_substitutionCache(),
+ d_substituteUnderQuantifiers(substituteUnderQuantifiers),
d_cacheInvalidated(false),
d_cacheInvalidator(context, d_cacheInvalidated) {
}
diff --git a/src/theory/theory_engine.cpp b/src/theory/theory_engine.cpp
index 35ed63bed..f7f689850 100644
--- a/src/theory/theory_engine.cpp
+++ b/src/theory/theory_engine.cpp
@@ -286,7 +286,9 @@ void TheoryEngine::check(Theory::Effort effort) {
#endif
#define CVC4_FOR_EACH_THEORY_STATEMENT(THEORY) \
if (theory::TheoryTraits<THEORY>::hasCheck && d_logicInfo.isTheoryEnabled(THEORY)) { \
+Debug("theory") << "check<" << THEORY << ">" << std::endl; \
theoryOf(THEORY)->check(effort); \
+Debug("theory") << "done<" << THEORY << ">" << std::endl; \
if (d_inConflict) { \
break; \
} \
@@ -726,16 +728,6 @@ theory::Theory::PPAssertStatus TheoryEngine::solve(TNode literal, SubstitutionMa
Theory::PPAssertStatus solveStatus = theoryOf(atom)->ppAssert(literal, substitutionOut);
Trace("theory::solve") << "TheoryEngine::solve(" << literal << ") => " << solveStatus << endl;
- //must add substitutions to model
- theory::TheoryModel* m = getModel();
- if( m ){
- for( SubstitutionMap::iterator pos = substitutionOut.begin(); pos != substitutionOut.end(); ++pos) {
- Node n = (*pos).first;
- Node v = (*pos).second;
- Trace("model") << "Add substitution : " << n << " " << v << std::endl;
- m->addSubstitution( n, v );
- }
- }
return solveStatus;
}
@@ -817,7 +809,7 @@ Node TheoryEngine::preprocess(TNode assertion) {
stringstream ss;
ss << "The logic was specified as " << d_logicInfo.getLogicString()
<< ", which doesn't include " << Theory::theoryOf(current)
- << ", but got a preprocesing-time fact for that theory." << endl
+ << ", but got a preprocessing-time fact for that theory." << endl
<< "The fact:" << endl
<< current;
throw LogicException(ss.str());
diff --git a/src/theory/theory_engine.h b/src/theory/theory_engine.h
index 27371eac3..a3779f0e8 100644
--- a/src/theory/theory_engine.h
+++ b/src/theory/theory_engine.h
@@ -41,6 +41,7 @@
#include "util/hash.h"
#include "util/cache.h"
#include "util/cvc4_assert.h"
+#include "util/sort_inference.h"
#include "theory/ite_simplifier.h"
#include "theory/unconstrained_simplifier.h"
#include "theory/uf/equality_engine.h"
@@ -268,7 +269,7 @@ class TheoryEngine {
void safePoint() throw(theory::Interrupted, AssertionException) {
if (d_engine->d_interrupted)
throw theory::Interrupted();
- }
+ }
void conflict(TNode conflictNode) throw(AssertionException) {
Trace("theory::conflict") << "EngineOutputChannel<" << d_theory << ">::conflict(" << conflictNode << ")" << std::endl;
@@ -422,6 +423,9 @@ class TheoryEngine {
RemoveITE& d_iteRemover;
+ /** sort inference module */
+ SortInference d_sortInfer;
+
/** Time spent in theory combination */
TimerStat d_combineTheoriesTime;
@@ -732,24 +736,28 @@ public:
SharedTermsDatabase* getSharedTermsDatabase() { return &d_sharedTerms; }
+ SortInference* getSortInference() { return &d_sortInfer; }
private:
std::map< std::string, std::vector< theory::Theory* > > d_attr_handle;
public:
- /** Set user attribute
- * This function is called when an attribute is set by a user. In SMT-LIBv2 this is done
- * via the syntax (! n :attr)
- */
+ /**
+ * Set user attribute.
+ * This function is called when an attribute is set by a user. In SMT-LIBv2 this is done
+ * via the syntax (! n :attr)
+ */
void setUserAttribute(const std::string& attr, Node n);
- /** Handle user attribute
- * Associates theory t with the attribute attr. Theory t will be
- * notifed whenever an attribute of name attr is set.
- */
+ /**
+ * Handle user attribute.
+ * Associates theory t with the attribute attr. Theory t will be
+ * notified whenever an attribute of name attr is set.
+ */
void handleUserAttribute(const char* attr, theory::Theory* t);
- /** Check that the theory assertions are satisfied in the model
- * This function is called from the smt engine's checkModel routine
+ /**
+ * Check that the theory assertions are satisfied in the model.
+ * This function is called from the smt engine's checkModel routine.
*/
void checkTheoryAssertionsWithModel();
diff --git a/src/theory/uf/options b/src/theory/uf/options
index 2569ccbff..33d1255ef 100644
--- a/src/theory/uf/options
+++ b/src/theory/uf/options
@@ -25,6 +25,10 @@ option ufssAbortCardinality --uf-ss-abort-card=N int :default -1
option ufssSmartSplits --uf-ss-smart-split bool :default false
use smart splitting heuristic for uf strong solver
option ufssExplainedCliques --uf-ss-explained-cliques bool :default false
- add explained clique lemmas for uf strong solver
+ use explained clique lemmas for uf strong solver
+option ufssSimpleCliques --uf-ss-simple-cliques bool :default true
+ always use simple clique lemmas for uf strong solver
+option ufssDiseqPropagation --uf-ss-deq-prop bool :default false
+ eagerly propagate disequalities for uf strong solver
endmodule
diff --git a/src/theory/uf/theory_uf.cpp b/src/theory/uf/theory_uf.cpp
index 3f033f3b8..bdbb79195 100644
--- a/src/theory/uf/theory_uf.cpp
+++ b/src/theory/uf/theory_uf.cpp
@@ -33,7 +33,7 @@ TheoryUF::TheoryUF(context::Context* c, context::UserContext* u, OutputChannel&
d_notify(*this),
/* The strong theory solver can be notified by EqualityEngine::init(),
* so make sure it's initialized first. */
- d_thss(options::finiteModelFind() ? new StrongSolverTheoryUf(c, u, out, this) : NULL),
+ d_thss(options::finiteModelFind() ? new StrongSolverTheoryUF(c, u, out, this) : NULL),
d_equalityEngine(d_notify, c, "theory::uf::TheoryUF"),
d_conflict(c, false),
d_literalsToPropagate(c),
@@ -101,12 +101,10 @@ void TheoryUF::check(Effort level) {
}
- if (d_thss != NULL) {
- if (! d_conflict) {
- d_thss->check(level);
- if( d_thss->isConflict() ){
- d_conflict = true;
- }
+ if (d_thss != NULL && ! d_conflict) {
+ d_thss->check(level);
+ if( d_thss->isConflict() ){
+ d_conflict = true;
}
}
diff --git a/src/theory/uf/theory_uf.h b/src/theory/uf/theory_uf.h
index fe1fc5137..00e270bd0 100644
--- a/src/theory/uf/theory_uf.h
+++ b/src/theory/uf/theory_uf.h
@@ -35,11 +35,11 @@ namespace theory {
namespace uf {
class UfTermDb;
-class StrongSolverTheoryUf;
+class StrongSolverTheoryUF;
class TheoryUF : public Theory {
- friend class StrongSolverTheoryUf;
+ friend class StrongSolverTheoryUF;
public:
@@ -116,7 +116,7 @@ private:
NotifyClass d_notify;
/** The associated theory strong solver (or NULL if none) */
- StrongSolverTheoryUf* d_thss;
+ StrongSolverTheoryUF* d_thss;
/** Equaltity engine */
eq::EqualityEngine d_equalityEngine;
@@ -212,7 +212,7 @@ public:
return &d_equalityEngine;
}
- StrongSolverTheoryUf* getStrongSolver() {
+ StrongSolverTheoryUF* getStrongSolver() {
return d_thss;
}
diff --git a/src/theory/uf/theory_uf_strong_solver.cpp b/src/theory/uf/theory_uf_strong_solver.cpp
index 46ac5aa60..25cb8b66c 100644
--- a/src/theory/uf/theory_uf_strong_solver.cpp
+++ b/src/theory/uf/theory_uf_strong_solver.cpp
@@ -32,11 +32,11 @@ using namespace CVC4::context;
using namespace CVC4::theory;
using namespace CVC4::theory::uf;
-void StrongSolverTheoryUf::SortRepModel::Region::addRep( Node n ) {
+void StrongSolverTheoryUF::SortModel::Region::addRep( Node n ) {
setRep( n, true );
}
-void StrongSolverTheoryUf::SortRepModel::Region::takeNode( StrongSolverTheoryUf::SortRepModel::Region* r, Node n ){
+void StrongSolverTheoryUF::SortModel::Region::takeNode( StrongSolverTheoryUF::SortModel::Region* r, Node n ){
Assert( !hasRep( n ) );
Assert( r->hasRep( n ) );
//add representative
@@ -68,7 +68,7 @@ void StrongSolverTheoryUf::SortRepModel::Region::takeNode( StrongSolverTheoryUf:
r->setRep( n, false );
}
-void StrongSolverTheoryUf::SortRepModel::Region::combine( StrongSolverTheoryUf::SortRepModel::Region* r ){
+void StrongSolverTheoryUF::SortModel::Region::combine( StrongSolverTheoryUF::SortModel::Region* r ){
//take all nodes from r
for( std::map< Node, RegionNodeInfo* >::iterator it = r->d_nodes.begin(); it != r->d_nodes.end(); ++it ){
if( it->second->d_valid ){
@@ -100,7 +100,7 @@ void StrongSolverTheoryUf::SortRepModel::Region::combine( StrongSolverTheoryUf::
}
/** setEqual */
-void StrongSolverTheoryUf::SortRepModel::Region::setEqual( Node a, Node b ){
+void StrongSolverTheoryUF::SortModel::Region::setEqual( Node a, Node b ){
Assert( hasRep( a ) && hasRep( b ) );
//move disequalities of b over to a
for( int t=0; t<2; t++ ){
@@ -108,10 +108,15 @@ void StrongSolverTheoryUf::SortRepModel::Region::setEqual( Node a, Node b ){
for( NodeBoolMap::iterator it = del->d_disequalities.begin(); it != del->d_disequalities.end(); ++it ){
if( (*it).second ){
Node n = (*it).first;
+ //get the region that contains the endpoint of the disequality b != ...
Region* nr = d_cf->d_regions[ d_cf->d_regions_map[ n ] ];
if( !isDisequal( a, n, t ) ){
setDisequal( a, n, t, true );
nr->setDisequal( n, a, t, true );
+ //notify the disequality propagator
+ if( options::ufssDiseqPropagation() ){
+ d_cf->d_thss->getDisequalityPropagator()->assertDisequal(a, n, Node::null());
+ }
}
setDisequal( b, n, t, false );
nr->setDisequal( n, b, t, false );
@@ -122,7 +127,7 @@ void StrongSolverTheoryUf::SortRepModel::Region::setEqual( Node a, Node b ){
setRep( b, false );
}
-void StrongSolverTheoryUf::SortRepModel::Region::setDisequal( Node n1, Node n2, int type, bool valid ){
+void StrongSolverTheoryUF::SortModel::Region::setDisequal( Node n1, Node n2, int type, bool valid ){
//Debug("uf-ss-region-debug") << "set disequal " << n1 << " " << n2 << " " << type << " " << valid << std::endl;
//debugPrint("uf-ss-region-debug");
//Assert( isDisequal( n1, n2, type )!=valid );
@@ -148,10 +153,10 @@ void StrongSolverTheoryUf::SortRepModel::Region::setDisequal( Node n1, Node n2,
}
}
-void StrongSolverTheoryUf::SortRepModel::Region::setRep( Node n, bool valid ){
+void StrongSolverTheoryUF::SortModel::Region::setRep( Node n, bool valid ){
Assert( hasRep( n )!=valid );
if( valid && d_nodes.find( n )==d_nodes.end() ){
- d_nodes[n] = new RegionNodeInfo( d_cf->d_th->getSatContext() );
+ d_nodes[n] = new RegionNodeInfo( d_cf->d_thss->getSatContext() );
}
d_nodes[n]->d_valid = valid;
d_reps_size = d_reps_size + ( valid ? 1 : -1 );
@@ -172,24 +177,24 @@ void StrongSolverTheoryUf::SortRepModel::Region::setRep( Node n, bool valid ){
}
}
-bool StrongSolverTheoryUf::SortRepModel::Region::isDisequal( Node n1, Node n2, int type ){
+bool StrongSolverTheoryUF::SortModel::Region::isDisequal( Node n1, Node n2, int type ){
RegionNodeInfo::DiseqList* del = d_nodes[ n1 ]->d_disequalities[type];
return del->d_disequalities.find( n2 )!=del->d_disequalities.end() && del->d_disequalities[n2];
}
struct sortInternalDegree {
- StrongSolverTheoryUf::SortRepModel::Region* r;
+ StrongSolverTheoryUF::SortModel::Region* r;
bool operator() (Node i,Node j) { return (r->d_nodes[i]->getNumInternalDisequalities()>r->d_nodes[j]->getNumInternalDisequalities());}
};
struct sortExternalDegree {
- StrongSolverTheoryUf::SortRepModel::Region* r;
+ StrongSolverTheoryUF::SortModel::Region* r;
bool operator() (Node i,Node j) { return (r->d_nodes[i]->getNumExternalDisequalities()>r->d_nodes[j]->getNumExternalDisequalities());}
};
int gmcCount = 0;
-bool StrongSolverTheoryUf::SortRepModel::Region::getMustCombine( int cardinality ){
+bool StrongSolverTheoryUF::SortModel::Region::getMustCombine( int cardinality ){
if( options::ufssRegions() && d_total_diseq_external>=long(cardinality) ){
//The number of external disequalities is greater than or equal to cardinality.
//Thus, a clique of size cardinality+1 may exist between nodes in d_regions[i] and other regions
@@ -228,7 +233,7 @@ bool StrongSolverTheoryUf::SortRepModel::Region::getMustCombine( int cardinality
return false;
}
-bool StrongSolverTheoryUf::SortRepModel::Region::check( Theory::Effort level, int cardinality, std::vector< Node >& clique ){
+bool StrongSolverTheoryUF::SortModel::Region::check( Theory::Effort level, int cardinality, std::vector< Node >& clique ){
if( d_reps_size>long(cardinality) ){
if( d_total_diseq_internal==d_reps_size*( d_reps_size - 1 ) ){
if( d_reps_size>1 ){
@@ -317,7 +322,7 @@ bool StrongSolverTheoryUf::SortRepModel::Region::check( Theory::Effort level, in
return false;
}
-void StrongSolverTheoryUf::SortRepModel::Region::getRepresentatives( std::vector< Node >& reps ){
+void StrongSolverTheoryUF::SortModel::Region::getRepresentatives( std::vector< Node >& reps ){
for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
RegionNodeInfo* rni = it->second;
if( rni->d_valid ){
@@ -326,7 +331,7 @@ void StrongSolverTheoryUf::SortRepModel::Region::getRepresentatives( std::vector
}
}
-void StrongSolverTheoryUf::SortRepModel::Region::getNumExternalDisequalities( std::map< Node, int >& num_ext_disequalities ){
+void StrongSolverTheoryUF::SortModel::Region::getNumExternalDisequalities( std::map< Node, int >& num_ext_disequalities ){
for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
RegionNodeInfo* rni = it->second;
if( rni->d_valid ){
@@ -340,7 +345,7 @@ void StrongSolverTheoryUf::SortRepModel::Region::getNumExternalDisequalities( st
}
}
-void StrongSolverTheoryUf::SortRepModel::Region::debugPrint( const char* c, bool incClique ){
+void StrongSolverTheoryUF::SortModel::Region::debugPrint( const char* c, bool incClique ){
Debug( c ) << "Num reps: " << d_reps_size << std::endl;
for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
RegionNodeInfo* rni = it->second;
@@ -389,27 +394,27 @@ void StrongSolverTheoryUf::SortRepModel::Region::debugPrint( const char* c, bool
-StrongSolverTheoryUf::SortRepModel::SortRepModel( Node n, context::Context* c, TheoryUF* th ) : RepModel( n.getType() ),
- d_th( th ), d_regions_index( c, 0 ), d_regions_map( c ), d_split_score( c ), d_disequalities_index( c, 0 ),
+StrongSolverTheoryUF::SortModel::SortModel( Node n, context::Context* c, StrongSolverTheoryUF* thss ) : d_type( n.getType() ),
+ d_thss( thss ), d_regions_index( c, 0 ), d_regions_map( c ), d_split_score( c ), d_disequalities_index( c, 0 ),
d_reps( c, 0 ), d_conflict( c, false ), d_cardinality( c, 1 ), d_aloc_cardinality( 0 ),
d_cardinality_assertions( c ), d_hasCard( c, false ){
d_cardinality_term = n;
}
/** initialize */
-void StrongSolverTheoryUf::SortRepModel::initialize( OutputChannel* out ){
+void StrongSolverTheoryUF::SortModel::initialize( OutputChannel* out ){
allocateCardinality( out );
}
/** new node */
-void StrongSolverTheoryUf::SortRepModel::newEqClass( Node n ){
+void StrongSolverTheoryUF::SortModel::newEqClass( Node n ){
if( !d_conflict ){
if( d_regions_map.find( n )==d_regions_map.end() ){
if( !options::ufssTotalityLazy() ){
//must generate totality axioms for every cardinality we have allocated thus far
for( std::map< int, Node >::iterator it = d_cardinality_literal.begin(); it != d_cardinality_literal.end(); ++it ){
if( applyTotality( it->first ) ){
- addTotalityAxiom( n, it->first, &d_th->getOutputChannel() );
+ addTotalityAxiom( n, it->first, &d_thss->getOutputChannel() );
}
}
}
@@ -429,14 +434,14 @@ void StrongSolverTheoryUf::SortRepModel::newEqClass( Node n ){
if( options::ufssSmartSplits() ){
setSplitScore( n, 0 );
}
- Debug("uf-ss") << "StrongSolverTheoryUf: New Eq Class " << n << std::endl;
+ Debug("uf-ss") << "StrongSolverTheoryUF: New Eq Class " << n << std::endl;
Debug("uf-ss-debug") << d_regions_index << " " << (int)d_regions.size() << std::endl;
if( d_regions_index<d_regions.size() ){
d_regions[ d_regions_index ]->debugPrint("uf-ss-debug",true);
d_regions[ d_regions_index ]->d_valid = true;
Assert( !options::ufssRegions() || d_regions[ d_regions_index ]->getNumReps()==0 );
}else{
- d_regions.push_back( new Region( this, d_th->getSatContext() ) );
+ d_regions.push_back( new Region( this, d_thss->getSatContext() ) );
}
d_regions[ d_regions_index ]->addRep( n );
d_regions_index = d_regions_index + 1;
@@ -447,7 +452,7 @@ void StrongSolverTheoryUf::SortRepModel::newEqClass( Node n ){
}
/** merge */
-void StrongSolverTheoryUf::SortRepModel::merge( Node a, Node b ){
+void StrongSolverTheoryUF::SortModel::merge( Node a, Node b ){
if( !d_conflict ){
if( options::ufssTotality() ){
if( d_regions_map[b]==-1 ){
@@ -457,7 +462,7 @@ void StrongSolverTheoryUf::SortRepModel::merge( Node a, Node b ){
}else{
//Assert( a==d_th->d_equalityEngine.getRepresentative( a ) );
//Assert( b==d_th->d_equalityEngine.getRepresentative( b ) );
- Debug("uf-ss") << "StrongSolverTheoryUf: Merging " << a << " = " << b << "..." << std::endl;
+ Debug("uf-ss") << "StrongSolverTheoryUF: Merging " << a << " = " << b << "..." << std::endl;
if( a!=b ){
Assert( d_regions_map.find( a )!=d_regions_map.end() );
Assert( d_regions_map.find( b )!=d_regions_map.end() );
@@ -495,21 +500,25 @@ void StrongSolverTheoryUf::SortRepModel::merge( Node a, Node b ){
d_regions_map[b] = -1;
}
d_reps = d_reps - 1;
- Debug("uf-ss") << "Done merge." << std::endl;
+
+ if( options::ufssDiseqPropagation() && !d_conflict ){
+ //notify the disequality propagator
+ d_thss->getDisequalityPropagator()->merge(a, b);
+ }
}
}
}
/** assert terms are disequal */
-void StrongSolverTheoryUf::SortRepModel::assertDisequal( Node a, Node b, Node reason ){
+void StrongSolverTheoryUF::SortModel::assertDisequal( Node a, Node b, Node reason ){
if( !d_conflict ){
if( options::ufssTotality() ){
//do nothing
}else{
//if they are not already disequal
- a = d_th->d_equalityEngine.getRepresentative( a );
- b = d_th->d_equalityEngine.getRepresentative( b );
- if( !d_th->d_equalityEngine.areDisequal( a, b, true ) ){
+ a = d_thss->getTheory()->d_equalityEngine.getRepresentative( a );
+ b = d_thss->getTheory()->d_equalityEngine.getRepresentative( b );
+ if( !d_thss->getTheory()->d_equalityEngine.areDisequal( a, b, true ) ){
Debug("uf-ss") << "Assert disequal " << a << " != " << b << "..." << std::endl;
//if( reason.getKind()!=NOT || ( reason[0].getKind()!=EQUAL && reason[0].getKind()!=IFF ) ||
// a!=reason[0][0] || b!=reason[0][1] ){
@@ -533,6 +542,7 @@ void StrongSolverTheoryUf::SortRepModel::assertDisequal( Node a, Node b, Node re
//internal disequality
d_regions[ai]->setDisequal( a, b, 1, true );
d_regions[ai]->setDisequal( b, a, 1, true );
+ checkRegion( ai, false ); //do not need to check if it needs to combine (no new ext. disequalities)
}else{
//external disequality
d_regions[ai]->setDisequal( a, b, 0, true );
@@ -540,18 +550,34 @@ void StrongSolverTheoryUf::SortRepModel::assertDisequal( Node a, Node b, Node re
checkRegion( ai );
checkRegion( bi );
}
- //Notice() << "done" << std::endl;
+
+ if( options::ufssDiseqPropagation() && !d_conflict ){
+ //notify the disequality propagator
+ d_thss->getDisequalityPropagator()->assertDisequal(a, b, Node::null());
+ }
}
}
}
}
+bool StrongSolverTheoryUF::SortModel::areDisequal( Node a, Node b ) {
+ Assert( a == d_thss->getTheory()->d_equalityEngine.getRepresentative( a ) );
+ Assert( b == d_thss->getTheory()->d_equalityEngine.getRepresentative( b ) );
+ if( d_regions_map.find( a )!=d_regions_map.end() &&
+ d_regions_map.find( b )!=d_regions_map.end() ){
+ int ai = d_regions_map[a];
+ int bi = d_regions_map[b];
+ return d_regions[ai]->isDisequal(a, b, ai==bi ? 1 : 0);
+ }else{
+ return false;
+ }
+}
/** check */
-void StrongSolverTheoryUf::SortRepModel::check( Theory::Effort level, OutputChannel* out ){
+void StrongSolverTheoryUF::SortModel::check( Theory::Effort level, OutputChannel* out ){
if( level>=Theory::EFFORT_STANDARD && d_hasCard && !d_conflict ){
- Debug("uf-ss") << "StrongSolverTheoryUf: Check " << level << " " << d_type << std::endl;
- //Notice() << "StrongSolverTheoryUf: Check " << level << std::endl;
+ Debug("uf-ss") << "StrongSolverTheoryUF: Check " << level << " " << d_type << std::endl;
+ //Notice() << "StrongSolverTheoryUF: Check " << level << std::endl;
if( d_reps<=(unsigned)d_cardinality ){
Debug("uf-ss-debug") << "We have " << d_reps << " representatives for type " << d_type << ", <= " << d_cardinality << std::endl;
if( level==Theory::EFFORT_FULL ){
@@ -584,7 +610,7 @@ void StrongSolverTheoryUf::SortRepModel::check( Theory::Effort level, OutputChan
if( level==Theory::EFFORT_FULL ){
for( NodeIntMap::iterator it = d_regions_map.begin(); it != d_regions_map.end(); ++it ){
if( !options::ufssTotality() || d_regions_map[ (*it).first ]!=-1 ){
- addTotalityAxiom( (*it).first, d_cardinality, &d_th->getOutputChannel() );
+ addTotalityAxiom( (*it).first, d_cardinality, &d_thss->getOutputChannel() );
}
}
}
@@ -610,8 +636,26 @@ void StrongSolverTheoryUf::SortRepModel::check( Theory::Effort level, OutputChan
if( level==Theory::EFFORT_FULL ){
if( !addedLemma ){
Trace("uf-ss-debug") << "No splits added. " << d_cardinality << std::endl;
- if( !options::ufssColoringSat() ){
- bool recheck = false;
+ Trace("uf-ss-si") << "Must combine region" << std::endl;
+ bool recheck = false;
+ if( options::sortInference()){
+ //if sort inference is enabled, search for regions with same sort
+ std::map< int, int > sortsFound;
+ for( int i=0; i<(int)d_regions_index; i++ ){
+ if( d_regions[i]->d_valid ){
+ Node op = d_regions[i]->d_nodes.begin()->first;
+ int sort_id = d_thss->getTheory()->getQuantifiersEngine()->getTheoryEngine()->getSortInference()->getSortId(op);
+ if( sortsFound.find( sort_id )!=sortsFound.end() ){
+ combineRegions( sortsFound[sort_id], i );
+ recheck = true;
+ break;
+ }else{
+ sortsFound[sort_id] = i;
+ }
+ }
+ }
+ }
+ if( !recheck ) {
//naive strategy, force region combination involving the first valid region
for( int i=0; i<(int)d_regions_index; i++ ){
if( d_regions[i]->d_valid ){
@@ -620,9 +664,9 @@ void StrongSolverTheoryUf::SortRepModel::check( Theory::Effort level, OutputChan
break;
}
}
- if( recheck ){
- check( level, out );
- }
+ }
+ if( recheck ){
+ check( level, out );
}
}
}
@@ -631,11 +675,11 @@ void StrongSolverTheoryUf::SortRepModel::check( Theory::Effort level, OutputChan
}
}
-void StrongSolverTheoryUf::SortRepModel::propagate( Theory::Effort level, OutputChannel* out ){
+void StrongSolverTheoryUF::SortModel::propagate( Theory::Effort level, OutputChannel* out ){
}
-Node StrongSolverTheoryUf::SortRepModel::getNextDecisionRequest(){
+Node StrongSolverTheoryUF::SortModel::getNextDecisionRequest(){
//request the current cardinality as a decision literal, if not already asserted
for( int i=1; i<=d_aloc_cardinality; i++ ){
if( !d_hasCard || i<d_cardinality ){
@@ -650,7 +694,7 @@ Node StrongSolverTheoryUf::SortRepModel::getNextDecisionRequest(){
return Node::null();
}
-bool StrongSolverTheoryUf::SortRepModel::minimize( OutputChannel* out, TheoryModel* m ){
+bool StrongSolverTheoryUF::SortModel::minimize( OutputChannel* out, TheoryModel* m ){
if( options::ufssTotality() ){
//do nothing
}else{
@@ -672,7 +716,7 @@ bool StrongSolverTheoryUf::SortRepModel::minimize( OutputChannel* out, TheoryMod
out->split( splitEq );
//tell the sat solver to explore the equals branch first
out->requirePhase( splitEq, true );
- ++( d_th->getStrongSolver()->d_statistics.d_split_lemmas );
+ ++( d_thss->d_statistics.d_split_lemmas );
return false;
}
}
@@ -706,7 +750,7 @@ bool StrongSolverTheoryUf::SortRepModel::minimize( OutputChannel* out, TheoryMod
}
-int StrongSolverTheoryUf::SortRepModel::getNumDisequalitiesToRegion( Node n, int ri ){
+int StrongSolverTheoryUF::SortModel::getNumDisequalitiesToRegion( Node n, int ri ){
int ni = d_regions_map[n];
int counter = 0;
Region::RegionNodeInfo::DiseqList* del = d_regions[ni]->d_nodes[n]->d_disequalities[0];
@@ -720,7 +764,7 @@ int StrongSolverTheoryUf::SortRepModel::getNumDisequalitiesToRegion( Node n, int
return counter;
}
-void StrongSolverTheoryUf::SortRepModel::getDisequalitiesToRegions( int ri, std::map< int, int >& regions_diseq ){
+void StrongSolverTheoryUF::SortModel::getDisequalitiesToRegions( int ri, std::map< int, int >& regions_diseq ){
for( std::map< Node, Region::RegionNodeInfo* >::iterator it = d_regions[ri]->d_nodes.begin();
it != d_regions[ri]->d_nodes.end(); ++it ){
if( it->second->d_valid ){
@@ -736,7 +780,7 @@ void StrongSolverTheoryUf::SortRepModel::getDisequalitiesToRegions( int ri, std:
}
}
-void StrongSolverTheoryUf::SortRepModel::setSplitScore( Node n, int s ){
+void StrongSolverTheoryUF::SortModel::setSplitScore( Node n, int s ){
if( d_split_score.find( n )!=d_split_score.end() ){
int ss = d_split_score[ n ];
d_split_score[ n ] = s>ss ? s : ss;
@@ -748,9 +792,10 @@ void StrongSolverTheoryUf::SortRepModel::setSplitScore( Node n, int s ){
}
}
-void StrongSolverTheoryUf::SortRepModel::assertCardinality( OutputChannel* out, int c, bool val ){
+void StrongSolverTheoryUF::SortModel::assertCardinality( OutputChannel* out, int c, bool val ){
if( !d_conflict ){
- Trace("uf-ss-assert") << "Assert cardinality " << d_type << " " << c << " " << val << " level = " << d_th->d_valuation.getAssertionLevel() << std::endl;
+ Trace("uf-ss-assert") << "Assert cardinality " << d_type << " " << c << " " << val << " level = ";
+ Trace("uf-ss-assert") << d_thss->getTheory()->d_valuation.getAssertionLevel() << std::endl;
Assert( d_cardinality_literal.find( c )!=d_cardinality_literal.end() );
d_cardinality_assertions[ d_cardinality_literal[c] ] = val;
if( val ){
@@ -803,15 +848,10 @@ void StrongSolverTheoryUf::SortRepModel::assertCardinality( OutputChannel* out,
}
}
-void StrongSolverTheoryUf::SortRepModel::checkRegion( int ri, bool rec ){
+void StrongSolverTheoryUF::SortModel::checkRegion( int ri, bool checkCombine ){
if( isValid(ri) && d_hasCard ){
Assert( d_cardinality>0 );
- //first check if region is in conflict
- std::vector< Node > clique;
- if( d_regions[ri]->check( Theory::EFFORT_STANDARD, d_cardinality, clique ) ){
- //explain clique
- addCliqueLemma( clique, &d_th->getOutputChannel() );
- }else if( d_regions[ri]->getMustCombine( d_cardinality ) ){
+ if( checkCombine && d_regions[ri]->getMustCombine( d_cardinality ) ){
////alternatively, check if we can reduce the number of external disequalities by moving single nodes
//for( std::map< Node, bool >::iterator it = d_regions[i]->d_reps.begin(); it != d_regions[i]->d_reps.end(); ++it ){
// if( it->second ){
@@ -822,14 +862,20 @@ void StrongSolverTheoryUf::SortRepModel::checkRegion( int ri, bool rec ){
// }
//}
int riNew = forceCombineRegion( ri, true );
- if( riNew>=0 && rec ){
- checkRegion( riNew, rec );
+ if( riNew>=0 ){
+ checkRegion( riNew, checkCombine );
}
}
+ //now check if region is in conflict
+ std::vector< Node > clique;
+ if( d_regions[ri]->check( Theory::EFFORT_STANDARD, d_cardinality, clique ) ){
+ //explain clique
+ addCliqueLemma( clique, &d_thss->getOutputChannel() );
+ }
}
}
-int StrongSolverTheoryUf::SortRepModel::forceCombineRegion( int ri, bool useDensity ){
+int StrongSolverTheoryUF::SortModel::forceCombineRegion( int ri, bool useDensity ){
if( !useDensity ){
for( int i=0; i<(int)d_regions_index; i++ ){
if( ri!=i && d_regions[i]->d_valid ){
@@ -869,7 +915,7 @@ int StrongSolverTheoryUf::SortRepModel::forceCombineRegion( int ri, bool useDens
}
-int StrongSolverTheoryUf::SortRepModel::combineRegions( int ai, int bi ){
+int StrongSolverTheoryUF::SortModel::combineRegions( int ai, int bi ){
#ifdef COMBINE_REGIONS_SMALL_INTO_LARGE
if( d_regions[ai]->getNumReps()<d_regions[bi]->getNumReps() ){
return combineRegions( bi, ai );
@@ -889,7 +935,7 @@ int StrongSolverTheoryUf::SortRepModel::combineRegions( int ai, int bi ){
return ai;
}
-void StrongSolverTheoryUf::SortRepModel::moveNode( Node n, int ri ){
+void StrongSolverTheoryUF::SortModel::moveNode( Node n, int ri ){
Debug("uf-ss-region") << "uf-ss: Move node " << n << " to Region #" << ri << std::endl;
Assert( isValid( d_regions_map[ n ] ) );
Assert( isValid( ri ) );
@@ -898,7 +944,7 @@ void StrongSolverTheoryUf::SortRepModel::moveNode( Node n, int ri ){
d_regions_map[n] = ri;
}
-void StrongSolverTheoryUf::SortRepModel::allocateCardinality( OutputChannel* out ){
+void StrongSolverTheoryUF::SortModel::allocateCardinality( OutputChannel* out ){
if( d_aloc_cardinality>0 ){
Trace("uf-ss-fmf") << "No model of size " << d_aloc_cardinality << " exists for type " << d_type << " in this branch" << std::endl;
if( Trace.isOn("uf-ss-cliques") ){
@@ -936,7 +982,7 @@ void StrongSolverTheoryUf::SortRepModel::allocateCardinality( OutputChannel* out
//must be distinct from all other cardinality terms
for( int i=0; i<(int)(d_totality_terms[0].size()-1); i++ ){
Node lem = NodeManager::currentNM()->mkNode( NOT, var.eqNode( d_totality_terms[0][i] ) );
- d_th->getOutputChannel().lemma( lem );
+ d_thss->getOutputChannel().lemma( lem );
}
}
@@ -955,18 +1001,18 @@ void StrongSolverTheoryUf::SortRepModel::allocateCardinality( OutputChannel* out
//add the appropriate lemma, propagate as decision
//Trace("uf-ss-prop-as-dec") << "Propagate as decision " << lem[0] << " " << d_type << std::endl;
//out->propagateAsDecision( lem[0] );
- d_th->getStrongSolver()->d_statistics.d_max_model_size.maxAssign( d_aloc_cardinality );
+ d_thss->d_statistics.d_max_model_size.maxAssign( d_aloc_cardinality );
if( applyTotality( d_aloc_cardinality ) && !options::ufssTotalityLazy() ){
//must send totality axioms for each existing term
for( NodeIntMap::iterator it = d_regions_map.begin(); it != d_regions_map.end(); ++it ){
- addTotalityAxiom( (*it).first, d_aloc_cardinality, &d_th->getOutputChannel() );
+ addTotalityAxiom( (*it).first, d_aloc_cardinality, &d_thss->getOutputChannel() );
}
}
}
}
-bool StrongSolverTheoryUf::SortRepModel::addSplit( Region* r, OutputChannel* out ){
+bool StrongSolverTheoryUF::SortModel::addSplit( Region* r, OutputChannel* out ){
if( r->hasSplits() ){
Node s;
if( !options::ufssSmartSplits() ){
@@ -996,6 +1042,13 @@ bool StrongSolverTheoryUf::SortRepModel::addSplit( Region* r, OutputChannel* out
Assert( s!=Node::null() && s.getKind()==EQUAL );
s = Rewriter::rewrite( s );
Trace("uf-ss-lemma") << "*** Split on " << s << std::endl;
+ if( options::sortInference()) {
+ for( int i=0; i<2; i++ ){
+ int si = d_thss->getTheory()->getQuantifiersEngine()->getTheoryEngine()->getSortInference()->getSortId( s[i] );
+ Trace("uf-ss-split-si") << si << " ";
+ }
+ Trace("uf-ss-split-si") << std::endl;
+ }
//Trace("uf-ss-lemma") << d_th->getEqualityEngine()->areEqual( s[0], s[1] ) << " ";
//Trace("uf-ss-lemma") << d_th->getEqualityEngine()->areDisequal( s[0], s[1] ) << std::endl;
//Trace("uf-ss-lemma") << s[0].getType() << " " << s[1].getType() << std::endl;
@@ -1004,7 +1057,7 @@ bool StrongSolverTheoryUf::SortRepModel::addSplit( Region* r, OutputChannel* out
out->split( s );
//tell the sat solver to explore the equals branch first
out->requirePhase( s, true );
- ++( d_th->getStrongSolver()->d_statistics.d_split_lemmas );
+ ++( d_thss->d_statistics.d_split_lemmas );
return true;
}else{
return false;
@@ -1012,126 +1065,158 @@ bool StrongSolverTheoryUf::SortRepModel::addSplit( Region* r, OutputChannel* out
}
-void StrongSolverTheoryUf::SortRepModel::addCliqueLemma( std::vector< Node >& clique, OutputChannel* out ){
+void StrongSolverTheoryUF::SortModel::addCliqueLemma( std::vector< Node >& clique, OutputChannel* out ){
Assert( d_hasCard );
Assert( d_cardinality>0 );
while( clique.size()>size_t(d_cardinality+1) ){
clique.pop_back();
}
- if( !options::ufssExplainedCliques() ){
+ if( options::ufssSimpleCliques() && !options::ufssExplainedCliques() ){
//add as lemma
std::vector< Node > eqs;
for( int i=0; i<(int)clique.size(); i++ ){
for( int j=0; j<i; j++ ){
+ Node r1 = d_thss->getTheory()->d_equalityEngine.getRepresentative(clique[i]);
+ Node r2 = d_thss->getTheory()->d_equalityEngine.getRepresentative(clique[j]);
eqs.push_back( clique[i].eqNode( clique[j] ) );
}
}
eqs.push_back( d_cardinality_literal[ d_cardinality ].notNode() );
Node lem = NodeManager::currentNM()->mkNode( OR, eqs );
+ Trace("uf-ss-lemma") << "*** Add clique conflict " << lem << std::endl;
+ ++( d_thss->d_statistics.d_clique_lemmas );
out->lemma( lem );
- return;
- }
- //if( options::ufssModelInference() ||
- if( Trace.isOn("uf-ss-cliques") ){
- std::vector< Node > clique_vec;
- clique_vec.insert( clique_vec.begin(), clique.begin(), clique.end() );
- d_cliques[ d_cardinality ].push_back( clique_vec );
- }
-
- //found a clique
- Debug("uf-ss-cliques") << "Found a clique (cardinality=" << d_cardinality << ") :" << std::endl;
- Debug("uf-ss-cliques") << " ";
- for( int i=0; i<(int)clique.size(); i++ ){
- Debug("uf-ss-cliques") << clique[i] << " ";
- }
- Debug("uf-ss-cliques") << std::endl;
- Debug("uf-ss-cliques") << "Finding clique disequalities..." << std::endl;
- std::vector< Node > conflict;
- //collect disequalities, and nodes that must be equal within representatives
- std::map< Node, std::map< Node, bool > > explained;
- std::map< Node, std::map< Node, bool > > nodesWithinRep;
- for( int i=0; i<(int)d_disequalities_index; i++ ){
- //if both sides of disequality exist in clique
- Node r1 = d_th->d_equalityEngine.getRepresentative( d_disequalities[i][0][0] );
- Node r2 = d_th->d_equalityEngine.getRepresentative( d_disequalities[i][0][1] );
- if( r1!=r2 && ( explained.find( r1 )==explained.end() || explained[r1].find( r2 )==explained[r1].end() ) &&
- std::find( clique.begin(), clique.end(), r1 )!=clique.end() &&
- std::find( clique.begin(), clique.end(), r2 )!=clique.end() ){
- explained[r1][r2] = true;
- explained[r2][r1] = true;
- conflict.push_back( d_disequalities[i] );
- Debug("uf-ss-cliques") << " -> disequality : " << d_disequalities[i] << std::endl;
- nodesWithinRep[r1][ d_disequalities[i][0][0] ] = true;
- nodesWithinRep[r2][ d_disequalities[i][0][1] ] = true;
- if( conflict.size()==(clique.size()*( clique.size()-1 )/2) ){
- break;
+ }else{
+ //debugging information
+ if( Trace.isOn("uf-ss-cliques") ){
+ std::vector< Node > clique_vec;
+ clique_vec.insert( clique_vec.begin(), clique.begin(), clique.end() );
+ d_cliques[ d_cardinality ].push_back( clique_vec );
+ }
+ //found a clique
+ Debug("uf-ss-cliques") << "Found a clique (cardinality=" << d_cardinality << ") :" << std::endl;
+ Debug("uf-ss-cliques") << " ";
+ for( int i=0; i<(int)clique.size(); i++ ){
+ Debug("uf-ss-cliques") << clique[i] << " ";
+ }
+ Debug("uf-ss-cliques") << std::endl;
+ Debug("uf-ss-cliques") << "Finding clique disequalities..." << std::endl;
+
+ //we will scan through each of the disequaltities
+ bool isSatConflict = true;
+ std::vector< Node > conflict;
+ //collect disequalities, and nodes that must be equal within representatives
+ std::map< Node, std::map< Node, bool > > explained;
+ std::map< Node, std::map< Node, bool > > nodesWithinRep;
+ //map from the reprorted clique members to those reported in the lemma
+ std::map< Node, Node > cliqueRepMap;
+ for( int i=0; i<(int)d_disequalities_index; i++ ){
+ //if both sides of disequality exist in clique
+ Node r1 = d_thss->getTheory()->d_equalityEngine.getRepresentative( d_disequalities[i][0][0] );
+ Node r2 = d_thss->getTheory()->d_equalityEngine.getRepresentative( d_disequalities[i][0][1] );
+ if( r1!=r2 && ( explained.find( r1 )==explained.end() || explained[r1].find( r2 )==explained[r1].end() ) &&
+ std::find( clique.begin(), clique.end(), r1 )!=clique.end() &&
+ std::find( clique.begin(), clique.end(), r2 )!=clique.end() ){
+ explained[r1][r2] = true;
+ explained[r2][r1] = true;
+ if( options::ufssExplainedCliques() ){
+ conflict.push_back( d_disequalities[i] );
+ Debug("uf-ss-cliques") << " -> disequality : " << d_disequalities[i] << std::endl;
+ nodesWithinRep[r1][ d_disequalities[i][0][0] ] = true;
+ nodesWithinRep[r2][ d_disequalities[i][0][1] ] = true;
+ }else{
+ //get the terms we report in the lemma
+ Node ru1 = r1;
+ if( cliqueRepMap.find( r1 )==cliqueRepMap.end() ){
+ ru1 = d_disequalities[i][0][0];
+ cliqueRepMap[r1] = ru1;
+ }else{
+ ru1 = cliqueRepMap[r1];
+ }
+ Node ru2 = r2;
+ if( cliqueRepMap.find( r2 )==cliqueRepMap.end() ){
+ ru2 = d_disequalities[i][0][1];
+ cliqueRepMap[r2] = ru2;
+ }else{
+ ru2 = cliqueRepMap[r2];
+ }
+ if( ru1!=d_disequalities[i][0][0] || ru2!=d_disequalities[i][0][1] ){
+ //disequalities have endpoints that are not connected within an equivalence class
+ // we will be producing a lemma, introducing a new literal ru1 != ru2
+ conflict.push_back( ru1.eqNode( ru2 ).notNode() );
+ isSatConflict = false;
+ }else{
+ conflict.push_back( d_disequalities[i] );
+ }
+ }
+ if( conflict.size()==(clique.size()*( clique.size()-1 )/2) ){
+ break;
+ }
}
}
- }
- //Debug("uf-ss-cliques") << conflict.size() << " " << clique.size() << std::endl;
- Assert( (int)conflict.size()==((int)clique.size()*( (int)clique.size()-1 )/2) );
- //Assert( (int)conflict.size()==(int)clique.size()*( (int)clique.size()-1 )/2 );
- Debug("uf-ss-cliques") << "Finding clique equalities internal to eq classes..." << std::endl;
- //now, we must explain equalities within each equivalence class
- for( std::map< Node, std::map< Node, bool > >::iterator it = nodesWithinRep.begin(); it != nodesWithinRep.end(); ++it ){
- if( it->second.size()>1 ){
- Node prev;
- //add explanation of t1 = t2 = ... = tn
- Debug("uf-ss-cliques") << "Explain ";
- for( std::map< Node, bool >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
- if( prev!=Node::null() ){
- Debug("uf-ss-cliques") << " = ";
- //explain it2->first and prev
- std::vector< TNode > expl;
- d_th->d_equalityEngine.explainEquality( it2->first, prev, true, expl );
- for( int i=0; i<(int)expl.size(); i++ ){
- if( std::find( conflict.begin(), conflict.end(), expl[i] )==conflict.end() ){
- conflict.push_back( expl[i] );
+ if( options::ufssExplainedCliques() ){
+ //Debug("uf-ss-cliques") << conflict.size() << " " << clique.size() << std::endl;
+ Assert( (int)conflict.size()==((int)clique.size()*( (int)clique.size()-1 )/2) );
+ //Assert( (int)conflict.size()==(int)clique.size()*( (int)clique.size()-1 )/2 );
+ Debug("uf-ss-cliques") << "Finding clique equalities internal to eq classes..." << std::endl;
+ //now, we must explain equalities within each equivalence class
+ for( std::map< Node, std::map< Node, bool > >::iterator it = nodesWithinRep.begin(); it != nodesWithinRep.end(); ++it ){
+ if( it->second.size()>1 ){
+ Node prev;
+ //add explanation of t1 = t2 = ... = tn
+ Debug("uf-ss-cliques") << "Explain ";
+ for( std::map< Node, bool >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
+ if( prev!=Node::null() ){
+ Debug("uf-ss-cliques") << " = ";
+ //explain it2->first and prev
+ std::vector< TNode > expl;
+ d_thss->getTheory()->d_equalityEngine.explainEquality( it2->first, prev, true, expl );
+ for( int i=0; i<(int)expl.size(); i++ ){
+ if( std::find( conflict.begin(), conflict.end(), expl[i] )==conflict.end() ){
+ conflict.push_back( expl[i] );
+ }
+ }
}
+ prev = it2->first;
+ Debug("uf-ss-cliques") << prev;
}
+ Debug("uf-ss-cliques") << std::endl;
}
- prev = it2->first;
- Debug("uf-ss-cliques") << prev;
+ }
+ Debug("uf-ss-cliques") << "Explanation of clique (size=" << conflict.size() << ") = " << std::endl;
+ for( int i=0; i<(int)conflict.size(); i++ ){
+ Debug("uf-ss-cliques") << conflict[i] << " ";
}
Debug("uf-ss-cliques") << std::endl;
}
- }
- Debug("uf-ss-cliques") << "Explanation of clique (size=" << conflict.size() << ") = " << std::endl;
- for( int i=0; i<(int)conflict.size(); i++ ){
- Debug("uf-ss-cliques") << conflict[i] << " ";
- //bool value;
- //bool hasValue = d_th->getValuation().hasSatValue( conflict[i], value );
- //Assert( hasValue );
- //Assert( value );
- }
- Debug("uf-ss-cliques") << std::endl;
- //now, make the conflict
-#if 1
- conflict.push_back( d_cardinality_literal[ d_cardinality ] );
- Node conflictNode = NodeManager::currentNM()->mkNode( AND, conflict );
- Trace("uf-ss-lemma") << "*** Add clique conflict " << conflictNode << std::endl;
- //Notice() << "*** Add clique conflict " << conflictNode << std::endl;
- out->conflict( conflictNode );
- d_conflict = true;
-#else
- Node conflictNode = conflict.size()==1 ? conflict[0] : NodeManager::currentNM()->mkNode( AND, conflict );
- //add cardinality constraint
- Node cardNode = d_cardinality_literal[ d_cardinality ];
- //bool value;
- //bool hasValue = d_th->getValuation().hasSatValue( cardNode, value );
- //Assert( hasValue );
- //Assert( value );
- conflictNode = NodeManager::currentNM()->mkNode( IMPLIES, conflictNode, cardNode.notNode() );
- Trace("uf-ss-lemma") << "*** Add clique conflict " << conflictNode << std::endl;
- //Notice() << "*** Add clique conflict " << conflictNode << std::endl;
- out->lemma( conflictNode );
-#endif
- ++( d_th->getStrongSolver()->d_statistics.d_clique_lemmas );
+ //now, make the conflict
+ if( isSatConflict ){
+ conflict.push_back( d_cardinality_literal[ d_cardinality ] );
+ Node conflictNode = NodeManager::currentNM()->mkNode( AND, conflict );
+ Trace("uf-ss-lemma") << "*** Add clique conflict " << conflictNode << std::endl;
+ //Notice() << "*** Add clique conflict " << conflictNode << std::endl;
+ out->conflict( conflictNode );
+ d_conflict = true;
+ ++( d_thss->d_statistics.d_clique_conflicts );
+ }else{
+ Node conflictNode = conflict.size()==1 ? conflict[0] : NodeManager::currentNM()->mkNode( AND, conflict );
+ //add cardinality constraint
+ Node cardNode = d_cardinality_literal[ d_cardinality ];
+ //bool value;
+ //bool hasValue = d_th->getValuation().hasSatValue( cardNode, value );
+ //Assert( hasValue );
+ //Assert( value );
+ conflictNode = NodeManager::currentNM()->mkNode( IMPLIES, conflictNode, cardNode.notNode() );
+ Trace("uf-ss-lemma") << "*** Add clique lemma " << conflictNode << std::endl;
+ out->lemma( conflictNode );
+ ++( d_thss->d_statistics.d_clique_lemmas );
+ }
- //DO_THIS: ensure that the same clique is not reported??? Check standard effort after assertDisequal can produce same clique.
+ //DO_THIS: ensure that the same clique is not reported??? Check standard effort after assertDisequal can produce same clique.
+ }
}
-void StrongSolverTheoryUf::SortRepModel::addTotalityAxiom( Node n, int cardinality, OutputChannel* out ){
+void StrongSolverTheoryUF::SortModel::addTotalityAxiom( Node n, int cardinality, OutputChannel* out ){
Node cardLit = d_cardinality_literal[ cardinality ];
std::vector< Node > eqs;
for( int i=0; i<cardinality; i++ ){
@@ -1141,25 +1226,25 @@ void StrongSolverTheoryUf::SortRepModel::addTotalityAxiom( Node n, int cardinali
Node lem = NodeManager::currentNM()->mkNode( IMPLIES, cardLit, ax );
Trace("uf-ss-lemma") << "*** Add totality axiom " << lem << std::endl;
//send as lemma to the output channel
- d_th->getOutputChannel().lemma( lem );
- ++( d_th->getStrongSolver()->d_statistics.d_totality_lemmas );
+ d_thss->getOutputChannel().lemma( lem );
+ ++( d_thss->d_statistics.d_totality_lemmas );
}
/** apply totality */
-bool StrongSolverTheoryUf::SortRepModel::applyTotality( int cardinality ){
+bool StrongSolverTheoryUF::SortModel::applyTotality( int cardinality ){
return options::ufssTotality() || cardinality<=options::ufssTotalityLimited();
// || ( options::ufssModelInference() && !d_totality_terms[cardinality].empty() );
}
/** get totality lemma terms */
-Node StrongSolverTheoryUf::SortRepModel::getTotalityLemmaTerm( int cardinality, int i ){
+Node StrongSolverTheoryUF::SortModel::getTotalityLemmaTerm( int cardinality, int i ){
return d_totality_terms[0][i];
//}else{
// return d_totality_terms[cardinality][i];
//}
}
-void StrongSolverTheoryUf::SortRepModel::debugPrint( const char* c ){
+void StrongSolverTheoryUF::SortModel::debugPrint( const char* c ){
Debug( c ) << "-- Conflict Find:" << std::endl;
Debug( c ) << "Number of reps = " << d_reps << std::endl;
Debug( c ) << "Cardinality req = " << d_cardinality << std::endl;
@@ -1184,7 +1269,7 @@ void StrongSolverTheoryUf::SortRepModel::debugPrint( const char* c ){
}
}
-void StrongSolverTheoryUf::SortRepModel::debugModel( TheoryModel* m ){
+void StrongSolverTheoryUF::SortModel::debugModel( TheoryModel* m ){
if( Trace.isOn("uf-ss-warn") ){
std::vector< Node > eqcs;
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &m->d_equalityEngine );
@@ -1211,7 +1296,7 @@ void StrongSolverTheoryUf::SortRepModel::debugModel( TheoryModel* m ){
}
}
-int StrongSolverTheoryUf::SortRepModel::getNumRegions(){
+int StrongSolverTheoryUF::SortModel::getNumRegions(){
int count = 0;
for( int i=0; i<(int)d_regions_index; i++ ){
if( d_regions[i]->d_valid ){
@@ -1221,8 +1306,8 @@ int StrongSolverTheoryUf::SortRepModel::getNumRegions(){
return count;
}
-void StrongSolverTheoryUf::SortRepModel::getRepresentatives( std::vector< Node >& reps ){
- if( !options::ufssColoringSat() ){
+void StrongSolverTheoryUF::SortModel::getRepresentatives( std::vector< Node >& reps ){
+ //if( !options::ufssColoringSat() ){
bool foundRegion = false;
for( int i=0; i<(int)d_regions_index; i++ ){
//should not have multiple regions at this point
@@ -1235,126 +1320,12 @@ void StrongSolverTheoryUf::SortRepModel::getRepresentatives( std::vector< Node >
foundRegion = true;
}
}
- }else{
- Unimplemented("Build representatives for fmf region sat is not implemented");
- }
-}
-
-
-/** initialize */
-void StrongSolverTheoryUf::InfRepModel::initialize( OutputChannel* out ){
-
-}
-
-/** new node */
-void StrongSolverTheoryUf::InfRepModel::newEqClass( Node n ){
- d_rep[n] = n;
- //d_const_rep[n] = n.getMetaKind()==metakind::CONSTANT;
-}
-
-/** merge */
-void StrongSolverTheoryUf::InfRepModel::merge( Node a, Node b ){
- //d_rep[b] = false;
- //d_const_rep[a] = d_const_rep[a] || d_const_rep[b];
- Node repb = d_rep[b];
- Assert( !repb.isNull() );
- if( repb.getMetaKind()==metakind::CONSTANT || isBadRepresentative( d_rep[a] ) ){
- d_rep[a] = repb;
- }
- d_rep[b] = Node::null();
-}
-
-/** check */
-void StrongSolverTheoryUf::InfRepModel::check( Theory::Effort level, OutputChannel* out ){
-
-}
-
-/** minimize */
-bool StrongSolverTheoryUf::InfRepModel::minimize( OutputChannel* out ){
-#if 0
- bool retVal = true;
-#else
- bool retVal = !addSplit( out );
-#endif
- if( retVal ){
- std::vector< Node > reps;
- getRepresentatives( reps );
- Trace("uf-ss-fmf") << "Num representatives of type " << d_type << " : " << reps.size() << std::endl;
- /*
- for( int i=0; i<(int)reps.size(); i++ ){
- std::cout << reps[i] << " ";
- }
- std::cout << std::endl;
- for( int i=0; i<(int)reps.size(); i++ ){
- std::cout << reps[i].getMetaKind() << " ";
- }
- std::cout << std::endl;
- for( NodeNodeMap::iterator it = d_rep.begin(); it != d_rep.end(); ++it ){
- Node rep = (*it).second;
- if( !rep.isNull() && !isBadRepresentative( rep ) ){
- for( NodeNodeMap::iterator it2 = d_rep.begin(); it2 != d_rep.end(); ++it2 ){
- Node rep2 = (*it2).second;
- if( !rep2.isNull() && !isBadRepresentative( rep2 ) ){
- if( d_th->getQuantifiersEngine()->getEqualityQuery()->areDisequal( rep, rep2 ) ){
- std::cout << "1 ";
- }else{
- std::cout << "0 ";
- }
- }
- }
- //std::cout << " : " << rep;
- std::cout << std::endl;
- }
- }
- */
- }
- return retVal;
-}
-
-/** get representatives */
-void StrongSolverTheoryUf::InfRepModel::getRepresentatives( std::vector< Node >& reps ){
- for( NodeNodeMap::iterator it = d_rep.begin(); it != d_rep.end(); ++it ){
- if( !(*it).second.isNull() ){
- reps.push_back( (*it).first );
- }
- }
-}
-
-
-/** add split function */
-bool StrongSolverTheoryUf::InfRepModel::addSplit( OutputChannel* out ){
- std::vector< Node > visited;
- for( NodeNodeMap::iterator it = d_rep.begin(); it != d_rep.end(); ++it ){
- Node rep = (*it).second;
- if( !rep.isNull() && !isBadRepresentative( rep ) ){
- bool constRep = rep.getMetaKind()==metakind::CONSTANT;
- for( size_t i=0; i<visited.size(); i++ ){
- if( !constRep || !visited[i].getMetaKind()==metakind::CONSTANT ){
- if( !d_th->getQuantifiersEngine()->getEqualityQuery()->areDisequal( rep, visited[i] ) ){
- //split on these nodes
- Node eq = rep.eqNode( visited[i] );
- Trace("uf-ss-lemma") << "*** Split on " << eq << std::endl;
- eq = Rewriter::rewrite( eq );
- Debug("uf-ss-lemma-debug") << "Rewritten " << eq << std::endl;
- out->split( eq );
- //explore the equals branch first
- out->requirePhase( eq, true );
- ++( d_th->getStrongSolver()->d_statistics.d_split_lemmas );
- return true;
- }
- }
- }
- visited.push_back( rep );
- }
- }
- return false;
-}
-
-bool StrongSolverTheoryUf::InfRepModel::isBadRepresentative( Node n ){
- return n.getKind()==kind::PLUS;
+ //}else{
+ // Unimplemented("Build representatives for fmf region sat is not implemented");
+ //}
}
-StrongSolverTheoryUf::StrongSolverTheoryUf(context::Context* c, context::UserContext* u, OutputChannel& out, TheoryUF* th) :
+StrongSolverTheoryUF::StrongSolverTheoryUF(context::Context* c, context::UserContext* u, OutputChannel& out, TheoryUF* th) :
d_out( &out ),
d_th( th ),
d_conflict( c, false ),
@@ -1367,78 +1338,129 @@ d_rep_model_init( c )
}else{
d_term_amb = NULL;
}
+ if( options::ufssDiseqPropagation() ){
+ d_deq_prop = new DisequalityPropagator( th->getQuantifiersEngine(), this );
+ }else{
+ d_deq_prop = NULL;
+ }
+}
+
+/** get default sat context */
+context::Context* StrongSolverTheoryUF::getSatContext() {
+ return d_th->getSatContext();
+}
+
+/** get default output channel */
+OutputChannel& StrongSolverTheoryUF::getOutputChannel() {
+ return d_th->getOutputChannel();
}
/** new node */
-void StrongSolverTheoryUf::newEqClass( Node n ){
- RepModel* c = getRepModel( n );
+void StrongSolverTheoryUF::newEqClass( Node n ){
+ SortModel* c = getSortModel( n );
if( c ){
- Trace("uf-ss-solver") << "StrongSolverTheoryUf: New eq class " << n << " : " << n.getType() << std::endl;
+ Trace("uf-ss-solver") << "StrongSolverTheoryUF: New eq class " << n << " : " << n.getType() << std::endl;
c->newEqClass( n );
}
}
/** merge */
-void StrongSolverTheoryUf::merge( Node a, Node b ){
- RepModel* c = getRepModel( a );
+void StrongSolverTheoryUF::merge( Node a, Node b ){
+ SortModel* c = getSortModel( a );
if( c ){
- Trace("uf-ss-solver") << "StrongSolverTheoryUf: Merge " << a << " " << b << " : " << a.getType() << std::endl;
+ Trace("uf-ss-solver") << "StrongSolverTheoryUF: Merge " << a << " " << b << " : " << a.getType() << std::endl;
c->merge( a, b );
+ }else{
+ if( options::ufssDiseqPropagation() ){
+ d_deq_prop->merge(a, b);
+ }
}
}
/** assert terms are disequal */
-void StrongSolverTheoryUf::assertDisequal( Node a, Node b, Node reason ){
- RepModel* c = getRepModel( a );
+void StrongSolverTheoryUF::assertDisequal( Node a, Node b, Node reason ){
+ SortModel* c = getSortModel( a );
if( c ){
- Trace("uf-ss-solver") << "StrongSolverTheoryUf: Assert disequal " << a << " " << b << " : " << a.getType() << std::endl;
+ 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 );
c->assertDisequal( a, b, reason );
+ }else{
+ if( options::ufssDiseqPropagation() ){
+ d_deq_prop->assertDisequal(a, b, reason);
+ }
}
}
/** assert a node */
-void StrongSolverTheoryUf::assertNode( Node n, bool isDecision ){
+void StrongSolverTheoryUF::assertNode( Node n, bool isDecision ){
Trace("uf-ss") << "Assert " << n << " " << isDecision << std::endl;
- if( n.getKind()==CARDINALITY_CONSTRAINT ){
- TypeNode tn = n[0].getType();
+ bool polarity = n.getKind() != kind::NOT;
+ TNode lit = polarity ? n : n[0];
+ if( lit.getKind()==CARDINALITY_CONSTRAINT ){
+ TypeNode tn = lit[0].getType();
Assert( tn.isSort() );
Assert( d_rep_model[tn] );
- long nCard = n[1].getConst<Rational>().getNumerator().getLong();
- d_rep_model[tn]->assertCardinality( d_out, nCard, true );
- }else if( n.getKind()==NOT && n[0].getKind()==CARDINALITY_CONSTRAINT ){
- Node nn = n[0];
- TypeNode tn = nn[0].getType();
- Assert( tn.isSort() );
- Assert( d_rep_model[tn] );
- long nCard = nn[1].getConst<Rational>().getNumerator().getLong();
- d_rep_model[tn]->assertCardinality( d_out, nCard, false );
+ long nCard = lit[1].getConst<Rational>().getNumerator().getLong();
+ d_rep_model[tn]->assertCardinality( d_out, nCard, polarity );
}else{
- ////FIXME: this is too strict: theory propagations are showing up as isDecision=true, but
- //// a theory propagation is not a decision.
- if( isDecision ){
- for( std::map< TypeNode, RepModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
- if( !it->second->hasCardinalityAsserted() ){
- Trace("uf-ss-warn") << "WARNING: Assert " << n << " as a decision before cardinality for " << it->first << "." << std::endl;
- //Message() << "Error: constraint asserted before cardinality for " << it->first << std::endl;
- //Unimplemented();
+ if( Trace.isOn("uf-ss-warn") ){
+ ////FIXME: this is too strict: theory propagations are showing up as isDecision=true, but
+ //// a theory propagation is not a decision.
+ if( isDecision ){
+ for( std::map< TypeNode, SortModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
+ if( !it->second->hasCardinalityAsserted() ){
+ Trace("uf-ss-warn") << "WARNING: Assert " << n << " as a decision before cardinality for " << it->first << "." << std::endl;
+ //Message() << "Error: constraint asserted before cardinality for " << it->first << std::endl;
+ //Unimplemented();
+ }
}
}
}
+ if( lit.getKind()!=EQUAL ){
+ //it is a predicate
+ if( options::ufssDiseqPropagation() ){
+ d_deq_prop->assertPredicate(lit, polarity);
+ }
+ }
}
Trace("uf-ss") << "Assert: done " << n << " " << isDecision << std::endl;
}
+bool StrongSolverTheoryUF::areDisequal( Node a, Node b ) {
+ if( a==b ){
+ return false;
+ }else{
+ a = d_th->d_equalityEngine.getRepresentative( a );
+ b = d_th->d_equalityEngine.getRepresentative( b );
+ if( d_th->d_equalityEngine.areDisequal( a, b, false ) ){
+ return true;
+ }else{
+ SortModel* c = getSortModel( a );
+ if( c ){
+ return c->areDisequal( a, b );
+ }else{
+ return false;
+ }
+ }
+ }
+}
/** check */
-void StrongSolverTheoryUf::check( Theory::Effort level ){
+void StrongSolverTheoryUF::check( Theory::Effort level ){
if( !d_conflict ){
- Trace("uf-ss-solver") << "StrongSolverTheoryUf: check " << level << std::endl;
+ Trace("uf-ss-solver") << "StrongSolverTheoryUF: check " << level << std::endl;
if( level==Theory::EFFORT_FULL ){
debugPrint( "uf-ss-debug" );
}
- for( std::map< TypeNode, RepModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
+ if( !d_conflict && level==Theory::EFFORT_FULL && options::ufssColoringSat() ){
+ int lemmas = d_term_amb->disambiguateTerms( d_out );
+ d_statistics.d_disamb_term_lemmas += lemmas;
+ if( lemmas>=0 ){
+ return;
+ }
+ }
+ for( std::map< TypeNode, SortModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
it->second->check( level, d_out );
if( it->second->isConflict() ){
d_conflict = true;
@@ -1446,24 +1468,24 @@ void StrongSolverTheoryUf::check( Theory::Effort level ){
}
}
//disambiguate terms if necessary
- if( !d_conflict && level==Theory::EFFORT_FULL && options::ufssColoringSat() ){
- Assert( d_term_amb!=NULL );
- d_statistics.d_disamb_term_lemmas += d_term_amb->disambiguateTerms( d_out );
- }
- Trace("uf-ss-solver") << "Done StrongSolverTheoryUf: check " << level << std::endl;
+ //if( !d_conflict && level==Theory::EFFORT_FULL && options::ufssColoringSat() ){
+ // Assert( d_term_amb!=NULL );
+ // d_statistics.d_disamb_term_lemmas += d_term_amb->disambiguateTerms( d_out );
+ //}
+ Trace("uf-ss-solver") << "Done StrongSolverTheoryUF: check " << level << std::endl;
}
}
/** propagate */
-void StrongSolverTheoryUf::propagate( Theory::Effort level ){
- //for( std::map< TypeNode, RepModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
+void StrongSolverTheoryUF::propagate( Theory::Effort level ){
+ //for( std::map< TypeNode, SortModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
// it->second->propagate( level, d_out );
//}
}
/** get next decision request */
-Node StrongSolverTheoryUf::getNextDecisionRequest(){
- for( std::map< TypeNode, RepModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
+Node StrongSolverTheoryUF::getNextDecisionRequest(){
+ for( std::map< TypeNode, SortModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
Node n = it->second->getNextDecisionRequest();
if( !n.isNull() ){
return n;
@@ -1472,18 +1494,15 @@ Node StrongSolverTheoryUf::getNextDecisionRequest(){
return Node::null();
}
-void StrongSolverTheoryUf::preRegisterTerm( TNode n ){
+void StrongSolverTheoryUF::preRegisterTerm( TNode n ){
Trace("uf-ss-register") << "Preregister " << n << "." << std::endl;
//shouldn't have to preregister this type (it may be that there are no quantifiers over tn)
TypeNode tn = n.getType();
if( d_rep_model.find( tn )==d_rep_model.end() ){
- RepModel* rm = NULL;
+ SortModel* rm = NULL;
if( tn.isSort() ){
Trace("uf-ss-register") << "Preregister sort " << tn << "." << std::endl;
- rm = new SortRepModel( n, d_th->getSatContext(), d_th );
- }else if( tn.isInteger() ){
- //rm = new InfRepModel( tn, d_th->getSatContext(), d_th );
- //rm = new SortRepModel( tn, d_th->getSatContext(), d_th );
+ rm = new SortModel( n, d_th->getSatContext(), this );
}else{
/*
if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){
@@ -1509,7 +1528,7 @@ void StrongSolverTheoryUf::preRegisterTerm( TNode n ){
}
}
-void StrongSolverTheoryUf::registerQuantifier( Node f ){
+void StrongSolverTheoryUF::registerQuantifier( Node f ){
Debug("uf-ss-register") << "Register quantifier " << f << std::endl;
//must ensure the quantifier does not quantify over arithmetic
//for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
@@ -1519,9 +1538,9 @@ void StrongSolverTheoryUf::registerQuantifier( Node f ){
}
-StrongSolverTheoryUf::RepModel* StrongSolverTheoryUf::getRepModel( Node n ){
+StrongSolverTheoryUF::SortModel* StrongSolverTheoryUF::getSortModel( Node n ){
TypeNode tn = n.getType();
- std::map< TypeNode, RepModel* >::iterator it = d_rep_model.find( tn );
+ std::map< TypeNode, SortModel* >::iterator it = d_rep_model.find( tn );
//pre-register the type if not done already
if( it==d_rep_model.end() ){
preRegisterTerm( n );
@@ -1539,13 +1558,13 @@ StrongSolverTheoryUf::RepModel* StrongSolverTheoryUf::getRepModel( Node n ){
return NULL;
}
-void StrongSolverTheoryUf::notifyRestart(){
+void StrongSolverTheoryUF::notifyRestart(){
}
/** get cardinality for sort */
-int StrongSolverTheoryUf::getCardinality( Node n ) {
- RepModel* c = getRepModel( n );
+int StrongSolverTheoryUF::getCardinality( Node n ) {
+ SortModel* c = getSortModel( n );
if( c ){
return c->getCardinality();
}else{
@@ -1553,27 +1572,27 @@ int StrongSolverTheoryUf::getCardinality( Node n ) {
}
}
-void StrongSolverTheoryUf::getRepresentatives( Node n, std::vector< Node >& reps ){
- RepModel* c = getRepModel( n );
+void StrongSolverTheoryUF::getRepresentatives( Node n, std::vector< Node >& reps ){
+ SortModel* c = getSortModel( n );
if( c ){
c->getRepresentatives( reps );
}
}
-bool StrongSolverTheoryUf::minimize( TheoryModel* m ){
- for( std::map< TypeNode, RepModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
+bool StrongSolverTheoryUF::minimize( TheoryModel* m ){
+ for( std::map< TypeNode, SortModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
if( !it->second->minimize( d_out, m ) ){
return false;
}
}
- for( std::map< TypeNode, RepModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
+ for( std::map< TypeNode, SortModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
Trace("uf-ss-minimize") << "Cardinality( " << it->first << " ) : " << it->second->getCardinality() << std::endl;
}
return true;
}
//print debug
-void StrongSolverTheoryUf::debugPrint( const char* c ){
+void StrongSolverTheoryUF::debugPrint( const char* c ){
//EqClassesIterator< TheoryUF::NotifyClass > eqc_iter( &((TheoryUF*)d_th)->d_equalityEngine );
//while( !eqc_iter.isFinished() ){
// Debug( c ) << "Eq class [[" << (*eqc_iter) << "]]" << std::endl;
@@ -1587,28 +1606,30 @@ void StrongSolverTheoryUf::debugPrint( const char* c ){
// eqc_iter++;
//}
- for( std::map< TypeNode, RepModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
+ for( std::map< TypeNode, SortModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
Debug( c ) << "Conflict find structure for " << it->first << ": " << std::endl;
it->second->debugPrint( c );
Debug( c ) << std::endl;
}
}
-void StrongSolverTheoryUf::debugModel( TheoryModel* m ){
+void StrongSolverTheoryUF::debugModel( TheoryModel* m ){
if( Trace.isOn("uf-ss-warn") ){
- for( std::map< TypeNode, RepModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
+ for( std::map< TypeNode, SortModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
it->second->debugModel( m );
}
}
}
-StrongSolverTheoryUf::Statistics::Statistics():
- d_clique_lemmas("StrongSolverTheoryUf::Clique_Lemmas", 0),
- d_split_lemmas("StrongSolverTheoryUf::Split_Lemmas", 0),
- d_disamb_term_lemmas("StrongSolverTheoryUf::Disambiguate_Term_Lemmas", 0),
- d_totality_lemmas("StrongSolverTheoryUf::Totality_Lemmas", 0),
- d_max_model_size("StrongSolverTheoryUf::Max_Model_Size", 1)
+StrongSolverTheoryUF::Statistics::Statistics():
+ d_clique_conflicts("StrongSolverTheoryUF::Clique_Conflicts", 0),
+ d_clique_lemmas("StrongSolverTheoryUF::Clique_Lemmas", 0),
+ d_split_lemmas("StrongSolverTheoryUF::Split_Lemmas", 0),
+ d_disamb_term_lemmas("StrongSolverTheoryUF::Disambiguate_Term_Lemmas", 0),
+ d_totality_lemmas("StrongSolverTheoryUF::Totality_Lemmas", 0),
+ d_max_model_size("StrongSolverTheoryUF::Max_Model_Size", 1)
{
+ StatisticsRegistry::registerStat(&d_clique_conflicts);
StatisticsRegistry::registerStat(&d_clique_lemmas);
StatisticsRegistry::registerStat(&d_split_lemmas);
StatisticsRegistry::registerStat(&d_disamb_term_lemmas);
@@ -1616,7 +1637,8 @@ StrongSolverTheoryUf::Statistics::Statistics():
StatisticsRegistry::registerStat(&d_max_model_size);
}
-StrongSolverTheoryUf::Statistics::~Statistics(){
+StrongSolverTheoryUF::Statistics::~Statistics(){
+ StatisticsRegistry::unregisterStat(&d_clique_conflicts);
StatisticsRegistry::unregisterStat(&d_clique_lemmas);
StatisticsRegistry::unregisterStat(&d_split_lemmas);
StatisticsRegistry::unregisterStat(&d_disamb_term_lemmas);
@@ -1667,11 +1689,12 @@ int TermDisambiguator::disambiguateTerms( OutputChannel* out ){
}
Assert( children.size()>1 );
Node lem = NodeManager::currentNM()->mkNode( OR, children );
- Debug( "uf-ss-lemma" ) << "*** Disambiguate lemma : " << lem << std::endl;
+ Trace( "uf-ss-lemma" ) << "*** Disambiguate lemma : " << lem << std::endl;
//Notice() << "*** Disambiguate lemma : " << lem << std::endl;
out->lemma( lem );
d_term_amb[ eq ] = false;
lemmaAdded++;
+ return lemmaAdded;
}
}
}
@@ -1693,3 +1716,73 @@ bool TermDisambiguator::involvesRelevantType( Node n ){
}
return false;
}
+
+DisequalityPropagator::DisequalityPropagator(QuantifiersEngine* qe, StrongSolverTheoryUF* ufss) :
+ d_qe(qe), d_ufss(ufss){
+ d_true = NodeManager::currentNM()->mkConst( true );
+ d_false = NodeManager::currentNM()->mkConst( false );
+}
+
+void DisequalityPropagator::checkEquivalenceClass( Node t, Node eqc ) {
+ if( t.getKind()==APPLY_UF ){
+ Node op = t.getOperator();
+ eqc = d_ufss->getTheory()->getEqualityEngine()->getRepresentative( eqc );
+ eq::EqClassIterator eqc_i(eqc, d_ufss->getTheory()->getEqualityEngine());
+ while( !eqc_i.isFinished() ){
+ Node s = *eqc_i;
+ if( s.getKind()==APPLY_UF && s.getOperator()==op ){
+ int unkIndex = -1;
+ for( size_t i=0; i<t.getNumChildren(); i++ ){
+ //should consult strong solver since it knows more disequalities
+ if( d_ufss->areDisequal( t[i], s[i] ) ){
+ //if( d_qe->getEqualityQuery()->areDisequal( t[i], s[i] ) ){
+ unkIndex = -1;
+ break;
+ }else if( !d_qe->getEqualityQuery()->areEqual( t[i], s[i] ) ){
+ if( unkIndex==-1 ){
+ unkIndex = i;
+ }else{
+ unkIndex = -1;
+ break;
+ }
+ }
+ }
+ if( unkIndex!=-1 ){
+ Trace("deq-prop") << "propagate disequality " << t[unkIndex] << " " << s[unkIndex] << std::endl;
+ d_ufss->assertDisequal(t[unkIndex], s[unkIndex], Node::null());
+ ++( d_statistics.d_propagations );
+ if( d_ufss->isConflict() ){
+ return;
+ }
+ }
+ }
+ ++eqc_i;
+ }
+ }
+}
+
+/** merge */
+void DisequalityPropagator::merge( Node a, Node b ){
+
+}
+
+/** assert terms are disequal */
+void DisequalityPropagator::assertDisequal( Node a, Node b, Node reason ){
+ Trace("deq-prop") << "Notify disequal : " << a << " " << b << std::endl;
+}
+
+
+void DisequalityPropagator::assertPredicate( Node p, bool polarity ) {
+ Trace("deq-prop") << "Assert predicate : " << p << " " << polarity << std::endl;
+ checkEquivalenceClass( p, polarity ? d_false : d_true );
+}
+
+DisequalityPropagator::Statistics::Statistics():
+ d_propagations("StrongSolverTheoryUF::Disequality_Propagations", 0)
+{
+ StatisticsRegistry::registerStat(& d_propagations);
+}
+
+DisequalityPropagator::Statistics::~Statistics(){
+ StatisticsRegistry::unregisterStat(& d_propagations);
+} \ No newline at end of file
diff --git a/src/theory/uf/theory_uf_strong_solver.h b/src/theory/uf/theory_uf_strong_solver.h
index febae2eae..33493248d 100644
--- a/src/theory/uf/theory_uf_strong_solver.h
+++ b/src/theory/uf/theory_uf_strong_solver.h
@@ -31,8 +31,9 @@ namespace uf {
class TheoryUF;
class TermDisambiguator;
+class DisequalityPropagator;
-class StrongSolverTheoryUf{
+class StrongSolverTheoryUF{
protected:
typedef context::CDHashMap<Node, bool, NodeHashFunction> NodeBoolMap;
typedef context::CDHashMap<Node, int, NodeHashFunction> NodeIntMap;
@@ -42,51 +43,14 @@ protected:
typedef context::CDList<bool> IntList;
typedef context::CDHashMap<TypeNode, bool, TypeNodeHashFunction> TypeNodeBoolMap;
public:
- class RepModel {
- protected:
- /** type */
- TypeNode d_type;
- public:
- RepModel( TypeNode tn ) : d_type( tn ){}
- virtual ~RepModel(){}
- /** initialize */
- virtual void initialize( OutputChannel* out ) = 0;
- /** new node */
- virtual void newEqClass( Node n ) = 0;
- /** merge */
- virtual void merge( Node a, Node b ) = 0;
- /** assert terms are disequal */
- virtual void assertDisequal( Node a, Node b, Node reason ) = 0;
- /** check */
- virtual void check( Theory::Effort level, OutputChannel* out ){}
- /** get next decision request */
- virtual Node getNextDecisionRequest() { return Node::null(); }
- /** minimize */
- virtual bool minimize( OutputChannel* out, TheoryModel* m ){ return true; }
- /** assert cardinality */
- virtual void assertCardinality( OutputChannel* out, int c, bool val ){}
- /** is in conflict */
- virtual bool isConflict() { return false; }
- /** get cardinality */
- virtual int getCardinality() { return -1; }
- /** has cardinality */
- virtual bool hasCardinalityAsserted() { return true; }
- /** get representatives */
- virtual void getRepresentatives( std::vector< Node >& reps ){}
- /** print debug */
- virtual void debugPrint( const char* c ){}
- /** debug a model */
- virtual void debugModel( TheoryModel* m ){}
- };
-public:
/** information for incremental conflict/clique finding for a particular sort */
- class SortRepModel : public RepModel {
+ class SortModel {
public:
/** a partition of the current equality graph for which cliques can occur internally */
class Region {
public:
/** conflict find pointer */
- SortRepModel* d_cf;
+ SortModel* d_cf;
/** information stored about each node in region */
class RegionNodeInfo {
public:
@@ -142,7 +106,7 @@ public:
void setRep( Node n, bool valid );
public:
//constructor
- Region( SortRepModel* cf, context::Context* c ) : d_cf( cf ), d_testCliqueSize( c, 0 ),
+ Region( SortModel* cf, context::Context* c ) : d_cf( cf ), d_testCliqueSize( c, 0 ),
d_splitsSize( c, 0 ), d_testClique( c ), d_splits( c ), d_reps_size( c, 0 ),
d_total_diseq_external( c, 0 ), d_total_diseq_internal( c, 0 ), d_valid( c, true ) {
}
@@ -186,8 +150,10 @@ public:
void debugPrint( const char* c, bool incClique = false );
};
private:
- /** theory uf pointer */
- TheoryUF* d_th;
+ /** the type this model is for */
+ TypeNode d_type;
+ /** strong solver pointer */
+ StrongSolverTheoryUF* d_thss;
/** regions used to d_region_index */
context::CDO< unsigned > d_regions_index;
/** vector of regions */
@@ -213,7 +179,7 @@ public:
void setSplitScore( Node n, int s );
private:
/** check if we need to combine region ri */
- void checkRegion( int ri, bool rec = true );
+ void checkRegion( int ri, bool checkCombine = true );
/** force combine region */
int forceCombineRegion( int ri, bool useDensity = true );
/** merge regions */
@@ -256,8 +222,8 @@ public:
/** get totality lemma terms */
Node getTotalityLemmaTerm( int cardinality, int i );
public:
- SortRepModel( Node n, context::Context* c, TheoryUF* th );
- virtual ~SortRepModel(){}
+ SortModel( Node n, context::Context* c, StrongSolverTheoryUF* thss );
+ virtual ~SortModel(){}
/** initialize */
void initialize( OutputChannel* out );
/** new node */
@@ -266,6 +232,8 @@ public:
void merge( Node a, Node b );
/** assert terms are disequal */
void assertDisequal( Node a, Node b, Node reason );
+ /** are disequal */
+ bool areDisequal( Node a, Node b );
/** check */
void check( Theory::Effort level, OutputChannel* out );
/** propagate */
@@ -291,43 +259,7 @@ public:
public:
/** get number of regions (for debugging) */
int getNumRegions();
- }; /** class SortRepModel */
-private:
- /** infinite rep model */
- class InfRepModel : public RepModel
- {
- protected:
- /** theory uf pointer */
- TheoryUF* d_th;
- /** list of representatives */
- NodeNodeMap d_rep;
- /** whether representatives are constant */
- NodeBoolMap d_const_rep;
- /** add split */
- bool addSplit( OutputChannel* out );
- /** is bad representative */
- bool isBadRepresentative( Node n );
- public:
- InfRepModel( TypeNode tn, context::Context* c, TheoryUF* th ) : RepModel( tn ),
- d_th( th ), d_rep( c ), d_const_rep( c ){}
- virtual ~InfRepModel(){}
- /** initialize */
- void initialize( OutputChannel* out );
- /** new node */
- void newEqClass( Node n );
- /** merge */
- void merge( Node a, Node b );
- /** assert terms are disequal */
- void assertDisequal( Node a, Node b, Node reason ){}
- /** check */
- void check( Theory::Effort level, OutputChannel* out );
- /** minimize */
- bool minimize( OutputChannel* out );
- /** get representatives */
- void getRepresentatives( std::vector< Node >& reps );
- /** print debug */
- void debugPrint( const char* c ){}
- };
+ }; /** class SortModel */
private:
/** The output channel for the strong solver. */
OutputChannel* d_out;
@@ -336,19 +268,31 @@ private:
/** Are we in conflict */
context::CDO<bool> d_conflict;
/** rep model structure, one for each type */
- std::map< TypeNode, RepModel* > d_rep_model;
+ std::map< TypeNode, SortModel* > d_rep_model;
/** all types */
std::vector< TypeNode > d_conf_types;
/** whether conflict find data structures have been initialized */
TypeNodeBoolMap d_rep_model_init;
/** get conflict find */
- RepModel* getRepModel( Node n );
+ SortModel* getSortModel( Node n );
private:
/** term disambiguator */
TermDisambiguator* d_term_amb;
+ /** disequality propagator */
+ DisequalityPropagator* d_deq_prop;
public:
- StrongSolverTheoryUf(context::Context* c, context::UserContext* u, OutputChannel& out, TheoryUF* th);
- ~StrongSolverTheoryUf() {}
+ StrongSolverTheoryUF(context::Context* c, context::UserContext* u, OutputChannel& out, TheoryUF* th);
+ ~StrongSolverTheoryUF() {}
+ /** get theory */
+ TheoryUF* getTheory() { return d_th; }
+ /** term disambiguator */
+ TermDisambiguator* getTermDisambiguator() { return d_term_amb; }
+ /** disequality propagator */
+ DisequalityPropagator* getDisequalityPropagator() { return d_deq_prop; }
+ /** get default sat context */
+ context::Context* getSatContext();
+ /** get default output channel */
+ OutputChannel& getOutputChannel();
/** new node */
void newEqClass( Node n );
/** merge */
@@ -357,6 +301,8 @@ public:
void assertDisequal( Node a, Node b, Node reason );
/** assert node */
void assertNode( Node n, bool isDecision );
+ /** are disequal */
+ bool areDisequal( Node a, Node b );
public:
/** check */
void check( Theory::Effort level );
@@ -372,7 +318,7 @@ public:
void notifyRestart();
public:
/** identify */
- std::string identify() const { return std::string("StrongSolverTheoryUf"); }
+ std::string identify() const { return std::string("StrongSolverTheoryUF"); }
//print debug
void debugPrint( const char* c );
/** debug a model */
@@ -393,6 +339,7 @@ public:
class Statistics {
public:
+ IntStat d_clique_conflicts;
IntStat d_clique_lemmas;
IntStat d_split_lemmas;
IntStat d_disamb_term_lemmas;
@@ -403,7 +350,7 @@ public:
};
/** statistics class */
Statistics d_statistics;
-};/* class StrongSolverTheoryUf */
+};/* class StrongSolverTheoryUF */
class TermDisambiguator
@@ -422,6 +369,37 @@ public:
int disambiguateTerms( OutputChannel* out );
};
+class DisequalityPropagator
+{
+private:
+ /** quantifiers engine */
+ QuantifiersEngine* d_qe;
+ /** strong solver */
+ StrongSolverTheoryUF* d_ufss;
+ /** true,false */
+ Node d_true;
+ Node d_false;
+ /** check term t against equivalence class that t is disequal from */
+ void checkEquivalenceClass( Node t, Node eqc );
+public:
+ DisequalityPropagator(QuantifiersEngine* qe, StrongSolverTheoryUF* ufss);
+ /** merge */
+ void merge( Node a, Node b );
+ /** assert terms are disequal */
+ void assertDisequal( Node a, Node b, Node reason );
+ /** assert predicate */
+ void assertPredicate( Node p, bool polarity );
+public:
+ class Statistics {
+ public:
+ IntStat d_propagations;
+ Statistics();
+ ~Statistics();
+ };
+ /** statistics class */
+ Statistics d_statistics;
+};
+
}
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/util/configuration.cpp b/src/util/configuration.cpp
index 59fe28eca..c6e951049 100644
--- a/src/util/configuration.cpp
+++ b/src/util/configuration.cpp
@@ -195,6 +195,33 @@ bool Configuration::isTraceTag(char const * tag){
return false;
}
+bool Configuration::isGitBuild() {
+ return IS_GIT_BUILD;
+}
+
+const char* Configuration::getGitBranchName() {
+ return GIT_BRANCH_NAME;
+}
+
+const char* Configuration::getGitCommit() {
+ return GIT_COMMIT;
+}
+
+bool Configuration::hasGitModifications() {
+ return GIT_HAS_MODIFICATIONS;
+}
+
+std::string Configuration::getGitId() {
+ if(! isGitBuild()) {
+ return "";
+ }
+
+ stringstream ss;
+ ss << "git " << getGitBranchName() << " " << string(getGitCommit()).substr(0, 8)
+ << ( ::CVC4::Configuration::hasGitModifications() ? " (with modifications)" : "" );
+ return ss.str();
+}
+
bool Configuration::isSubversionBuild() {
return IS_SUBVERSION_BUILD;
}
@@ -211,7 +238,7 @@ bool Configuration::hasSubversionModifications() {
return SUBVERSION_HAS_MODIFICATIONS;
}
-string Configuration::getSubversionId() {
+std::string Configuration::getSubversionId() {
if(! isSubversionBuild()) {
return "";
}
diff --git a/src/util/configuration.h b/src/util/configuration.h
index 3f6547872..c85f62f7f 100644
--- a/src/util/configuration.h
+++ b/src/util/configuration.h
@@ -38,6 +38,10 @@ class CVC4_PUBLIC Configuration {
static const char* const SUBVERSION_BRANCH_NAME;
static const unsigned SUBVERSION_REVISION;
static const bool SUBVERSION_HAS_MODIFICATIONS;
+ static const bool IS_GIT_BUILD;
+ static const char* const GIT_BRANCH_NAME;
+ static const char* const GIT_COMMIT;
+ static const bool GIT_HAS_MODIFICATIONS;
public:
@@ -101,6 +105,12 @@ public:
/* Test if the given argument is a known trace tag name */
static bool isTraceTag(char const *);
+ static bool isGitBuild();
+ static const char* getGitBranchName();
+ static const char* getGitCommit();
+ static bool hasGitModifications();
+ static std::string getGitId();
+
static bool isSubversionBuild();
static const char* getSubversionBranchName();
static unsigned getSubversionRevision();
diff --git a/src/util/configuration_private.h b/src/util/configuration_private.h
index c480b4318..4378badc8 100644
--- a/src/util/configuration_private.h
+++ b/src/util/configuration_private.h
@@ -115,13 +115,16 @@ namespace CVC4 {
#define CVC4_ABOUT_STRING ( ::std::string("\
This is CVC4 version " CVC4_RELEASE_STRING ) + \
+ ( ::CVC4::Configuration::isGitBuild() \
+ ? ( ::std::string(" [") + ::CVC4::Configuration::getGitId() + "]" ) \
+ : \
( ::CVC4::Configuration::isSubversionBuild() \
? ( ::std::string(" [") + ::CVC4::Configuration::getSubversionId() + "]" ) \
: ::std::string("") \
- ) + "\n\
+ )) + "\n\
compiled with " + ::CVC4::Configuration::getCompiler() + "\n\
on " + ::CVC4::Configuration::getCompiledDateTime() + "\n\n\
-Copyright (C) 2009, 2010, 2011, 2012\n\
+Copyright (C) 2009, 2010, 2011, 2012, 2013\n\
New York University and The University of Iowa\n\n" + \
( IS_CLN_BUILD ? "\
This CVC4 library uses CLN as its multi-precision arithmetic library.\n\n\
diff --git a/src/util/integer.h.in b/src/util/integer.h.in
index 1f0174083..27b589b5a 100644
--- a/src/util/integer.h.in
+++ b/src/util/integer.h.in
@@ -1,5 +1,5 @@
/********************* */
-/*! \file integer.h
+/*! \file integer.h.in
** \verbatim
** Original author: taking
** Major contributors: none
diff --git a/src/util/rational.h.in b/src/util/rational.h.in
index c8e42a253..7f5b1feb4 100644
--- a/src/util/rational.h.in
+++ b/src/util/rational.h.in
@@ -1,5 +1,5 @@
/********************* */
-/*! \file rational.h
+/*! \file rational.h.in
** \verbatim
** Original author: taking
** Major contributors: none
diff --git a/src/util/sort_inference.cpp b/src/util/sort_inference.cpp
index 7e0af3e9f..d700b70d9 100755..100644
--- a/src/util/sort_inference.cpp
+++ b/src/util/sort_inference.cpp
@@ -1,408 +1,428 @@
-/********************* */
-/*! \file sort_inference.cpp
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Sort inference module
- **
- ** This class implements sort inference, based on a simple algorithm:
- ** First, we assume all functions and predicates have distinct uninterpreted types.
- ** One pass is made through the input assertions, while a union-find data structure
- ** maintains necessary information regarding constraints on these types.
- **/
-
-#include <vector>
-
-#include "util/sort_inference.h"
-
-using namespace CVC4;
-using namespace std;
-
-namespace CVC4 {
-
-
-void SortInference::printSort( const char* c, int t ){
- int rt = getRepresentative( t );
- if( d_type_types.find( rt )!=d_type_types.end() ){
- Trace(c) << d_type_types[rt];
- }else{
- Trace(c) << "s_" << rt;
- }
-}
-
-void SortInference::simplify( std::vector< Node >& assertions, bool doRewrite ){
- //process all assertions
- for( unsigned i=0; i<assertions.size(); i++ ){
- Trace("sort-inference-debug") << "Process " << assertions[i] << std::endl;
- std::map< Node, Node > var_bound;
- process( assertions[i], var_bound );
- }
- //print debug
- if( Trace.isOn("sort-inference") ){
- for( std::map< Node, int >::iterator it = d_op_return_types.begin(); it != d_op_return_types.end(); ++it ){
- Trace("sort-inference") << it->first << " : ";
- if( !d_op_arg_types[ it->first ].empty() ){
- Trace("sort-inference") << "( ";
- for( size_t i=0; i<d_op_arg_types[ it->first ].size(); i++ ){
- printSort( "sort-inference", d_op_arg_types[ it->first ][i] );
- Trace("sort-inference") << " ";
- }
- Trace("sort-inference") << ") -> ";
- }
- printSort( "sort-inference", it->second );
- Trace("sort-inference") << std::endl;
- }
- }
- if( doRewrite ){
- //simplify all assertions by introducing new symbols wherever necessary (NOTE: this is unsound for quantifiers)
- for( unsigned i=0; i<assertions.size(); i++ ){
- std::map< Node, Node > var_bound;
- assertions[i] = simplify( assertions[i], var_bound );
- Trace("sort-inference-rewrite") << " --> " << assertions[i] << std::endl;
- }
- //now, ensure constants are distinct
- for( std::map< TypeNode, std::map< Node, Node > >::iterator it = d_const_map.begin(); it != d_const_map.end(); ++it ){
- std::vector< Node > consts;
- for( std::map< Node, Node >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
- consts.push_back( it2->second );
- }
- //add lemma enforcing introduced constants to be distinct?
- }
- }
-}
-
-int SortInference::getRepresentative( int t ){
- std::map< int, int >::iterator it = d_type_union_find.find( t );
- if( it!=d_type_union_find.end() ){
- if( it->second==t ){
- return t;
- }else{
- int rt = getRepresentative( it->second );
- d_type_union_find[t] = rt;
- return rt;
- }
- }else{
- return t;
- }
-}
-
-void SortInference::setEqual( int t1, int t2 ){
- if( t1!=t2 ){
- int rt1 = getRepresentative( t1 );
- int rt2 = getRepresentative( t2 );
- if( rt1!=rt2 ){
- Trace("sort-inference-debug") << "Set equal : ";
- printSort( "sort-inference-debug", rt1 );
- Trace("sort-inference-debug") << " ";
- printSort( "sort-inference-debug", rt2 );
- Trace("sort-inference-debug") << std::endl;
- //check if they must be a type
- std::map< int, TypeNode >::iterator it1 = d_type_types.find( rt1 );
- std::map< int, TypeNode >::iterator it2 = d_type_types.find( rt2 );
- if( it2!=d_type_types.end() ){
- if( it1==d_type_types.end() ){
- //swap sides
- int swap = rt1;
- rt1 = rt2;
- rt2 = swap;
- }else{
- Assert( rt1==rt2 );
- }
- }
- /*
- d_type_eq_class[rt1].insert( d_type_eq_class[rt1].end(), d_type_eq_class[rt2].begin(), d_type_eq_class[rt2].end() );
- d_type_eq_class[rt2].clear();
- Trace("sort-inference-debug") << "EqClass : { ";
- for( int i=0; i<(int)d_type_eq_class[rt1].size(); i++ ){
- Trace("sort-inference-debug") << d_type_eq_class[rt1][i] << ", ";
- }
- Trace("sort-inference-debug") << "}" << std::endl;
- */
- d_type_union_find[rt2] = rt1;
- }
- }
-}
-
-int SortInference::getIdForType( TypeNode tn ){
- //register the return type
- std::map< TypeNode, int >::iterator it = d_id_for_types.find( tn );
- if( it==d_id_for_types.end() ){
- int sc = sortCount;
- d_type_types[ sortCount ] = tn;
- d_id_for_types[ tn ] = sortCount;
- sortCount++;
- return sc;
- }else{
- return it->second;
- }
-}
-
-int SortInference::process( Node n, std::map< Node, Node >& var_bound ){
- Trace("sort-inference-debug") << "Process " << n << std::endl;
- //add to variable bindings
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
- for( size_t i=0; i<n[0].getNumChildren(); i++ ){
- //TODO: try applying sort inference to quantified variables
- //d_var_types[n][ n[0][i] ] = sortCount;
- //sortCount++;
-
- //type of the quantified variable must be the same
- d_var_types[n][ n[0][i] ] = getIdForType( n[0][i].getType() );
- var_bound[ n[0][i] ] = n;
- }
- }
-
- //process children
- std::vector< Node > children;
- std::vector< int > child_types;
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- bool processChild = true;
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
- processChild = i==1;
- }
- if( processChild ){
- children.push_back( n[i] );
- child_types.push_back( process( n[i], var_bound ) );
- }
- }
-
- //remove from variable bindings
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
- //erase from variable bound
- for( size_t i=0; i<n[0].getNumChildren(); i++ ){
- var_bound.erase( n[0][i] );
- }
- }
-
- int retType;
- if( n.getKind()==kind::EQUAL ){
- //we only require that the left and right hand side must be equal
- setEqual( child_types[0], child_types[1] );
- retType = getIdForType( n.getType() );
- }else if( n.getKind()==kind::APPLY_UF ){
- Node op = n.getOperator();
- if( d_op_return_types.find( op )==d_op_return_types.end() ){
- //assign arbitrary sort for return type
- d_op_return_types[op] = sortCount;
- sortCount++;
- //d_type_eq_class[sortCount].push_back( op );
- //assign arbitrary sort for argument types
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- d_op_arg_types[op].push_back( sortCount );
- sortCount++;
- }
- }
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- //the argument of the operator must match the return type of the subterm
- setEqual( child_types[i], d_op_arg_types[op][i] );
- }
- //return type is the return type
- retType = d_op_return_types[op];
- }else{
- std::map< Node, Node >::iterator it = var_bound.find( n );
- if( it!=var_bound.end() ){
- Trace("sort-inference-debug") << n << " is a bound variable." << std::endl;
- //the return type was specified while binding
- retType = d_var_types[it->second][n];
- }else if( n.getKind() == kind::VARIABLE ){
- Trace("sort-inference-debug") << n << " is a variable." << std::endl;
- if( d_op_return_types.find( n )==d_op_return_types.end() ){
- //assign arbitrary sort
- d_op_return_types[n] = sortCount;
- sortCount++;
- //d_type_eq_class[sortCount].push_back( n );
- }
- retType = d_op_return_types[n];
- }else if( n.isConst() ){
- Trace("sort-inference-debug") << n << " is a constant." << std::endl;
- //can be any type we want
- retType = sortCount;
- sortCount++;
- }else{
- Trace("sort-inference-debug") << n << " is a interpreted symbol." << std::endl;
- //it is an interpretted term
- for( size_t i=0; i<children.size(); i++ ){
- Trace("sort-inference-debug") << children[i] << " forced to have " << children[i].getType() << std::endl;
- //must enforce the actual type of the operator on the children
- int ct = getIdForType( children[i].getType() );
- setEqual( child_types[i], ct );
- }
- //return type must be the actual return type
- retType = getIdForType( n.getType() );
- }
- }
- Trace("sort-inference-debug") << "Type( " << n << " ) = ";
- printSort("sort-inference-debug", retType );
- Trace("sort-inference-debug") << std::endl;
- return retType;
-}
-
-
-TypeNode SortInference::getOrCreateTypeForId( int t, TypeNode pref ){
- int rt = getRepresentative( t );
- if( d_type_types.find( rt )!=d_type_types.end() ){
- return d_type_types[rt];
- }else{
- TypeNode retType;
- //see if we can assign pref
- if( !pref.isNull() && d_id_for_types.find( pref )==d_id_for_types.end() ){
- retType = pref;
- }else{
- if( d_subtype_count.find( pref )==d_subtype_count.end() ){
- d_subtype_count[pref] = 0;
- }
- //must create new type
- std::stringstream ss;
- ss << "it_" << d_subtype_count[pref] << "_" << pref;
- d_subtype_count[pref]++;
- retType = NodeManager::currentNM()->mkSort( ss.str() );
- }
- d_id_for_types[ retType ] = rt;
- d_type_types[ rt ] = retType;
- return retType;
- }
-}
-
-TypeNode SortInference::getTypeForId( int t ){
- int rt = getRepresentative( t );
- if( d_type_types.find( rt )!=d_type_types.end() ){
- return d_type_types[rt];
- }else{
- return TypeNode::null();
- }
-}
-
-Node SortInference::getNewSymbol( Node old, TypeNode tn ){
- if( tn==old.getType() ){
- return old;
- }else if( old.isConst() ){
- //must make constant of type tn
- if( d_const_map[tn].find( old )==d_const_map[tn].end() ){
- std::stringstream ss;
- ss << "ic_" << tn << "_" << old;
- d_const_map[tn][ old ] = NodeManager::currentNM()->mkSkolem( ss.str(), tn, "constant created during sort inference" ); //use mkConst???
- }
- return d_const_map[tn][ old ];
- }else{
- std::stringstream ss;
- ss << "i_$$_" << old;
- return NodeManager::currentNM()->mkSkolem( ss.str(), tn, "created during sort inference" );
- }
-}
-
-Node SortInference::simplify( Node n, std::map< Node, Node >& var_bound ){
- std::vector< Node > children;
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
- //recreate based on types of variables
- std::vector< Node > new_children;
- for( size_t i=0; i<n[0].getNumChildren(); i++ ){
- TypeNode tn = getOrCreateTypeForId( d_var_types[n][ n[0][i] ], n[0][i].getType() );
- Node v = getNewSymbol( n[0][i], tn );
- new_children.push_back( v );
- var_bound[ n[0][i] ] = v;
- }
- children.push_back( NodeManager::currentNM()->mkNode( n[0].getKind(), new_children ) );
- }
-
- //process children
- if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
- children.push_back( n.getOperator() );
- }
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- bool processChild = true;
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
- processChild = i>=1;
- }
- if( processChild ){
- children.push_back( simplify( n[i], var_bound ) );
- }
- }
-
- //remove from variable bindings
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
- //erase from variable bound
- for( size_t i=0; i<n[0].getNumChildren(); i++ ){
- var_bound.erase( n[0][i] );
- }
- return NodeManager::currentNM()->mkNode( n.getKind(), children );
- }else if( n.getKind()==kind::EQUAL ){
- if( children[0].getType()!=children[1].getType() ){
- if( children[0].isConst() ){
- children[0] = getNewSymbol( children[0], children[1].getType() );
- }else if( children[1].isConst() ){
- children[1] = getNewSymbol( children[1], children[0].getType() );
- }else{
- Trace("sort-inference-warn") << "Sort inference created bad equality: " << children[0] << " = " << children[1] << std::endl;
- Trace("sort-inference-warn") << " Types : " << children[0].getType() << " " << children[1].getType() << std::endl;
- Assert( false );
- }
- }
- return NodeManager::currentNM()->mkNode( kind::APPLY_UF, children );
- }else if( n.getKind()==kind::APPLY_UF ){
- Node op = n.getOperator();
- if( d_symbol_map.find( op )==d_symbol_map.end() ){
- //make the new operator if necessary
- bool opChanged = false;
- std::vector< TypeNode > argTypes;
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- TypeNode tn = getOrCreateTypeForId( d_op_arg_types[op][i], n[i].getType() );
- argTypes.push_back( tn );
- if( tn!=n[i].getType() ){
- opChanged = true;
- }
- }
- TypeNode retType = getOrCreateTypeForId( d_op_return_types[op], n.getType() );
- if( retType!=n.getType() ){
- opChanged = true;
- }
- if( opChanged ){
- std::stringstream ss;
- ss << "io_$$_" << op;
- TypeNode typ = NodeManager::currentNM()->mkFunctionType( argTypes, retType );
- d_symbol_map[op] = NodeManager::currentNM()->mkSkolem( ss.str(), typ, "op created during sort inference" );
- }else{
- d_symbol_map[op] = op;
- }
- }
- children[0] = d_symbol_map[op];
- //make sure all children have been taken care of
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- TypeNode tn = children[i+1].getType();
- TypeNode tna = getTypeForId( d_op_arg_types[op][i] );
- if( tn!=tna ){
- if( n[i].isConst() ){
- children[i+1] = getNewSymbol( n[i], tna );
- }else{
- Trace("sort-inference-warn") << "Sort inference created bad child: " << n[i] << " " << tn << " " << tna << std::endl;
- Assert( false );
- }
- }
- }
- return NodeManager::currentNM()->mkNode( kind::APPLY_UF, children );
- }else{
- std::map< Node, Node >::iterator it = var_bound.find( n );
- if( it!=var_bound.end() ){
- return it->second;
- }else if( n.getKind() == kind::VARIABLE ){
- if( d_symbol_map.find( n )==d_symbol_map.end() ){
- TypeNode tn = getOrCreateTypeForId( d_op_return_types[n], n.getType() );
- d_symbol_map[n] = getNewSymbol( n, tn );
- }
- return d_symbol_map[n];
- }else if( n.isConst() ){
- //just return n, we will fix at higher scope
- return n;
- }else{
- return NodeManager::currentNM()->mkNode( n.getKind(), children );
- }
- }
-
-}
-
-}
+/********************* */
+/*! \file sort_inference.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Sort inference module
+ **
+ ** This class implements sort inference, based on a simple algorithm:
+ ** First, we assume all functions and predicates have distinct uninterpreted types.
+ ** One pass is made through the input assertions, while a union-find data structure
+ ** maintains necessary information regarding constraints on these types.
+ **/
+
+#include <vector>
+
+#include "util/sort_inference.h"
+
+using namespace CVC4;
+using namespace std;
+
+namespace CVC4 {
+
+
+void SortInference::printSort( const char* c, int t ){
+ int rt = getRepresentative( t );
+ if( d_type_types.find( rt )!=d_type_types.end() ){
+ Trace(c) << d_type_types[rt];
+ }else{
+ Trace(c) << "s_" << rt;
+ }
+}
+
+void SortInference::simplify( std::vector< Node >& assertions, bool doRewrite ){
+ //process all assertions
+ for( unsigned i=0; i<assertions.size(); i++ ){
+ Trace("sort-inference-debug") << "Process " << assertions[i] << std::endl;
+ std::map< Node, Node > var_bound;
+ process( assertions[i], var_bound );
+ }
+ //print debug
+ if( Trace.isOn("sort-inference") ){
+ for( std::map< Node, int >::iterator it = d_op_return_types.begin(); it != d_op_return_types.end(); ++it ){
+ Trace("sort-inference") << it->first << " : ";
+ if( !d_op_arg_types[ it->first ].empty() ){
+ Trace("sort-inference") << "( ";
+ for( size_t i=0; i<d_op_arg_types[ it->first ].size(); i++ ){
+ printSort( "sort-inference", d_op_arg_types[ it->first ][i] );
+ Trace("sort-inference") << " ";
+ }
+ Trace("sort-inference") << ") -> ";
+ }
+ printSort( "sort-inference", it->second );
+ Trace("sort-inference") << std::endl;
+ }
+ for( std::map< Node, std::map< Node, int > >::iterator it = d_var_types.begin(); it != d_var_types.end(); ++it ){
+ Trace("sort-inference") << "Quantified formula " << it->first << " : " << std::endl;
+ for( std::map< Node, int >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
+ printSort( "sort-inference", it2->second );
+ Trace("sort-inference") << std::endl;
+ }
+ Trace("sort-inference") << std::endl;
+ }
+ }
+ if( doRewrite ){
+ //simplify all assertions by introducing new symbols wherever necessary (NOTE: this is unsound for quantifiers)
+ for( unsigned i=0; i<assertions.size(); i++ ){
+ std::map< Node, Node > var_bound;
+ assertions[i] = simplify( assertions[i], var_bound );
+ Trace("sort-inference-rewrite") << " --> " << assertions[i] << std::endl;
+ }
+ //now, ensure constants are distinct
+ for( std::map< TypeNode, std::map< Node, Node > >::iterator it = d_const_map.begin(); it != d_const_map.end(); ++it ){
+ std::vector< Node > consts;
+ for( std::map< Node, Node >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
+ consts.push_back( it2->second );
+ }
+ //add lemma enforcing introduced constants to be distinct?
+ }
+ }
+}
+
+int SortInference::getRepresentative( int t ){
+ std::map< int, int >::iterator it = d_type_union_find.find( t );
+ if( it!=d_type_union_find.end() ){
+ if( it->second==t ){
+ return t;
+ }else{
+ int rt = getRepresentative( it->second );
+ d_type_union_find[t] = rt;
+ return rt;
+ }
+ }else{
+ return t;
+ }
+}
+
+void SortInference::setEqual( int t1, int t2 ){
+ if( t1!=t2 ){
+ int rt1 = getRepresentative( t1 );
+ int rt2 = getRepresentative( t2 );
+ if( rt1!=rt2 ){
+ Trace("sort-inference-debug") << "Set equal : ";
+ printSort( "sort-inference-debug", rt1 );
+ Trace("sort-inference-debug") << " ";
+ printSort( "sort-inference-debug", rt2 );
+ Trace("sort-inference-debug") << std::endl;
+ //check if they must be a type
+ std::map< int, TypeNode >::iterator it1 = d_type_types.find( rt1 );
+ std::map< int, TypeNode >::iterator it2 = d_type_types.find( rt2 );
+ if( it2!=d_type_types.end() ){
+ if( it1==d_type_types.end() ){
+ //swap sides
+ int swap = rt1;
+ rt1 = rt2;
+ rt2 = swap;
+ }else{
+ Assert( rt1==rt2 );
+ }
+ }
+ /*
+ d_type_eq_class[rt1].insert( d_type_eq_class[rt1].end(), d_type_eq_class[rt2].begin(), d_type_eq_class[rt2].end() );
+ d_type_eq_class[rt2].clear();
+ Trace("sort-inference-debug") << "EqClass : { ";
+ for( int i=0; i<(int)d_type_eq_class[rt1].size(); i++ ){
+ Trace("sort-inference-debug") << d_type_eq_class[rt1][i] << ", ";
+ }
+ Trace("sort-inference-debug") << "}" << std::endl;
+ */
+ d_type_union_find[rt2] = rt1;
+ }
+ }
+}
+
+int SortInference::getIdForType( TypeNode tn ){
+ //register the return type
+ std::map< TypeNode, int >::iterator it = d_id_for_types.find( tn );
+ if( it==d_id_for_types.end() ){
+ int sc = sortCount;
+ d_type_types[ sortCount ] = tn;
+ d_id_for_types[ tn ] = sortCount;
+ sortCount++;
+ return sc;
+ }else{
+ return it->second;
+ }
+}
+
+int SortInference::process( Node n, std::map< Node, Node >& var_bound ){
+ Trace("sort-inference-debug") << "Process " << n << std::endl;
+ //add to variable bindings
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ for( size_t i=0; i<n[0].getNumChildren(); i++ ){
+ //TODO: try applying sort inference to quantified variables
+ d_var_types[n][ n[0][i] ] = sortCount;
+ sortCount++;
+
+ //type of the quantified variable must be the same
+ //d_var_types[n][ n[0][i] ] = getIdForType( n[0][i].getType() );
+ var_bound[ n[0][i] ] = n;
+ }
+ }
+
+ //process children
+ std::vector< Node > children;
+ std::vector< int > child_types;
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ bool processChild = true;
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ processChild = i==1;
+ }
+ if( processChild ){
+ children.push_back( n[i] );
+ child_types.push_back( process( n[i], var_bound ) );
+ }
+ }
+
+ //remove from variable bindings
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ //erase from variable bound
+ for( size_t i=0; i<n[0].getNumChildren(); i++ ){
+ var_bound.erase( n[0][i] );
+ }
+ }
+
+ int retType;
+ if( n.getKind()==kind::EQUAL ){
+ //we only require that the left and right hand side must be equal
+ setEqual( child_types[0], child_types[1] );
+ retType = getIdForType( n.getType() );
+ }else if( n.getKind()==kind::APPLY_UF ){
+ Node op = n.getOperator();
+ if( d_op_return_types.find( op )==d_op_return_types.end() ){
+ //assign arbitrary sort for return type
+ d_op_return_types[op] = sortCount;
+ sortCount++;
+ //d_type_eq_class[sortCount].push_back( op );
+ //assign arbitrary sort for argument types
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ d_op_arg_types[op].push_back( sortCount );
+ sortCount++;
+ }
+ }
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ //the argument of the operator must match the return type of the subterm
+ setEqual( child_types[i], d_op_arg_types[op][i] );
+ }
+ //return type is the return type
+ retType = d_op_return_types[op];
+ }else{
+ std::map< Node, Node >::iterator it = var_bound.find( n );
+ if( it!=var_bound.end() ){
+ Trace("sort-inference-debug") << n << " is a bound variable." << std::endl;
+ //the return type was specified while binding
+ retType = d_var_types[it->second][n];
+ }else if( n.getKind() == kind::VARIABLE ){
+ Trace("sort-inference-debug") << n << " is a variable." << std::endl;
+ if( d_op_return_types.find( n )==d_op_return_types.end() ){
+ //assign arbitrary sort
+ d_op_return_types[n] = sortCount;
+ sortCount++;
+ //d_type_eq_class[sortCount].push_back( n );
+ }
+ retType = d_op_return_types[n];
+ }else if( n.isConst() ){
+ Trace("sort-inference-debug") << n << " is a constant." << std::endl;
+ //can be any type we want
+ retType = sortCount;
+ sortCount++;
+ }else{
+ Trace("sort-inference-debug") << n << " is a interpreted symbol." << std::endl;
+ //it is an interpretted term
+ for( size_t i=0; i<children.size(); i++ ){
+ Trace("sort-inference-debug") << children[i] << " forced to have " << children[i].getType() << std::endl;
+ //must enforce the actual type of the operator on the children
+ int ct = getIdForType( children[i].getType() );
+ setEqual( child_types[i], ct );
+ }
+ //return type must be the actual return type
+ retType = getIdForType( n.getType() );
+ }
+ }
+ Trace("sort-inference-debug") << "Type( " << n << " ) = ";
+ printSort("sort-inference-debug", retType );
+ Trace("sort-inference-debug") << std::endl;
+ return retType;
+}
+
+
+TypeNode SortInference::getOrCreateTypeForId( int t, TypeNode pref ){
+ int rt = getRepresentative( t );
+ if( d_type_types.find( rt )!=d_type_types.end() ){
+ return d_type_types[rt];
+ }else{
+ TypeNode retType;
+ //see if we can assign pref
+ if( !pref.isNull() && d_id_for_types.find( pref )==d_id_for_types.end() ){
+ retType = pref;
+ }else{
+ if( d_subtype_count.find( pref )==d_subtype_count.end() ){
+ d_subtype_count[pref] = 0;
+ }
+ //must create new type
+ std::stringstream ss;
+ ss << "it_" << d_subtype_count[pref] << "_" << pref;
+ d_subtype_count[pref]++;
+ retType = NodeManager::currentNM()->mkSort( ss.str() );
+ }
+ d_id_for_types[ retType ] = rt;
+ d_type_types[ rt ] = retType;
+ return retType;
+ }
+}
+
+TypeNode SortInference::getTypeForId( int t ){
+ int rt = getRepresentative( t );
+ if( d_type_types.find( rt )!=d_type_types.end() ){
+ return d_type_types[rt];
+ }else{
+ return TypeNode::null();
+ }
+}
+
+Node SortInference::getNewSymbol( Node old, TypeNode tn ){
+ if( tn==old.getType() ){
+ return old;
+ }else if( old.isConst() ){
+ //must make constant of type tn
+ if( d_const_map[tn].find( old )==d_const_map[tn].end() ){
+ std::stringstream ss;
+ ss << "ic_" << tn << "_" << old;
+ d_const_map[tn][ old ] = NodeManager::currentNM()->mkSkolem( ss.str(), tn, "constant created during sort inference" ); //use mkConst???
+ }
+ return d_const_map[tn][ old ];
+ }else{
+ std::stringstream ss;
+ ss << "i_$$_" << old;
+ return NodeManager::currentNM()->mkSkolem( ss.str(), tn, "created during sort inference" );
+ }
+}
+
+Node SortInference::simplify( Node n, std::map< Node, Node >& var_bound ){
+ std::vector< Node > children;
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ //recreate based on types of variables
+ std::vector< Node > new_children;
+ for( size_t i=0; i<n[0].getNumChildren(); i++ ){
+ TypeNode tn = getOrCreateTypeForId( d_var_types[n][ n[0][i] ], n[0][i].getType() );
+ Node v = getNewSymbol( n[0][i], tn );
+ new_children.push_back( v );
+ var_bound[ n[0][i] ] = v;
+ }
+ children.push_back( NodeManager::currentNM()->mkNode( n[0].getKind(), new_children ) );
+ }
+
+ //process children
+ if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ children.push_back( n.getOperator() );
+ }
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ bool processChild = true;
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ processChild = i>=1;
+ }
+ if( processChild ){
+ children.push_back( simplify( n[i], var_bound ) );
+ }
+ }
+
+ //remove from variable bindings
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ //erase from variable bound
+ for( size_t i=0; i<n[0].getNumChildren(); i++ ){
+ var_bound.erase( n[0][i] );
+ }
+ return NodeManager::currentNM()->mkNode( n.getKind(), children );
+ }else if( n.getKind()==kind::EQUAL ){
+ if( children[0].getType()!=children[1].getType() ){
+ if( children[0].isConst() ){
+ children[0] = getNewSymbol( children[0], children[1].getType() );
+ }else if( children[1].isConst() ){
+ children[1] = getNewSymbol( children[1], children[0].getType() );
+ }else{
+ Trace("sort-inference-warn") << "Sort inference created bad equality: " << children[0] << " = " << children[1] << std::endl;
+ Trace("sort-inference-warn") << " Types : " << children[0].getType() << " " << children[1].getType() << std::endl;
+ Assert( false );
+ }
+ }
+ return NodeManager::currentNM()->mkNode( kind::APPLY_UF, children );
+ }else if( n.getKind()==kind::APPLY_UF ){
+ Node op = n.getOperator();
+ if( d_symbol_map.find( op )==d_symbol_map.end() ){
+ //make the new operator if necessary
+ bool opChanged = false;
+ std::vector< TypeNode > argTypes;
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ TypeNode tn = getOrCreateTypeForId( d_op_arg_types[op][i], n[i].getType() );
+ argTypes.push_back( tn );
+ if( tn!=n[i].getType() ){
+ opChanged = true;
+ }
+ }
+ TypeNode retType = getOrCreateTypeForId( d_op_return_types[op], n.getType() );
+ if( retType!=n.getType() ){
+ opChanged = true;
+ }
+ if( opChanged ){
+ std::stringstream ss;
+ ss << "io_$$_" << op;
+ TypeNode typ = NodeManager::currentNM()->mkFunctionType( argTypes, retType );
+ d_symbol_map[op] = NodeManager::currentNM()->mkSkolem( ss.str(), typ, "op created during sort inference" );
+ }else{
+ d_symbol_map[op] = op;
+ }
+ }
+ children[0] = d_symbol_map[op];
+ //make sure all children have been taken care of
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ TypeNode tn = children[i+1].getType();
+ TypeNode tna = getTypeForId( d_op_arg_types[op][i] );
+ if( tn!=tna ){
+ if( n[i].isConst() ){
+ children[i+1] = getNewSymbol( n[i], tna );
+ }else{
+ Trace("sort-inference-warn") << "Sort inference created bad child: " << n[i] << " " << tn << " " << tna << std::endl;
+ Assert( false );
+ }
+ }
+ }
+ return NodeManager::currentNM()->mkNode( kind::APPLY_UF, children );
+ }else{
+ std::map< Node, Node >::iterator it = var_bound.find( n );
+ if( it!=var_bound.end() ){
+ return it->second;
+ }else if( n.getKind() == kind::VARIABLE ){
+ if( d_symbol_map.find( n )==d_symbol_map.end() ){
+ TypeNode tn = getOrCreateTypeForId( d_op_return_types[n], n.getType() );
+ d_symbol_map[n] = getNewSymbol( n, tn );
+ }
+ return d_symbol_map[n];
+ }else if( n.isConst() ){
+ //just return n, we will fix at higher scope
+ return n;
+ }else{
+ return NodeManager::currentNM()->mkNode( n.getKind(), children );
+ }
+ }
+
+}
+int SortInference::getSortId( Node n ) {
+ Node op = n.getKind()==kind::APPLY_UF ? n.getOperator() : n;
+ return getRepresentative( d_op_return_types[op] );
+}
+
+int SortInference::getSortId( Node f, Node v ) {
+ return getRepresentative( d_var_types[f][v] );
+}
+
+void SortInference::setSkolemVar( Node f, Node v, Node sk ){
+ d_op_return_types[sk] = getSortId( f, v );
+}
+
+}/* CVC4 namespace */
diff --git a/src/util/sort_inference.h b/src/util/sort_inference.h
index 363dbd84d..0b1f96f85 100755..100644
--- a/src/util/sort_inference.h
+++ b/src/util/sort_inference.h
@@ -1,72 +1,76 @@
-/********************* */
-/*! \file sort_inference.h
- ** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief Pre-process step for performing sort inference
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__SORT_INFERENCE_H
-#define __CVC4__SORT_INFERENCE_H
-
-#include <iostream>
-#include <string>
-#include <vector>
-#include <map>
-#include "expr/node.h"
-#include "expr/type_node.h"
-
-namespace CVC4 {
-
-class SortInference{
-private:
- //for debugging
- //std::map< int, std::vector< Node > > d_type_eq_class;
-private:
- int sortCount;
- std::map< int, int > d_type_union_find;
- std::map< int, TypeNode > d_type_types;
- std::map< TypeNode, int > d_id_for_types;
- //for apply uf operators
- std::map< Node, int > d_op_return_types;
- std::map< Node, std::vector< int > > d_op_arg_types;
- //for bound variables
- std::map< Node, std::map< Node, int > > d_var_types;
- //get representative
- int getRepresentative( int t );
- void setEqual( int t1, int t2 );
- int getIdForType( TypeNode tn );
- void printSort( const char* c, int t );
- //process
- int process( Node n, std::map< Node, Node >& var_bound );
-private:
- //mapping from old symbols to new symbols
- std::map< Node, Node > d_symbol_map;
- //mapping from constants to new symbols
- std::map< TypeNode, std::map< Node, Node > > d_const_map;
- //number of subtypes generated
- std::map< TypeNode, int > d_subtype_count;
- //helper functions for simplify
- TypeNode getOrCreateTypeForId( int t, TypeNode pref );
- TypeNode getTypeForId( int t );
- Node getNewSymbol( Node old, TypeNode tn );
- //simplify
- Node simplify( Node n, std::map< Node, Node >& var_bound );
-public:
- SortInference() : sortCount( 0 ){}
- ~SortInference(){}
-
- void simplify( std::vector< Node >& assertions, bool doRewrite = false );
-};
-
-}
-
-#endif
+/********************* */
+/*! \file sort_inference.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Pre-process step for performing sort inference
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__SORT_INFERENCE_H
+#define __CVC4__SORT_INFERENCE_H
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <map>
+#include "expr/node.h"
+#include "expr/type_node.h"
+
+namespace CVC4 {
+
+class SortInference{
+private:
+ //for debugging
+ //std::map< int, std::vector< Node > > d_type_eq_class;
+private:
+ int sortCount;
+ std::map< int, int > d_type_union_find;
+ std::map< int, TypeNode > d_type_types;
+ std::map< TypeNode, int > d_id_for_types;
+ //for apply uf operators
+ std::map< Node, int > d_op_return_types;
+ std::map< Node, std::vector< int > > d_op_arg_types;
+ //for bound variables
+ std::map< Node, std::map< Node, int > > d_var_types;
+ //get representative
+ int getRepresentative( int t );
+ void setEqual( int t1, int t2 );
+ int getIdForType( TypeNode tn );
+ void printSort( const char* c, int t );
+ //process
+ int process( Node n, std::map< Node, Node >& var_bound );
+private:
+ //mapping from old symbols to new symbols
+ std::map< Node, Node > d_symbol_map;
+ //mapping from constants to new symbols
+ std::map< TypeNode, std::map< Node, Node > > d_const_map;
+ //number of subtypes generated
+ std::map< TypeNode, int > d_subtype_count;
+ //helper functions for simplify
+ TypeNode getOrCreateTypeForId( int t, TypeNode pref );
+ TypeNode getTypeForId( int t );
+ Node getNewSymbol( Node old, TypeNode tn );
+ //simplify
+ Node simplify( Node n, std::map< Node, Node >& var_bound );
+public:
+ SortInference() : sortCount( 0 ){}
+ ~SortInference(){}
+
+ void simplify( std::vector< Node >& assertions, bool doRewrite = false );
+ int getSortId( Node n );
+ int getSortId( Node f, Node v );
+ //set that sk is the skolem variable of v for quantifier f
+ void setSkolemVar( Node f, Node v, Node sk );
+};
+
+}
+
+#endif
diff --git a/src/util/tls.h.in b/src/util/tls.h.in
index 17f1f1d6e..935586f77 100644
--- a/src/util/tls.h.in
+++ b/src/util/tls.h.in
@@ -1,5 +1,5 @@
/********************* */
-/*! \file tls.h
+/*! \file tls.h.in
** \verbatim
** Original author: mdeters
** Major contributors: none
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback