summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac4
-rwxr-xr-xcontrib/run-script-casc24-fnt38
-rwxr-xr-xcontrib/run-script-casc24-fnt-no-models36
-rwxr-xr-xcontrib/run-script-casc24-fof37
-rw-r--r--library_versions1
-rw-r--r--src/decision/Makefile.am4
-rw-r--r--src/decision/decision_engine.cpp31
-rw-r--r--src/decision/options8
-rw-r--r--src/decision/options_handlers.h50
-rw-r--r--src/decision/relevancy.cpp379
-rw-r--r--src/decision/relevancy.h421
-rw-r--r--src/main/command_executor.cpp13
-rw-r--r--src/parser/options3
-rw-r--r--src/parser/parser_builder.cpp7
-rw-r--r--src/parser/parser_builder.h3
-rw-r--r--src/parser/tptp/tptp.cpp1
-rw-r--r--src/parser/tptp/tptp.h13
-rw-r--r--src/printer/smt2/smt2_printer.cpp32
-rw-r--r--src/proof/cnf_proof.cpp2
-rw-r--r--src/proof/cnf_proof.h2
-rw-r--r--src/proof/sat_proof.cpp57
-rw-r--r--src/proof/sat_proof.h31
-rw-r--r--src/prop/cnf_stream.cpp6
-rw-r--r--src/prop/minisat/core/Solver.cc11
-rw-r--r--src/prop/prop_engine.cpp3
-rw-r--r--src/smt/options2
-rw-r--r--src/smt/smt_engine.cpp36
-rw-r--r--src/theory/arith/normal_form.cpp33
-rw-r--r--src/theory/arith/normal_form.h9
-rw-r--r--src/theory/arith/theory_arith_private.cpp7
-rw-r--r--src/theory/arith/theory_arith_private.h3
-rw-r--r--src/theory/arrays/Makefile.am4
-rw-r--r--src/theory/arrays/theory_arrays.cpp9
-rw-r--r--src/theory/arrays/theory_arrays_model.cpp65
-rw-r--r--src/theory/arrays/theory_arrays_model.h58
-rw-r--r--src/theory/bv/bv_subtheory.h3
-rw-r--r--src/theory/bv/bv_subtheory_bitblast.cpp3
-rw-r--r--src/theory/bv/bv_subtheory_bitblast.h1
-rw-r--r--src/theory/bv/bv_subtheory_core.cpp69
-rw-r--r--src/theory/bv/options6
-rw-r--r--src/theory/bv/theory_bv.cpp11
-rw-r--r--src/theory/quantifiers/Makefile.am10
-rwxr-xr-xsrc/theory/quantifiers/bounded_integers.cpp366
-rwxr-xr-xsrc/theory/quantifiers/bounded_integers.h122
-rw-r--r--src/theory/quantifiers/candidate_generator.cpp2
-rw-r--r--src/theory/quantifiers/first_order_model.cpp84
-rw-r--r--src/theory/quantifiers/first_order_model.h65
-rwxr-xr-xsrc/theory/quantifiers/first_order_reasoning.cpp171
-rwxr-xr-xsrc/theory/quantifiers/first_order_reasoning.h45
-rwxr-xr-xsrc/theory/quantifiers/full_model_check.cpp1010
-rwxr-xr-xsrc/theory/quantifiers/full_model_check.h173
-rw-r--r--src/theory/quantifiers/inst_gen.cpp10
-rw-r--r--src/theory/quantifiers/inst_match.cpp21
-rw-r--r--src/theory/quantifiers/inst_match.h3
-rw-r--r--src/theory/quantifiers/inst_match_generator.cpp88
-rw-r--r--src/theory/quantifiers/inst_strategy_cbqi.cpp82
-rw-r--r--src/theory/quantifiers/inst_strategy_e_matching.cpp4
-rw-r--r--src/theory/quantifiers/model_builder.cpp240
-rw-r--r--src/theory/quantifiers/model_builder.h79
-rw-r--r--src/theory/quantifiers/model_engine.cpp267
-rw-r--r--src/theory/quantifiers/model_engine.h16
-rw-r--r--src/theory/quantifiers/options18
-rw-r--r--src/theory/quantifiers/quant_util.cpp102
-rw-r--r--src/theory/quantifiers/quant_util.h12
-rw-r--r--src/theory/quantifiers/quantifiers_rewriter.cpp4
-rw-r--r--src/theory/quantifiers/relevant_domain.cpp198
-rw-r--r--src/theory/quantifiers/relevant_domain.h54
-rw-r--r--src/theory/quantifiers/term_database.cpp81
-rw-r--r--src/theory/quantifiers/term_database.h19
-rw-r--r--src/theory/quantifiers/theory_quantifiers.cpp6
-rw-r--r--src/theory/quantifiers/trigger.cpp134
-rw-r--r--src/theory/quantifiers/trigger.h3
-rw-r--r--src/theory/quantifiers_engine.cpp20
-rw-r--r--src/theory/quantifiers_engine.h7
-rw-r--r--src/theory/rep_set.cpp147
-rw-r--r--src/theory/rep_set.h21
-rw-r--r--src/theory/rewriterules/rr_inst_match.cpp23
-rw-r--r--src/theory/rewriterules/rr_inst_match.h2
-rw-r--r--src/theory/rewriterules/rr_trigger.cpp20
-rw-r--r--src/theory/rewriterules/rr_trigger.h3
-rw-r--r--src/theory/rewriterules/theory_rewriterules.h2
-rw-r--r--src/theory/rewriterules/theory_rewriterules_rules.cpp9
-rw-r--r--src/theory/uf/options2
-rw-r--r--src/theory/uf/theory_uf_model.cpp19
-rw-r--r--src/theory/uf/theory_uf_model.h10
-rw-r--r--src/theory/uf/theory_uf_strong_solver.cpp46
-rw-r--r--test/Makefile.am1
-rw-r--r--test/regress/regress0/Makefile.am4
-rw-r--r--test/regress/regress0/arith/integers/Makefile.am11
-rw-r--r--test/regress/regress0/fmf/ALG008-1.smt273
-rw-r--r--test/regress/regress0/fmf/Arrow_Order-smtlib.778341.smt265
-rw-r--r--test/regress/regress0/fmf/Hoare-z3.931718.smt50
-rwxr-xr-xtest/regress/regress0/fmf/Makefile.am47
-rw-r--r--test/regress/regress0/fmf/PUZ001+1.smt2119
-rw-r--r--test/regress/regress0/fmf/QEpres-uf.855035.smt85
-rw-r--r--test/regress/regress0/fmf/agree466.smt2475
-rw-r--r--test/regress/regress0/fmf/agree467.smt2342
-rwxr-xr-xtest/regress/regress0/fmf/german169.smt2104
-rwxr-xr-xtest/regress/regress0/fmf/german73.smt2106
-rwxr-xr-xtest/regress/regress0/fmf/refcount24.cvc.smt238
-rw-r--r--test/unit/theory/theory_arith_white.h36
101 files changed, 5123 insertions, 1965 deletions
diff --git a/configure.ac b/configure.ac
index 407b47b16..bdce30f28 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,8 +2,8 @@
# Process this file with autoconf to produce a configure script.
m4_define(_CVC4_MAJOR, 1) dnl version (major)
-m4_define(_CVC4_MINOR, 2) dnl version (minor)
-m4_define(_CVC4_RELEASE, 1) dnl version (alpha)
+m4_define(_CVC4_MINOR, 3) dnl version (minor)
+m4_define(_CVC4_RELEASE, 0) dnl version (alpha)
m4_define(_CVC4_EXTRAVERSION, [-prerelease]) dnl version (extra)
m4_define(_CVC4_RELEASE_STRING, _CVC4_MAJOR[.]_CVC4_MINOR[]m4_if(_CVC4_RELEASE,[0],,[.]_CVC4_RELEASE)_CVC4_EXTRAVERSION) dnl version string
diff --git a/contrib/run-script-casc24-fnt b/contrib/run-script-casc24-fnt
new file mode 100755
index 000000000..2a10c5347
--- /dev/null
+++ b/contrib/run-script-casc24-fnt
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+cvc4=./cvc4
+bench="$1"
+let "to = $2 - 60"
+
+file=${bench##*/}
+filename=${file%.*}
+
+# use: trywith [params..]
+# to attempt a run. Only thing printed on stdout is "sat" or "unsat", in
+# which case this run script terminates immediately. Otherwise, this
+# function returns normally.
+function trywith {
+ limit=$1; shift;
+ (ulimit -t "$limit";$cvc4 -L tptp --szs-compliant --no-checking --no-interactive --dump-models --produce-models "$@" $bench) 2>/dev/null |
+ (read result;
+ case "$result" in
+ sat) echo "% SZS Satisfiable for $filename";
+ echo "% SZS output start FiniteModel for $filename";
+ cat;
+ echo "% SZS output end FiniteModel for $filename";
+ exit 0;;
+ unsat) echo "% SZS Unsatisfiable for $filename"; exit 0;;
+ conjecture-sat) echo "% SZS CounterSatisfiable for $filename";
+ echo "% SZS output start FiniteModel for $filename";
+ cat;
+ echo "% SZS output end FiniteModel for $filename";
+ exit 0;;
+ conjecture-unsat) echo "% SZS Theorem for $filename"; exit 0;;
+ esac; exit 1)
+ if [ ${PIPESTATUS[1]} -eq 0 ]; then exit 0; fi
+}
+
+trywith 30 --finite-model-find --uf-ss-totality
+trywith 30 --finite-model-find --decision=justification --fmf-fmc
+trywith $to --finite-model-find --decision=justification
+echo "% SZS GaveUp for $filename" \ No newline at end of file
diff --git a/contrib/run-script-casc24-fnt-no-models b/contrib/run-script-casc24-fnt-no-models
new file mode 100755
index 000000000..a189c10bd
--- /dev/null
+++ b/contrib/run-script-casc24-fnt-no-models
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+cvc4=./cvc4
+bench="$1"
+let "to = $2 - 60"
+
+file=${bench##*/}
+filename=${file%.*}
+
+# use: trywith [params..]
+# to attempt a run. Only thing printed on stdout is "sat" or "unsat", in
+# which case this run script terminates immediately. Otherwise, this
+# function returns normally.
+function trywith {
+ result="$( ulimit -t "$1";shift;$cvc4 -L tptp --szs-compliant --no-checking --no-interactive "$@" $bench)"
+ case "$result" in
+ sat) echo "% SZS Satisfiable for $filename"; exit 0;;
+ unsat) echo "% SZS Unsatisfiable for $filename"; exit 0;;
+ conjecture-sat) echo "% SZS CounterSatisfiable for $filename"; exit 0;;
+ conjecture-unsat) echo "% SZS Theorem for $filename"; exit 0;;
+ esac
+}
+function finishwith {
+ result="$( $cvc4 -L tptp --szs-compliant --no-checking --no-interactive "$@" $bench)"
+ case "$result" in
+ sat) echo "% SZS Satisfiable for $filename"; exit 0;;
+ unsat) echo "% SZS Unsatisfiable for $filename"; exit 0;;
+ conjecture-sat) echo "% SZS CounterSatisfiable for $filename"; exit 0;;
+ conjecture-unsat) echo "% SZS Theorem for $filename"; exit 0;;
+ esac
+}
+
+trywith 30 --finite-model-find --uf-ss-totality
+trywith 30 --finite-model-find --decision=justification --fmf-fmc
+trywith $to --finite-model-find --decision=justification
+echo "% SZS GaveUp for $filename" \ No newline at end of file
diff --git a/contrib/run-script-casc24-fof b/contrib/run-script-casc24-fof
new file mode 100755
index 000000000..940e26946
--- /dev/null
+++ b/contrib/run-script-casc24-fof
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+cvc4=./cvc4
+bench="$1"
+let "to = $2 - 75"
+
+file=${bench##*/}
+filename=${file%.*}
+
+# use: trywith [params..]
+# to attempt a run. Only thing printed on stdout is "sat" or "unsat", in
+# which case this run script terminates immediately. Otherwise, this
+# function returns normally.
+function trywith {
+ result="$( ulimit -t "$1";shift;$cvc4 -L tptp --szs-compliant --no-checking --no-interactive "$@" $bench)"
+ case "$result" in
+ sat) echo "% SZS Satisfiable for $filename"; exit 0;;
+ unsat) echo "% SZS Unsatisfiable for $filename"; exit 0;;
+ conjecture-sat) echo "% SZS CounterSatisfiable for $filename"; exit 0;;
+ conjecture-unsat) echo "% SZS Theorem for $filename"; exit 0;;
+ esac
+}
+function finishwith {
+ result="$( $cvc4 -L tptp --szs-compliant --no-checking --no-interactive "$@" $bench)"
+ case "$result" in
+ sat) echo "% SZS Satisfiable for $filename"; exit 0;;
+ unsat) echo "% SZS Unsatisfiable for $filename"; exit 0;;
+ conjecture-sat) echo "% SZS CounterSatisfiable for $filename"; exit 0;;
+ conjecture-unsat) echo "% SZS Theorem for $filename"; exit 0;;
+ esac
+}
+
+trywith 30
+trywith 15 --finite-model-find --fmf-inst-engine
+trywith 30 --finite-model-find --decision=justification --fmf-fmc
+trywith $to --decision=justification
+echo "% SZS GaveUp for $filename" \ No newline at end of file
diff --git a/library_versions b/library_versions
index c686e8f46..ad37ce67a 100644
--- a/library_versions
+++ b/library_versions
@@ -52,5 +52,6 @@
1\.2-prerelease libcvc4:1:0:0 libcvc4parser:1:0:0 libcvc4compat:1:0:0 libcvc4bindings:1:0:0
1\.2 libcvc4:1:1:1 libcvc4parser:1:1:0 libcvc4compat:1:0:0 libcvc4bindings:1:0:0
1\.2\.1-prerelease libcvc4:1:1:1 libcvc4parser:1:1:0 libcvc4compat:1:0:0 libcvc4bindings:1:0:0
+1\.3-prerelease libcvc4:1:1:1 libcvc4parser:1:1:0 libcvc4compat:1:0:0 libcvc4bindings:1:0:0
# note: SmtEngine::setLogicString() exceptions have changed, bump library version on next release?
# note: removed Parser::getDeclarationLevel(), added other interfaces
diff --git a/src/decision/Makefile.am b/src/decision/Makefile.am
index 6d49c6301..f75a17a69 100644
--- a/src/decision/Makefile.am
+++ b/src/decision/Makefile.am
@@ -12,9 +12,7 @@ libdecision_la_SOURCES = \
decision_engine.cpp \
decision_strategy.h \
justification_heuristic.h \
- justification_heuristic.cpp \
- relevancy.h \
- relevancy.cpp
+ justification_heuristic.cpp
EXTRA_DIST = \
options_handlers.h
diff --git a/src/decision/decision_engine.cpp b/src/decision/decision_engine.cpp
index f634a28d9..073a3ff6b 100644
--- a/src/decision/decision_engine.cpp
+++ b/src/decision/decision_engine.cpp
@@ -16,7 +16,6 @@
#include "decision/decision_engine.h"
#include "decision/justification_heuristic.h"
-#include "decision/relevancy.h"
#include "expr/node.h"
#include "decision/options.h"
@@ -62,18 +61,6 @@ void DecisionEngine::init()
enableStrategy(ds);
d_needIteSkolemMap.push_back(ds);
}
- if(options::decisionMode() == decision::DECISION_STRATEGY_RELEVANCY) {
- if(options::incrementalSolving()) {
- Warning() << "Relevancy decision heuristic and incremental not supported together"
- << std::endl;
- return; // Currently not supported with incremental
- }
- RelevancyStrategy* ds =
- new decision::Relevancy(this, d_satContext);
- enableStrategy(ds);
- d_needIteSkolemMap.push_back(ds);
- d_relevancyStrategy = ds;
- }
}
@@ -112,13 +99,6 @@ SatValue DecisionEngine::getPolarity(SatVariable var)
}
}
-
-
-
-
-
-
-
void DecisionEngine::addAssertions(const vector<Node> &assertions)
{
Assert(false); // doing this so that we revisit what to do
@@ -146,15 +126,4 @@ void DecisionEngine::addAssertions(const vector<Node> &assertions,
addAssertions(assertions, assertionsEnd, iteSkolemMap);
}
-// void DecisionEngine::addAssertion(Node n)
-// {
-// d_result = SAT_VALUE_UNKNOWN;
-// if(needIteSkolemMap()) {
-// d_assertions.push_back(n);
-// }
-// for(unsigned i = 0; i < d_needIteSkolemMap.size(); ++i)
-// d_needIteSkolemMap[i]->notifyAssertionsAvailable();
-// }
-
-
}/* CVC4 namespace */
diff --git a/src/decision/options b/src/decision/options
index b86577e7b..5f89e9611 100644
--- a/src/decision/options
+++ b/src/decision/options
@@ -9,14 +9,6 @@ module DECISION "decision/options.h" Decision heuristics
option decisionMode --decision=MODE decision::DecisionMode :handler CVC4::decision::stringToDecisionMode :default decision::DECISION_STRATEGY_INTERNAL :read-write :include "decision/decision_mode.h" :handler-include "decision/options_handlers.h"
choose decision mode, see --decision=help
-option decisionRelevancyLeaves bool
-# permille = part per thousand
-option decisionMaxRelTimeAsPermille --decision-budget=N "unsigned short" :read-write :predicate less_equal(1000L) :predicate CVC4::decision::checkDecisionBudget :predicate-include "decision/options_handlers.h"
- impose a budget for relevancy heuristic which increases linearly with each decision. N between 0 and 1000. (default: 1000, no budget)
-# if false, do justification stuff using relevancy.h
-option decisionComputeRelevancy bool
-# use the must be relevant
-option decisionMustRelevancy bool
# only use DE to determine when to stop, not to make decisions
option decisionStopOnly bool
diff --git a/src/decision/options_handlers.h b/src/decision/options_handlers.h
index 05d975ef1..44a623970 100644
--- a/src/decision/options_handlers.h
+++ b/src/decision/options_handlers.h
@@ -37,31 +37,8 @@ justification\n\
justification-stoponly\n\
+ Use the justification heuristic only to stop early, not for decisions\n\
";
-/** Under-development options, commenting out from help for the release */
-/*
-\n\
-relevancy\n\
-+ Under development may-relevancy\n\
-\n\
-relevancy-leaves\n\
-+ May-relevancy, but decide only on leaves\n\
-\n\
-Developer modes:\n\
-\n\
-justification-rel\n\
-+ Use the relevancy code to do the justification stuff\n\
-+ (This should do exact same thing as justification)\n\
-\n\
-justification-must\n\
-+ Start deciding on literals close to root instead of those\n\
-+ near leaves (don't expect it to work well) [Unimplemented]\n\
-";*/
inline DecisionMode stringToDecisionMode(std::string option, std::string optarg, SmtEngine* smt) throw(OptionException) {
- options::decisionRelevancyLeaves.set(false);
- options::decisionMaxRelTimeAsPermille.set(1000);
- options::decisionComputeRelevancy.set(true);
- options::decisionMustRelevancy.set(false);
options::decisionStopOnly.set(false);
if(optarg == "internal") {
@@ -71,25 +48,6 @@ inline DecisionMode stringToDecisionMode(std::string option, std::string optarg,
} else if(optarg == "justification-stoponly") {
options::decisionStopOnly.set(true);
return DECISION_STRATEGY_JUSTIFICATION;
- } else if(optarg == "relevancy") {
- options::decisionRelevancyLeaves.set(false);
- return DECISION_STRATEGY_RELEVANCY;
- } else if(optarg == "relevancy-leaves") {
- options::decisionRelevancyLeaves.set(true);
- Trace("options") << "version is " << options::version() << std::endl;
- return DECISION_STRATEGY_RELEVANCY;
- } else if(optarg == "justification-rel") {
- // relevancyLeaves : irrelevant
- // maxRelTimeAsPermille : irrelevant
- options::decisionComputeRelevancy.set(false);
- options::decisionMustRelevancy.set(false);
- return DECISION_STRATEGY_RELEVANCY;
- } else if(optarg == "justification-must") {
- // relevancyLeaves : irrelevant
- // maxRelTimeAsPermille : irrelevant
- options::decisionComputeRelevancy.set(false);
- options::decisionMustRelevancy.set(true);
- return DECISION_STRATEGY_RELEVANCY;
} else if(optarg == "help") {
puts(decisionModeHelp.c_str());
exit(1);
@@ -99,14 +57,6 @@ inline DecisionMode stringToDecisionMode(std::string option, std::string optarg,
}
}
-inline void checkDecisionBudget(std::string option, unsigned short budget, SmtEngine* smt) throw(OptionException) {
- if(budget == 0) {
- Warning() << "Decision budget is 0. Consider using internal decision heuristic and "
- << std::endl << " removing this option." << std::endl;
-
- }
-}
-
inline DecisionWeightInternal stringToDecisionWeightInternal(std::string option, std::string optarg, SmtEngine* smt) throw(OptionException) {
if(optarg == "off")
return DECISION_WEIGHT_INTERNAL_OFF;
diff --git a/src/decision/relevancy.cpp b/src/decision/relevancy.cpp
deleted file mode 100644
index f83e238d4..000000000
--- a/src/decision/relevancy.cpp
+++ /dev/null
@@ -1,379 +0,0 @@
-/********************* */
-/*! \file relevancy.cpp
- ** \verbatim
- ** Original author: Kshitij Bansal
- ** Major contributors: none
- ** Minor contributors (to current version): Dejan Jovanovic, Morgan Deters
- ** 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 Justification heuristic for decision making
- **
- ** A ATGP-inspired justification-based decision heuristic. See
- ** [insert reference] for more details. This code is, or not, based
- ** on the CVC3 implementation of the same heuristic -- note below.
- **
- ** It needs access to the simplified but non-clausal formula.
- **/
-/*****************************************************************************/
-
-#include "relevancy.h"
-
-#include "expr/node_manager.h"
-#include "expr/kind.h"
-#include "theory/rewriter.h"
-#include "util/ite_removal.h"
-
-// Relevancy stuff
-
-const double Relevancy::secondsPerDecision = 0.001;
-const double Relevancy::secondsPerExpense = 1e-7;
-const double Relevancy::EPS = 1e-9;
-
-
-void Relevancy::setJustified(TNode n)
-{
- Debug("decision") << " marking [" << n.getId() << "]"<< n << "as justified" << std::endl;
- d_justified.insert(n);
- if(options::decisionComputeRelevancy()) {
- d_relevancy[n] = d_maxRelevancy[n];
- updateRelevancy(n);
- }
-}
-
-bool Relevancy::checkJustified(TNode n)
-{
- return d_justified.find(n) != d_justified.end();
-}
-
-SatValue Relevancy::tryGetSatValue(Node n)
-{
- Debug("decision") << " " << n << " has sat value " << " ";
- if(d_decisionEngine->hasSatLiteral(n) ) {
- Debug("decision") << d_decisionEngine->getSatValue(n) << std::endl;
- return d_decisionEngine->getSatValue(n);
- } else {
- Debug("decision") << "NO SAT LITERAL" << std::endl;
- return SAT_VALUE_UNKNOWN;
- }//end of else
-}
-
-void Relevancy::computeITEs(TNode n, IteList &l)
-{
- Debug("jh-ite") << " computeITEs( " << n << ", &l)\n";
- for(unsigned i=0; i<n.getNumChildren(); ++i) {
- SkolemMap::iterator it2 = d_iteAssertions.find(n[i]);
- if(it2 != d_iteAssertions.end())
- l.push_back(it2->second);
- computeITEs(n[i], l);
- }
-}
-
-const Relevancy::IteList& Relevancy::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] = vector<TNode>();
- computeITEs(n, d_iteCache[n]);
- return d_iteCache[n];
- }
-}
-
-bool Relevancy::findSplitterRec(TNode node,
- SatValue desiredVal)
-{
- Trace("decision")
- << "findSplitterRec([" << node.getId() << "]" << node << ", "
- << desiredVal << ", .. )" << std::endl;
-
- ++d_expense;
-
- /* Handle NOT as a special case */
- while (node.getKind() == kind::NOT) {
- desiredVal = invertValue(desiredVal);
- node = node[0];
- }
-
- /* Avoid infinite loops */
- if(d_visited.find(node) != d_visited.end()) {
- Debug("decision") << " node repeated. kind was " << node.getKind() << std::endl;
- Assert(false);
- Assert(node.getKind() == kind::ITE);
- return false;
- }
-
- /* Base case */
- if(checkJustified(node)) {
- return false;
- }
-
- /**
- * If we have already explored the subtree for some desiredVal, we
- * skip this and continue exploring the rest
- */
- if(d_polarityCache.find(node) == d_polarityCache.end()) {
- d_polarityCache[node] = desiredVal;
- } else {
- Assert(d_multipleBacktrace || options::decisionComputeRelevancy());
- return true;
- }
-
- d_visited.insert(node);
-
-#if defined CVC4_ASSERTIONS || defined CVC4_TRACING
- // We don't always have a sat literal, so remember that. Will need
- // it for some assertions we make.
- bool litPresent = d_decisionEngine->hasSatLiteral(node);
- if(Trace.isOn("decision")) {
- if(!litPresent) {
- Trace("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
- SatValue litVal = tryGetSatValue(node);
-
- /* You'd better know what you want */
- Assert(desiredVal != SAT_VALUE_UNKNOWN, "expected known value");
-
- /* Good luck, hope you can get what you want */
- Assert(litVal == desiredVal || litVal == SAT_VALUE_UNKNOWN,
- "invariant violated");
-
- /* What type of node is this */
- Kind k = node.getKind();
- theory::TheoryId tId = theory::kindToTheoryId(k);
-
- /* Some debugging stuff */
- Trace("jh-findSplitterRec") << "kind = " << k << std::endl;
- Trace("jh-findSplitterRec") << "theoryId = " << tId << std::endl;
- Trace("jh-findSplitterRec") << "node = " << node << std::endl;
- Trace("jh-findSplitterRec") << "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(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);
- Debug("jh-ite") << " ite size = " << l.size() << std::endl;
- for(unsigned i = 0; i < l.size(); ++i) {
- Assert(l[i].getKind() == kind::ITE, "Expected ITE");
- Debug("jh-ite") << " i = " << i
- << " l[i] = " << l[i] << std::endl;
- if(d_visited.find(node) != d_visited.end() ) continue;
- if(findSplitterRec(l[i], SAT_VALUE_TRUE)) {
- d_visited.erase(node);
- return true;
- }
- }
- Debug("jh-ite") << " ite done " << l.size() << std::endl;
-
- if(litVal != SAT_VALUE_UNKNOWN) {
- d_visited.erase(node);
- setJustified(node);
- return false;
- } else {
- /* if(not d_decisionEngine->hasSatLiteral(node))
- throw GiveUpException(); */
- Assert(d_decisionEngine->hasSatLiteral(node));
- SatVariable v = d_decisionEngine->getSatLiteral(node).getSatVariable();
- *d_curDecision = SatLiteral(v, desiredVal != SAT_VALUE_TRUE );
- Trace("decision") << "decision " << *d_curDecision << std::endl;
- Trace("decision") << "Found something to split. Glad to be able to serve you." << std::endl;
- d_visited.erase(node);
- return true;
- }
- }
-
- bool ret = false;
- SatValue flipCaseVal = SAT_VALUE_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);
- break;
-
- case kind::AND:
- if (desiredVal == SAT_VALUE_FALSE) ret = handleOrTrue(node, SAT_VALUE_FALSE);
- else ret = handleOrFalse(node, SAT_VALUE_TRUE);
- break;
-
- case kind::OR:
- if (desiredVal == SAT_VALUE_FALSE) ret = handleOrFalse(node, SAT_VALUE_FALSE);
- else ret = handleOrTrue(node, SAT_VALUE_TRUE);
- break;
-
- case kind::IMPLIES:
- Assert(node.getNumChildren() == 2, "Expected 2 fanins");
- if (desiredVal == SAT_VALUE_FALSE) {
- ret = findSplitterRec(node[0], SAT_VALUE_TRUE);
- if(ret) break;
- ret = findSplitterRec(node[1], SAT_VALUE_FALSE);
- break;
- }
- else {
- if (tryGetSatValue(node[0]) != SAT_VALUE_TRUE) {
- ret = findSplitterRec(node[0], SAT_VALUE_FALSE);
- //if(!ret || !d_multipleBacktrace)
- break;
- }
- if (tryGetSatValue(node[1]) != SAT_VALUE_FALSE) {
- ret = findSplitterRec(node[1], SAT_VALUE_TRUE);
- break;
- }
- Assert(d_multipleBacktrace, "No controlling input found (3)");
- }
- break;
-
- case kind::XOR:
- flipCaseVal = SAT_VALUE_TRUE;
- case kind::IFF: {
- SatValue val = tryGetSatValue(node[0]);
- if (val != SAT_VALUE_UNKNOWN) {
- ret = findSplitterRec(node[0], val);
- if (ret) break;
- if (desiredVal == flipCaseVal) val = invertValue(val);
- ret = findSplitterRec(node[1], val);
- }
- else {
- val = tryGetSatValue(node[1]);
- if (val == SAT_VALUE_UNKNOWN) val = SAT_VALUE_FALSE;
- if (desiredVal == flipCaseVal) val = invertValue(val);
- ret = findSplitterRec(node[0], val);
- if(ret) break;
- Assert(false, "Unable to find controlling input (4)");
- }
- break;
- }
-
- case kind::ITE:
- ret = handleITE(node, desiredVal);
- break;
-
- default:
- Assert(false, "Unexpected Boolean operator");
- break;
- }//end of switch(k)
-
- d_visited.erase(node);
- if(ret == false) {
- Assert(litPresent == false || litVal == desiredVal,
- "Output should be justified");
- setJustified(node);
- }
- return ret;
-
- Unreachable();
-}/* findRecSplit method */
-
-bool Relevancy::handleOrFalse(TNode node, SatValue desiredVal) {
- Debug("jh-findSplitterRec") << " handleOrFalse (" << node << ", "
- << desiredVal << std::endl;
-
- Assert( (node.getKind() == kind::AND and desiredVal == SAT_VALUE_TRUE) or
- (node.getKind() == kind::OR and desiredVal == SAT_VALUE_FALSE) );
-
- int n = node.getNumChildren();
- bool ret = false;
- for(int i = 0; i < n; ++i) {
- if (findSplitterRec(node[i], desiredVal)) {
- if(!options::decisionComputeRelevancy())
- return true;
- else
- ret = true;
- }
- }
- return ret;
-}
-
-bool Relevancy::handleOrTrue(TNode node, SatValue desiredVal) {
- Debug("jh-findSplitterRec") << " handleOrTrue (" << node << ", "
- << desiredVal << std::endl;
-
- Assert( (node.getKind() == kind::AND and desiredVal == SAT_VALUE_FALSE) or
- (node.getKind() == kind::OR and desiredVal == SAT_VALUE_TRUE) );
-
- int n = node.getNumChildren();
- SatValue desiredValInverted = invertValue(desiredVal);
- for(int i = 0; i < n; ++i) {
- if ( tryGetSatValue(node[i]) != desiredValInverted ) {
- // PRE RELEVANCY return findSplitterRec(node[i], desiredVal);
- bool ret = findSplitterRec(node[i], desiredVal);
- if(ret) {
- // Splitter could be found... so can't justify this node
- if(!d_multipleBacktrace)
- return true;
- }
- else {
- // Splitter couldn't be found... should be justified
- return false;
- }
- }
- }
- // Multiple backtrace is on, so must have reached here because
- // everything had splitter
- if(d_multipleBacktrace) return true;
-
- 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");
- return false;
-}
-
-bool Relevancy::handleITE(TNode node, SatValue desiredVal)
-{
- Debug("jh-findSplitterRec") << " 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
- 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;
- int chVal = tryGetSatValue(node[ch]);
- if( (chVal == SAT_VALUE_UNKNOWN || chVal == desiredVal) &&
- findSplitterRec(node[ch], desiredVal) ) {
- return true;
- }
- }// else (...ifVal...)
- return false;
-}//handleITE
diff --git a/src/decision/relevancy.h b/src/decision/relevancy.h
deleted file mode 100644
index fd16eb0cc..000000000
--- a/src/decision/relevancy.h
+++ /dev/null
@@ -1,421 +0,0 @@
-/********************* */
-/*! \file relevancy.h
- ** \verbatim
- ** Original author: Kshitij Bansal
- ** Major contributors: none
- ** Minor contributors (to current version): Tim King, Dejan Jovanovic, Morgan Deters
- ** 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 Justification heuristic for decision making
- **
- ** A ATGP-inspired justification-based decision heuristic. See
- ** [insert reference] for more details. This code is, or not, based
- ** on the CVC3 implementation of the same heuristic.
- **
- ** It needs access to the simplified but non-clausal formula.
- **
- ** Relevancy
- ** ---------
- **
- ** This class also currently computes the may-relevancy of a node
- **
- ** A node is may-relevant if there is a path from the root of the
- ** formula to the node such that no node on the path is justified. As
- ** contrapositive, a node is not relevant (with the may-notion) if all
- ** path from the root to the node go through a justified node.
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__DECISION__RELEVANCY
-#define __CVC4__DECISION__RELEVANCY
-
-#include "decision_engine.h"
-#include "decision_strategy.h"
-#include "decision/options.h"
-
-#include "context/cdhashset.h"
-#include "context/cdhashmap.h"
-#include "expr/node.h"
-#include "prop/sat_solver_types.h"
-
-namespace CVC4 {
-
-namespace decision {
-
-class RelGiveUpException : public Exception {
-public:
- RelGiveUpException() :
- Exception("relevancy: giving up") {
- }
-};/* class GiveUpException */
-
-class Relevancy : public RelevancyStrategy {
- typedef std::vector<TNode> IteList;
- typedef hash_map<TNode,IteList,TNodeHashFunction> IteCache;
- typedef hash_map<TNode,TNode,TNodeHashFunction> SkolemMap;
- typedef hash_map<TNode,SatValue,TNodeHashFunction> PolarityCache;
-
- // being 'justified' is monotonic with respect to decisions
- context::CDHashSet<Node, NodeHashFunction> d_justified;
- context::CDO<unsigned> d_prvsIndex;
-
- IntStat d_helfulness;
- IntStat d_polqueries;
- IntStat d_polhelp;
- IntStat d_giveup;
- IntStat d_expense; /* Total number of nodes considered over
- all calls to the findSplitter function */
- TimerStat d_timestat;
-
- /**
- * A copy of the assertions that need to be justified
- * directly. Doesn't have ones introduced during during ITE-removal.
- */
- std::vector<TNode> d_assertions;
- //TNode is fine since decisionEngine has them too
-
- /** map from ite-rewrite skolem to a boolean-ite assertion */
- SkolemMap d_iteAssertions;
- // 'key' being TNode is fine since if a skolem didn't exist anywhere,
- // we won't look it up. as for 'value', same reason as d_assertions
-
- /** Cache for ITE skolems present in a atomic formula */
- IteCache d_iteCache;
-
- /**
- * This is used to prevent infinite loop when trying to find a
- * splitter. Can happen when exploring assertion corresponding to a
- * term-ITE.
- */
- hash_set<TNode,TNodeHashFunction> d_visited;
-
- /**
- * May-relevancy of a node is an integer. For a node n, it becomes
- * irrelevant when d_maxRelevancy[n] = d_relevancy[n]
- */
- hash_map<TNode,int,TNodeHashFunction> d_maxRelevancy;
- context::CDHashMap<TNode,int,TNodeHashFunction> d_relevancy;
- PolarityCache d_polarityCache;
-
- /** **** * * *** * * OPTIONS *** * * ** * * **** */
-
- /**
- * do we do "multiple-backtrace" to try to justify a node
- */
- bool d_multipleBacktrace;
- //bool d_computeRelevancy; // are we in a mode where we compute relevancy?
-
- static const double secondsPerDecision;
- static const double secondsPerExpense;
- static const double EPS;
-
- /** Maximum time this algorithm should spent as part of whole algorithm */
- double d_maxTimeAsPercentageOfTotalTime;
-
- /** current decision for the recursive call */
- SatLiteral* d_curDecision;
-public:
- Relevancy(CVC4::DecisionEngine* de, context::Context *c):
- RelevancyStrategy(de, c),
- d_justified(c),
- d_prvsIndex(c, 0),
- d_helfulness("decision::rel::preventedDecisions", 0),
- d_polqueries("decision::rel::polarityQueries", 0),
- d_polhelp("decision::rel::polarityHelp", 0),
- d_giveup("decision::rel::giveup", 0),
- d_expense("decision::rel::expense", 0),
- d_timestat("decision::rel::time"),
- d_relevancy(c),
- d_multipleBacktrace(options::decisionComputeRelevancy()),
- // d_computeRelevancy(decOpt.computeRelevancy),
- d_maxTimeAsPercentageOfTotalTime(options::decisionMaxRelTimeAsPermille()*1.0/10.0),
- d_curDecision(NULL)
- {
- Warning() << "There are known bugs in this Relevancy code which we know"
- << "how to fix (but haven't yet)." << std::endl
- << "Please bug kshitij if you wish to use." << std::endl;
-
- StatisticsRegistry::registerStat(&d_helfulness);
- StatisticsRegistry::registerStat(&d_polqueries);
- StatisticsRegistry::registerStat(&d_polhelp);
- StatisticsRegistry::registerStat(&d_giveup);
- StatisticsRegistry::registerStat(&d_expense);
- StatisticsRegistry::registerStat(&d_timestat);
- Trace("decision") << "relevancy enabled with" << std::endl;
- Trace("decision") << " * computeRelevancy: " << (options::decisionComputeRelevancy() ? "on" : "off")
- << std::endl;
- Trace("decision") << " * relevancyLeaves: " << (options::decisionRelevancyLeaves() ? "on" : "off")
- << std::endl;
- Trace("decision") << " * mustRelevancy [unimplemented]: " << (options::decisionMustRelevancy() ? "on" : "off")
- << std::endl;
- }
- ~Relevancy() {
- StatisticsRegistry::unregisterStat(&d_helfulness);
- StatisticsRegistry::unregisterStat(&d_polqueries);
- StatisticsRegistry::unregisterStat(&d_polhelp);
- StatisticsRegistry::unregisterStat(&d_giveup);
- StatisticsRegistry::unregisterStat(&d_expense);
- StatisticsRegistry::unregisterStat(&d_timestat);
- }
- prop::SatLiteral getNext(bool &stopSearch) {
- Debug("decision") << std::endl;
- Trace("decision") << "Relevancy::getNext()" << std::endl;
- TimerStat::CodeTimer codeTimer(d_timestat);
-
- if( d_maxTimeAsPercentageOfTotalTime < 100.0 - EPS &&
- double(d_polqueries.getData())*secondsPerDecision <
- d_maxTimeAsPercentageOfTotalTime*double(d_expense.getData())*secondsPerExpense
- ) {
- ++d_giveup;
- return undefSatLiteral;
- }
-
- d_visited.clear();
- d_polarityCache.clear();
-
- for(unsigned i = d_prvsIndex; i < d_assertions.size(); ++i) {
- Trace("decision") << 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 = findSplitter(d_assertions[i], desiredVal);
-
- if(!options::decisionComputeRelevancy() && litDecision != undefSatLiteral) {
- d_prvsIndex = i;
- return litDecision;
- }
- }
-
- if(options::decisionComputeRelevancy()) return undefSatLiteral;
-
- Trace("decision") << "jh: Nothing to split on " << std::endl;
-
-#if defined CVC4_ASSERTIONS || 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;
- }
-
- void addAssertions(const std::vector<Node> &assertions,
- unsigned assertionsEnd,
- IteSkolemMap iteSkolemMap) {
- Trace("decision")
- << "Relevancy::addAssertions()"
- << " size = " << assertions.size()
- << " assertionsEnd = " << assertionsEnd
- << std::endl;
-
- // Save mapping between ite skolems and ite assertions
- for(IteSkolemMap::iterator i = iteSkolemMap.begin();
- i != iteSkolemMap.end(); ++i) {
- Assert(i->second >= assertionsEnd && i->second < assertions.size());
- Debug("jh-ite") << " jh-ite: " << (i->first) << " maps to "
- << assertions[(i->second)] << std::endl;
- d_iteAssertions[i->first] = assertions[i->second];
- }
-
- // Save the 'real' assertions locally
- for(unsigned i = 0; i < assertionsEnd; ++i) {
- d_assertions.push_back(assertions[i]);
- d_visited.clear();
- if(options::decisionComputeRelevancy()) increaseMaxRelevancy(assertions[i]);
- d_visited.clear();
- }
-
- }
-
- bool isRelevant(TNode n) {
- Trace("decision") << "isRelevant(" << n << "): ";
-
- if(Debug.isOn("decision")) {
- if(d_maxRelevancy.find(n) == d_maxRelevancy.end()) {
- // we are becuase of not getting information about literals
- // created using newLiteral command... need to figure how to
- // handle that
- Message() << "isRelevant: WARNING: didn't find node when we should had" << std::endl;
- }
- }
-
- if(d_maxRelevancy.find(n) == d_maxRelevancy.end()) {
- Trace("decision") << "yes [not found in db]" << std::endl;
- return true;
- }
-
- if(options::decisionRelevancyLeaves() && !isAtomicFormula(n)) {
- Trace("decision") << "no [not a leaf]" << std::endl;
- return false;
- }
-
- Trace("decision") << (d_maxRelevancy[n] == d_relevancy[n] ? "no":"yes")
- << std::endl;
-
- Debug("decision") << " maxRel: " << (d_maxRelevancy[n] )
- << " rel: " << d_relevancy[n].get() << std::endl;
- // Assert(d_maxRelevancy.find(n) != d_maxRelevancy.end());
- Assert(0 <= d_relevancy[n] && d_relevancy[n] <= d_maxRelevancy[n]);
-
- if(d_maxRelevancy[n] == d_relevancy[n]) {
- ++d_helfulness; // preventedDecisions
- return false;
- } else {
- return true;
- }
- }
-
- SatValue getPolarity(TNode n) {
- Trace("decision") << "getPolarity([" << n.getId() << "]" << n << "): ";
- Assert(n.getKind() != kind::NOT);
- ++d_polqueries;
- PolarityCache::iterator it = d_polarityCache.find(n);
- if(it == d_polarityCache.end()) {
- Trace("decision") << "don't know" << std::endl;
- return SAT_VALUE_UNKNOWN;
- } else {
- ++d_polhelp;
- Trace("decision") << it->second << std::endl;
- return it->second;
- }
- }
-
- /* Compute justified */
- /*bool computeJustified() {
-
- }*/
-private:
- SatLiteral findSplitter(TNode node, SatValue desiredVal)
- {
- bool ret;
- SatLiteral litDecision;
- try {
- // init
- d_curDecision = &litDecision;
-
- // solve
- ret = findSplitterRec(node, desiredVal);
-
- // post
- d_curDecision = NULL;
- }catch(RelGiveUpException &e) {
- return prop::undefSatLiteral;
- }
- if(ret == true) {
- Trace("decision") << "Yippee!!" << std::endl;
- return litDecision;
- } else {
- return undefSatLiteral;
- }
- }
-
- /**
- * Do all the hardwork.
- * Return 'true' if the node cannot be justfied, 'false' it it can be.
- * Sets 'd_curDecision' if unable to justify (depending on the mode)
- * If 'd_computeRelevancy' is on does multiple backtrace
- */
- bool findSplitterRec(TNode node, SatValue value);
- // Functions to make findSplitterRec modular...
- bool handleOrFalse(TNode node, SatValue desiredVal);
- bool handleOrTrue(TNode node, SatValue desiredVal);
- bool handleITE(TNode node, SatValue desiredVal);
-
- /* Helper functions */
- void setJustified(TNode);
- bool checkJustified(TNode);
-
- /* If literal exists corresponding to the node return
- that. Otherwise an UNKNOWN */
- SatValue tryGetSatValue(Node n);
-
- /* Get list of all term-ITEs for the atomic formula v */
- const Relevancy::IteList& getITEs(TNode n);
-
- /* Compute all term-ITEs in a node recursively */
- void computeITEs(TNode n, IteList &l);
-
- /* Checks whether something is an atomic formula or not */
- bool isAtomicFormula(TNode n) {
- return theory::kindToTheoryId(n.getKind()) != theory::THEORY_BOOL;
- }
-
- /** Recursively increase relevancies */
- void updateRelevancy(TNode n) {
- if(d_visited.find(n) != d_visited.end()) return;
-
- Assert(d_relevancy[n] <= d_maxRelevancy[n]);
-
- if(d_relevancy[n] != d_maxRelevancy[n])
- return;
-
- d_visited.insert(n);
- if(isAtomicFormula(n)) {
- const IteList& l = getITEs(n);
- for(unsigned i = 0; i < l.size(); ++i) {
- if(d_visited.find(l[i]) == d_visited.end()) continue;
- d_relevancy[l[i]] = d_relevancy[l[i]] + 1;
- updateRelevancy(l[i]);
- }
- } else {
- for(unsigned i = 0; i < n.getNumChildren(); ++i) {
- if(d_visited.find(n[i]) == d_visited.end()) continue;
- d_relevancy[n[i]] = d_relevancy[n[i]] + 1;
- updateRelevancy(n[i]);
- }
- }
- d_visited.erase(n);
- }
-
- /* */
- void increaseMaxRelevancy(TNode n) {
-
- Debug("decision")
- << "increaseMaxRelevancy([" << n.getId() << "]" << n << ")"
- << std::endl;
-
- d_maxRelevancy[n]++;
-
- // don't update children multiple times
- if(d_visited.find(n) != d_visited.end()) return;
-
- d_visited.insert(n);
- // Part to make the recursive call
- if(isAtomicFormula(n)) {
- const IteList& l = getITEs(n);
- for(unsigned i = 0; i < l.size(); ++i)
- if(d_visited.find(l[i]) == d_visited.end())
- increaseMaxRelevancy(l[i]);
- } else {
- for(unsigned i = 0; i < n.getNumChildren(); ++i)
- increaseMaxRelevancy(n[i]);
- } //else (...atomic formula...)
- }
-
-};/* class Relevancy */
-
-}/* namespace decision */
-
-}/* namespace CVC4 */
-
-#endif /* __CVC4__DECISION__RELEVANCY */
diff --git a/src/main/command_executor.cpp b/src/main/command_executor.cpp
index f1742b549..556e51216 100644
--- a/src/main/command_executor.cpp
+++ b/src/main/command_executor.cpp
@@ -19,6 +19,8 @@
#include "main/main.h"
+#include "smt/options.h"
+
namespace CVC4 {
namespace main {
@@ -64,6 +66,17 @@ bool CommandExecutor::doCommandSingleton(Command *cmd)
} else {
status = smtEngineInvoke(&d_smtEngine, cmd, NULL);
}
+ //dump the model if option is set
+ if(status && d_options[options::produceModels] && d_options[options::dumpModels]) {
+ CheckSatCommand *cs = dynamic_cast<CheckSatCommand*>(cmd);
+ if(cs != NULL) {
+ if(cs->getResult().asSatisfiabilityResult().isSat() == Result::SAT ||
+ (cs->getResult().isUnknown() && cs->getResult().whyUnknown() == Result::INCOMPLETE) ){
+ Command * gm = new GetModelCommand;
+ status = doCommandSingleton(gm);
+ }
+ }
+ }
return status;
}
diff --git a/src/parser/options b/src/parser/options
index beae09823..b3e69a992 100644
--- a/src/parser/options
+++ b/src/parser/options
@@ -14,4 +14,7 @@ option memoryMap --mmap bool
option semanticChecks /--no-checking bool :default DO_SEMANTIC_CHECKS_BY_DEFAULT :link /--no-type-checking
disable ALL semantic checks, including type checks
+option szsCompliant --szs-compliant bool :default false
+ temporary support for szs ontolotogy, print if conjecture is found
+
endmodule
diff --git a/src/parser/parser_builder.cpp b/src/parser/parser_builder.cpp
index 721337c9e..e1e4053ac 100644
--- a/src/parser/parser_builder.cpp
+++ b/src/parser/parser_builder.cpp
@@ -89,7 +89,11 @@ Parser* ParserBuilder::build()
parser = new Smt2(d_exprManager, input, d_strictMode, d_parseOnly);
break;
case language::input::LANG_TPTP:
- parser = new Tptp(d_exprManager, input, d_strictMode, d_parseOnly);
+ {
+ Tptp * tparser = new Tptp(d_exprManager, input, d_strictMode, d_parseOnly);
+ tparser->d_szsCompliant = d_szsCompliant;
+ parser = tparser;
+ }
break;
default:
parser = new Parser(d_exprManager, input, d_strictMode, d_parseOnly);
@@ -141,6 +145,7 @@ ParserBuilder& ParserBuilder::withParseOnly(bool flag) {
}
ParserBuilder& ParserBuilder::withOptions(const Options& options) {
+ d_szsCompliant = options[options::szsCompliant];
return
withInputLanguage(options[options::inputLanguage])
.withMmap(options[options::memoryMap])
diff --git a/src/parser/parser_builder.h b/src/parser/parser_builder.h
index 75e2b4fbe..607547beb 100644
--- a/src/parser/parser_builder.h
+++ b/src/parser/parser_builder.h
@@ -77,6 +77,9 @@ class CVC4_PUBLIC ParserBuilder {
/** Are we parsing only? */
bool d_parseOnly;
+ /** hack for szs compliance */
+ bool d_szsCompliant;
+
/** Initialize this parser builder */
void init(ExprManager* exprManager, const std::string& filename);
diff --git a/src/parser/tptp/tptp.cpp b/src/parser/tptp/tptp.cpp
index ee7ee4c61..ab4ea14c4 100644
--- a/src/parser/tptp/tptp.cpp
+++ b/src/parser/tptp/tptp.cpp
@@ -52,6 +52,7 @@ Tptp::Tptp(ExprManager* exprManager, Input* input, bool strictMode, bool parseOn
d_tptpDir.append("/");
}
}
+ d_hasConjecture = false;
}
void Tptp::addTheory(Theory theory) {
diff --git a/src/parser/tptp/tptp.h b/src/parser/tptp/tptp.h
index 6b7adbbf7..cea246282 100644
--- a/src/parser/tptp/tptp.h
+++ b/src/parser/tptp/tptp.h
@@ -24,6 +24,7 @@
#include "util/hash.h"
#include <ext/hash_set>
#include <cassert>
+#include "parser/options.h"
namespace CVC4 {
@@ -49,6 +50,11 @@ class Tptp : public Parser {
// empty if none could be determined
std::string d_tptpDir;
+ //hack to make output SZS ontology-compliant
+ bool d_hasConjecture;
+ // hack for szs compliance
+ bool d_szsCompliant;
+
public:
bool cnf; //in a cnf formula
@@ -181,6 +187,13 @@ inline void Tptp::makeApplication(Expr & expr, std::string & name,
};
inline Command* Tptp::makeCommand(FormulaRole fr, Expr & expr){
+ //hack for SZS ontology compliance
+ if(d_szsCompliant && (fr==FR_NEGATED_CONJECTURE || fr==FR_CONJECTURE)){
+ if( !d_hasConjecture ){
+ d_hasConjecture = true;
+ std::cout << "conjecture-";
+ }
+ }
switch(fr){
case FR_AXIOM:
case FR_HYPOTHESIS:
diff --git a/src/printer/smt2/smt2_printer.cpp b/src/printer/smt2/smt2_printer.cpp
index b84d86a49..fc2574036 100644
--- a/src/printer/smt2/smt2_printer.cpp
+++ b/src/printer/smt2/smt2_printer.cpp
@@ -214,7 +214,7 @@ void Smt2Printer::toStream(std::ostream& out, TNode n,
bool stillNeedToPrintParams = true;
// operator
- if(n.getNumChildren() != 0) out << '(';
+ if(n.getNumChildren() != 0 && n.getKind()!=kind::INST_PATTERN_LIST) out << '(';
switch(Kind k = n.getKind()) {
// builtin theory
case kind::APPLY: break;
@@ -317,12 +317,29 @@ void Smt2Printer::toStream(std::ostream& out, TNode n,
break;
// quantifiers
- case kind::FORALL: out << "forall "; break;
- case kind::EXISTS: out << "exists "; break;
+ case kind::FORALL:
+ case kind::EXISTS:
+ if( k==kind::FORALL ){
+ out << "forall ";
+ }else{
+ out << "exists ";
+ }
+ for( unsigned i=0; i<2; i++) {
+ out << n[i] << " ";
+ if( i==0 && n.getNumChildren()==3 ){
+ out << "(! ";
+ }
+ }
+ if( n.getNumChildren()==3 ){
+ out << n[2];
+ out << ")";
+ }
+ out << ")";
+ return;
+ break;
case kind::BOUND_VAR_LIST:
// the left parenthesis is already printed (before the switch)
- for(TNode::iterator i = n.begin(),
- iend = n.end();
+ for(TNode::iterator i = n.begin(), iend = n.end();
i != iend; ) {
out << '(';
toStream(out, (*i), toDepth < 0 ? toDepth : toDepth - 1, types);
@@ -339,8 +356,13 @@ void Smt2Printer::toStream(std::ostream& out, TNode n,
out << ')';
return;
case kind::INST_PATTERN:
+ break;
case kind::INST_PATTERN_LIST:
// TODO user patterns
+ for(unsigned i=0; i<n.getNumChildren(); i++) {
+ out << ":pattern " << n[i];
+ }
+ return;
break;
default:
diff --git a/src/proof/cnf_proof.cpp b/src/proof/cnf_proof.cpp
index d6e493c8d..5f03ef5cf 100644
--- a/src/proof/cnf_proof.cpp
+++ b/src/proof/cnf_proof.cpp
@@ -19,8 +19,8 @@
using namespace CVC4::prop;
namespace CVC4 {
+
CnfProof::CnfProof(CnfStream* stream) :
d_cnfStream(stream) {}
-
} /* CVC4 namespace */
diff --git a/src/proof/cnf_proof.h b/src/proof/cnf_proof.h
index c265e46df..984dc76c6 100644
--- a/src/proof/cnf_proof.h
+++ b/src/proof/cnf_proof.h
@@ -17,7 +17,7 @@
**/
#include "cvc4_private.h"
-
+#include "util/proof.h"
#ifndef __CVC4__CNF_PROOF_H
#define __CVC4__CNF_PROOF_H
diff --git a/src/proof/sat_proof.cpp b/src/proof/sat_proof.cpp
index df695c2d1..82478464f 100644
--- a/src/proof/sat_proof.cpp
+++ b/src/proof/sat_proof.cpp
@@ -173,7 +173,10 @@ SatProof::SatProof(Minisat::Solver* solver, bool checkRes) :
d_emptyClauseId(-1),
d_nullId(-2),
d_temp_clauseId(),
- d_temp_idClause()
+ d_temp_idClause(),
+ d_unitConflictId(),
+ d_storedUnitConflict(false),
+ d_atomToVar()
{
d_proxy = new ProofProxy(this);
}
@@ -353,6 +356,7 @@ ClauseId SatProof::registerClause(::Minisat::CRef clause, bool isInput) {
d_inputClauses.insert(newId);
}
}
+ Debug("proof:sat:detailed") <<"registerClause " << d_clauseId[clause] << " " <<isInput << "\n";
return d_clauseId[clause];
}
@@ -367,6 +371,7 @@ ClauseId SatProof::registerUnitClause(::Minisat::Lit lit, bool isInput) {
d_inputClauses.insert(newId);
}
}
+ Debug("proof:sat:detailed") <<"registerUnitClause " << d_unitId[toInt(lit)] << " " << isInput <<"\n";
return d_unitId[toInt(lit)];
}
@@ -527,10 +532,25 @@ void SatProof::toStream(std::ostream& out) {
Unimplemented("native proof printing not supported yet");
}
+void SatProof::storeUnitConflict(::Minisat::Lit conflict_lit) {
+ Assert (!d_storedUnitConflict);
+ d_unitConflictId = registerUnitClause(conflict_lit);
+ d_storedUnitConflict = true;
+ Debug("proof:sat:detailed") <<"storeUnitConflict " << d_unitConflictId << "\n";
+}
+
void SatProof::finalizeProof(::Minisat::CRef conflict_ref) {
Assert(d_resStack.size() == 0);
- //ClauseId conflict_id = getClauseId(conflict_ref);
- ClauseId conflict_id = registerClause(conflict_ref); //FIXME
+ Assert (conflict_ref != ::Minisat::CRef_Undef);
+ ClauseId conflict_id;
+ if (conflict_ref == ::Minisat::CRef_Lazy) {
+ Assert (d_storedUnitConflict);
+ conflict_id = d_unitConflictId;
+ } else {
+ Assert (!d_storedUnitConflict);
+ conflict_id = registerClause(conflict_ref); //FIXME
+ }
+
Debug("proof:sat") << "proof::finalizeProof Final Conflict ";
print(conflict_id);
@@ -573,6 +593,14 @@ void SatProof::markDeleted(CRef clause) {
}
}
+/// store mapping from theory atoms to new variables
+void SatProof::storeAtom(::Minisat::Lit literal, Expr atom) {
+ (d_atomToVar.find(atom) == d_atomToVar.end());
+ d_atomToVar[atom] = literal;
+}
+
+
+
/// LFSCSatProof class
std::string LFSCSatProof::varName(::Minisat::Lit lit) {
@@ -613,6 +641,7 @@ void LFSCSatProof::collectLemmas(ClauseId id) {
d_seenLemmas.insert(id);
}
+ Assert (d_resChains.find(id) != d_resChains.end());
ResChain* res = d_resChains[id];
ClauseId start = res->getStart();
collectLemmas(start);
@@ -658,6 +687,14 @@ void LFSCSatProof::printResolution(ClauseId id) {
void LFSCSatProof::printInputClause(ClauseId id) {
+ if (isUnit(id)) {
+ ::Minisat::Lit lit = getUnit(id);
+ d_clauseSS << "(% " << clauseName(id) << " (holds (clc ";
+ d_clauseSS << varName(lit) << "cln ))";
+ d_paren << ")";
+ return;
+ }
+
ostringstream os;
CRef ref = getClauseRef(id);
Assert (ref != CRef_Undef);
@@ -692,6 +729,7 @@ void LFSCSatProof::printVariables() {
void LFSCSatProof::flush(std::ostream& out) {
+ out << d_atomsSS.str();
out << "(check \n";
d_paren <<")";
out << d_varSS.str();
@@ -705,7 +743,7 @@ void LFSCSatProof::flush(std::ostream& out) {
void LFSCSatProof::toStream(std::ostream& out) {
Debug("proof:sat") << " LFSCSatProof::printProof \n";
-
+
// first collect lemmas to print in reverse order
collectLemmas(d_emptyClauseId);
for(IdSet::iterator it = d_seenLemmas.begin(); it!= d_seenLemmas.end(); ++it) {
@@ -713,13 +751,22 @@ void LFSCSatProof::toStream(std::ostream& out) {
printResolution(*it);
}
}
+ printAtoms();
// last resolution to be printed is the empty clause
printResolution(d_emptyClauseId);
-
+
printClauses();
printVariables();
flush(out);
}
+void LFSCSatProof::printAtoms() {
+ d_atomsSS << "; Mapping between boolean variables and theory atoms \n";
+ for (AtomToVar::iterator it = d_atomToVar.begin(); it != d_atomToVar.end(); ++it) {
+ d_atomsSS << "; " << it->first << " => v" << var(it->second) << "\n";
+ }
+}
+
+
} /* CVC4 namespace */
diff --git a/src/proof/sat_proof.h b/src/proof/sat_proof.h
index d497a4eba..fb8966400 100644
--- a/src/proof/sat_proof.h
+++ b/src/proof/sat_proof.h
@@ -26,6 +26,8 @@
#include <ext/hash_map>
#include <ext/hash_set>
#include <sstream>
+#include "expr/expr.h"
+
namespace Minisat {
class Solver;
@@ -90,6 +92,8 @@ typedef std::vector < ResChain* > ResStack;
typedef std::hash_set < int > VarSet;
typedef std::set < ClauseId > IdSet;
typedef std::vector < ::Minisat::Lit > LitVector;
+typedef __gnu_cxx::hash_map<Expr, ::Minisat::Lit, ExprHashFunction > AtomToVar;
+
class SatProof;
class ProofProxy : public ProofProxyAbstract {
@@ -124,7 +128,14 @@ protected:
// temporary map for updating CRefs
ClauseIdMap d_temp_clauseId;
- IdClauseMap d_temp_idClause;
+ IdClauseMap d_temp_idClause;
+
+ // unit conflict
+ ClauseId d_unitConflictId;
+ bool d_storedUnitConflict;
+
+ // atom mapping
+ AtomToVar d_atomToVar;
public:
SatProof(::Minisat::Solver* solver, bool checkRes = false);
protected:
@@ -197,6 +208,9 @@ public:
/// clause registration methods
ClauseId registerClause(const ::Minisat::CRef clause, bool isInput = false);
ClauseId registerUnitClause(const ::Minisat::Lit lit, bool isInput = false);
+
+ void storeUnitConflict(::Minisat::Lit lit);
+
/**
* Marks the deleted clauses as deleted. Note we may still use them in the final
* resolution.
@@ -216,12 +230,20 @@ public:
*/
void storeUnitResolution(::Minisat::Lit lit);
- ProofProxy* getProxy() {return d_proxy; }
+ ProofProxy* getProxy() {return d_proxy; }
+ /**
+ * At mapping between literal and theory-atom it represents
+ *
+ * @param literal
+ * @param atom
+ */
+ void storeAtom(::Minisat::Lit literal, Expr atom);
};/* class SatProof */
class LFSCSatProof: public SatProof {
private:
- VarSet d_seenVars;
+ VarSet d_seenVars;
+ std::ostringstream d_atomsSS;
std::ostringstream d_varSS;
std::ostringstream d_lemmaSS;
std::ostringstream d_clauseSS;
@@ -239,11 +261,12 @@ private:
void printVariables();
void printClauses();
void flush(std::ostream& out);
-
+ void printAtoms();
public:
LFSCSatProof(::Minisat::Solver* solver, bool checkRes = false):
SatProof(solver, checkRes),
d_seenVars(),
+ d_atomsSS(),
d_varSS(),
d_lemmaSS(),
d_paren(),
diff --git a/src/prop/cnf_stream.cpp b/src/prop/cnf_stream.cpp
index 4be58bdef..8ebb461e5 100644
--- a/src/prop/cnf_stream.cpp
+++ b/src/prop/cnf_stream.cpp
@@ -27,7 +27,9 @@
#include "expr/expr.h"
#include "prop/theory_proxy.h"
#include "theory/bv/options.h"
-
+#include "proof/proof_manager.h"
+#include "proof/sat_proof.h"
+#include "prop/minisat/minisat.h"
#include <queue>
using namespace std;
@@ -236,7 +238,7 @@ SatLiteral CnfStream::convertAtom(TNode node) {
// Make a new literal (variables are not considered theory literals)
SatLiteral lit = newLiteral(node, theoryLiteral, preRegister, canEliminate);
-
+ PROOF (ProofManager::getSatProof()->storeAtom(MinisatSatSolver::toMinisatLit(lit), node.toExpr()); );
// Return the resulting literal
return lit;
}
diff --git a/src/prop/minisat/core/Solver.cc b/src/prop/minisat/core/Solver.cc
index 6196ca357..4cce83fef 100644
--- a/src/prop/minisat/core/Solver.cc
+++ b/src/prop/minisat/core/Solver.cc
@@ -261,6 +261,7 @@ CRef Solver::reason(Var x) {
// Construct the reason
CRef real_reason = ca.alloc(explLevel, explanation, true);
+ PROOF (ProofManager::getSatProof()->registerClause(real_reason, true); );
vardata[x] = VarData(real_reason, level(x), user_level(x), intro_level(x), trail_index(x));
clauses_removable.push(real_reason);
attachClause(real_reason);
@@ -298,7 +299,7 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable)
continue;
}
// If a literals is false at 0 level (both sat and user level) we also ignore it
- if (value(ps[i]) == l_False) {
+ if (value(ps[i]) == l_False && !PROOF_ON() ) {
if (level(var(ps[i])) == 0 && user_level(var(ps[i])) == 0) {
continue;
} else {
@@ -789,7 +790,8 @@ CRef Solver::propagate(TheoryCheckType type)
// If there are lemmas (or conflicts) update them
if (lemmas.size() > 0) {
recheck = true;
- return updateLemmas();
+ confl = updateLemmas();
+ return confl;
} else {
recheck = proxy->theoryNeedCheck();
return confl;
@@ -801,7 +803,6 @@ CRef Solver::propagate(TheoryCheckType type)
do {
// Propagate on the clauses
confl = propagateBool();
-
// If no conflict, do the theory check
if (confl == CRef_Undef && type != CHECK_WITHOUTH_THEORY) {
// Do the theory check
@@ -836,7 +837,6 @@ CRef Solver::propagate(TheoryCheckType type)
}
}
} while (confl == CRef_Undef && qhead < trail.size());
-
return confl;
}
@@ -1579,6 +1579,7 @@ CRef Solver::updateLemmas() {
vec<Lit>& lemma = lemmas[i];
// If it's an empty lemma, we have a conflict at zero level
if (lemma.size() == 0) {
+ Assert (! PROOF_ON());
conflict = CRef_Lazy;
backtrackLevel = 0;
Debug("minisat::lemmas") << "Solver::updateLemmas(): found empty clause" << std::endl;
@@ -1628,6 +1629,7 @@ CRef Solver::updateLemmas() {
}
lemma_ref = ca.alloc(clauseLevel, lemma, removable);
+ PROOF (ProofManager::getSatProof()->registerClause(lemma_ref, true); );
if (removable) {
clauses_removable.push(lemma_ref);
} else {
@@ -1647,6 +1649,7 @@ CRef Solver::updateLemmas() {
} else {
Debug("minisat::lemmas") << "Solver::updateLemmas(): unit conflict or empty clause" << std::endl;
conflict = CRef_Lazy;
+ PROOF(ProofManager::getSatProof()->storeUnitConflict(lemma[0]););
}
} else {
Debug("minisat::lemmas") << "lemma size is " << lemma.size() << std::endl;
diff --git a/src/prop/prop_engine.cpp b/src/prop/prop_engine.cpp
index 5d6356a5b..a169d31e6 100644
--- a/src/prop/prop_engine.cpp
+++ b/src/prop/prop_engine.cpp
@@ -83,7 +83,8 @@ PropEngine::PropEngine(TheoryEngine* te, DecisionEngine *de, Context* satContext
userContext,
// fullLitToNode Map =
options::threads() > 1 ||
- options::decisionMode() == decision::DECISION_STRATEGY_RELEVANCY);
+ options::decisionMode() == decision::DECISION_STRATEGY_RELEVANCY
+ );
d_satSolver->initialize(d_context, new TheoryProxy(this, d_theoryEngine, d_decisionEngine, d_context, d_cnfStream));
diff --git a/src/smt/options b/src/smt/options
index 2680f4105..e5f9c2eaf 100644
--- a/src/smt/options
+++ b/src/smt/options
@@ -24,6 +24,8 @@ common-option produceModels produce-models -m --produce-models bool :default fal
support the get-value and get-model commands
option checkModels check-models --check-models bool :predicate CVC4::smt::beforeSearch :predicate-include "smt/options_handlers.h"
after SAT/INVALID/UNKNOWN, check that the generated model satisfies user assertions
+option dumpModels --dump-models bool :default false
+ output models after every SAT/INVALID/UNKNOWN response
option proof produce-proofs --proof bool :default false :predicate CVC4::smt::proofEnabledBuild CVC4::smt::beforeSearch :predicate-include "smt/options_handlers.h"
turn on proof generation
# this is just a placeholder for later; it doesn't show up in command-line options listings
diff --git a/src/smt/smt_engine.cpp b/src/smt/smt_engine.cpp
index 76d4c973f..ca89ce36d 100644
--- a/src/smt/smt_engine.cpp
+++ b/src/smt/smt_engine.cpp
@@ -74,6 +74,7 @@
#include "util/sort_inference.h"
#include "theory/quantifiers/macros.h"
#include "theory/datatypes/options.h"
+#include "theory/quantifiers/first_order_reasoning.h"
using namespace std;
using namespace CVC4;
@@ -349,8 +350,8 @@ private:
bool checkForBadSkolems(TNode n, TNode skolem, hash_map<Node, bool, NodeHashFunction>& cache);
// Lift bit-vectors of size 1 to booleans
- void bvToBool();
-
+ void bvToBool();
+
// Simplify ITE structure
void simpITE();
@@ -1009,11 +1010,18 @@ void SmtEngine::setLogicInternal() throw() {
//for finite model finding
if( ! options::instWhenMode.wasSetByUser()){
+ //instantiate only on last call
if( options::fmfInstEngine() ){
Trace("smt") << "setting inst when mode to LAST_CALL" << endl;
options::instWhenMode.set( INST_WHEN_LAST_CALL );
}
}
+ if ( ! options::fmfInstGen.wasSetByUser()) {
+ //if full model checking is on, disable inst-gen techniques
+ if( options::fmfFullModelCheck() ){
+ options::fmfInstGen.set( false );
+ }
+ }
//until bugs 371,431 are fixed
if( ! options::minisatUseElim.wasSetByUser()){
@@ -1824,15 +1832,15 @@ bool SmtEnginePrivate::nonClausalSimplify() {
}
hash_set<TNode, TNodeHashFunction> s;
- Trace("debugging") << "NonClausal simplify pre-preprocess\n";
+ Trace("debugging") << "NonClausal simplify pre-preprocess\n";
for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
Node assertion = d_assertionsToPreprocess[i];
Node assertionNew = d_topLevelSubstitutions.apply(assertion);
Trace("debugging") << "assertion = " << assertion << endl;
- Trace("debugging") << "assertionNew = " << assertionNew << endl;
+ Trace("debugging") << "assertionNew = " << assertionNew << endl;
if (assertion != assertionNew) {
assertion = Rewriter::rewrite(assertionNew);
- Trace("debugging") << "rewrite(assertion) = " << assertion << endl;
+ Trace("debugging") << "rewrite(assertion) = " << assertion << endl;
}
Assert(Rewriter::rewrite(assertion) == assertion);
for (;;) {
@@ -1841,11 +1849,11 @@ bool SmtEnginePrivate::nonClausalSimplify() {
break;
}
++d_smt.d_stats->d_numConstantProps;
- Trace("debugging") << "assertionNew = " << assertionNew << endl;
+ Trace("debugging") << "assertionNew = " << assertionNew << endl;
assertion = Rewriter::rewrite(assertionNew);
- Trace("debugging") << "assertionNew = " << assertionNew << endl;
+ Trace("debugging") << "assertionNew = " << assertionNew << endl;
}
- Trace("debugging") << "\n";
+ Trace("debugging") << "\n";
s.insert(assertion);
d_assertionsToCheck.push_back(assertion);
Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
@@ -1936,7 +1944,7 @@ bool SmtEnginePrivate::nonClausalSimplify() {
void SmtEnginePrivate::bvToBool() {
Trace("bv-to-bool") << "SmtEnginePrivate::bvToBool()" << endl;
std::vector<Node> new_assertions;
- d_smt.d_theoryEngine->ppBvToBool(d_assertionsToCheck, new_assertions);
+ d_smt.d_theoryEngine->ppBvToBool(d_assertionsToCheck, new_assertions);
for (unsigned i = 0; i < d_assertionsToCheck.size(); ++ i) {
d_assertionsToCheck[i] = Rewriter::rewrite(new_assertions[i]);
}
@@ -2790,6 +2798,12 @@ void SmtEnginePrivate::processAssertions() {
}while( success );
}
+ Trace("fo-rsn-enable") << std::endl;
+ if( options::foPropQuant() ){
+ FirstOrderPropagation fop;
+ fop.simplify( d_assertionsToPreprocess );
+ }
+
if( options::sortInference() ){
//sort inference technique
d_smt.d_theoryEngine->getSortInference()->simplify( d_assertionsToPreprocess );
@@ -2810,7 +2824,7 @@ void SmtEnginePrivate::processAssertions() {
}
dumpAssertions("post-static-learning", d_assertionsToCheck);
- // Lift bit-vectors of size 1 to bool
+ // Lift bit-vectors of size 1 to bool
if(options::bvToBool()) {
Chat() << "...doing bvToBool..." << endl;
bvToBool();
@@ -2820,7 +2834,7 @@ void SmtEnginePrivate::processAssertions() {
Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
-
+
dumpAssertions("pre-ite-removal", d_assertionsToCheck);
{
Chat() << "removing term ITEs..." << endl;
diff --git a/src/theory/arith/normal_form.cpp b/src/theory/arith/normal_form.cpp
index 8454ca210..1ebbe49e0 100644
--- a/src/theory/arith/normal_form.cpp
+++ b/src/theory/arith/normal_form.cpp
@@ -745,9 +745,8 @@ bool Comparison::isNormalGEQ() const {
return false;
}else{
if(left.isIntegral()){
- return left.denominatorLCMIsOne() && left.numeratorGCDIsOne();
+ return left.signNormalizedReducedSum();
}else{
- Debug("nf::tmp") << "imme sdfhkdjfh "<< left.leadingCoefficientIsAbsOne() << endl;
return left.leadingCoefficientIsAbsOne();
}
}
@@ -768,7 +767,7 @@ bool Comparison::isNormalLT() const {
return false;
}else{
if(left.isIntegral()){
- return left.denominatorLCMIsOne() && left.numeratorGCDIsOne();
+ return left.signNormalizedReducedSum();
}else{
return left.leadingCoefficientIsAbsOne();
}
@@ -889,6 +888,7 @@ Node Comparison::mkIntInequality(Kind k, const Polynomial& p){
Polynomial left = sp.getPolynomial();
Rational right = - (sp.getConstant().getValue());
+
Monomial m = left.getHead();
Assert(!m.isConstant());
@@ -899,16 +899,31 @@ Node Comparison::mkIntInequality(Kind k, const Polynomial& p){
Polynomial newLeft = left * mult;
Rational rightMult = right * mult;
+ bool negateResult = false;
+ if(!newLeft.leadingCoefficientIsPositive()){
+ // multiply by -1
+ // a: left >= right or b: left > right
+ // becomes
+ // a: -left <= -right or b: -left < -right
+ // a: not (-left > -right) or b: (not -left >= -right)
+ newLeft = -newLeft;
+ rightMult = -rightMult;
+ k = (kind::GT == k) ? kind::GEQ : kind::GT;
+ negateResult = true;
+ // the later stages handle:
+ // a: not (-left >= -right + 1) or b: (not -left >= -right)
+ }
+ Node result = Node::null();
if(rightMult.isIntegral()){
if(k == kind::GT){
// (> p z)
// (>= p (+ z 1))
Constant rightMultPlusOne = Constant::mkConstant(rightMult + 1);
- return toNode(kind::GEQ, newLeft, rightMultPlusOne);
+ result = toNode(kind::GEQ, newLeft, rightMultPlusOne);
}else{
Constant newRight = Constant::mkConstant(rightMult);
- return toNode(kind::GEQ, newLeft, newRight);
+ result = toNode(kind::GEQ, newLeft, newRight);
}
}else{
//(>= l (/ n d))
@@ -916,7 +931,13 @@ Node Comparison::mkIntInequality(Kind k, const Polynomial& p){
//This also hold for GT as (ceil (/ n d)) > (/ n d)
Integer ceilr = rightMult.ceiling();
Constant ceilRight = Constant::mkConstant(ceilr);
- return toNode(kind::GEQ, newLeft, ceilRight);
+ result = toNode(kind::GEQ, newLeft, ceilRight);
+ }
+ Assert(!result.isNull());
+ if(negateResult){
+ return result.notNode();
+ }else{
+ return result;
}
}
diff --git a/src/theory/arith/normal_form.h b/src/theory/arith/normal_form.h
index bcf9cbfa4..c6af7010f 100644
--- a/src/theory/arith/normal_form.h
+++ b/src/theory/arith/normal_form.h
@@ -76,12 +76,13 @@ namespace arith {
* (exists realMonomial (monomialList qpolynomial))
* abs(monomialCoefficient (head (monomialList qpolynomial))) == 1
*
- * integer_cmp := (<= zpolynomial constant)
+ * integer_cmp := (>= zpolynomial constant)
* where
* not (exists constantMonomial (monomialList zpolynomial))
* (forall integerMonomial (monomialList zpolynomial))
* the gcd of all numerators of coefficients is 1
* the denominator of all coefficients and the constant is 1
+ * the leading coefficient is positive
*
* rational_eq := (= qvarlist qpolynomial)
* where
@@ -939,6 +940,10 @@ public:
bool denominatorLCMIsOne() const;
bool numeratorGCDIsOne() const;
+ bool signNormalizedReducedSum() const {
+ return leadingCoefficientIsPositive() && denominatorLCMIsOne() && numeratorGCDIsOne();
+ }
+
/**
* Returns the Least Common Multiple of the denominators of the coefficients
* of the monomials.
@@ -1265,7 +1270,7 @@ private:
* Creates a comparison equivalent to (k l 0).
* k is either GT or GEQ.
* It is not the case that all variables in l are integral.
- */
+ */
static Node mkRatInequality(Kind k, const Polynomial& l);
public:
diff --git a/src/theory/arith/theory_arith_private.cpp b/src/theory/arith/theory_arith_private.cpp
index d911ecf77..dd5e404c6 100644
--- a/src/theory/arith/theory_arith_private.cpp
+++ b/src/theory/arith/theory_arith_private.cpp
@@ -67,6 +67,8 @@
#include "theory/arith/options.h"
+#include "theory/quantifiers/bounded_integers.h"
+
#include <stdint.h>
#include <vector>
@@ -89,6 +91,7 @@ TheoryArithPrivate::TheoryArithPrivate(TheoryArith& containing, context::Context
d_unknownsInARow(0),
d_hasDoneWorkSinceCut(false),
d_learner(u),
+ d_quantEngine(qe),
d_assertionsThatDoNotMatchTheirLiterals(c),
d_nextIntegerCheckVar(0),
d_constantIntegerVariables(c),
@@ -1373,6 +1376,10 @@ Constraint TheoryArithPrivate::constraintFromFactQueue(){
Assert(!done());
TNode assertion = get();
+ if( options::finiteModelFind() && d_quantEngine && d_quantEngine->getBoundedIntegers() ){
+ d_quantEngine->getBoundedIntegers()->assertNode(assertion);
+ }
+
Kind simpleKind = Comparison::comparisonKind(assertion);
Constraint constraint = d_constraintDatabase.lookup(assertion);
if(constraint == NullConstraint){
diff --git a/src/theory/arith/theory_arith_private.h b/src/theory/arith/theory_arith_private.h
index 2ea3bb68e..86c8e213e 100644
--- a/src/theory/arith/theory_arith_private.h
+++ b/src/theory/arith/theory_arith_private.h
@@ -132,7 +132,8 @@ private:
/** Static learner. */
ArithStaticLearner d_learner;
-
+ /** quantifiers engine */
+ QuantifiersEngine * d_quantEngine;
//std::vector<ArithVar> d_pool;
public:
void releaseArithVar(ArithVar v);
diff --git a/src/theory/arrays/Makefile.am b/src/theory/arrays/Makefile.am
index ec834522f..77f102cf8 100644
--- a/src/theory/arrays/Makefile.am
+++ b/src/theory/arrays/Makefile.am
@@ -16,9 +16,7 @@ libarrays_la_SOURCES = \
array_info.h \
array_info.cpp \
static_fact_manager.h \
- static_fact_manager.cpp \
- theory_arrays_model.h \
- theory_arrays_model.cpp
+ static_fact_manager.cpp
EXTRA_DIST = \
kinds
diff --git a/src/theory/arrays/theory_arrays.cpp b/src/theory/arrays/theory_arrays.cpp
index 89f1dbf2c..98346d0e3 100644
--- a/src/theory/arrays/theory_arrays.cpp
+++ b/src/theory/arrays/theory_arrays.cpp
@@ -21,7 +21,6 @@
#include <map>
#include "theory/rewriter.h"
#include "expr/command.h"
-#include "theory/arrays/theory_arrays_model.h"
#include "theory/model.h"
#include "theory/arrays/options.h"
#include "smt/logic_exception.h"
@@ -495,7 +494,7 @@ void TheoryArrays::preRegisterTermInternal(TNode node)
}
case kind::STORE_ALL: {
throw LogicException("Array theory solver does not yet support assertions using constant array value");
- }
+ }
default:
// Variables etc
if (node.getType().isArray()) {
@@ -1082,7 +1081,7 @@ void TheoryArrays::checkModel(Effort e)
if (constraintIdx == d_modelConstraints.size()) {
break;
}
-
+
if (assertion.getKind() == kind::EQUAL && assertion[0].getType().isArray()) {
assertionToCheck = solveWrite(expandStores(assertion[0], assumptions).eqNode(expandStores(assertion[1], assumptions)), true, true, false);
if (assertionToCheck.getKind() == kind::AND &&
@@ -1429,7 +1428,7 @@ Node TheoryArrays::getModelValRec(TNode node)
}
++d_numGetModelValConflicts;
getSatContext()->pop();
- }
+ }
++te;
if (te.isFinished()) {
Assert(false);
@@ -1466,7 +1465,7 @@ bool TheoryArrays::hasLoop(TNode node, TNode target)
return true;
}
}
-
+
return false;
}
diff --git a/src/theory/arrays/theory_arrays_model.cpp b/src/theory/arrays/theory_arrays_model.cpp
deleted file mode 100644
index b5c81ef69..000000000
--- a/src/theory/arrays/theory_arrays_model.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/********************* */
-/*! \file theory_arrays_model.cpp
- ** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-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_arrays_model class
- **/
-
-#include "theory/theory_engine.h"
-#include "theory/arrays/theory_arrays_model.h"
-#include "theory/model.h"
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::arrays;
-
-ArrayModel::ArrayModel( Node arr, TheoryModel* m ) : d_arr( arr ){
- d_base_arr = arr;
- while( d_base_arr.getKind()==STORE ){
- Node ri = m->getRepresentative( d_base_arr[1] );
- if( d_values.find( ri )==d_values.end() ){
- d_values[ ri ] = m->getRepresentative( d_base_arr[2] );
- }
- d_base_arr = d_base_arr[0];
- }
-}
-
-Node ArrayModel::getValue( TheoryModel* m, Node i ){
- i = m->getRepresentative( i );
- std::map< Node, Node >::iterator it = d_values.find( i );
- if( it!=d_values.end() ){
- return it->second;
- }else{
- return NodeManager::currentNM()->mkNode( SELECT, getArrayValue(), i );
- //return d_default_value; //TODO: guarantee I can return this here
- }
-}
-
-void ArrayModel::setValue( TheoryModel* m, Node i, Node e ){
- Node ri = m->getRepresentative( i );
- if( d_values.find( ri )==d_values.end() ){
- d_values[ ri ] = m->getRepresentative( e );
- }
-}
-
-void ArrayModel::setDefaultArray( Node arr ){
- d_base_arr = arr;
-}
-
-Node ArrayModel::getArrayValue(){
- Node curr = d_base_arr;
- for( std::map< Node, Node >::iterator it = d_values.begin(); it != d_values.end(); ++it ){
- curr = NodeManager::currentNM()->mkNode( STORE, curr, it->first, it->second );
- }
- return curr;
-}
diff --git a/src/theory/arrays/theory_arrays_model.h b/src/theory/arrays/theory_arrays_model.h
deleted file mode 100644
index 66dc80568..000000000
--- a/src/theory/arrays/theory_arrays_model.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/********************* */
-/*! \file theory_arrays_model.h
- ** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-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 */
-
-}
-}
-}
-
-#endif \ No newline at end of file
diff --git a/src/theory/bv/bv_subtheory.h b/src/theory/bv/bv_subtheory.h
index 8374a3f75..1c6920236 100644
--- a/src/theory/bv/bv_subtheory.h
+++ b/src/theory/bv/bv_subtheory.h
@@ -55,9 +55,6 @@ inline std::ostream& operator << (std::ostream& out, SubTheory subtheory) {
}
-const bool d_useEqualityEngine = true;
-const bool d_useSatPropagation = true;
-
// forward declaration
class TheoryBV;
diff --git a/src/theory/bv/bv_subtheory_bitblast.cpp b/src/theory/bv/bv_subtheory_bitblast.cpp
index 2308f36a3..244d87233 100644
--- a/src/theory/bv/bv_subtheory_bitblast.cpp
+++ b/src/theory/bv/bv_subtheory_bitblast.cpp
@@ -34,7 +34,8 @@ BitblastSolver::BitblastSolver(context::Context* c, TheoryBV* bv)
d_bitblaster(new Bitblaster(c, bv)),
d_bitblastQueue(c),
d_statistics(),
- d_validModelCache(c, true)
+ d_validModelCache(c, true),
+ d_useSatPropagation(options::bvPropagate())
{}
BitblastSolver::~BitblastSolver() {
diff --git a/src/theory/bv/bv_subtheory_bitblast.h b/src/theory/bv/bv_subtheory_bitblast.h
index 819b3d62c..315254c8e 100644
--- a/src/theory/bv/bv_subtheory_bitblast.h
+++ b/src/theory/bv/bv_subtheory_bitblast.h
@@ -47,6 +47,7 @@ class BitblastSolver : public SubtheorySolver {
context::CDO<bool> d_validModelCache;
Node getModelValueRec(TNode node);
+ bool d_useSatPropagation;
public:
BitblastSolver(context::Context* c, TheoryBV* bv);
~BitblastSolver();
diff --git a/src/theory/bv/bv_subtheory_core.cpp b/src/theory/bv/bv_subtheory_core.cpp
index c0546f892..f7209d326 100644
--- a/src/theory/bv/bv_subtheory_core.cpp
+++ b/src/theory/bv/bv_subtheory_core.cpp
@@ -37,40 +37,38 @@ CoreSolver::CoreSolver(context::Context* c, TheoryBV* bv)
d_isCoreTheory(c, true),
d_reasons(c)
{
- if (d_useEqualityEngine) {
- // The kinds we are treating as function application in congruence
- d_equalityEngine.addFunctionKind(kind::BITVECTOR_CONCAT, true);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_AND);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_OR);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_XOR);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_NOT);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_NAND);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_NOR);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_XNOR);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_COMP);
- d_equalityEngine.addFunctionKind(kind::BITVECTOR_MULT, true);
- d_equalityEngine.addFunctionKind(kind::BITVECTOR_PLUS, true);
- d_equalityEngine.addFunctionKind(kind::BITVECTOR_EXTRACT, true);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SUB);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_NEG);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_UDIV);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_UREM);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SDIV);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SREM);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SMOD);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SHL);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_LSHR);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_ASHR);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_ULT);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_ULE);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_UGT);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_UGE);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SLT);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SLE);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SGT);
- // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SGE);
- }
+ // The kinds we are treating as function application in congruence
+ d_equalityEngine.addFunctionKind(kind::BITVECTOR_CONCAT, true);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_AND);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_OR);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_XOR);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_NOT);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_NAND);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_NOR);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_XNOR);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_COMP);
+ d_equalityEngine.addFunctionKind(kind::BITVECTOR_MULT, true);
+ d_equalityEngine.addFunctionKind(kind::BITVECTOR_PLUS, true);
+ d_equalityEngine.addFunctionKind(kind::BITVECTOR_EXTRACT, true);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SUB);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_NEG);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_UDIV);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_UREM);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SDIV);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SREM);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SMOD);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SHL);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_LSHR);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_ASHR);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_ULT);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_ULE);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_UGT);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_UGE);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SLT);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SLE);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SGT);
+ // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SGE);
}
CoreSolver::~CoreSolver() {
@@ -81,9 +79,6 @@ void CoreSolver::setMasterEqualityEngine(eq::EqualityEngine* eq) {
}
void CoreSolver::preRegister(TNode node) {
- if (!d_useEqualityEngine)
- return;
-
if (node.getKind() == kind::EQUAL) {
d_equalityEngine.addTriggerEquality(node);
if (options::bitvectorCoreSolver()) {
@@ -291,7 +286,7 @@ void CoreSolver::buildModel() {
bool CoreSolver::assertFactToEqualityEngine(TNode fact, TNode reason) {
// Notify the equality engine
- if (d_useEqualityEngine && !d_bv->inConflict() && (!d_bv->wasPropagatedBySubtheory(fact) || !d_bv->getPropagatingSubtheory(fact) == SUB_CORE)) {
+ if (!d_bv->inConflict() && (!d_bv->wasPropagatedBySubtheory(fact) || !d_bv->getPropagatingSubtheory(fact) == SUB_CORE)) {
Debug("bv-slicer-eq") << "CoreSolver::assertFactToEqualityEngine fact=" << fact << endl;
// Debug("bv-slicer-eq") << " reason=" << reason << endl;
bool negated = fact.getKind() == kind::NOT;
diff --git a/src/theory/bv/options b/src/theory/bv/options
index 7b87baa21..077299d1f 100644
--- a/src/theory/bv/options
+++ b/src/theory/bv/options
@@ -22,5 +22,11 @@ option bitvectorCoreSolver --bv-core-solver bool
option bvToBool --bv-to-bool bool
lift bit-vectors of size 1 to booleans when possible
+
+option bvPropagate --bv-propagate bool :default true
+ use bit-vector propagation in the bit-blaster
+
+option bvEquality --bv-eq bool :default true
+ use the equality engine for the bit-vector theory
endmodule
diff --git a/src/theory/bv/theory_bv.cpp b/src/theory/bv/theory_bv.cpp
index 4803fd62e..224359952 100644
--- a/src/theory/bv/theory_bv.cpp
+++ b/src/theory/bv/theory_bv.cpp
@@ -49,10 +49,11 @@ TheoryBV::TheoryBV(context::Context* c, context::UserContext* u, OutputChannel&
d_literalsToPropagateIndex(c, 0),
d_propagatedBy(c)
{
- SubtheorySolver* core_solver = new CoreSolver(c, this);
- d_subtheories.push_back(core_solver);
- d_subtheoryMap[SUB_CORE] = core_solver;
-
+ if (options::bvEquality()) {
+ SubtheorySolver* core_solver = new CoreSolver(c, this);
+ d_subtheories.push_back(core_solver);
+ d_subtheoryMap[SUB_CORE] = core_solver;
+ }
if (options::bitvectorInequalitySolver()) {
SubtheorySolver* ineq_solver = new InequalitySolver(c, this);
d_subtheories.push_back(ineq_solver);
@@ -366,7 +367,7 @@ Node TheoryBV::explain(TNode node) {
void TheoryBV::addSharedTerm(TNode t) {
Debug("bitvector::sharing") << indent() << "TheoryBV::addSharedTerm(" << t << ")" << std::endl;
d_sharedTermsSet.insert(t);
- if (!options::bitvectorEagerBitblast() && d_useEqualityEngine) {
+ if (!options::bitvectorEagerBitblast() && options::bvEquality()) {
for (unsigned i = 0; i < d_subtheories.size(); ++i) {
d_subtheories[i]->addSharedTerm(t);
}
diff --git a/src/theory/quantifiers/Makefile.am b/src/theory/quantifiers/Makefile.am
index 7fea8cf3a..60f2ee7f7 100644
--- a/src/theory/quantifiers/Makefile.am
+++ b/src/theory/quantifiers/Makefile.am
@@ -23,8 +23,6 @@ libquantifiers_la_SOURCES = \
model_engine.cpp \
modes.cpp \
modes.h \
- relevant_domain.h \
- relevant_domain.cpp \
term_database.h \
term_database.cpp \
first_order_model.h \
@@ -44,7 +42,13 @@ libquantifiers_la_SOURCES = \
inst_strategy_e_matching.h \
inst_strategy_e_matching.cpp \
inst_strategy_cbqi.h \
- inst_strategy_cbqi.cpp
+ inst_strategy_cbqi.cpp \
+ full_model_check.h \
+ full_model_check.cpp \
+ bounded_integers.h \
+ bounded_integers.cpp \
+ first_order_reasoning.h \
+ first_order_reasoning.cpp
EXTRA_DIST = \
kinds \
diff --git a/src/theory/quantifiers/bounded_integers.cpp b/src/theory/quantifiers/bounded_integers.cpp
new file mode 100755
index 000000000..e33cd2131
--- /dev/null
+++ b/src/theory/quantifiers/bounded_integers.cpp
@@ -0,0 +1,366 @@
+/********************* */
+/*! \file bounded_integers.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds
+ ** 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 Bounded integers module
+ **
+ ** This class manages integer bounds for quantifiers
+ **/
+
+#include "theory/quantifiers/bounded_integers.h"
+#include "theory/quantifiers/quant_util.h"
+#include "theory/quantifiers/first_order_model.h"
+#include "theory/quantifiers/model_engine.h"
+
+using namespace CVC4;
+using namespace std;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+using namespace CVC4::kind;
+
+void BoundedIntegers::RangeModel::initialize() {
+ //add initial split lemma
+ Node ltr = NodeManager::currentNM()->mkNode( LT, d_range, NodeManager::currentNM()->mkConst( Rational(0) ) );
+ ltr = Rewriter::rewrite( ltr );
+ Trace("bound-int-lemma") << " *** bound int: initial split on " << ltr << std::endl;
+ d_bi->getQuantifiersEngine()->getOutputChannel().split( ltr );
+ Node ltr_lit = ltr.getKind()==NOT ? ltr[0] : ltr;
+ d_range_literal[-1] = ltr_lit;
+ d_lit_to_range[ltr_lit] = -1;
+ d_lit_to_pol[ltr_lit] = ltr.getKind()!=NOT;
+ //register with bounded integers
+ Trace("bound-int-debug") << "Literal " << ltr_lit << " is literal for " << d_range << std::endl;
+ d_bi->addLiteralFromRange(ltr_lit, d_range);
+}
+
+void BoundedIntegers::RangeModel::assertNode(Node n) {
+ bool pol = n.getKind()!=NOT;
+ Node nlit = n.getKind()==NOT ? n[0] : n;
+ if( d_lit_to_range.find( nlit )!=d_lit_to_range.end() ){
+ Trace("bound-int-assert") << "With polarity = " << pol << " (req "<< d_lit_to_pol[nlit] << ")";
+ Trace("bound-int-assert") << ", found literal " << nlit;
+ Trace("bound-int-assert") << ", it is bound literal " << d_lit_to_range[nlit] << " for " << d_range << std::endl;
+ d_range_assertions[nlit] = (pol==d_lit_to_pol[nlit]);
+ if( pol!=d_lit_to_pol[nlit] ){
+ //check if we need a new split?
+ if( !d_has_range ){
+ bool needsRange = true;
+ for( std::map< Node, int >::iterator it = d_lit_to_range.begin(); it != d_lit_to_range.end(); ++it ){
+ if( d_range_assertions.find( it->first )==d_range_assertions.end() ){
+ needsRange = false;
+ break;
+ }
+ }
+ if( needsRange ){
+ allocateRange();
+ }
+ }
+ }else{
+ if (!d_has_range || d_lit_to_range[nlit]<d_curr_range ){
+ Trace("bound-int-bound") << "Successfully bound " << d_range << " to " << d_lit_to_range[nlit] << std::endl;
+ d_curr_range = d_lit_to_range[nlit];
+ }
+ //set the range
+ d_has_range = true;
+ }
+ }else{
+ Message() << "Could not find literal " << nlit << " for range " << d_range << std::endl;
+ exit(0);
+ }
+}
+
+void BoundedIntegers::RangeModel::allocateRange() {
+ d_curr_max++;
+ int newBound = d_curr_max;
+ Trace("bound-int-proc") << "Allocate range bound " << newBound << " for " << d_range << std::endl;
+ //TODO: newBound should be chosen in a smarter way
+ Node ltr = NodeManager::currentNM()->mkNode( LEQ, d_range, NodeManager::currentNM()->mkConst( Rational(newBound) ) );
+ ltr = Rewriter::rewrite( ltr );
+ Trace("bound-int-lemma") << " *** bound int: split on " << ltr << std::endl;
+ d_bi->getQuantifiersEngine()->getOutputChannel().split( ltr );
+ Node ltr_lit = ltr.getKind()==NOT ? ltr[0] : ltr;
+ d_range_literal[newBound] = ltr_lit;
+ d_lit_to_range[ltr_lit] = newBound;
+ d_lit_to_pol[ltr_lit] = ltr.getKind()!=NOT;
+ //register with bounded integers
+ d_bi->addLiteralFromRange(ltr_lit, d_range);
+}
+
+Node BoundedIntegers::RangeModel::getNextDecisionRequest() {
+ //request the current cardinality as a decision literal, if not already asserted
+ for( std::map< Node, int >::iterator it = d_lit_to_range.begin(); it != d_lit_to_range.end(); ++it ){
+ int i = it->second;
+ if( !d_has_range || i<d_curr_range ){
+ Node rn = it->first;
+ Assert( !rn.isNull() );
+ if( d_range_assertions.find( rn )==d_range_assertions.end() ){
+ if (!d_lit_to_pol[it->first]) {
+ rn = rn.negate();
+ }
+ Trace("bound-int-dec") << "For " << d_range << ", make decision " << rn << " to make range " << i << std::endl;
+ return rn;
+ }
+ }
+ }
+ return Node::null();
+}
+
+
+BoundedIntegers::BoundedIntegers(context::Context* c, QuantifiersEngine* qe) :
+QuantifiersModule(qe), d_assertions(c){
+
+}
+
+bool BoundedIntegers::isBound( Node f, Node v ) {
+ return std::find( d_set[f].begin(), d_set[f].end(), v )!=d_set[f].end();
+}
+
+bool BoundedIntegers::hasNonBoundVar( Node f, Node b ) {
+ if( b.getKind()==BOUND_VARIABLE ){
+ if( !isBound( f, b ) ){
+ return true;
+ }
+ }else{
+ for( unsigned i=0; i<b.getNumChildren(); i++ ){
+ if( hasNonBoundVar( f, b[i] ) ){
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void BoundedIntegers::processLiteral( Node f, Node lit, bool pol ) {
+ if( lit.getKind()==GEQ && lit[0].getType().isInteger() ){
+ std::map< Node, Node > msum;
+ if (QuantArith::getMonomialSumLit( lit, msum )){
+ Trace("bound-int-debug") << "Literal (polarity = " << pol << ") " << lit << " is monomial sum : " << std::endl;
+ for(std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){
+ Trace("bound-int-debug") << " ";
+ if( !it->second.isNull() ){
+ Trace("bound-int-debug") << it->second;
+ if( !it->first.isNull() ){
+ Trace("bound-int-debug") << " * ";
+ }
+ }
+ if( !it->first.isNull() ){
+ Trace("bound-int-debug") << it->first;
+ }
+ Trace("bound-int-debug") << std::endl;
+ }
+ Trace("bound-int-debug") << std::endl;
+ for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){
+ if ( !it->first.isNull() && it->first.getKind()==BOUND_VARIABLE && !isBound( f, it->first ) ){
+ Node veq;
+ if( QuantArith::isolate( it->first, msum, veq, GEQ ) ){
+ Node n1 = veq[0];
+ Node n2 = veq[1];
+ if(pol){
+ //flip
+ n1 = veq[1];
+ n2 = veq[0];
+ if( n1.getKind()==BOUND_VARIABLE ){
+ n2 = QuantArith::offset( n2, 1 );
+ }else{
+ n1 = QuantArith::offset( n1, -1 );
+ }
+ veq = NodeManager::currentNM()->mkNode( GEQ, n1, n2 );
+ }
+ Trace("bound-int-debug") << "Isolated for " << it->first << " : (" << n1 << " >= " << n2 << ")" << std::endl;
+ Node bv = n1.getKind()==BOUND_VARIABLE ? n1 : n2;
+ if( !isBound( f, bv ) ){
+ if( !hasNonBoundVar( f, n1.getKind()==BOUND_VARIABLE ? n2 : n1 ) ) {
+ Trace("bound-int-debug") << "The bound is relevant." << std::endl;
+ d_bounds[n1.getKind()==BOUND_VARIABLE ? 0 : 1][f][bv] = (n1.getKind()==BOUND_VARIABLE ? n2 : n1);
+ }
+ }
+ }
+ }
+ }
+ }
+ }else if( lit.getKind()==LEQ || lit.getKind()==LT || lit.getKind()==GT ) {
+ std::cout << "BoundedIntegers : Bad kind for literal : " << lit << std::endl;
+ exit(0);
+ }
+}
+
+void BoundedIntegers::process( Node f, Node n, bool pol ){
+ if( (( n.getKind()==IMPLIES || n.getKind()==OR) && pol) || (n.getKind()==AND && !pol) ){
+ for( unsigned i=0; i<n.getNumChildren(); i++) {
+ bool newPol = n.getKind()==IMPLIES && i==0 ? !pol : pol;
+ process( f, n[i], newPol );
+ }
+ }else if( n.getKind()==NOT ){
+ process( f, n[0], !pol );
+ }else {
+ processLiteral( f, n, pol );
+ }
+}
+
+void BoundedIntegers::check( Theory::Effort e ) {
+
+}
+
+
+void BoundedIntegers::addLiteralFromRange( Node lit, Node r ) {
+ d_lit_to_ranges[lit].push_back(r);
+ //check if it is already asserted?
+ if(d_assertions.find(lit)!=d_assertions.end()){
+ d_rms[r]->assertNode( d_assertions[lit] ? lit : lit.negate() );
+ }
+}
+
+void BoundedIntegers::registerQuantifier( Node f ) {
+ Trace("bound-int") << "Register quantifier " << f << std::endl;
+ bool hasIntType = false;
+ std::map< Node, int > numMap;
+ for( unsigned i=0; i<f[0].getNumChildren(); i++) {
+ numMap[f[0][i]] = i;
+ if( f[0][i].getType().isInteger() ){
+ hasIntType = true;
+ }
+ }
+ if( hasIntType ){
+ bool success;
+ do{
+ success = false;
+ process( f, f[1], true );
+ for( std::map< Node, Node >::iterator it = d_bounds[0][f].begin(); it != d_bounds[0][f].end(); ++it ){
+ Node v = it->first;
+ if( !isBound(f,v) ){
+ if( d_bounds[1][f].find(v)!=d_bounds[1][f].end() ){
+ d_set[f].push_back(v);
+ d_set_nums[f].push_back(numMap[v]);
+ success = true;
+ }
+ }
+ }
+ }while( success );
+ Trace("bound-int") << "Bounds are : " << std::endl;
+ for( unsigned i=0; i<d_set[f].size(); i++) {
+ Node v = d_set[f][i];
+ Node r = NodeManager::currentNM()->mkNode( MINUS, d_bounds[1][f][v], d_bounds[0][f][v] );
+ d_range[f][v] = Rewriter::rewrite( r );
+ Trace("bound-int") << " " << d_bounds[0][f][v] << " <= " << v << " <= " << d_bounds[1][f][v] << " (range is " << d_range[f][v] << ")" << std::endl;
+ }
+ if( d_set[f].size()==f[0].getNumChildren() ){
+ d_bound_quants.push_back( f );
+ for( unsigned i=0; i<d_set[f].size(); i++) {
+ Node v = d_set[f][i];
+ Node r = d_range[f][v];
+ if( quantifiers::TermDb::hasBoundVarAttr(r) ){
+ //introduce a new bound
+ Node new_range = NodeManager::currentNM()->mkSkolem( "bir_$$", r.getType(), "bound for term" );
+ /*
+ std::vector< Node > bvs;
+ quantifiers::TermDb::getBoundVars(r, bvs);
+ Assert(bvs.size()>0);
+ Node body = NodeManager::currentNM()->mkNode( LEQ, r, new_range );
+ std::vector< Node > children;
+ //get all the other bounds
+ for( unsigned j=0; j<bvs.size(); j++) {
+ Node l = NodeManager::currentNM()->mkNode( LEQ, NodeManager::currentNM()->mkConst(Rational(0)), bvs[j]);
+ Node u = NodeManager::currentNM()->mkNode( LEQ, bvs[j], d_range[f][bvs[j]] );
+ children.push_back(l);
+ children.push_back(u);
+ }
+ Node antec = NodeManager::currentNM()->mkNode( AND, children );
+ body = NodeManager::currentNM()->mkNode( IMPLIES, antec, body );
+
+ Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, bvs );
+
+ Node lem = NodeManager::currentNM()->mkNode( FORALL, bvl, body );
+ Trace("bound-int") << "For " << v << ", the quantified formula " << lem << " will be used to minimize the bound." << std::endl;
+ Trace("bound-int-lemma") << " *** bound int: bounding quantified lemma " << lem << std::endl;
+ d_quantEngine->getOutputChannel().lemma( lem );
+ */
+ d_nground_range[f][v] = d_range[f][v];
+ d_range[f][v] = new_range;
+ r = new_range;
+ }
+ if( std::find(d_ranges.begin(), d_ranges.end(), r)==d_ranges.end() ){
+ Trace("bound-int") << "For " << v << ", bounded Integer Module will try to minimize : " << r << std::endl;
+ d_ranges.push_back( r );
+ d_rms[r] = new RangeModel(this, r, d_quantEngine->getSatContext() );
+ d_rms[r]->initialize();
+ }
+ }
+ }
+ }
+}
+
+void BoundedIntegers::assertNode( Node n ) {
+ Trace("bound-int-assert") << "Assert " << n << std::endl;
+ Node nlit = n.getKind()==NOT ? n[0] : n;
+ if( d_lit_to_ranges.find(nlit)!=d_lit_to_ranges.end() ){
+ Trace("bound-int-assert") << "This is the bounding literal for " << d_lit_to_ranges[nlit].size() << " ranges." << std::endl;
+ for( unsigned i=0; i<d_lit_to_ranges[nlit].size(); i++) {
+ Node r = d_lit_to_ranges[nlit][i];
+ Trace("bound-int-assert") << " ...this is a bounding literal for " << r << std::endl;
+ d_rms[r]->assertNode( n );
+ }
+ }
+ d_assertions[nlit] = n.getKind()!=NOT;
+}
+
+Node BoundedIntegers::getNextDecisionRequest() {
+ Trace("bound-int-dec") << "bi: Get next decision request?" << std::endl;
+ for( unsigned i=0; i<d_ranges.size(); i++) {
+ Node d = d_rms[d_ranges[i]]->getNextDecisionRequest();
+ if (!d.isNull()) {
+ return d;
+ }
+ }
+ return Node::null();
+}
+
+void BoundedIntegers::getBoundValues( Node f, Node v, RepSetIterator * rsi, Node & l, Node & u ) {
+ l = d_bounds[0][f][v];
+ u = d_bounds[1][f][v];
+ if( d_nground_range[f].find(v)!=d_nground_range[f].end() ){
+ //must create substitution
+ std::vector< Node > vars;
+ std::vector< Node > subs;
+ Trace("bound-int-rsi") << "Get bound value in model of variable " << v << std::endl;
+ for( unsigned i=0; i<d_set[f].size(); i++) {
+ if( d_set[f][i]!=v ){
+ Trace("bound-int-rsi") << "Look up the value for " << d_set[f][i] << " " << rsi->d_var_order[d_set_nums[f][i]] << std::endl;
+ Trace("bound-int-rsi") << "term : " << rsi->getTerm(rsi->d_var_order[d_set_nums[f][i]]) << std::endl;
+ vars.push_back(d_set[f][i]);
+ subs.push_back(rsi->getTerm(rsi->d_var_order[d_set_nums[f][i]]));
+ }else{
+ break;
+ }
+ }
+ Trace("bound-int-rsi") << "Do substitution..." << std::endl;
+ //check if it has been instantiated
+ if (!vars.empty() && !d_bnd_it[f][v].hasInstantiated(subs)){
+ //must add the lemma
+ Node nn = d_nground_range[f][v];
+ nn = nn.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ Node lem = NodeManager::currentNM()->mkNode( LEQ, nn, d_range[f][v] );
+ Trace("bound-int-lemma") << "*** Add lemma to minimize instantiated non-ground term " << lem << std::endl;
+ d_quantEngine->getOutputChannel().lemma(lem);
+ l = Node::null();
+ u = Node::null();
+ return;
+ }else{
+ u = u.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ l = l.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ }
+ }
+ Trace("bound-int-rsi") << "Get value in model for..." << l << " and " << u << std::endl;
+ l = d_quantEngine->getModel()->getCurrentModelValue( l );
+ u = d_quantEngine->getModel()->getCurrentModelValue( u );
+ Trace("bound-int-rsi") << "Value is " << l << " ... " << u << std::endl;
+ return;
+}
+
+bool BoundedIntegers::isGroundRange(Node f, Node v) {
+ return isBoundVar(f,v) && !quantifiers::TermDb::hasBoundVarAttr(getLowerBound(f,v)) && !quantifiers::TermDb::hasBoundVarAttr(getUpperBound(f,v));
+} \ No newline at end of file
diff --git a/src/theory/quantifiers/bounded_integers.h b/src/theory/quantifiers/bounded_integers.h
new file mode 100755
index 000000000..f40e2180c
--- /dev/null
+++ b/src/theory/quantifiers/bounded_integers.h
@@ -0,0 +1,122 @@
+/********************* */
+/*! \file bounded_integers.h
+** \verbatim
+** Original author: Andrew Reynolds
+** 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 This class manages integer bounds for quantifiers
+**/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__BOUNDED_INTEGERS_H
+#define __CVC4__BOUNDED_INTEGERS_H
+
+
+#include "theory/quantifiers_engine.h"
+
+#include "context/context.h"
+#include "context/context_mm.h"
+#include "context/cdchunk_list.h"
+
+namespace CVC4 {
+namespace theory {
+
+class RepSetIterator;
+
+namespace quantifiers {
+
+
+class BoundedIntegers : public QuantifiersModule
+{
+ typedef context::CDHashMap<Node, bool, NodeHashFunction> NodeBoolMap;
+ typedef context::CDHashMap<Node, int, NodeHashFunction> NodeIntMap;
+ typedef context::CDHashMap<Node, Node, NodeHashFunction> NodeNodeMap;
+private:
+ //for determining bounds
+ bool isBound( Node f, Node v );
+ bool hasNonBoundVar( Node f, Node b );
+ std::map< Node, std::map< Node, Node > > d_bounds[2];
+ std::map< Node, std::vector< Node > > d_set;
+ std::map< Node, std::vector< int > > d_set_nums;
+ std::map< Node, std::map< Node, Node > > d_range;
+ std::map< Node, std::map< Node, Node > > d_nground_range;
+ void hasFreeVar( Node f, Node n );
+ void process( Node f, Node n, bool pol );
+ void processLiteral( Node f, Node lit, bool pol );
+ std::vector< Node > d_bound_quants;
+private:
+ class RangeModel {
+ private:
+ BoundedIntegers * d_bi;
+ void allocateRange();
+ public:
+ RangeModel(BoundedIntegers * bi, Node r, context::Context* c) : d_bi(bi),
+ d_range(r), d_curr_max(-1), d_range_assertions(c), d_has_range(c,false), d_curr_range(c,-1) {}
+ Node d_range;
+ int d_curr_max;
+ std::map< int, Node > d_range_literal;
+ std::map< Node, bool > d_lit_to_pol;
+ std::map< Node, int > d_lit_to_range;
+ NodeBoolMap d_range_assertions;
+ context::CDO< bool > d_has_range;
+ context::CDO< int > d_curr_range;
+ void initialize();
+ void assertNode(Node n);
+ Node getNextDecisionRequest();
+ };
+private:
+ //information for minimizing ranges
+ std::vector< Node > d_ranges;
+ //map to range model objects
+ std::map< Node, RangeModel * > d_rms;
+ //literal to range
+ std::map< Node, std::vector< Node > > d_lit_to_ranges;
+ //list of currently asserted arithmetic literals
+ NodeBoolMap d_assertions;
+private:
+ //class to store whether bounding lemmas have been added
+ class BoundInstTrie
+ {
+ public:
+ std::map< Node, BoundInstTrie > d_children;
+ bool hasInstantiated( std::vector< Node > & vals, int index = 0, bool madeNew = false ){
+ if( index>=(int)vals.size() ){
+ return !madeNew;
+ }else{
+ Node n = vals[index];
+ if( d_children.find(n)==d_children.end() ){
+ madeNew = true;
+ }
+ return d_children[n].hasInstantiated(vals,index+1,madeNew);
+ }
+ }
+ };
+ std::map< Node, std::map< Node, BoundInstTrie > > d_bnd_it;
+private:
+ void addLiteralFromRange( Node lit, Node r );
+public:
+ BoundedIntegers( context::Context* c, QuantifiersEngine* qe );
+
+ void check( Theory::Effort e );
+ void registerQuantifier( Node f );
+ void assertNode( Node n );
+ Node getNextDecisionRequest();
+ bool isBoundVar( Node f, Node v ) { return std::find( d_set[f].begin(), d_set[f].end(), v )!=d_set[f].end(); }
+ unsigned getNumBoundVars( Node f ) { return d_set[f].size(); }
+ Node getBoundVar( Node f, int i ) { return d_set[f][i]; }
+ int getBoundVarNum( Node f, int i ) { return d_set_nums[f][i]; }
+ Node getLowerBound( Node f, Node v ){ return d_bounds[0][f][v]; }
+ Node getUpperBound( Node f, Node v ){ return d_bounds[1][f][v]; }
+ void getBoundValues( Node f, Node v, RepSetIterator * rsi, Node & l, Node & u );
+ bool isGroundRange(Node f, Node v);
+};
+
+}
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/theory/quantifiers/candidate_generator.cpp b/src/theory/quantifiers/candidate_generator.cpp
index 0c423de19..6c6a80b90 100644
--- a/src/theory/quantifiers/candidate_generator.cpp
+++ b/src/theory/quantifiers/candidate_generator.cpp
@@ -27,7 +27,7 @@ using namespace CVC4::theory;
using namespace CVC4::theory::inst;
bool CandidateGenerator::isLegalCandidate( Node n ){
- return ( !n.getAttribute(NoMatchAttribute()) && ( !options::cbqi() || !n.hasAttribute(InstConstantAttribute()) ) );
+ return ( !n.getAttribute(NoMatchAttribute()) && ( !options::cbqi() || !quantifiers::TermDb::hasInstConstAttr(n) ) );
}
void CandidateGeneratorQueue::addCandidate( Node n ) {
diff --git a/src/theory/quantifiers/first_order_model.cpp b/src/theory/quantifiers/first_order_model.cpp
index bba9c0163..cf4381c02 100644
--- a/src/theory/quantifiers/first_order_model.cpp
+++ b/src/theory/quantifiers/first_order_model.cpp
@@ -38,15 +38,34 @@ void FirstOrderModel::assertQuantifier( Node n ){
}
}
-void FirstOrderModel::reset(){
- TheoryModel::reset();
+Node FirstOrderModel::getCurrentModelValue( Node n, bool partial ) {
+ std::vector< Node > children;
+ if( n.getNumChildren()>0 ){
+ if( n.getKind()!=APPLY_UF && n.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ children.push_back( n.getOperator() );
+ }
+ for (unsigned i=0; i<n.getNumChildren(); i++) {
+ Node nc = getCurrentModelValue( n[i], partial );
+ if (nc.isNull()) {
+ return Node::null();
+ }else{
+ children.push_back( nc );
+ }
+ }
+ if( n.getKind()==APPLY_UF ){
+ return getCurrentUfModelValue( n, children, partial );
+ }else{
+ Node nn = NodeManager::currentNM()->mkNode( n.getKind(), children );
+ nn = Rewriter::rewrite( nn );
+ return nn;
+ }
+ }else{
+ return getRepresentative(n);
+ }
}
-void FirstOrderModel::initialize( bool considerAxioms ){
- //rebuild models
- d_uf_model_tree.clear();
- d_uf_model_gen.clear();
- d_array_model.clear();
+void FirstOrderModel::initialize( bool considerAxioms ) {
+ processInitialize();
//this is called after representatives have been chosen and the equality engine has been built
//for each quantifier, collect all operators we care about
for( int i=0; i<getNumAssertedQuantifiers(); i++ ){
@@ -59,6 +78,23 @@ void FirstOrderModel::initialize( bool considerAxioms ){
}
void FirstOrderModel::initializeModelForTerm( Node n ){
+ processInitializeModelForTerm( n );
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ initializeModelForTerm( n[i] );
+ }
+}
+
+FirstOrderModelIG::FirstOrderModelIG(context::Context* c, std::string name) : FirstOrderModel(c,name) {
+
+}
+
+void FirstOrderModelIG::processInitialize(){
+ //rebuild models
+ d_uf_model_tree.clear();
+ d_uf_model_gen.clear();
+}
+
+void FirstOrderModelIG::processInitializeModelForTerm( Node n ){
if( n.getKind()==APPLY_UF ){
Node op = n.getOperator();
if( d_uf_model_tree.find( op )==d_uf_model_tree.end() ){
@@ -82,14 +118,11 @@ void FirstOrderModel::initializeModelForTerm( Node n ){
}
}
*/
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- initializeModelForTerm( n[i] );
- }
}
//for evaluation of quantifier bodies
-void FirstOrderModel::resetEvaluate(){
+void FirstOrderModelIG::resetEvaluate(){
d_eval_uf_use_default.clear();
d_eval_uf_model.clear();
d_eval_term_index_order.clear();
@@ -107,7 +140,7 @@ void FirstOrderModel::resetEvaluate(){
// if eVal = 0, then n' cannot be proven to be equal to phaseReq
// if eVal is not 0, then
// each n{ri->d_index[0]/x_0...ri->d_index[depIndex]/x_depIndex, */x_(depIndex+1) ... */x_n } is equivalent in the current model
-int FirstOrderModel::evaluate( Node n, int& depIndex, RepSetIterator* ri ){
+int FirstOrderModelIG::evaluate( Node n, int& depIndex, RepSetIterator* ri ){
++d_eval_formulas;
//Debug("fmf-eval-debug") << "Evaluate " << n << " " << phaseReq << std::endl;
//Notice() << "Eval " << n << std::endl;
@@ -226,7 +259,7 @@ int FirstOrderModel::evaluate( Node n, int& depIndex, RepSetIterator* ri ){
}
}
-Node FirstOrderModel::evaluateTerm( Node n, int& depIndex, RepSetIterator* ri ){
+Node FirstOrderModelIG::evaluateTerm( Node n, int& depIndex, RepSetIterator* ri ){
//Message() << "Eval term " << n << std::endl;
Node val;
depIndex = ri->getNumTerms()-1;
@@ -342,7 +375,7 @@ Node FirstOrderModel::evaluateTerm( Node n, int& depIndex, RepSetIterator* ri ){
return val;
}
-Node FirstOrderModel::evaluateTermDefault( Node n, int& depIndex, std::vector< int >& childDepIndex, RepSetIterator* ri ){
+Node FirstOrderModelIG::evaluateTermDefault( Node n, int& depIndex, std::vector< int >& childDepIndex, RepSetIterator* ri ){
depIndex = -1;
if( n.getNumChildren()==0 ){
return n;
@@ -372,14 +405,14 @@ Node FirstOrderModel::evaluateTermDefault( Node n, int& depIndex, std::vector< i
}
}
-void FirstOrderModel::clearEvalFailed( int index ){
+void FirstOrderModelIG::clearEvalFailed( int index ){
for( int i=0; i<(int)d_eval_failed_lits[index].size(); i++ ){
d_eval_failed[ d_eval_failed_lits[index][i] ] = false;
}
d_eval_failed_lits[index].clear();
}
-void FirstOrderModel::makeEvalUfModel( Node n ){
+void FirstOrderModelIG::makeEvalUfModel( Node n ){
if( d_eval_uf_model.find( n )==d_eval_uf_model.end() ){
makeEvalUfIndexOrder( n );
if( !d_eval_uf_use_default[n] ){
@@ -397,7 +430,7 @@ struct sortGetMaxVariableNum {
int computeMaxVariableNum( Node n ){
if( n.getKind()==INST_CONSTANT ){
return n.getAttribute(InstVarNumAttribute());
- }else if( n.hasAttribute(InstConstantAttribute()) ){
+ }else if( TermDb::hasInstConstAttr(n) ){
int maxVal = -1;
for( int i=0; i<(int)n.getNumChildren(); i++ ){
int val = getMaxVariableNum( n[i] );
@@ -423,7 +456,7 @@ struct sortGetMaxVariableNum {
bool operator() (Node i,Node j) { return (getMaxVariableNum(i)<getMaxVariableNum(j));}
};
-void FirstOrderModel::makeEvalUfIndexOrder( Node n ){
+void FirstOrderModelIG::makeEvalUfIndexOrder( Node n ){
if( d_eval_term_index_order.find( n )==d_eval_term_index_order.end() ){
#ifdef USE_INDEX_ORDERING
//sort arguments in order of least significant vs. most significant variable in default ordering
@@ -460,3 +493,18 @@ void FirstOrderModel::makeEvalUfIndexOrder( Node n ){
#endif
}
}
+
+Node FirstOrderModelIG::getCurrentUfModelValue( Node n, std::vector< Node > & args, bool partial ) {
+ std::vector< Node > children;
+ children.push_back(n.getOperator());
+ children.insert(children.end(), args.begin(), args.end());
+ Node nv = NodeManager::currentNM()->mkNode(APPLY_UF, children);
+ //make the term model specifically for nv
+ makeEvalUfModel( nv );
+ int argDepIndex;
+ if( d_eval_uf_use_default[nv] ){
+ return d_uf_model_tree[ n.getOperator() ].getValue( this, nv, argDepIndex );
+ }else{
+ return d_eval_uf_model[ nv ].getValue( this, nv, argDepIndex );
+ }
+} \ No newline at end of file
diff --git a/src/theory/quantifiers/first_order_model.h b/src/theory/quantifiers/first_order_model.h
index 76f21e19c..491e97097 100644
--- a/src/theory/quantifiers/first_order_model.h
+++ b/src/theory/quantifiers/first_order_model.h
@@ -19,7 +19,6 @@
#include "theory/model.h"
#include "theory/uf/theory_uf_model.h"
-#include "theory/arrays/theory_arrays_model.h"
namespace CVC4 {
namespace theory {
@@ -30,33 +29,22 @@ namespace quantifiers{
class TermDb;
+class FirstOrderModelIG;
+namespace fmcheck {
+ class FirstOrderModelFmc;
+}
+
class FirstOrderModel : public TheoryModel
{
private:
- //for initialize model
- void initializeModelForTerm( Node n );
/** whether an axiom is asserted */
context::CDO< bool > d_axiom_asserted;
/** list of quantifiers asserted in the current context */
context::CDList<Node> d_forall_asserts;
/** is model set */
context::CDO< bool > d_isModelSet;
-public: //for Theory UF:
- //models for each UF operator
- std::map< Node, uf::UfModelTree > d_uf_model_tree;
- //model generators
- std::map< Node, uf::UfModelTreeGenerator > d_uf_model_gen;
-private:
- //map from terms to the models used to calculate their value
- std::map< Node, bool > d_eval_uf_use_default;
- std::map< Node, uf::UfModelTree > d_eval_uf_model;
- void makeEvalUfModel( Node n );
- //index ordering to use for each term
- std::map< Node, std::vector< int > > d_eval_term_index_order;
- void makeEvalUfIndexOrder( Node n );
-public: //for Theory Arrays:
- //default value for each non-store array
- std::map< Node, arrays::ArrayModel > d_array_model;
+ /** get current model value */
+ virtual Node getCurrentUfModelValue( Node n, std::vector< Node > & args, bool partial ) = 0;
public: //for Theory Quantifiers:
/** assert quantifier */
void assertQuantifier( Node n );
@@ -66,19 +54,51 @@ public: //for Theory Quantifiers:
Node getAssertedQuantifier( int i ) { return d_forall_asserts[i]; }
/** bool axiom asserted */
bool isAxiomAsserted() { return d_axiom_asserted; }
+ /** initialize model for term */
+ void initializeModelForTerm( Node n );
+ virtual void processInitializeModelForTerm( Node n ) = 0;
public:
FirstOrderModel( context::Context* c, std::string name );
virtual ~FirstOrderModel(){}
- // reset the model
- void reset();
+ virtual FirstOrderModelIG * asFirstOrderModelIG() { return NULL; }
+ virtual fmcheck::FirstOrderModelFmc * asFirstOrderModelFmc() { return NULL; }
// initialize the model
void initialize( bool considerAxioms = true );
+ virtual void processInitialize() = 0;
/** mark model set */
void markModelSet() { d_isModelSet = true; }
/** is model set */
bool isModelSet() { return d_isModelSet; }
+ /** get current model value */
+ Node getCurrentModelValue( Node n, bool partial = false );
+};/* class FirstOrderModel */
+
+
+class FirstOrderModelIG : public FirstOrderModel
+{
+public: //for Theory UF:
+ //models for each UF operator
+ std::map< Node, uf::UfModelTree > d_uf_model_tree;
+ //model generators
+ std::map< Node, uf::UfModelTreeGenerator > d_uf_model_gen;
+private:
+ //map from terms to the models used to calculate their value
+ std::map< Node, bool > d_eval_uf_use_default;
+ std::map< Node, uf::UfModelTree > d_eval_uf_model;
+ void makeEvalUfModel( Node n );
+ //index ordering to use for each term
+ std::map< Node, std::vector< int > > d_eval_term_index_order;
+ void makeEvalUfIndexOrder( Node n );
+ /** get current model value */
+ Node getCurrentUfModelValue( Node n, std::vector< Node > & args, bool partial );
//the following functions are for evaluating quantifier bodies
public:
+ FirstOrderModelIG(context::Context* c, std::string name);
+ FirstOrderModelIG * asFirstOrderModelIG() { return this; }
+ // initialize the model
+ void processInitialize();
+ //for initialize model
+ void processInitializeModelForTerm( Node n );
/** reset evaluation */
void resetEvaluate();
/** evaluate functions */
@@ -97,7 +117,8 @@ private:
void clearEvalFailed( int index );
std::map< Node, bool > d_eval_failed;
std::map< int, std::vector< Node > > d_eval_failed_lits;
-};/* class FirstOrderModel */
+};
+
}/* CVC4::theory::quantifiers namespace */
}/* CVC4::theory namespace */
diff --git a/src/theory/quantifiers/first_order_reasoning.cpp b/src/theory/quantifiers/first_order_reasoning.cpp
new file mode 100755
index 000000000..27fcebccf
--- /dev/null
+++ b/src/theory/quantifiers/first_order_reasoning.cpp
@@ -0,0 +1,171 @@
+/********************* */
+/*! \file first_order_reasoning.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 first order reasoning module
+ **
+ **/
+
+#include <vector>
+
+#include "theory/quantifiers/first_order_reasoning.h"
+#include "theory/rewriter.h"
+
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace std;
+
+namespace CVC4 {
+
+
+void FirstOrderPropagation::collectLits( Node n, std::vector<Node> & lits ){
+ if( n.getKind()==FORALL ){
+ collectLits( n[1], lits );
+ }else if( n.getKind()==OR ){
+ for(unsigned j=0; j<n.getNumChildren(); j++) {
+ collectLits(n[j], lits );
+ }
+ }else{
+ lits.push_back( n );
+ }
+}
+
+void FirstOrderPropagation::simplify( std::vector< Node >& assertions ){
+ for( unsigned i=0; i<assertions.size(); i++) {
+ Trace("fo-rsn") << "Assert : " << assertions[i] << std::endl;
+ }
+
+ //process all assertions
+ int num_processed;
+ int num_true = 0;
+ int num_rounds = 0;
+ do {
+ num_processed = 0;
+ for( unsigned i=0; i<assertions.size(); i++ ){
+ if( d_assertion_true.find(assertions[i])==d_assertion_true.end() ){
+ std::vector< Node > fo_lits;
+ collectLits( assertions[i], fo_lits );
+ Node unitLit = process( assertions[i], fo_lits );
+ if( !unitLit.isNull() ){
+ Trace("fo-rsn-debug") << "...possible unit literal : " << unitLit << " from " << assertions[i] << std::endl;
+ bool pol = unitLit.getKind()!=NOT;
+ unitLit = unitLit.getKind()==NOT ? unitLit[0] : unitLit;
+ if( unitLit.getKind()==EQUAL ){
+
+ }else if( unitLit.getKind()==APPLY_UF ){
+ //make sure all are unique vars;
+ bool success = true;
+ std::vector< Node > unique_vars;
+ for( unsigned j=0; j<unitLit.getNumChildren(); j++) {
+ if( unitLit[j].getKind()==BOUND_VARIABLE ){
+ if( std::find(unique_vars.begin(), unique_vars.end(), unitLit[j])==unique_vars.end() ){
+ unique_vars.push_back( unitLit[j] );
+ }else{
+ success = false;
+ break;
+ }
+ }else{
+ success = false;
+ break;
+ }
+ }
+ if( success ){
+ d_const_def[unitLit.getOperator()] = NodeManager::currentNM()->mkConst(pol);
+ Trace("fo-rsn") << "Propagate : " << unitLit.getOperator() << " == " << pol << std::endl;
+ Trace("fo-rsn") << " from : " << assertions[i] << std::endl;
+ d_assertion_true[assertions[i]] = true;
+ num_processed++;
+ }
+ }else if( unitLit.getKind()==VARIABLE ){
+ d_const_def[unitLit] = NodeManager::currentNM()->mkConst(pol);
+ Trace("fo-rsn") << "Propagate variable : " << unitLit << " == " << pol << std::endl;
+ Trace("fo-rsn") << " from : " << assertions[i] << std::endl;
+ d_assertion_true[assertions[i]] = true;
+ num_processed++;
+ }
+ }
+ if( d_assertion_true.find(assertions[i])!=d_assertion_true.end() ){
+ num_true++;
+ }
+ }
+ }
+ num_rounds++;
+ }while( num_processed>0 );
+ Trace("fo-rsn-sum") << "Simplified " << num_true << " / " << assertions.size() << " in " << num_rounds << " rounds." << std::endl;
+ for( unsigned i=0; i<assertions.size(); i++ ){
+ assertions[i] = theory::Rewriter::rewrite( simplify( assertions[i] ) );
+ }
+}
+
+Node FirstOrderPropagation::process(Node a, std::vector< Node > & lits) {
+ int index = -1;
+ for( unsigned i=0; i<lits.size(); i++) {
+ bool pol = lits[i].getKind()!=NOT;
+ Node n = lits[i].getKind()==NOT ? lits[i][0] : lits[i];
+ Node litDef;
+ if( n.getKind()==APPLY_UF ){
+ if( d_const_def.find(n.getOperator())!=d_const_def.end() ){
+ litDef = d_const_def[n.getOperator()];
+ }
+ }else if( n.getKind()==VARIABLE ){
+ if( d_const_def.find(n)!=d_const_def.end() ){
+ litDef = d_const_def[n];
+ }
+ }
+ if( !litDef.isNull() ){
+ Node poln = NodeManager::currentNM()->mkConst( pol );
+ if( litDef==poln ){
+ Trace("fo-rsn-debug") << "Assertion " << a << " is true because of " << lits[i] << std::endl;
+ d_assertion_true[a] = true;
+ return Node::null();
+ }
+ }
+ if( litDef.isNull() ){
+ if( index==-1 ){
+ //store undefined index
+ index = i;
+ }else{
+ //two undefined, return null
+ return Node::null();
+ }
+ }
+ }
+ if( index!=-1 ){
+ return lits[index];
+ }else{
+ return Node::null();
+ }
+}
+
+Node FirstOrderPropagation::simplify( Node n ) {
+ if( n.getKind()==VARIABLE ){
+ if( d_const_def.find(n)!=d_const_def.end() ){
+ return d_const_def[n];
+ }
+ }else if( n.getKind()==APPLY_UF ){
+ if( d_const_def.find(n.getOperator())!=d_const_def.end() ){
+ return d_const_def[n.getOperator()];
+ }
+ }
+ if( n.getNumChildren()==0 ){
+ return n;
+ }else{
+ std::vector< Node > children;
+ if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ children.push_back( n.getOperator() );
+ }
+ for(unsigned i=0; i<n.getNumChildren(); i++) {
+ children.push_back( simplify(n[i]) );
+ }
+ return NodeManager::currentNM()->mkNode( n.getKind(), children );
+ }
+}
+
+}
diff --git a/src/theory/quantifiers/first_order_reasoning.h b/src/theory/quantifiers/first_order_reasoning.h
new file mode 100755
index 000000000..0dbf23a3b
--- /dev/null
+++ b/src/theory/quantifiers/first_order_reasoning.h
@@ -0,0 +1,45 @@
+/********************* */
+/*! \file first_order_reasoning.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 first-order reasoning
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__FIRST_ORDER_REASONING_H
+#define __CVC4__FIRST_ORDER_REASONING_H
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <map>
+#include "expr/node.h"
+#include "expr/type_node.h"
+
+namespace CVC4 {
+
+class FirstOrderPropagation {
+private:
+ std::map< Node, Node > d_const_def;
+ std::map< Node, bool > d_assertion_true;
+ Node process(Node a, std::vector< Node > & lits);
+ void collectLits( Node n, std::vector<Node> & lits );
+ Node simplify( Node n );
+public:
+ FirstOrderPropagation(){}
+ ~FirstOrderPropagation(){}
+
+ void simplify( std::vector< Node >& assertions );
+};
+
+}
+
+#endif
diff --git a/src/theory/quantifiers/full_model_check.cpp b/src/theory/quantifiers/full_model_check.cpp
new file mode 100755
index 000000000..2513cb08e
--- /dev/null
+++ b/src/theory/quantifiers/full_model_check.cpp
@@ -0,0 +1,1010 @@
+
+/********************* */
+/*! \file full_model_check.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds
+ ** 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 full model check class
+ **/
+
+#include "theory/quantifiers/full_model_check.h"
+#include "theory/quantifiers/first_order_model.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;
+using namespace CVC4::theory::inst;
+using namespace CVC4::theory::quantifiers::fmcheck;
+
+struct ModelBasisArgSort
+{
+ std::vector< Node > d_terms;
+ bool operator() (int i,int j) {
+ return (d_terms[i].getAttribute(ModelBasisArgAttribute()) <
+ d_terms[j].getAttribute(ModelBasisArgAttribute()) );
+ }
+};
+
+
+bool EntryTrie::hasGeneralization( FirstOrderModelFmc * m, Node c, int index ) {
+ if (index==(int)c.getNumChildren()) {
+ return d_data!=-1;
+ }else{
+ Node st = m->getStar(c[index].getType());
+ if(d_child.find(st)!=d_child.end()) {
+ if( d_child[st].hasGeneralization(m, c, index+1) ){
+ return true;
+ }
+ }
+ if( d_child.find( c[index] )!=d_child.end() ){
+ if( d_child[ c[index] ].hasGeneralization(m, c, index+1) ){
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+int EntryTrie::getGeneralizationIndex( FirstOrderModelFmc * m, std::vector<Node> & inst, int index ) {
+ if (index==(int)inst.size()) {
+ return d_data;
+ }else{
+ int minIndex = -1;
+ Node st = m->getStar(inst[index].getType());
+ if(d_child.find(st)!=d_child.end()) {
+ minIndex = d_child[st].getGeneralizationIndex(m, inst, index+1);
+ }
+ Node cc = inst[index];
+ if( d_child.find( cc )!=d_child.end() ){
+ int gindex = d_child[ cc ].getGeneralizationIndex(m, inst, index+1);
+ if (minIndex==-1 || (gindex!=-1 && gindex<minIndex) ){
+ minIndex = gindex;
+ }
+ }
+ return minIndex;
+ }
+}
+
+void EntryTrie::addEntry( FirstOrderModelFmc * m, Node c, Node v, int data, int index ) {
+ if (index==(int)c.getNumChildren()) {
+ if(d_data==-1) {
+ d_data = data;
+ }
+ }
+ else {
+ d_child[ c[index] ].addEntry(m,c,v,data,index+1);
+ }
+}
+
+void EntryTrie::getEntries( FirstOrderModelFmc * m, Node c, std::vector<int> & compat, std::vector<int> & gen, int index, bool is_gen ) {
+ if (index==(int)c.getNumChildren()) {
+ if( d_data!=-1) {
+ if( is_gen ){
+ gen.push_back(d_data);
+ }
+ compat.push_back(d_data);
+ }
+ }else{
+ if (m->isStar(c[index])) {
+ for ( std::map<Node,EntryTrie>::iterator it = d_child.begin(); it != d_child.end(); ++it ){
+ it->second.getEntries(m, c, compat, gen, index+1, is_gen );
+ }
+ }else{
+ Node st = m->getStar(c[index].getType());
+ if(d_child.find(st)!=d_child.end()) {
+ d_child[st].getEntries(m, c, compat, gen, index+1, false);
+ }
+ if( d_child.find( c[index] )!=d_child.end() ){
+ d_child[ c[index] ].getEntries(m, c, compat, gen, index+1, is_gen);
+ }
+ }
+
+ }
+}
+
+
+bool Def::addEntry( FirstOrderModelFmc * m, Node c, Node v) {
+ if (!d_et.hasGeneralization(m, c)) {
+ int newIndex = (int)d_cond.size();
+ if (!d_has_simplified) {
+ std::vector<int> compat;
+ std::vector<int> gen;
+ d_et.getEntries(m, c, compat, gen);
+ for( unsigned i=0; i<compat.size(); i++) {
+ if( d_status[compat[i]]==status_unk ){
+ if( d_value[compat[i]]!=v ){
+ d_status[compat[i]] = status_non_redundant;
+ }
+ }
+ }
+ for( unsigned i=0; i<gen.size(); i++) {
+ if( d_status[gen[i]]==status_unk ){
+ if( d_value[gen[i]]==v ){
+ d_status[gen[i]] = status_redundant;
+ }
+ }
+ }
+ d_status.push_back( status_unk );
+ }
+ d_et.addEntry(m, c, v, newIndex);
+ d_cond.push_back(c);
+ d_value.push_back(v);
+ return true;
+ }else{
+ return false;
+ }
+}
+
+Node Def::evaluate( FirstOrderModelFmc * m, std::vector<Node>& inst ) {
+ int gindex = d_et.getGeneralizationIndex(m, inst);
+ if (gindex!=-1) {
+ return d_value[gindex];
+ }else{
+ return Node::null();
+ }
+}
+
+int Def::getGeneralizationIndex( FirstOrderModelFmc * m, std::vector<Node>& inst ) {
+ return d_et.getGeneralizationIndex(m, inst);
+}
+
+void Def::simplify(FirstOrderModelFmc * m) {
+ d_has_simplified = true;
+ std::vector< Node > cond;
+ cond.insert( cond.end(), d_cond.begin(), d_cond.end() );
+ d_cond.clear();
+ std::vector< Node > value;
+ value.insert( value.end(), d_value.begin(), d_value.end() );
+ d_value.clear();
+ d_et.reset();
+ for (unsigned i=0; i<d_status.size(); i++) {
+ if( d_status[i]!=status_redundant ){
+ addEntry(m, cond[i], value[i]);
+ }
+ }
+ d_status.clear();
+}
+
+void Def::debugPrint(const char * tr, Node op, FullModelChecker * m) {
+ if (!op.isNull()) {
+ Trace(tr) << "Model for " << op << " : " << std::endl;
+ }
+ for( unsigned i=0; i<d_cond.size(); i++) {
+ //print the condition
+ if (!op.isNull()) {
+ Trace(tr) << op;
+ }
+ m->debugPrintCond(tr, d_cond[i], true);
+ Trace(tr) << " -> ";
+ m->debugPrint(tr, d_value[i]);
+ Trace(tr) << std::endl;
+ }
+}
+
+
+
+FirstOrderModelFmc::FirstOrderModelFmc(QuantifiersEngine * qe, context::Context* c, std::string name) :
+FirstOrderModel(c, name), d_qe(qe){
+
+}
+
+Node FirstOrderModelFmc::getUsedRepresentative(Node n) {
+ //Assert( fm->hasTerm(n) );
+ TypeNode tn = n.getType();
+ if( tn.isBoolean() ){
+ return areEqual(n, d_true) ? d_true : d_false;
+ }else{
+ Node r = getRepresentative(n);
+ if (r==d_model_basis_rep[tn]) {
+ r = d_qe->getTermDatabase()->getModelBasisTerm(tn);
+ }
+ return r;
+ }
+}
+
+Node FirstOrderModelFmc::getCurrentUfModelValue( Node n, std::vector< Node > & args, bool partial ) {
+ Trace("fmc-uf-model") << "Get model value for " << n << " " << n.getKind() << std::endl;
+ for(unsigned i=0; i<args.size(); i++) {
+ args[i] = getUsedRepresentative(args[i]);
+ }
+ Assert( n.getKind()==APPLY_UF );
+ return d_models[n.getOperator()]->evaluate(this, args);
+}
+
+void FirstOrderModelFmc::processInitialize() {
+ for( std::map<Node, Def * >::iterator it = d_models.begin(); it != d_models.end(); ++it ){
+ it->second->reset();
+ }
+ d_model_basis_rep.clear();
+}
+
+void FirstOrderModelFmc::processInitializeModelForTerm(Node n) {
+ if( n.getKind()==APPLY_UF ){
+ if( d_models.find(n.getOperator())==d_models.end()) {
+ d_models[n.getOperator()] = new Def;
+ }
+ }
+}
+
+Node FirstOrderModelFmc::getSomeDomainElement(TypeNode tn){
+ //check if there is even any domain elements at all
+ if (!d_rep_set.hasType(tn)) {
+ Trace("fmc-model-debug") << "Must create domain element for " << tn << "..." << std::endl;
+ Node mbt = d_qe->getTermDatabase()->getModelBasisTerm(tn);
+ d_rep_set.d_type_reps[tn].push_back(mbt);
+ }else if( d_rep_set.d_type_reps[tn].size()==0 ){
+ Message() << "empty reps" << std::endl;
+ exit(0);
+ }
+ return d_rep_set.d_type_reps[tn][0];
+}
+
+
+bool FirstOrderModelFmc::isStar(Node n) {
+ return n==getStar(n.getType());
+}
+
+Node FirstOrderModelFmc::getStar(TypeNode tn) {
+ if( d_type_star.find(tn)==d_type_star.end() ){
+ Node st = NodeManager::currentNM()->mkSkolem( "star_$$", tn, "skolem created for full-model checking" );
+ d_type_star[tn] = st;
+ }
+ return d_type_star[tn];
+}
+
+bool FirstOrderModelFmc::isModelBasisTerm(Node n) {
+ return n==getModelBasisTerm(n.getType());
+}
+
+Node FirstOrderModelFmc::getModelBasisTerm(TypeNode tn) {
+ return d_qe->getTermDatabase()->getModelBasisTerm(tn);
+}
+
+Node FirstOrderModelFmc::getFunctionValue(Node op, const char* argPrefix ) {
+ TypeNode type = op.getType();
+ std::vector< Node > vars;
+ for( size_t i=0; i<type.getNumChildren()-1; i++ ){
+ std::stringstream ss;
+ ss << argPrefix << (i+1);
+ vars.push_back( NodeManager::currentNM()->mkBoundVar( ss.str(), type[i] ) );
+ }
+ Node boundVarList = NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, vars);
+ Node curr;
+ for( int i=(d_models[op]->d_cond.size()-1); i>=0; i--) {
+ Node v = getUsedRepresentative( d_models[op]->d_value[i] );
+ if( curr.isNull() ){
+ curr = v;
+ }else{
+ //make the condition
+ Node cond = d_models[op]->d_cond[i];
+ std::vector< Node > children;
+ for( unsigned j=0; j<cond.getNumChildren(); j++) {
+ if (!isStar(cond[j])){
+ Node c = getUsedRepresentative( cond[j] );
+ children.push_back( NodeManager::currentNM()->mkNode( EQUAL, vars[j], c ) );
+ }
+ }
+ Assert( !children.empty() );
+ Node cc = children.size()==1 ? children[0] : NodeManager::currentNM()->mkNode( AND, children );
+ curr = NodeManager::currentNM()->mkNode( ITE, cc, v, curr );
+ }
+ }
+ curr = Rewriter::rewrite( curr );
+ return NodeManager::currentNM()->mkNode(kind::LAMBDA, boundVarList, curr);
+}
+
+
+
+FullModelChecker::FullModelChecker(context::Context* c, QuantifiersEngine* qe) :
+QModelBuilder( c, qe ){
+ d_true = NodeManager::currentNM()->mkConst(true);
+ d_false = NodeManager::currentNM()->mkConst(false);
+}
+
+void FullModelChecker::processBuildModel(TheoryModel* m, bool fullModel){
+ d_addedLemmas = 0;
+ FirstOrderModelFmc * fm = ((FirstOrderModelFmc*)m)->asFirstOrderModelFmc();
+ if( fullModel ){
+ //make function values
+ for( std::map< Node, std::vector< Node > >::iterator it = m->d_uf_terms.begin(); it != m->d_uf_terms.end(); ++it ){
+ m->d_uf_models[ it->first ] = getFunctionValue( fm, it->first, "$x" );
+ }
+ TheoryEngineModelBuilder::processBuildModel( m, fullModel );
+ //mark that the model has been set
+ fm->markModelSet();
+ //debug the model
+ debugModel( fm );
+ }else{
+ Trace("fmc") << "---Full Model Check reset() " << std::endl;
+ fm->initialize( d_considerAxioms );
+ d_quant_models.clear();
+ d_rep_ids.clear();
+ d_star_insts.clear();
+ //process representatives
+ for( std::map< TypeNode, std::vector< Node > >::iterator it = fm->d_rep_set.d_type_reps.begin();
+ it != fm->d_rep_set.d_type_reps.end(); ++it ){
+ if( it->first.isSort() ){
+ Trace("fmc") << "Cardinality( " << it->first << " )" << " = " << it->second.size() << std::endl;
+ Node mbt = d_qe->getTermDatabase()->getModelBasisTerm(it->first);
+ Node rmbt = fm->getUsedRepresentative( mbt);
+ int mbt_index = -1;
+ Trace("fmc") << " Model basis term : " << mbt << std::endl;
+ for( size_t a=0; a<it->second.size(); a++ ){
+ Node r = fm->getUsedRepresentative( it->second[a] );
+ std::vector< Node > eqc;
+ ((EqualityQueryQuantifiersEngine*)d_qe->getEqualityQuery())->getEquivalenceClass( r, eqc );
+ Trace("fmc-model-debug") << " " << (it->second[a]==r) << (r==mbt);
+ Trace("fmc-model-debug") << " : " << it->second[a] << " : " << r << " : ";
+ //Trace("fmc-model-debug") << r2 << " : " << ir << " : ";
+ Trace("fmc-model-debug") << " {";
+ //find best selection for representative
+ for( size_t i=0; i<eqc.size(); i++ ){
+ Trace("fmc-model-debug") << eqc[i] << ", ";
+ }
+ Trace("fmc-model-debug") << "}" << std::endl;
+
+ //if this is the model basis eqc, replace with actual model basis term
+ if (r==rmbt || (mbt_index==-1 && a==(it->second.size()-1))) {
+ fm->d_model_basis_rep[it->first] = r;
+ r = mbt;
+ mbt_index = a;
+ }
+ d_rep_ids[it->first][r] = (int)a;
+ }
+ Trace("fmc-model-debug") << std::endl;
+
+ if (mbt_index==-1) {
+ std::cout << " WARNING: model basis term is not a representative!" << std::endl;
+ exit(0);
+ }else{
+ Trace("fmc") << "Star index for " << it->first << " is " << mbt_index << std::endl;
+ }
+ }
+ }
+ //now, make models
+ for( std::map<Node, Def * >::iterator it = fm->d_models.begin(); it != fm->d_models.end(); ++it ) {
+ Node op = it->first;
+ //reset the model
+ fm->d_models[op]->reset();
+
+ std::vector< Node > conds;
+ std::vector< Node > values;
+ std::vector< Node > entry_conds;
+ Trace("fmc-model-debug") << fm->d_uf_terms[op].size() << " model values for " << op << " ... " << std::endl;
+ for( size_t i=0; i<fm->d_uf_terms[op].size(); i++ ){
+ Node r = fm->getUsedRepresentative(fm->d_uf_terms[op][i]);
+ Trace("fmc-model-debug") << fm->d_uf_terms[op][i] << " -> " << r << std::endl;
+ }
+ Trace("fmc-model-debug") << std::endl;
+ //initialize the model
+ for( size_t i=0; i<fm->d_uf_terms[op].size(); i++ ){
+ Node n = fm->d_uf_terms[op][i];
+ if( !n.getAttribute(NoMatchAttribute()) ){
+ addEntry(fm, op, n, n, conds, values, entry_conds);
+ }
+ }
+ Node nmb = d_qe->getTermDatabase()->getModelBasisOpTerm(op);
+ //add default value
+ if( fm->hasTerm( nmb ) ){
+ Trace("fmc-model-debug") << "Add default " << nmb << std::endl;
+ addEntry(fm, op, nmb, nmb, conds, values, entry_conds);
+ }else{
+ Node vmb = fm->getSomeDomainElement(nmb.getType());
+ Trace("fmc-model-debug") << "Add default to default representative " << nmb << " ";
+ Trace("fmc-model-debug") << fm->d_rep_set.d_type_reps[nmb.getType()].size() << std::endl;
+ addEntry(fm, op, nmb, vmb, conds, values, entry_conds);
+ }
+
+ //sort based on # default arguments
+ std::vector< int > indices;
+ ModelBasisArgSort mbas;
+ for (int i=0; i<(int)conds.size(); i++) {
+ d_qe->getTermDatabase()->computeModelBasisArgAttribute( conds[i] );
+ mbas.d_terms.push_back(conds[i]);
+ indices.push_back(i);
+ }
+ std::sort( indices.begin(), indices.end(), mbas );
+
+
+ for (int i=0; i<(int)indices.size(); i++) {
+ fm->d_models[op]->addEntry(fm, entry_conds[indices[i]], values[indices[i]]);
+ }
+ fm->d_models[op]->debugPrint("fmc-model", op, this);
+ Trace("fmc-model") << std::endl;
+
+ fm->d_models[op]->simplify( fm );
+ Trace("fmc-model-simplify") << "After simplification : " << std::endl;
+ fm->d_models[op]->debugPrint("fmc-model-simplify", op, this);
+ Trace("fmc-model-simplify") << std::endl;
+ }
+ }
+}
+
+void FullModelChecker::debugPrintCond(const char * tr, Node n, bool dispStar) {
+ Trace(tr) << "(";
+ for( unsigned j=0; j<n.getNumChildren(); j++) {
+ if( j>0 ) Trace(tr) << ", ";
+ debugPrint(tr, n[j], dispStar);
+ }
+ Trace(tr) << ")";
+}
+
+void FullModelChecker::debugPrint(const char * tr, Node n, bool dispStar) {
+ FirstOrderModelFmc * fm = (FirstOrderModelFmc *)d_qe->getModel();
+ if( n.isNull() ){
+ Trace(tr) << "null";
+ }
+ else if(fm->isStar(n) && dispStar) {
+ Trace(tr) << "*";
+ }else{
+ TypeNode tn = n.getType();
+ if( d_rep_ids.find(tn)!=d_rep_ids.end() ){
+ if (d_rep_ids[tn].find(n)!=d_rep_ids[tn].end()) {
+ Trace(tr) << d_rep_ids[tn][n];
+ }else{
+ Trace(tr) << n;
+ }
+ }else{
+ Trace(tr) << n;
+ }
+ }
+}
+
+
+bool FullModelChecker::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort, int & lemmas ) {
+ Trace("fmc") << "Full model check " << f << ", effort = " << effort << "..." << std::endl;
+ if (!options::fmfModelBasedInst()) {
+ return false;
+ }else{
+ FirstOrderModelFmc * fmfmc = fm->asFirstOrderModelFmc();
+ if (effort==0) {
+ //register the quantifier
+ if (d_quant_cond.find(f)==d_quant_cond.end()) {
+ std::vector< TypeNode > types;
+ for(unsigned i=0; i<f[0].getNumChildren(); i++){
+ types.push_back(f[0][i].getType());
+ d_quant_var_id[f][f[0][i]] = i;
+ }
+ TypeNode typ = NodeManager::currentNM()->mkFunctionType( types, NodeManager::currentNM()->booleanType() );
+ Node op = NodeManager::currentNM()->mkSkolem( "fmc_$$", typ, "op created for full-model checking" );
+ d_quant_cond[f] = op;
+ }
+
+ //model check the quantifier
+ doCheck(fmfmc, f, d_quant_models[f], f[1]);
+ Trace("fmc") << "Definition for quantifier " << f << " is : " << std::endl;
+ d_quant_models[f].debugPrint("fmc", Node::null(), this);
+ Trace("fmc") << std::endl;
+ //consider all entries going to false
+ for (unsigned i=0; i<d_quant_models[f].d_cond.size(); i++) {
+ if( d_quant_models[f].d_value[i]!=d_true) {
+ Trace("fmc-inst") << "Instantiate based on " << d_quant_models[f].d_cond[i] << "..." << std::endl;
+ bool hasStar = false;
+ std::vector< Node > inst;
+ for (unsigned j=0; j<d_quant_models[f].d_cond[i].getNumChildren(); j++) {
+ if (fmfmc->isStar(d_quant_models[f].d_cond[i][j])) {
+ hasStar = true;
+ inst.push_back(fmfmc->getModelBasisTerm(d_quant_models[f].d_cond[i][j].getType()));
+ }else{
+ inst.push_back(d_quant_models[f].d_cond[i][j]);
+ }
+ }
+ bool addInst = true;
+ if( hasStar ){
+ //try obvious (specified by inst)
+ Node ev = d_quant_models[f].evaluate(fmfmc, inst);
+ if (ev==d_true) {
+ addInst = false;
+ }
+ }else{
+ //for debugging
+ if (Trace.isOn("fmc-test-inst")) {
+ Node ev = d_quant_models[f].evaluate(fmfmc, inst);
+ if( ev==d_true ){
+ std::cout << "WARNING: instantiation was true! " << f << " " << d_quant_models[f].d_cond[i] << std::endl;
+ exit(0);
+ }else{
+ Trace("fmc-test-inst") << "...instantiation evaluated to false." << std::endl;
+ }
+ }
+ }
+ if( addInst ){
+ InstMatch m;
+ for( unsigned j=0; j<inst.size(); j++) {
+ m.set( d_qe, f, j, inst[j] );
+ }
+ if( d_qe->addInstantiation( f, m ) ){
+ lemmas++;
+ }else{
+ //this can happen if evaluation is unknown
+ //might try it next effort level
+ d_star_insts[f].push_back(i);
+ }
+ }else{
+ //might try it next effort level
+ d_star_insts[f].push_back(i);
+ }
+ }
+ }
+ }else{
+ if (!d_star_insts[f].empty()) {
+ Trace("fmc-exh") << "Exhaustive instantiate " << f << std::endl;
+ Trace("fmc-exh") << "Definition was : " << std::endl;
+ d_quant_models[f].debugPrint("fmc-exh", Node::null(), this);
+ Trace("fmc-exh") << std::endl;
+ Def temp;
+ //simplify the exceptions?
+ for( int i=(d_star_insts[f].size()-1); i>=0; i--) {
+ //get witness for d_star_insts[f][i]
+ int j = d_star_insts[f][i];
+ if( temp.addEntry(fmfmc, d_quant_models[f].d_cond[j], d_quant_models[f].d_value[j] ) ){
+ int lem = exhaustiveInstantiate(fmfmc, f, d_quant_models[f].d_cond[j], j );
+ if( lem==-1 ){
+ //something went wrong, resort to exhaustive instantiation
+ return false;
+ }else{
+ lemmas += lem;
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+}
+
+int FullModelChecker::exhaustiveInstantiate(FirstOrderModelFmc * fm, Node f, Node c, int c_index) {
+ int addedLemmas = 0;
+ RepSetIterator riter( d_qe, &(fm->d_rep_set) );
+ Trace("fmc-exh") << "Exhaustive instantiate based on index " << c_index << " : " << c << " ";
+ debugPrintCond("fmc-exh", c, true);
+ Trace("fmc-exh")<< std::endl;
+ if( riter.setQuantifier( f ) ){
+ std::vector< RepDomain > dom;
+ for (unsigned i=0; i<c.getNumChildren(); i++) {
+ TypeNode tn = c[i].getType();
+ if( d_rep_ids.find(tn)!=d_rep_ids.end() ){
+ //RepDomain rd;
+ if( fm->isStar(c[i]) ){
+ //add the full range
+ //for( std::map< Node, int >::iterator it = d_rep_ids[tn].begin();
+ // it != d_rep_ids[tn].end(); ++it ){
+ // rd.push_back(it->second);
+ //}
+ }else{
+ if (d_rep_ids[tn].find(c[i])!=d_rep_ids[tn].end()) {
+ //rd.push_back(d_rep_ids[tn][c[i]]);
+ riter.d_domain[i].clear();
+ riter.d_domain[i].push_back(d_rep_ids[tn][c[i]]);
+ }else{
+ return -1;
+ }
+ }
+ //dom.push_back(rd);
+ }else{
+ return -1;
+ }
+ }
+ //riter.setDomain(dom);
+ //now do full iteration
+ while( !riter.isFinished() ){
+ Trace("fmc-exh-debug") << "Inst : ";
+ std::vector< Node > inst;
+ for( int i=0; i<riter.getNumTerms(); i++ ){
+ //m.set( d_quantEngine, f, riter.d_index_order[i], riter.getTerm( i ) );
+ Node r = fm->getUsedRepresentative( riter.getTerm( i ) );
+ debugPrint("fmc-exh-debug", r);
+ Trace("fmc-exh-debug") << " ";
+ inst.push_back(r);
+ }
+
+ int ev_index = d_quant_models[f].getGeneralizationIndex(fm, inst);
+ Trace("fmc-exh-debug") << ", index = " << ev_index;
+ Node ev = ev_index==-1 ? Node::null() : d_quant_models[f].d_value[ev_index];
+ if (ev!=d_true) {
+ InstMatch m;
+ for( int i=0; i<riter.getNumTerms(); i++ ){
+ m.set( d_qe, f, i, riter.getTerm( i ) );
+ }
+ Trace("fmc-exh-debug") << ", add!";
+ //add as instantiation
+ if( d_qe->addInstantiation( f, m ) ){
+ addedLemmas++;
+ }
+ }
+ Trace("fmc-exh-debug") << std::endl;
+ riter.increment();
+ }
+ }
+ return addedLemmas;
+}
+
+void FullModelChecker::doCheck(FirstOrderModelFmc * fm, Node f, Def & d, Node n ) {
+ Trace("fmc-debug") << "Check " << n << " " << n.getKind() << std::endl;
+ if( n.getKind() == kind::BOUND_VARIABLE ){
+ d.addEntry(fm, mkCondDefault(fm, f), n);
+ Trace("fmc-debug") << "Done with " << n << " " << n.getKind() << std::endl;
+ }
+ else if( n.getNumChildren()==0 ){
+ Node r = n;
+ if( !fm->hasTerm(n) ){
+ r = fm->getSomeDomainElement(n.getType() );
+ }
+ r = fm->getUsedRepresentative( r);
+ d.addEntry(fm, mkCondDefault(fm, f), r);
+ }
+ else if( n.getKind() == kind::NOT ){
+ //just do directly
+ doCheck( fm, f, d, n[0] );
+ doNegate( d );
+ }
+ else if( n.getKind() == kind::FORALL ){
+ d.addEntry(fm, mkCondDefault(fm, f), Node::null());
+ }
+ else{
+ std::vector< int > var_ch;
+ std::vector< Def > children;
+ for( int i=0; i<(int)n.getNumChildren(); i++) {
+ Def dc;
+ doCheck(fm, f, dc, n[i]);
+ children.push_back(dc);
+ if( n[i].getKind() == kind::BOUND_VARIABLE ){
+ var_ch.push_back(i);
+ }
+ }
+
+ if( n.getKind()==APPLY_UF ){
+ Trace("fmc-debug") << "Do uninterpreted compose " << n << std::endl;
+ //uninterpreted compose
+ doUninterpretedCompose( fm, f, d, n.getOperator(), children );
+ } else {
+ if( !var_ch.empty() ){
+ if( n.getKind()==EQUAL ){
+ if( var_ch.size()==2 ){
+ Trace("fmc-debug") << "Do variable equality " << n << std::endl;
+ doVariableEquality( fm, f, d, n );
+ }else{
+ Trace("fmc-debug") << "Do variable relation " << n << std::endl;
+ doVariableRelation( fm, f, d, var_ch[0]==0 ? children[1] : children[0], var_ch[0]==0 ? n[0] : n[1] );
+ }
+ }else{
+ std::cout << "Don't know how to check " << n << std::endl;
+ exit(0);
+ }
+ }else{
+ Trace("fmc-debug") << "Do interpreted compose " << n << std::endl;
+ std::vector< Node > cond;
+ mkCondDefaultVec(fm, f, cond);
+ std::vector< Node > val;
+ //interpreted compose
+ doInterpretedCompose( fm, f, d, n, children, 0, cond, val );
+ }
+ }
+ d.simplify(fm);
+ }
+ Trace("fmc-debug") << "Definition for " << n << " is : " << std::endl;
+ d.debugPrint("fmc-debug", Node::null(), this);
+ Trace("fmc-debug") << std::endl;
+}
+
+void FullModelChecker::doNegate( Def & dc ) {
+ for (unsigned i=0; i<dc.d_cond.size(); i++) {
+ if (!dc.d_value[i].isNull()) {
+ dc.d_value[i] = dc.d_value[i]==d_true ? d_false : d_true;
+ }
+ }
+}
+
+void FullModelChecker::doVariableEquality( FirstOrderModelFmc * fm, Node f, Def & d, Node eq ) {
+ std::vector<Node> cond;
+ mkCondDefaultVec(fm, f, cond);
+ if (eq[0]==eq[1]){
+ d.addEntry(fm, mkCond(cond), d_true);
+ }else{
+ int j = getVariableId(f, eq[0]);
+ int k = getVariableId(f, eq[1]);
+ TypeNode tn = eq[0].getType();
+ if( !fm->d_rep_set.hasType( tn ) ){
+ fm->getSomeDomainElement( tn ); //to verify the type is initialized
+ }
+ for (unsigned i=0; i<fm->d_rep_set.d_type_reps[tn].size(); i++) {
+ Node r = fm->getUsedRepresentative( fm->d_rep_set.d_type_reps[tn][i] );
+ cond[j+1] = r;
+ cond[k+1] = r;
+ d.addEntry( fm, mkCond(cond), d_true);
+ }
+ d.addEntry( fm, mkCondDefault(fm, f), d_false);
+ }
+}
+
+void FullModelChecker::doVariableRelation( FirstOrderModelFmc * fm, Node f, Def & d, Def & dc, Node v) {
+ int j = getVariableId(f, v);
+ for (unsigned i=0; i<dc.d_cond.size(); i++) {
+ Node val = dc.d_value[i];
+ if( dc.d_cond[i][j]!=val ){
+ if (fm->isStar(dc.d_cond[i][j])) {
+ std::vector<Node> cond;
+ mkCondVec(dc.d_cond[i],cond);
+ cond[j+1] = val;
+ d.addEntry(fm, mkCond(cond), d_true);
+ cond[j+1] = fm->getStar(val.getType());
+ d.addEntry(fm, mkCond(cond), d_false);
+ }else{
+ d.addEntry( fm, dc.d_cond[i], d_false);
+ }
+ }else{
+ d.addEntry( fm, dc.d_cond[i], d_true);
+ }
+ }
+}
+
+void FullModelChecker::doUninterpretedCompose( FirstOrderModelFmc * fm, Node f, Def & d, Node op, std::vector< Def > & dc ) {
+ Trace("fmc-uf-debug") << "Definition : " << std::endl;
+ fm->d_models[op]->debugPrint("fmc-uf-debug", op, this);
+ Trace("fmc-uf-debug") << std::endl;
+
+ std::vector< Node > cond;
+ mkCondDefaultVec(fm, f, cond);
+ std::vector< Node > val;
+ doUninterpretedCompose( fm, f, op, d, dc, 0, cond, val);
+}
+
+void FullModelChecker::doUninterpretedCompose( FirstOrderModelFmc * fm, Node f, Node op, Def & d,
+ std::vector< Def > & dc, int index,
+ std::vector< Node > & cond, std::vector<Node> & val ) {
+ Trace("fmc-uf-process") << "process at " << index << std::endl;
+ for( unsigned i=1; i<cond.size(); i++) {
+ debugPrint("fmc-uf-process", cond[i], true);
+ Trace("fmc-uf-process") << " ";
+ }
+ Trace("fmc-uf-process") << std::endl;
+ if (index==(int)dc.size()) {
+ //we have an entry, now do actual compose
+ std::map< int, Node > entries;
+ doUninterpretedCompose2( fm, f, entries, 0, cond, val, fm->d_models[op]->d_et);
+ //add them to the definition
+ for( unsigned e=0; e<fm->d_models[op]->d_cond.size(); e++ ){
+ if ( entries.find(e)!=entries.end() ){
+ d.addEntry(fm, entries[e], fm->d_models[op]->d_value[e] );
+ }
+ }
+ }else{
+ for (unsigned i=0; i<dc[index].d_cond.size(); i++) {
+ if (isCompat(fm, cond, dc[index].d_cond[i])!=0) {
+ std::vector< Node > new_cond;
+ new_cond.insert(new_cond.end(), cond.begin(), cond.end());
+ if( doMeet(fm, new_cond, dc[index].d_cond[i]) ){
+ Trace("fmc-uf-process") << "index " << i << " succeeded meet." << std::endl;
+ val.push_back(dc[index].d_value[i]);
+ doUninterpretedCompose(fm, f, op, d, dc, index+1, new_cond, val);
+ val.pop_back();
+ }else{
+ Trace("fmc-uf-process") << "index " << i << " failed meet." << std::endl;
+ }
+ }
+ }
+ }
+}
+
+void FullModelChecker::doUninterpretedCompose2( FirstOrderModelFmc * fm, Node f,
+ std::map< int, Node > & entries, int index,
+ std::vector< Node > & cond, std::vector< Node > & val,
+ EntryTrie & curr ) {
+ Trace("fmc-uf-process") << "compose " << index << std::endl;
+ for( unsigned i=1; i<cond.size(); i++) {
+ debugPrint("fmc-uf-process", cond[i], true);
+ Trace("fmc-uf-process") << " ";
+ }
+ Trace("fmc-uf-process") << std::endl;
+ if (index==(int)val.size()) {
+ Node c = mkCond(cond);
+ Trace("fmc-uf-entry") << "Entry : " << c << " -> index[" << curr.d_data << "]" << std::endl;
+ entries[curr.d_data] = c;
+ }else{
+ Node v = val[index];
+ bool bind_var = false;
+ if( v.getKind()==kind::BOUND_VARIABLE ){
+ int j = getVariableId(f, v);
+ Trace("fmc-uf-process") << v << " is variable #" << j << std::endl;
+ if (!fm->isStar(cond[j+1])) {
+ v = cond[j+1];
+ }else{
+ bind_var = true;
+ }
+ }
+ if (bind_var) {
+ Trace("fmc-uf-process") << "bind variable..." << std::endl;
+ int j = getVariableId(f, v);
+ for (std::map<Node, EntryTrie>::iterator it = curr.d_child.begin(); it != curr.d_child.end(); ++it) {
+ cond[j+1] = it->first;
+ doUninterpretedCompose2(fm, f, entries, index+1, cond, val, it->second);
+ }
+ cond[j+1] = fm->getStar(v.getType());
+ }else{
+ if (curr.d_child.find(v)!=curr.d_child.end()) {
+ Trace("fmc-uf-process") << "follow value..." << std::endl;
+ doUninterpretedCompose2(fm, f, entries, index+1, cond, val, curr.d_child[v]);
+ }
+ Node st = fm->getStar(v.getType());
+ if (curr.d_child.find(st)!=curr.d_child.end()) {
+ Trace("fmc-uf-process") << "follow star..." << std::endl;
+ doUninterpretedCompose2(fm, f, entries, index+1, cond, val, curr.d_child[st]);
+ }
+ }
+ }
+}
+
+void FullModelChecker::doInterpretedCompose( FirstOrderModelFmc * fm, Node f, Def & d, Node n,
+ std::vector< Def > & dc, int index,
+ std::vector< Node > & cond, std::vector<Node> & val ) {
+ if ( index==(int)dc.size() ){
+ Node c = mkCond(cond);
+ Node v = evaluateInterpreted(n, val);
+ d.addEntry(fm, c, v);
+ }
+ else {
+ TypeNode vtn = n.getType();
+ for (unsigned i=0; i<dc[index].d_cond.size(); i++) {
+ if (isCompat(fm, cond, dc[index].d_cond[i])!=0) {
+ std::vector< Node > new_cond;
+ new_cond.insert(new_cond.end(), cond.begin(), cond.end());
+ if( doMeet(fm, new_cond, dc[index].d_cond[i]) ){
+ bool process = true;
+ if (vtn.isBoolean()) {
+ //short circuit
+ if( (n.getKind()==OR && dc[index].d_value[i]==d_true) ||
+ (n.getKind()==AND && dc[index].d_value[i]==d_false) ){
+ Node c = mkCond(new_cond);
+ d.addEntry(fm, c, dc[index].d_value[i]);
+ process = false;
+ }
+ }
+ if (process) {
+ val.push_back(dc[index].d_value[i]);
+ doInterpretedCompose(fm, f, d, n, dc, index+1, new_cond, val);
+ val.pop_back();
+ }
+ }
+ }
+ }
+ }
+}
+
+int FullModelChecker::isCompat( FirstOrderModelFmc * fm, std::vector< Node > & cond, Node c ) {
+ Assert(cond.size()==c.getNumChildren()+1);
+ for (unsigned i=1; i<cond.size(); i++) {
+ if( cond[i]!=c[i-1] && !fm->isStar(cond[i]) && !fm->isStar(c[i-1]) ) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+bool FullModelChecker::doMeet( FirstOrderModelFmc * fm, std::vector< Node > & cond, Node c ) {
+ Assert(cond.size()==c.getNumChildren()+1);
+ for (unsigned i=1; i<cond.size(); i++) {
+ if( cond[i]!=c[i-1] ) {
+ if( fm->isStar(cond[i]) ){
+ cond[i] = c[i-1];
+ }else if( !fm->isStar(c[i-1]) ){
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+Node FullModelChecker::mkCond( std::vector< Node > & cond ) {
+ return NodeManager::currentNM()->mkNode(APPLY_UF, cond);
+}
+
+Node FullModelChecker::mkCondDefault( FirstOrderModelFmc * fm, Node f) {
+ std::vector< Node > cond;
+ mkCondDefaultVec(fm, f, cond);
+ return mkCond(cond);
+}
+
+void FullModelChecker::mkCondDefaultVec( FirstOrderModelFmc * fm, Node f, std::vector< Node > & cond ) {
+ //get function symbol for f
+ cond.push_back(d_quant_cond[f]);
+ for (unsigned i=0; i<f[0].getNumChildren(); i++) {
+ Node ts = fm->getStar( f[0][i].getType() );
+ cond.push_back(ts);
+ }
+}
+
+void FullModelChecker::mkCondVec( Node n, std::vector< Node > & cond ) {
+ cond.push_back(n.getOperator());
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ cond.push_back( n[i] );
+ }
+}
+
+Node FullModelChecker::evaluateInterpreted( Node n, std::vector< Node > & vals ) {
+ if( n.getKind()==EQUAL ){
+ return vals[0]==vals[1] ? d_true : d_false;
+ }else if( n.getKind()==ITE ){
+ if( vals[0]==d_true ){
+ return vals[1];
+ }else if( vals[0]==d_false ){
+ return vals[2];
+ }else{
+ return vals[1]==vals[2] ? vals[1] : Node::null();
+ }
+ }else if( n.getKind()==AND || n.getKind()==OR ){
+ bool isNull = false;
+ for (unsigned i=0; i<vals.size(); i++) {
+ if((vals[i]==d_true && n.getKind()==OR) || (vals[i]==d_false && n.getKind()==AND)) {
+ return vals[i];
+ }else if( vals[i].isNull() ){
+ isNull = true;
+ }
+ }
+ return isNull ? Node::null() : vals[0];
+ }else{
+ std::vector<Node> children;
+ if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ children.push_back( n.getOperator() );
+ }
+ for (unsigned i=0; i<vals.size(); i++) {
+ if( vals[i].isNull() ){
+ return Node::null();
+ }else{
+ children.push_back( vals[i] );
+ }
+ }
+ Node nc = NodeManager::currentNM()->mkNode(n.getKind(), children);
+ Trace("fmc-eval") << "Evaluate " << nc << " to ";
+ nc = Rewriter::rewrite(nc);
+ Trace("fmc-eval") << nc << std::endl;
+ return nc;
+ }
+}
+
+Node FullModelChecker::getFunctionValue(FirstOrderModelFmc * fm, Node op, const char* argPrefix ) {
+ return fm->getFunctionValue(op, argPrefix);
+}
+
+
+
+void FullModelChecker::addEntry( FirstOrderModelFmc * fm, Node op, Node c, Node v,
+ std::vector< Node > & conds,
+ std::vector< Node > & values,
+ std::vector< Node > & entry_conds ) {
+ std::vector< Node > children;
+ std::vector< Node > entry_children;
+ children.push_back(op);
+ entry_children.push_back(op);
+ bool hasNonStar = false;
+ for( unsigned i=0; i<c.getNumChildren(); i++) {
+ Node ri = fm->getUsedRepresentative( c[i]);
+ children.push_back(ri);
+ if (fm->isModelBasisTerm(ri)) {
+ ri = fm->getStar( ri.getType() );
+ }else{
+ hasNonStar = true;
+ }
+ entry_children.push_back(ri);
+ }
+ Node n = NodeManager::currentNM()->mkNode( APPLY_UF, children );
+ Node nv = fm->getUsedRepresentative( v);
+ Node en = (useSimpleModels() && hasNonStar) ? n : NodeManager::currentNM()->mkNode( APPLY_UF, entry_children );
+ if( std::find(conds.begin(), conds.end(), n )==conds.end() ){
+ Trace("fmc-model-debug") << "- add " << n << " -> " << nv << " (entry is " << en << ")" << std::endl;
+ conds.push_back(n);
+ values.push_back(nv);
+ entry_conds.push_back(en);
+ }
+}
+
+bool FullModelChecker::useSimpleModels() {
+ return options::fmfFullModelCheckSimple();
+}
diff --git a/src/theory/quantifiers/full_model_check.h b/src/theory/quantifiers/full_model_check.h
new file mode 100755
index 000000000..ddf298006
--- /dev/null
+++ b/src/theory/quantifiers/full_model_check.h
@@ -0,0 +1,173 @@
+/********************* */
+/*! \file full_model_check.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds
+ ** 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 Full model check class
+ **/
+
+#ifndef FULL_MODEL_CHECK
+#define FULL_MODEL_CHECK
+
+#include "theory/quantifiers/model_builder.h"
+#include "theory/quantifiers/first_order_model.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+namespace fmcheck {
+
+
+class FirstOrderModelFmc;
+class FullModelChecker;
+
+class EntryTrie
+{
+public:
+ EntryTrie() : d_data(-1){}
+ std::map<Node,EntryTrie> d_child;
+ int d_data;
+ void reset() { d_data = -1; d_child.clear(); }
+ void addEntry( FirstOrderModelFmc * m, Node c, Node v, int data, int index = 0 );
+ bool hasGeneralization( FirstOrderModelFmc * m, Node c, int index = 0 );
+ int getGeneralizationIndex( FirstOrderModelFmc * m, std::vector<Node> & inst, int index = 0 );
+ void getEntries( FirstOrderModelFmc * m, Node c, std::vector<int> & compat, std::vector<int> & gen, int index = 0, bool is_gen = true );
+};
+
+
+class Def
+{
+public:
+ EntryTrie d_et;
+ //cond is APPLY_UF whose arguments are returned by FullModelChecker::getRepresentative
+ std::vector< Node > d_cond;
+ //value is returned by FullModelChecker::getRepresentative
+ std::vector< Node > d_value;
+private:
+ enum {
+ status_unk,
+ status_redundant,
+ status_non_redundant
+ };
+ std::vector< int > d_status;
+ bool d_has_simplified;
+public:
+ Def() : d_has_simplified(false){}
+ void reset() {
+ d_et.reset();
+ d_cond.clear();
+ d_value.clear();
+ d_status.clear();
+ d_has_simplified = false;
+ }
+ bool addEntry( FirstOrderModelFmc * m, Node c, Node v);
+ Node evaluate( FirstOrderModelFmc * m, std::vector<Node>& inst );
+ int getGeneralizationIndex( FirstOrderModelFmc * m, std::vector<Node>& inst );
+ void simplify( FirstOrderModelFmc * m );
+ void debugPrint(const char * tr, Node op, FullModelChecker * m);
+};
+
+class FirstOrderModelFmc : public FirstOrderModel
+{
+ friend class FullModelChecker;
+private:
+ /** quant engine */
+ QuantifiersEngine * d_qe;
+ /** models for UF */
+ std::map<Node, Def * > d_models;
+ std::map<TypeNode, Node > d_model_basis_rep;
+ std::map<TypeNode, Node > d_type_star;
+ Node getUsedRepresentative(Node n);
+ /** get current model value */
+ Node getCurrentUfModelValue( Node n, std::vector< Node > & args, bool partial );
+ void processInitializeModelForTerm(Node n);
+public:
+ FirstOrderModelFmc(QuantifiersEngine * qe, context::Context* c, std::string name);
+ FirstOrderModelFmc * asFirstOrderModelFmc() { return this; }
+ // initialize the model
+ void processInitialize();
+
+ Node getFunctionValue(Node op, const char* argPrefix );
+
+ bool isStar(Node n);
+ Node getStar(TypeNode tn);
+ bool isModelBasisTerm(Node n);
+ Node getModelBasisTerm(TypeNode tn);
+ Node getSomeDomainElement(TypeNode tn);
+};
+
+
+class FullModelChecker : public QModelBuilder
+{
+protected:
+ Node d_true;
+ Node d_false;
+ std::map<TypeNode, std::map< Node, int > > d_rep_ids;
+ std::map<Node, Def > d_quant_models;
+ std::map<Node, Node > d_quant_cond;
+ std::map<Node, std::map< Node, int > > d_quant_var_id;
+ std::map<Node, std::vector< int > > d_star_insts;
+ Node normalizeArgReps(FirstOrderModelFmc * fm, Node op, Node n);
+ int exhaustiveInstantiate(FirstOrderModelFmc * fm, Node f, Node c, int c_index);
+protected:
+ void addEntry( FirstOrderModelFmc * fm, Node op, Node c, Node v,
+ std::vector< Node > & conds,
+ std::vector< Node > & values,
+ std::vector< Node > & entry_conds );
+private:
+ void doCheck(FirstOrderModelFmc * fm, Node f, Def & d, Node n );
+
+ void doNegate( Def & dc );
+ void doVariableEquality( FirstOrderModelFmc * fm, Node f, Def & d, Node eq );
+ void doVariableRelation( FirstOrderModelFmc * fm, Node f, Def & d, Def & dc, Node v);
+ void doUninterpretedCompose( FirstOrderModelFmc * fm, Node f, Def & d, Node n, std::vector< Def > & dc );
+
+ void doUninterpretedCompose( FirstOrderModelFmc * fm, Node f, Node op, Def & d,
+ std::vector< Def > & dc, int index,
+ std::vector< Node > & cond, std::vector<Node> & val );
+ void doUninterpretedCompose2( FirstOrderModelFmc * fm, Node f,
+ std::map< int, Node > & entries, int index,
+ std::vector< Node > & cond, std::vector< Node > & val,
+ EntryTrie & curr);
+
+ void doInterpretedCompose( FirstOrderModelFmc * fm, Node f, Def & d, Node n,
+ std::vector< Def > & dc, int index,
+ std::vector< Node > & cond, std::vector<Node> & val );
+ int isCompat( FirstOrderModelFmc * fm, std::vector< Node > & cond, Node c );
+ bool doMeet( FirstOrderModelFmc * fm, std::vector< Node > & cond, Node c );
+ Node mkCond( std::vector< Node > & cond );
+ Node mkCondDefault( FirstOrderModelFmc * fm, Node f );
+ void mkCondDefaultVec( FirstOrderModelFmc * fm, Node f, std::vector< Node > & cond );
+ void mkCondVec( Node n, std::vector< Node > & cond );
+ Node evaluateInterpreted( Node n, std::vector< Node > & vals );
+public:
+ FullModelChecker( context::Context* c, QuantifiersEngine* qe );
+ ~FullModelChecker(){}
+
+ int getVariableId(Node f, Node n) { return d_quant_var_id[f][n]; }
+
+ void debugPrintCond(const char * tr, Node n, bool dispStar = false);
+ void debugPrint(const char * tr, Node n, bool dispStar = false);
+
+ bool doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort, int & lemmas );
+
+ Node getFunctionValue(FirstOrderModelFmc * fm, Node op, const char* argPrefix );
+
+ /** process build model */
+ void processBuildModel(TheoryModel* m, bool fullModel);
+ /** get current model value */
+ Node getCurrentUfModelValue( FirstOrderModelFmc* fm, Node n, std::vector< Node > & args, bool partial );
+
+ bool useSimpleModels();
+};
+
+}
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/inst_gen.cpp b/src/theory/quantifiers/inst_gen.cpp
index e495b39c0..157861670 100644
--- a/src/theory/quantifiers/inst_gen.cpp
+++ b/src/theory/quantifiers/inst_gen.cpp
@@ -29,10 +29,10 @@ using namespace CVC4::theory::quantifiers;
InstGenProcess::InstGenProcess( Node n ) : d_node( n ){
- Assert( n.hasAttribute(InstConstantAttribute()) );
+ Assert( TermDb::hasInstConstAttr(n) );
int count = 0;
for( size_t i=0; i<n.getNumChildren(); i++ ){
- if( n[i].getKind()!=INST_CONSTANT && n[i].hasAttribute(InstConstantAttribute()) ){
+ if( n[i].getKind()!=INST_CONSTANT && TermDb::hasInstConstAttr(n[i]) ){
d_children.push_back( InstGenProcess( n[i] ) );
d_children_index.push_back( i );
d_children_map[ i ] = count;
@@ -47,7 +47,7 @@ void InstGenProcess::addMatchValue( QuantifiersEngine* qe, Node f, Node val, Ins
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++;
+ ((QModelBuilderIG*)qe->getModelEngine()->getModelBuilder())->d_instGenMatches++;
}
}
}
@@ -92,7 +92,7 @@ void InstGenProcess::calculateMatches( QuantifiersEngine* qe, Node f, std::vecto
//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 isSelected = ((QModelBuilderIG*)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()) ){
@@ -193,7 +193,7 @@ void InstGenProcess::calculateMatches( QuantifiersEngine* qe, Node f, std::vecto
//process all values
for( size_t i=0; i<considerTerms.size(); i++ ){
Node n = considerTerms[i];
- bool isSelected = qe->getModelEngine()->getModelBuilder()->isTermSelected( n );
+ bool isSelected = ((QModelBuilderIG*)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()) ){
diff --git a/src/theory/quantifiers/inst_match.cpp b/src/theory/quantifiers/inst_match.cpp
index f6a0dad11..d55f72a88 100644
--- a/src/theory/quantifiers/inst_match.cpp
+++ b/src/theory/quantifiers/inst_match.cpp
@@ -134,18 +134,27 @@ Node InstMatch::getValue( Node var ) const{
}
}
+Node InstMatch::get( QuantifiersEngine* qe, Node f, int i ) {
+ return get( qe->getTermDatabase()->getInstantiationConstant( f, i ) );
+}
+
void InstMatch::set(TNode var, TNode n){
Assert( !var.isNull() );
- if( !n.isNull() &&// For a strange use in inst_match.cpp InstMatchGeneratorSimple::addInstantiations
- //var.getType() == n.getType()
- !n.getType().isSubtypeOf( var.getType() ) ){
- Trace("inst-match-warn") << var.getAttribute(InstConstantAttribute()) << std::endl;
- Trace("inst-match-warn") << var << " " << var.getType() << " " << n << " " << n.getType() << std::endl ;
- Assert(false);
+ if (Trace.isOn("inst-match-warn")) {
+ // For a strange use in inst_match.cpp InstMatchGeneratorSimple::addInstantiations
+ if( !n.isNull() && !n.getType().isSubtypeOf( var.getType() ) ){
+ Trace("inst-match-warn") << quantifiers::TermDb::getInstConstAttr(var) << std::endl;
+ Trace("inst-match-warn") << var << " " << var.getType() << " " << n << " " << n.getType() << std::endl ;
+ }
}
+ Assert( n.isNull() || n.getType().isSubtypeOf( var.getType() ) );
d_map[var] = n;
}
+void InstMatch::set( QuantifiersEngine* qe, Node f, int i, TNode n ) {
+ set( qe->getTermDatabase()->getInstantiationConstant( f, i ), n );
+}
+
/** add match m for quantifier f starting at index, take into account equalities q, return true if successful */
void InstMatchTrie::addInstMatch2( QuantifiersEngine* qe, Node f, InstMatch& m, int index, ImtIndexOrder* imtio ){
if( long(index)<long(f[0].getNumChildren()) && ( !imtio || long(index)<long(imtio->d_order.size()) ) ){
diff --git a/src/theory/quantifiers/inst_match.h b/src/theory/quantifiers/inst_match.h
index 127f83c60..72447fd66 100644
--- a/src/theory/quantifiers/inst_match.h
+++ b/src/theory/quantifiers/inst_match.h
@@ -92,8 +92,11 @@ public:
void erase(Node node){ d_map.erase(node); }
/** get */
Node get( TNode var ) { return d_map[var]; }
+ Node get( QuantifiersEngine* qe, Node f, int i );
/** set */
void set(TNode var, TNode n);
+ void set( QuantifiersEngine* qe, Node f, int i, TNode n );
+ /** size */
size_t size(){ return d_map.size(); }
/* iterator */
std::map< Node, Node >::iterator begin(){ return d_map.begin(); };
diff --git a/src/theory/quantifiers/inst_match_generator.cpp b/src/theory/quantifiers/inst_match_generator.cpp
index de7f2f373..87c39f046 100644
--- a/src/theory/quantifiers/inst_match_generator.cpp
+++ b/src/theory/quantifiers/inst_match_generator.cpp
@@ -32,7 +32,7 @@ namespace inst {
InstMatchGenerator::InstMatchGenerator( Node pat, int matchPolicy ) : d_matchPolicy( matchPolicy ){
d_active_add = false;
- Assert( pat.hasAttribute(InstConstantAttribute()) );
+ Assert( quantifiers::TermDb::hasInstConstAttr(pat) );
d_pattern = pat;
d_match_pattern = pat;
d_next = NULL;
@@ -52,28 +52,34 @@ void InstMatchGenerator::initialize( QuantifiersEngine* qe, std::vector< InstMat
//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()) );
+ if( d_match_pattern.getKind()==IFF || d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==GEQ ){
+ if( !quantifiers::TermDb::hasInstConstAttr(d_match_pattern[0]) ||
+ d_match_pattern[0].getKind()==INST_CONSTANT ){
+ Assert( quantifiers::TermDb::hasInstConstAttr(d_match_pattern[1]) );
+ Node mp = d_match_pattern[1];
//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];
+ if(d_match_pattern.getKind()==GEQ){
+ d_pattern = NodeManager::currentNM()->mkNode( kind::GT, d_match_pattern[1], d_match_pattern[0] );
+ d_pattern = d_pattern.negate();
}else{
- d_match_pattern = d_pattern[0][0];
+ d_pattern = NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), d_match_pattern[1], d_match_pattern[0] );
}
- }else if( !d_match_pattern[1].hasAttribute(InstConstantAttribute()) ){
- Assert( d_match_pattern[0].hasAttribute(InstConstantAttribute()) );
+ d_pattern = pat.getKind()==NOT ? d_pattern.negate() : d_pattern;
+ d_match_pattern = mp;
+ }else if( !quantifiers::TermDb::hasInstConstAttr(d_match_pattern[1]) ||
+ d_match_pattern[1].getKind()==INST_CONSTANT ){
+ Assert( quantifiers::TermDb::hasInstConstAttr(d_match_pattern[0]) );
if( d_pattern.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching
d_match_pattern = d_match_pattern[0];
+ }else if( d_match_pattern[1].getKind()==INST_CONSTANT ){
+ 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( quantifiers::TermDb::hasInstConstAttr(d_match_pattern[i]) ){
if( d_match_pattern[i].getKind()!=INST_CONSTANT && !Trigger::isBooleanTermTrigger( d_match_pattern[i] ) ){
InstMatchGenerator * cimg = new InstMatchGenerator( d_match_pattern[i], childMatchPolicy );
d_children.push_back( cimg );
@@ -96,17 +102,23 @@ void InstMatchGenerator::initialize( QuantifiersEngine* qe, std::vector< InstMat
//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 ){
+ }else if( d_pattern.getKind()==EQUAL || d_pattern.getKind()==IFF ||
+ d_pattern.getKind()==GEQ || d_pattern.getKind()==GT || d_pattern.getKind()==NOT ){
Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
if( d_pattern.getKind()==NOT ){
- Unimplemented("Disequal generator unimplemented");
+ if (d_pattern[0][1].getKind()!=INST_CONSTANT) {
+ Unimplemented("Disequal generator unimplemented");
+ }else{
+ d_eq_class = d_pattern[0][1];
+ }
}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];
}
+ 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() );
+
}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;
@@ -115,7 +127,7 @@ void InstMatchGenerator::initialize( QuantifiersEngine* qe, std::vector< InstMat
d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
}else{
d_cg = new CandidateGeneratorQueue;
- if( !Trigger::isArithmeticTrigger( d_match_pattern.getAttribute(InstConstantAttribute()), d_match_pattern, d_arith_coeffs ) ){
+ if( !Trigger::isArithmeticTrigger( quantifiers::TermDb::getInstConstAttr(d_match_pattern), 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;
@@ -134,7 +146,7 @@ void InstMatchGenerator::initialize( QuantifiersEngine* qe, std::vector< InstMat
/** 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;
+ << m << ")" << ", " << d_children.size() << ", pattern is " << d_pattern << std::endl;
Assert( !d_match_pattern.isNull() );
if( qe->d_optMatchIgnoreModelBasis && t.getAttribute(ModelBasisAttribute()) ){
return true;
@@ -149,12 +161,12 @@ bool InstMatchGenerator::getMatch( Node f, Node t, InstMatch& m, QuantifiersEngi
InstMatch prev( &m );
//if t is null
Assert( !t.isNull() );
- Assert( !t.hasAttribute(InstConstantAttribute()) );
+ Assert( !quantifiers::TermDb::hasInstConstAttr(t) );
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( quantifiers::TermDb::hasInstConstAttr(d_match_pattern[i]) ){
if( d_match_pattern[i].getKind()==INST_CONSTANT || Trigger::isBooleanTermTrigger( d_match_pattern[i] ) ){
Node vv = d_match_pattern[i];
Node tt = t[i];
@@ -182,6 +194,36 @@ bool InstMatchGenerator::getMatch( Node f, Node t, InstMatch& m, QuantifiersEngi
}
}
}
+ //for relational matching
+ if( !d_eq_class.isNull() && d_eq_class.getKind()==INST_CONSTANT ){
+ //also must fit match to equivalence class
+ bool pol = d_pattern.getKind()!=NOT;
+ Node pat = d_pattern.getKind()==NOT ? d_pattern[0] : d_pattern;
+ Node t_match;
+ if( pol ){
+ if (pat.getKind()==GT) {
+ Node r = NodeManager::currentNM()->mkConst( Rational(-1) );
+ t_match = NodeManager::currentNM()->mkNode(PLUS, t, r);
+ }else{
+ t_match = t;
+ }
+ }else{
+ if(pat.getKind()==EQUAL) {
+ Node r = NodeManager::currentNM()->mkConst( Rational(1) );
+ t_match = NodeManager::currentNM()->mkNode(PLUS, t, r);
+ }else if( pat.getKind()==IFF ){
+ t_match = NodeManager::currentNM()->mkConst( !q->areEqual( NodeManager::currentNM()->mkConst(true), t ) );
+ }else if( pat.getKind()==GEQ ){
+ Node r = NodeManager::currentNM()->mkConst( Rational(1) );
+ t_match = NodeManager::currentNM()->mkNode(PLUS, t, r);
+ }else if( pat.getKind()==GT ){
+ t_match = t;
+ }
+ }
+ if( !t_match.isNull() && !m.setMatch( q, d_eq_class, t_match ) ){
+ success = false;
+ }
+ }
if( success ){
//now, fit children into match
//we will be requesting candidates for matching terms for each child
@@ -286,7 +328,7 @@ void InstMatchGenerator::reset( Node eqc, QuantifiersEngine* qe ){
//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 );
+ d_cg->reset( d_eq_class.getKind()==INST_CONSTANT ? Node::null() : d_eq_class );
}
bool InstMatchGenerator::getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ){
@@ -306,7 +348,7 @@ bool InstMatchGenerator::getNextMatch( Node f, InstMatch& m, QuantifiersEngine*
if( !success ){
//Debug("matching") << this << " failed, reset " << d_eq_class << std::endl;
//we failed, must reset
- reset( d_eq_class, qe );
+ reset( d_eq_class.getKind()==INST_CONSTANT ? Node::null() : d_eq_class, qe );
}
return success;
}
diff --git a/src/theory/quantifiers/inst_strategy_cbqi.cpp b/src/theory/quantifiers/inst_strategy_cbqi.cpp
index dbdf95613..a5031a061 100644
--- a/src/theory/quantifiers/inst_strategy_cbqi.cpp
+++ b/src/theory/quantifiers/inst_strategy_cbqi.cpp
@@ -143,8 +143,8 @@ int InstStrategySimplex::process( Node f, Theory::Effort effort, int e ){
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( TermDb::hasInstConstAttr(n[1]) ){
+ f = TermDb::getInstConstAttr(n[1]);
if( n[1].getKind()==INST_CONSTANT ){
d_ceTableaux[x][ n[1] ] = n[0];
}else{
@@ -155,8 +155,8 @@ void InstStrategySimplex::addTermToRow( ArithVar x, Node n, Node& f, NodeBuilder
t << n;
}
}else{
- if( n.hasAttribute(InstConstantAttribute()) ){
- f = n.getAttribute(InstConstantAttribute());
+ if( TermDb::hasInstConstAttr(n) ){
+ f = TermDb::getInstConstAttr(n);
if( n.getKind()==INST_CONSTANT ){
d_ceTableaux[x][ n ] = Node::null();
}else{
@@ -327,81 +327,9 @@ int InstStrategyDatatypesValue::process( Node f, Theory::Effort effort, int e ){
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()) ){
+ if( !TermDb::hasInstConstAttr(n) ){
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_e_matching.cpp b/src/theory/quantifiers/inst_strategy_e_matching.cpp
index 0e1266e0d..ef81d55a1 100644
--- a/src/theory/quantifiers/inst_strategy_e_matching.cpp
+++ b/src/theory/quantifiers/inst_strategy_e_matching.cpp
@@ -144,7 +144,11 @@ int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e )
}
if( gen ){
generateTriggers( f, effort, e, status );
+ if( d_auto_gen_trigger[f].empty() && f.getNumChildren()==2 ){
+ Trace("no-trigger") << "Could not find trigger for " << f << std::endl;
+ }
}
+
//if( e==4 ){
// d_processed_trigger.clear();
// d_quantEngine->getEqualityQuery()->setLiberal( true );
diff --git a/src/theory/quantifiers/model_builder.cpp b/src/theory/quantifiers/model_builder.cpp
index 0b74cfc5e..88fb7cd8f 100644
--- a/src/theory/quantifiers/model_builder.cpp
+++ b/src/theory/quantifiers/model_builder.cpp
@@ -18,7 +18,6 @@
#include "theory/uf/theory_uf.h"
#include "theory/uf/theory_uf_model.h"
#include "theory/uf/theory_uf_strong_solver.h"
-#include "theory/arrays/theory_arrays_model.h"
#include "theory/quantifiers/first_order_model.h"
#include "theory/quantifiers/term_database.h"
#include "theory/quantifiers/model_builder.h"
@@ -33,33 +32,19 @@ using namespace CVC4::context;
using namespace CVC4::theory;
using namespace CVC4::theory::quantifiers;
-bool TermArgBasisTrie::addTerm2( FirstOrderModel* fm, Node n, int argIndex ){
- if( argIndex<(int)n.getNumChildren() ){
- Node r;
- if( n[ argIndex ].getAttribute(ModelBasisAttribute()) ){
- r = n[ argIndex ];
- }else{
- r = fm->getRepresentative( n[ argIndex ] );
- }
- std::map< Node, TermArgBasisTrie >::iterator it = d_data.find( r );
- if( it==d_data.end() ){
- d_data[r].addTerm2( fm, n, argIndex+1 );
- return true;
- }else{
- return it->second.addTerm2( fm, n, argIndex+1 );
- }
- }else{
- return false;
- }
-}
-ModelEngineBuilder::ModelEngineBuilder( context::Context* c, QuantifiersEngine* qe ) :
-TheoryEngineModelBuilder( qe->getTheoryEngine() ),
-d_qe( qe ), d_curr_model( c, NULL ){
+QModelBuilder::QModelBuilder( context::Context* c, QuantifiersEngine* qe ) :
+TheoryEngineModelBuilder( qe->getTheoryEngine() ), d_curr_model( c, NULL ), d_qe( qe ){
d_considerAxioms = true;
+ d_addedLemmas = 0;
+}
+
+
+bool QModelBuilder::optUseModel() {
+ return options::fmfModelBasedInst();
}
-void ModelEngineBuilder::debugModel( FirstOrderModel* fm ){
+void QModelBuilder::debugModel( FirstOrderModel* fm ){
//debug the model: cycle through all instantiations for all quantifiers, report ones that are not true
if( Trace.isOn("quant-model-warn") ){
for( int i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
@@ -68,7 +53,7 @@ void ModelEngineBuilder::debugModel( FirstOrderModel* fm ){
for( int j=0; j<(int)f[0].getNumChildren(); j++ ){
vars.push_back( f[0][j] );
}
- RepSetIterator riter( &(fm->d_rep_set) );
+ RepSetIterator riter( d_qe, &(fm->d_rep_set) );
riter.setQuantifier( f );
while( !riter.isFinished() ){
std::vector< Node > terms;
@@ -88,14 +73,47 @@ void ModelEngineBuilder::debugModel( FirstOrderModel* fm ){
}
}
-void ModelEngineBuilder::processBuildModel( TheoryModel* m, bool fullModel ) {
- FirstOrderModel* fm = (FirstOrderModel*)m;
+
+
+bool TermArgBasisTrie::addTerm2( FirstOrderModel* fm, Node n, int argIndex ){
+ if( argIndex<(int)n.getNumChildren() ){
+ Node r;
+ if( n[ argIndex ].getAttribute(ModelBasisAttribute()) ){
+ r = n[ argIndex ];
+ }else{
+ r = fm->getRepresentative( n[ argIndex ] );
+ }
+ std::map< Node, TermArgBasisTrie >::iterator it = d_data.find( r );
+ if( it==d_data.end() ){
+ d_data[r].addTerm2( fm, n, argIndex+1 );
+ return true;
+ }else{
+ return it->second.addTerm2( fm, n, argIndex+1 );
+ }
+ }else{
+ return false;
+ }
+}
+
+
+QModelBuilderIG::QModelBuilderIG( context::Context* c, QuantifiersEngine* qe ) :
+QModelBuilder( c, qe ) {
+
+}
+
+Node QModelBuilderIG::getCurrentUfModelValue( FirstOrderModel* fm, Node n, std::vector< Node > & args, bool partial ) {
+ return n;
+}
+
+void QModelBuilderIG::processBuildModel( TheoryModel* m, bool fullModel ) {
+ FirstOrderModel* f = (FirstOrderModel*)m;
+ FirstOrderModelIG* fm = f->asFirstOrderModelIG();
if( fullModel ){
Assert( d_curr_model==fm );
//update models
for( std::map< Node, uf::UfModelTree >::iterator it = fm->d_uf_model_tree.begin(); it != fm->d_uf_model_tree.end(); ++it ){
it->second.update( fm );
- Trace("model-func") << "ModelEngineBuilder: Make function value from tree " << it->first << std::endl;
+ Trace("model-func") << "QModelBuilder: Make function value from tree " << it->first << std::endl;
//construct function values
fm->d_uf_models[ it->first ] = it->second.getFunctionValue( "$x" );
}
@@ -186,12 +204,13 @@ void ModelEngineBuilder::processBuildModel( TheoryModel* m, bool fullModel ) {
}
}
//construct the model if necessary
- if( d_addedLemmas==0 || optExhInstNonInstGenQuant() ){
+ if( d_addedLemmas==0 ){
//if no immediate exceptions, build the model
// this model will be an approximation that will need to be tested via exhaustive instantiation
Trace("model-engine-debug") << "Building model..." << std::endl;
//build model for UF
for( std::map< Node, uf::UfModelTree >::iterator it = fm->d_uf_model_tree.begin(); it != fm->d_uf_model_tree.end(); ++it ){
+ Trace("model-engine-debug-uf") << "Building model for " << it->first << "..." << std::endl;
constructModelUf( fm, it->first );
}
/*
@@ -211,7 +230,7 @@ void ModelEngineBuilder::processBuildModel( TheoryModel* m, bool fullModel ) {
}
}
-int ModelEngineBuilder::initializeQuantifier( Node f, Node fp ){
+int QModelBuilderIG::initializeQuantifier( Node f, Node fp ){
if( d_quant_basis_match_added.find( f )==d_quant_basis_match_added.end() ){
//create the basis match if necessary
if( d_quant_basis_match.find( f )==d_quant_basis_match.end() ){
@@ -254,17 +273,18 @@ int ModelEngineBuilder::initializeQuantifier( Node f, Node fp ){
return 0;
}
-void ModelEngineBuilder::analyzeModel( FirstOrderModel* fm ){
+void QModelBuilderIG::analyzeModel( FirstOrderModel* fm ){
+ FirstOrderModelIG* fmig = fm->asFirstOrderModelIG();
d_uf_model_constructed.clear();
//determine if any functions are constant
- for( std::map< Node, uf::UfModelTree >::iterator it = fm->d_uf_model_tree.begin(); it != fm->d_uf_model_tree.end(); ++it ){
+ for( std::map< Node, uf::UfModelTree >::iterator it = fmig->d_uf_model_tree.begin(); it != fmig->d_uf_model_tree.end(); ++it ){
Node op = it->first;
TermArgBasisTrie tabt;
- for( size_t i=0; i<fm->d_uf_terms[op].size(); i++ ){
- Node n = fm->d_uf_terms[op][i];
+ for( size_t i=0; i<fmig->d_uf_terms[op].size(); i++ ){
+ Node n = fmig->d_uf_terms[op][i];
//for calculating if op is constant
if( !n.getAttribute(NoMatchAttribute()) ){
- Node v = fm->getRepresentative( n );
+ Node v = fmig->getRepresentative( n );
if( i==0 ){
d_uf_prefs[op].d_const_val = v;
}else if( v!=d_uf_prefs[op].d_const_val ){
@@ -273,10 +293,10 @@ void ModelEngineBuilder::analyzeModel( FirstOrderModel* fm ){
}
}
//for calculating terms that we don't need to consider
- if( !n.getAttribute(NoMatchAttribute()) || n.getAttribute(ModelBasisArgAttribute())==1 ){
+ if( !n.getAttribute(NoMatchAttribute()) || n.getAttribute(ModelBasisArgAttribute())!=0 ){
if( !n.getAttribute(BasisNoMatchAttribute()) ){
//need to consider if it is not congruent modulo model basis
- if( !tabt.addTerm( fm, n ) ){
+ if( !tabt.addTerm( fmig, n ) ){
BasisNoMatchAttribute bnma;
n.setAttribute(bnma,true);
}
@@ -284,10 +304,10 @@ void ModelEngineBuilder::analyzeModel( FirstOrderModel* fm ){
}
}
if( !d_uf_prefs[op].d_const_val.isNull() ){
- fm->d_uf_model_gen[op].setDefaultValue( d_uf_prefs[op].d_const_val );
- fm->d_uf_model_gen[op].makeModel( fm, it->second );
+ fmig->d_uf_model_gen[op].setDefaultValue( d_uf_prefs[op].d_const_val );
+ fmig->d_uf_model_gen[op].makeModel( fmig, it->second );
Debug("fmf-model-cons") << "Function " << op << " is the constant function ";
- fm->printRepresentativeDebug( "fmf-model-cons", d_uf_prefs[op].d_const_val );
+ fmig->printRepresentativeDebug( "fmf-model-cons", d_uf_prefs[op].d_const_val );
Debug("fmf-model-cons") << std::endl;
d_uf_model_constructed[op] = true;
}else{
@@ -296,7 +316,7 @@ void ModelEngineBuilder::analyzeModel( FirstOrderModel* fm ){
}
}
-bool ModelEngineBuilder::hasConstantDefinition( Node n ){
+bool QModelBuilderIG::hasConstantDefinition( Node n ){
Node lit = n.getKind()==NOT ? n[0] : n;
if( lit.getKind()==APPLY_UF ){
Node op = lit.getOperator();
@@ -307,31 +327,19 @@ bool ModelEngineBuilder::hasConstantDefinition( Node n ){
return false;
}
-bool ModelEngineBuilder::optUseModel() {
- return options::fmfModelBasedInst();
-}
-
-bool ModelEngineBuilder::optInstGen(){
+bool QModelBuilderIG::optInstGen(){
return options::fmfInstGen();
}
-bool ModelEngineBuilder::optOneQuantPerRoundInstGen(){
+bool QModelBuilderIG::optOneQuantPerRoundInstGen(){
return options::fmfInstGenOneQuantPerRound();
}
-bool ModelEngineBuilder::optExhInstNonInstGenQuant(){
- return options::fmfNewInstGen();
-}
-
-void ModelEngineBuilder::setEffort( int effort ){
- d_considerAxioms = effort>=1;
-}
-
-ModelEngineBuilder::Statistics::Statistics():
- d_num_quants_init("ModelEngineBuilder::Number_Quantifiers", 0),
- d_num_partial_quants_init("ModelEngineBuilder::Number_Partial_Quantifiers", 0),
- d_init_inst_gen_lemmas("ModelEngineBuilder::Initialize_Inst_Gen_Lemmas", 0 ),
- d_inst_gen_lemmas("ModelEngineBuilder::Inst_Gen_Lemmas", 0 )
+QModelBuilderIG::Statistics::Statistics():
+ d_num_quants_init("QModelBuilder::Number_Quantifiers", 0),
+ d_num_partial_quants_init("QModelBuilder::Number_Partial_Quantifiers", 0),
+ d_init_inst_gen_lemmas("QModelBuilder::Initialize_Inst_Gen_Lemmas", 0 ),
+ d_inst_gen_lemmas("QModelBuilder::Inst_Gen_Lemmas", 0 )
{
StatisticsRegistry::registerStat(&d_num_quants_init);
StatisticsRegistry::registerStat(&d_num_partial_quants_init);
@@ -339,20 +347,20 @@ ModelEngineBuilder::Statistics::Statistics():
StatisticsRegistry::registerStat(&d_inst_gen_lemmas);
}
-ModelEngineBuilder::Statistics::~Statistics(){
+QModelBuilderIG::Statistics::~Statistics(){
StatisticsRegistry::unregisterStat(&d_num_quants_init);
StatisticsRegistry::unregisterStat(&d_num_partial_quants_init);
StatisticsRegistry::unregisterStat(&d_init_inst_gen_lemmas);
StatisticsRegistry::unregisterStat(&d_inst_gen_lemmas);
}
-bool ModelEngineBuilder::isQuantifierActive( Node f ){
+bool QModelBuilderIG::isQuantifierActive( Node f ){
return ( d_considerAxioms || !f.getAttribute(AxiomAttribute()) ) && d_quant_sat.find( f )==d_quant_sat.end();
}
-bool ModelEngineBuilder::isTermActive( Node n ){
+bool QModelBuilderIG::isTermActive( Node n ){
return !n.getAttribute(NoMatchAttribute()) || //it is not congruent to another active term
- ( n.getAttribute(ModelBasisArgAttribute())==1 && !n.getAttribute(BasisNoMatchAttribute()) ); //or it has model basis arguments
+ ( n.getAttribute(ModelBasisArgAttribute())!=0 && !n.getAttribute(BasisNoMatchAttribute()) ); //or it has model basis arguments
//and is not congruent modulo model basis
//to another active term
}
@@ -360,7 +368,7 @@ bool ModelEngineBuilder::isTermActive( Node n ){
-void ModelEngineBuilderDefault::reset( FirstOrderModel* fm ){
+void QModelBuilderDefault::reset( FirstOrderModel* fm ){
d_quant_selection_lit.clear();
d_quant_selection_lit_candidates.clear();
d_quant_selection_lit_terms.clear();
@@ -369,7 +377,7 @@ void ModelEngineBuilderDefault::reset( FirstOrderModel* fm ){
}
-int ModelEngineBuilderDefault::getSelectionScore( std::vector< Node >& uf_terms ) {
+int QModelBuilderDefault::getSelectionScore( std::vector< Node >& uf_terms ) {
/*
size_t maxChildren = 0;
for( size_t i=0; i<uf_terms.size(); i++ ){
@@ -383,7 +391,8 @@ int ModelEngineBuilderDefault::getSelectionScore( std::vector< Node >& uf_terms
return 0;
}
-void ModelEngineBuilderDefault::analyzeQuantifier( FirstOrderModel* fm, Node f ){
+void QModelBuilderDefault::analyzeQuantifier( FirstOrderModel* fm, Node f ){
+ FirstOrderModelIG* fmig = fm->asFirstOrderModelIG();
Debug("fmf-model-prefs") << "Analyze quantifier " << f << std::endl;
//the pro/con preferences for this quantifier
std::vector< Node > pro_con[2];
@@ -408,7 +417,7 @@ void ModelEngineBuilderDefault::analyzeQuantifier( FirstOrderModel* fm, Node f )
// constant definitions.
bool isConst = true;
std::vector< Node > uf_terms;
- if( n.hasAttribute(InstConstantAttribute()) ){
+ if( TermDb::hasInstConstAttr(n) ){
isConst = false;
if( gn.getKind()==APPLY_UF ){
uf_terms.push_back( gn );
@@ -416,9 +425,9 @@ void ModelEngineBuilderDefault::analyzeQuantifier( FirstOrderModel* fm, Node f )
}else if( gn.getKind()==EQUAL ){
isConst = true;
for( int j=0; j<2; j++ ){
- if( n[j].hasAttribute(InstConstantAttribute()) ){
+ if( TermDb::hasInstConstAttr(n[j]) ){
if( n[j].getKind()==APPLY_UF &&
- fm->d_uf_model_tree.find( gn[j].getOperator() )!=fm->d_uf_model_tree.end() ){
+ fmig->d_uf_model_tree.find( gn[j].getOperator() )!=fmig->d_uf_model_tree.end() ){
uf_terms.push_back( gn[j] );
isConst = isConst && hasConstantDefinition( gn[j] );
}else{
@@ -506,14 +515,14 @@ void ModelEngineBuilderDefault::analyzeQuantifier( FirstOrderModel* fm, Node f )
for( int k=0; k<2; k++ ){
for( int j=0; j<(int)pro_con[k].size(); j++ ){
Node op = pro_con[k][j].getOperator();
- Node r = fm->getRepresentative( pro_con[k][j] );
+ Node r = fmig->getRepresentative( pro_con[k][j] );
d_uf_prefs[op].setValuePreference( f, pro_con[k][j], r, k==0 );
}
}
}
}
-int ModelEngineBuilderDefault::doInstGen( FirstOrderModel* fm, Node f ){
+int QModelBuilderDefault::doInstGen( FirstOrderModel* fm, Node f ){
int addedLemmas = 0;
//we wish to add all known exceptions to our selection literal for f. this will help to refine our current model.
//This step is advantageous over exhaustive instantiation, since we are adding instantiations that involve model basis terms,
@@ -523,17 +532,16 @@ int ModelEngineBuilderDefault::doInstGen( FirstOrderModel* fm, Node f ){
for( size_t i=0; i<d_quant_selection_lit_candidates[f].size(); i++ ){
bool phase = d_quant_selection_lit_candidates[f][i].getKind()!=NOT;
Node lit = d_quant_selection_lit_candidates[f][i].getKind()==NOT ? d_quant_selection_lit_candidates[f][i][0] : d_quant_selection_lit_candidates[f][i];
- Assert( lit.hasAttribute(InstConstantAttribute()) );
+ Assert( TermDb::hasInstConstAttr(lit) );
std::vector< Node > tr_terms;
if( lit.getKind()==APPLY_UF ){
//only match predicates that are contrary to this one, use literal matching
Node eq = NodeManager::currentNM()->mkNode( IFF, lit, !phase ? fm->d_true : fm->d_false );
- d_qe->getTermDatabase()->setInstantiationConstantAttr( eq, f );
tr_terms.push_back( eq );
}else if( lit.getKind()==EQUAL ){
//collect trigger terms
for( int j=0; j<2; j++ ){
- if( lit[j].hasAttribute(InstConstantAttribute()) ){
+ if( TermDb::hasInstConstAttr(lit[j]) ){
if( lit[j].getKind()==APPLY_UF ){
tr_terms.push_back( lit[j] );
}else{
@@ -564,7 +572,8 @@ int ModelEngineBuilderDefault::doInstGen( FirstOrderModel* fm, Node f ){
return addedLemmas;
}
-void ModelEngineBuilderDefault::constructModelUf( FirstOrderModel* fm, Node op ){
+void QModelBuilderDefault::constructModelUf( FirstOrderModel* fm, Node op ){
+ FirstOrderModelIG* fmig = fm->asFirstOrderModelIG();
if( optReconsiderFuncConstants() ){
//reconsider constant functions that weren't necessary
if( d_uf_model_constructed[op] ){
@@ -573,8 +582,8 @@ void ModelEngineBuilderDefault::constructModelUf( FirstOrderModel* fm, Node op )
Node v = d_uf_prefs[op].d_const_val;
if( d_uf_prefs[op].d_value_pro_con[0][v].empty() ){
Debug("fmf-model-cons-debug") << "Consider changing the default value for " << op << std::endl;
- fm->d_uf_model_tree[op].clear();
- fm->d_uf_model_gen[op].clear();
+ fmig->d_uf_model_tree[op].clear();
+ fmig->d_uf_model_gen[op].clear();
d_uf_model_constructed[op] = false;
}
}
@@ -586,20 +595,20 @@ void ModelEngineBuilderDefault::constructModelUf( FirstOrderModel* fm, Node op )
Node defaultTerm = d_qe->getTermDatabase()->getModelBasisOpTerm( op );
Trace("fmf-model-cons") << "Construct model for " << op << "..." << std::endl;
//set the values in the model
- for( size_t i=0; i<fm->d_uf_terms[op].size(); i++ ){
- Node n = fm->d_uf_terms[op][i];
+ for( size_t i=0; i<fmig->d_uf_terms[op].size(); i++ ){
+ Node n = fmig->d_uf_terms[op][i];
if( isTermActive( n ) ){
- Node v = fm->getRepresentative( n );
- Trace("fmf-model-cons") << "Set term " << n << " : " << fm->d_rep_set.getIndexFor( v ) << " " << v << std::endl;
+ Node v = fmig->getRepresentative( n );
+ Trace("fmf-model-cons") << "Set term " << n << " : " << fmig->d_rep_set.getIndexFor( v ) << " " << v << std::endl;
//if this assertion did not help the model, just consider it ground
//set n = v in the model tree
//set it as ground value
- fm->d_uf_model_gen[op].setValue( fm, n, v );
- if( fm->d_uf_model_gen[op].optUsePartialDefaults() ){
+ fmig->d_uf_model_gen[op].setValue( fm, n, v );
+ if( fmig->d_uf_model_gen[op].optUsePartialDefaults() ){
//also set as default value if necessary
- if( n.hasAttribute(ModelBasisArgAttribute()) && n.getAttribute(ModelBasisArgAttribute())==1 ){
+ if( n.hasAttribute(ModelBasisArgAttribute()) && n.getAttribute(ModelBasisArgAttribute())!=0 ){
Trace("fmf-model-cons") << " Set as default." << std::endl;
- fm->d_uf_model_gen[op].setValue( fm, n, v, false );
+ fmig->d_uf_model_gen[op].setValue( fm, n, v, false );
if( n==defaultTerm ){
//incidentally already set, we will not need to find a default value
setDefaultVal = false;
@@ -607,7 +616,7 @@ void ModelEngineBuilderDefault::constructModelUf( FirstOrderModel* fm, Node op )
}
}else{
if( n==defaultTerm ){
- fm->d_uf_model_gen[op].setValue( fm, n, v, false );
+ fmig->d_uf_model_gen[op].setValue( fm, n, v, false );
//incidentally already set, we will not need to find a default value
setDefaultVal = false;
}
@@ -619,12 +628,19 @@ void ModelEngineBuilderDefault::constructModelUf( FirstOrderModel* fm, Node op )
Trace("fmf-model-cons") << " Choose default value..." << std::endl;
//chose defaultVal based on heuristic, currently the best ratio of "pro" responses
Node defaultVal = d_uf_prefs[op].getBestDefaultValue( defaultTerm, fm );
+ if( defaultVal.isNull() ){
+ if (!fmig->d_rep_set.hasType(defaultTerm.getType())) {
+ Node mbt = d_qe->getTermDatabase()->getModelBasisTerm(defaultTerm.getType());
+ fmig->d_rep_set.d_type_reps[defaultTerm.getType()].push_back(mbt);
+ }
+ defaultVal = fmig->d_rep_set.d_type_reps[defaultTerm.getType()][0];
+ }
Assert( !defaultVal.isNull() );
- Trace("fmf-model-cons") << "Set default term : " << fm->d_rep_set.getIndexFor( defaultVal ) << std::endl;
- fm->d_uf_model_gen[op].setValue( fm, defaultTerm, defaultVal, false );
+ Trace("fmf-model-cons") << "Set default term : " << fmig->d_rep_set.getIndexFor( defaultVal ) << std::endl;
+ fmig->d_uf_model_gen[op].setValue( fm, defaultTerm, defaultVal, false );
}
Debug("fmf-model-cons") << " Making model...";
- fm->d_uf_model_gen[op].makeModel( fm, fm->d_uf_model_tree[op] );
+ fmig->d_uf_model_gen[op].makeModel( fm, fmig->d_uf_model_tree[op] );
d_uf_model_constructed[op] = true;
Debug("fmf-model-cons") << " Finished constructing model for " << op << "." << std::endl;
}
@@ -635,7 +651,7 @@ void ModelEngineBuilderDefault::constructModelUf( FirstOrderModel* fm, Node op )
////////////////////// Inst-Gen style Model Builder ///////////
-void ModelEngineBuilderInstGen::reset( FirstOrderModel* fm ){
+void QModelBuilderInstGen::reset( FirstOrderModel* fm ){
//for new inst gen
d_quant_selection_formula.clear();
d_term_selected.clear();
@@ -643,15 +659,15 @@ void ModelEngineBuilderInstGen::reset( FirstOrderModel* fm ){
//d_sub_quant_inst_trie.clear();//*
}
-int ModelEngineBuilderInstGen::initializeQuantifier( Node f, Node fp ){
- int addedLemmas = ModelEngineBuilder::initializeQuantifier( f, fp );
+int QModelBuilderInstGen::initializeQuantifier( Node f, Node fp ){
+ int addedLemmas = QModelBuilderIG::initializeQuantifier( f, fp );
for( size_t i=0; i<d_sub_quants[f].size(); i++ ){
addedLemmas += initializeQuantifier( d_sub_quants[f][i], fp );
}
return addedLemmas;
}
-void ModelEngineBuilderInstGen::analyzeQuantifier( FirstOrderModel* fm, Node f ){
+void QModelBuilderInstGen::analyzeQuantifier( FirstOrderModel* fm, Node f ){
//Node fp = getParentQuantifier( f );//*
//bool quantRedundant = ( f!=fp && d_sub_quant_inst_trie[fp].addInstMatch( d_qe, fp, d_sub_quant_inst[ f ], true ) );
//if( f==fp || d_sub_quant_inst_trie[fp].addInstMatch( d_qe, fp, d_sub_quant_inst[ f ], true ) ){//*
@@ -662,7 +678,6 @@ void ModelEngineBuilderInstGen::analyzeQuantifier( FirstOrderModel* fm, Node f )
//if( !s.isNull() ){
// s = Rewriter::rewrite( s );
//}
- d_qe->getTermDatabase()->setInstantiationConstantAttr( s, f );
Trace("sel-form-debug") << "Selection formula " << f << std::endl;
Trace("sel-form-debug") << " " << s << std::endl;
if( !s.isNull() ){
@@ -685,7 +700,7 @@ void ModelEngineBuilderInstGen::analyzeQuantifier( FirstOrderModel* fm, Node f )
}
-int ModelEngineBuilderInstGen::doInstGen( FirstOrderModel* fm, Node f ){
+int QModelBuilderInstGen::doInstGen( FirstOrderModel* fm, Node f ){
int addedLemmas = 0;
if( d_quant_sat.find( f )==d_quant_sat.end() ){
Node fp = d_sub_quant_parent.find( f )==d_sub_quant_parent.end() ? f : d_sub_quant_parent[f];
@@ -802,7 +817,7 @@ Node mkAndSelectionFormula( Node n1, Node n2 ){
//if possible, returns a formula n' such that n' => ( n <=> polarity ), and n' is true in the current context,
// and NULL otherwise
-Node ModelEngineBuilderInstGen::getSelectionFormula( Node fn, Node n, bool polarity, int useOption ){
+Node QModelBuilderInstGen::getSelectionFormula( Node fn, Node n, bool polarity, int useOption ){
Trace("sel-form-debug") << "Looking for selection formula " << n << " " << polarity << std::endl;
Node ret;
if( n.getKind()==NOT ){
@@ -911,7 +926,7 @@ Node ModelEngineBuilderInstGen::getSelectionFormula( Node fn, Node n, bool polar
return ret;
}
-int ModelEngineBuilderInstGen::getSelectionFormulaScore( Node fn ){
+int QModelBuilderInstGen::getSelectionFormulaScore( Node fn ){
if( fn.getType().isBoolean() ){
if( fn.getKind()==APPLY_UF ){
Node op = fn.getOperator();
@@ -929,13 +944,13 @@ int ModelEngineBuilderInstGen::getSelectionFormulaScore( Node fn ){
}
}
-void ModelEngineBuilderInstGen::setSelectedTerms( Node s ){
+void QModelBuilderInstGen::setSelectedTerms( Node s ){
//if it is apply uf and has model basis arguments, then mark term as being "selected"
if( s.getKind()==APPLY_UF ){
Assert( s.hasAttribute(ModelBasisArgAttribute()) );
if( !s.hasAttribute(ModelBasisArgAttribute()) ) std::cout << "no mba!! " << s << std::endl;
- if( s.getAttribute(ModelBasisArgAttribute())==1 ){
+ if( s.getAttribute(ModelBasisArgAttribute())!=0 ){
d_term_selected[ s ] = true;
Trace("sel-form-term") << " " << s << " is a selected term." << std::endl;
}
@@ -945,7 +960,7 @@ void ModelEngineBuilderInstGen::setSelectedTerms( Node s ){
}
}
-bool ModelEngineBuilderInstGen::isUsableSelectionLiteral( Node n, int useOption ){
+bool QModelBuilderInstGen::isUsableSelectionLiteral( Node n, int useOption ){
if( n.getKind()==FORALL ){
return false;
}else if( n.getKind()!=APPLY_UF ){
@@ -964,7 +979,7 @@ bool ModelEngineBuilderInstGen::isUsableSelectionLiteral( Node n, int useOption
return true;
}
-void ModelEngineBuilderInstGen::getParentQuantifierMatch( InstMatch& mp, Node fp, InstMatch& m, Node f ){
+void QModelBuilderInstGen::getParentQuantifierMatch( InstMatch& mp, Node fp, InstMatch& m, Node f ){
if( f!=fp ){
//std::cout << "gpqm " << fp << " " << f << " " << m << std::endl;
//std::cout << " " << fp[0].getNumChildren() << " " << f[0].getNumChildren() << std::endl;
@@ -988,20 +1003,21 @@ void ModelEngineBuilderInstGen::getParentQuantifierMatch( InstMatch& mp, Node fp
}
}
-void ModelEngineBuilderInstGen::constructModelUf( FirstOrderModel* fm, Node op ){
+void QModelBuilderInstGen::constructModelUf( FirstOrderModel* fm, Node op ){
+ FirstOrderModelIG* fmig = fm->asFirstOrderModelIG();
bool setDefaultVal = true;
Node defaultTerm = d_qe->getTermDatabase()->getModelBasisOpTerm( op );
//set the values in the model
- for( size_t i=0; i<fm->d_uf_terms[op].size(); i++ ){
- Node n = fm->d_uf_terms[op][i];
+ for( size_t i=0; i<fmig->d_uf_terms[op].size(); i++ ){
+ Node n = fmig->d_uf_terms[op][i];
if( isTermActive( n ) ){
- Node v = fm->getRepresentative( n );
- fm->d_uf_model_gen[op].setValue( fm, n, v );
+ Node v = fmig->getRepresentative( n );
+ fmig->d_uf_model_gen[op].setValue( fm, n, v );
}
//also possible set as default
if( d_term_selected.find( n )!=d_term_selected.end() || n==defaultTerm ){
- Node v = fm->getRepresentative( n );
- fm->d_uf_model_gen[op].setValue( fm, n, v, false );
+ Node v = fmig->getRepresentative( n );
+ fmig->d_uf_model_gen[op].setValue( fm, n, v, false );
if( n==defaultTerm ){
setDefaultVal = false;
}
@@ -1010,12 +1026,12 @@ void ModelEngineBuilderInstGen::constructModelUf( FirstOrderModel* fm, Node op )
//set the overall default value if not set already (is this necessary??)
if( setDefaultVal ){
Node defaultVal = d_uf_prefs[op].getBestDefaultValue( defaultTerm, fm );
- fm->d_uf_model_gen[op].setValue( fm, defaultTerm, defaultVal, false );
+ fmig->d_uf_model_gen[op].setValue( fm, defaultTerm, defaultVal, false );
}
- fm->d_uf_model_gen[op].makeModel( fm, fm->d_uf_model_tree[op] );
+ fmig->d_uf_model_gen[op].makeModel( fm, fmig->d_uf_model_tree[op] );
d_uf_model_constructed[op] = true;
}
-bool ModelEngineBuilderInstGen::existsInstantiation( Node f, InstMatch& m, bool modEq, bool modInst ){
+bool QModelBuilderInstGen::existsInstantiation( Node f, InstMatch& m, bool modEq, bool modInst ){
return d_child_sub_quant_inst_trie[f].existsInstMatch( d_qe, f, m, modEq, true );
} \ No newline at end of file
diff --git a/src/theory/quantifiers/model_builder.h b/src/theory/quantifiers/model_builder.h
index 31448acee..715612975 100644
--- a/src/theory/quantifiers/model_builder.h
+++ b/src/theory/quantifiers/model_builder.h
@@ -25,6 +25,37 @@ namespace CVC4 {
namespace theory {
namespace quantifiers {
+
+class QModelBuilder : public TheoryEngineModelBuilder
+{
+protected:
+ //the model we are working with
+ context::CDO< FirstOrderModel* > d_curr_model;
+ //quantifiers engine
+ QuantifiersEngine* d_qe;
+public:
+ QModelBuilder( context::Context* c, QuantifiersEngine* qe );
+ virtual ~QModelBuilder(){}
+ // is quantifier active?
+ virtual bool isQuantifierActive( Node f ) { return true; }
+ //do exhaustive instantiation
+ virtual bool doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort, int & lemmas ) { return false; }
+ //whether to construct model
+ virtual bool optUseModel();
+ /** number of lemmas generated while building model */
+ int d_addedLemmas;
+ //consider axioms
+ bool d_considerAxioms;
+ /** exist instantiation ? */
+ virtual bool existsInstantiation( Node f, InstMatch& m, bool modEq = true, bool modInst = false ) { return false; }
+ //debug model
+ void debugModel( FirstOrderModel* fm );
+};
+
+
+
+
+
/** Attribute true for nodes that should not be used when considered for inst-gen basis */
struct BasisNoMatchAttributeId {};
/** use the special for boolean flag */
@@ -47,17 +78,13 @@ public:
/** model builder class
* This class is capable of building candidate models based on the current quantified formulas
* that are asserted. Use:
- * (1) call ModelEngineBuilder::buildModel( m, false );, where m is a FirstOrderModel
+ * (1) call QModelBuilder::buildModel( m, false );, where m is a FirstOrderModel
* (2) if candidate model is determined to be a real model,
- then call ModelEngineBuilder::buildModel( m, true );
+ then call QModelBuilder::buildModel( m, true );
*/
-class ModelEngineBuilder : public TheoryEngineModelBuilder
+class QModelBuilderIG : public QModelBuilder
{
protected:
- //quantifiers engine
- QuantifiersEngine* d_qe;
- //the model we are working with
- context::CDO< FirstOrderModel* > d_curr_model;
//map from operators to model preference data
std::map< Node, uf::UfModelPreferenceData > d_uf_prefs;
//built model uf
@@ -66,6 +93,8 @@ protected:
bool d_didInstGen;
/** process build model */
virtual void processBuildModel( TheoryModel* m, bool fullModel );
+ /** get current model value */
+ Node getCurrentUfModelValue( FirstOrderModel* fm, Node n, std::vector< Node > & args, bool partial );
protected:
//reset
virtual void reset( FirstOrderModel* fm ) = 0;
@@ -90,25 +119,13 @@ protected: //helper functions
/** term has constant definition */
bool hasConstantDefinition( Node n );
public:
- ModelEngineBuilder( context::Context* c, QuantifiersEngine* qe );
- virtual ~ModelEngineBuilder(){}
- /** number of lemmas generated while building model */
- int d_addedLemmas;
- //consider axioms
- bool d_considerAxioms;
- // set effort
- void setEffort( int effort );
- //debug model
- void debugModel( FirstOrderModel* fm );
+ QModelBuilderIG( context::Context* c, QuantifiersEngine* qe );
+ virtual ~QModelBuilderIG(){}
public:
- //whether to construct model
- virtual bool optUseModel();
//whether to add inst-gen lemmas
virtual bool optInstGen();
//whether to only consider only quantifier per round of inst-gen
virtual bool optOneQuantPerRoundInstGen();
- //whether we should exhaustively instantiate quantifiers where inst-gen is not working
- virtual bool optExhInstNonInstGenQuant();
/** statistics class */
class Statistics {
public:
@@ -120,18 +137,16 @@ public:
~Statistics();
};
Statistics d_statistics;
- // is quantifier active?
- bool isQuantifierActive( Node f );
// is term active
bool isTermActive( Node n );
// is term selected
virtual bool isTermSelected( Node n ) { return false; }
- /** exist instantiation ? */
- virtual bool existsInstantiation( Node f, InstMatch& m, bool modEq = true, bool modInst = false ) { return false; }
/** quantifier has inst-gen definition */
virtual bool hasInstGen( Node f ) = 0;
/** did inst gen this round? */
bool didInstGen() { return d_didInstGen; }
+ // is quantifier active?
+ bool isQuantifierActive( Node f );
//temporary stats
int d_numQuantSat;
@@ -140,10 +155,10 @@ public:
int d_numQuantNoSelForm;
//temporary stat
int d_instGenMatches;
-};/* class ModelEngineBuilder */
+};/* class QModelBuilder */
-class ModelEngineBuilderDefault : public ModelEngineBuilder
+class QModelBuilderDefault : public QModelBuilderIG
{
private: ///information for (old) InstGen
//map from quantifiers to their selection literals
@@ -167,15 +182,15 @@ protected:
//theory-specific build models
void constructModelUf( FirstOrderModel* fm, Node op );
public:
- ModelEngineBuilderDefault( context::Context* c, QuantifiersEngine* qe ) : ModelEngineBuilder( c, qe ){}
- ~ModelEngineBuilderDefault(){}
+ QModelBuilderDefault( context::Context* c, QuantifiersEngine* qe ) : QModelBuilderIG( c, qe ){}
+ ~QModelBuilderDefault(){}
//options
bool optReconsiderFuncConstants() { return true; }
//has inst gen
bool hasInstGen( Node f ) { return !d_quant_selection_lit[f].isNull(); }
};
-class ModelEngineBuilderInstGen : public ModelEngineBuilder
+class QModelBuilderInstGen : public QModelBuilderIG
{
private: ///information for (new) InstGen
//map from quantifiers to their selection formulas
@@ -217,8 +232,8 @@ private:
//get parent quantifier
Node getParentQuantifier( Node f ) { return d_sub_quant_parent.find( f )==d_sub_quant_parent.end() ? f : d_sub_quant_parent[f]; }
public:
- ModelEngineBuilderInstGen( context::Context* c, QuantifiersEngine* qe ) : ModelEngineBuilder( c, qe ){}
- ~ModelEngineBuilderInstGen(){}
+ QModelBuilderInstGen( context::Context* c, QuantifiersEngine* qe ) : QModelBuilderIG( c, qe ){}
+ ~QModelBuilderInstGen(){}
// is term selected
bool isTermSelected( Node n ) { return d_term_selected.find( n )!=d_term_selected.end(); }
/** exist instantiation ? */
diff --git a/src/theory/quantifiers/model_engine.cpp b/src/theory/quantifiers/model_engine.cpp
index a69b278c0..32deb9e47 100644
--- a/src/theory/quantifiers/model_engine.cpp
+++ b/src/theory/quantifiers/model_engine.cpp
@@ -18,7 +18,6 @@
#include "theory/uf/theory_uf.h"
#include "theory/uf/theory_uf_strong_solver.h"
#include "theory/quantifiers/options.h"
-#include "theory/arrays/theory_arrays_model.h"
#include "theory/quantifiers/first_order_model.h"
#include "theory/quantifiers/term_database.h"
#include "theory/quantifiers/quantifiers_attributes.h"
@@ -35,13 +34,14 @@ using namespace CVC4::theory::inst;
//Model Engine constructor
ModelEngine::ModelEngine( context::Context* c, QuantifiersEngine* qe ) :
-QuantifiersModule( qe ),
-d_rel_domain( qe, qe->getModel() ){
+QuantifiersModule( qe ){
- if( options::fmfNewInstGen() ){
- d_builder = new ModelEngineBuilderInstGen( c, qe );
+ if( options::fmfFullModelCheck() ){
+ d_builder = new fmcheck::FullModelChecker( c, qe );
+ }else if( options::fmfNewInstGen() ){
+ d_builder = new QModelBuilderInstGen( c, qe );
}else{
- d_builder = new ModelEngineBuilderDefault( c, qe );
+ d_builder = new QModelBuilderDefault( c, qe );
}
}
@@ -66,7 +66,7 @@ void ModelEngine::check( Theory::Effort e ){
Trace("model-engine") << "---Model Engine Round---" << std::endl;
//initialize the model
Trace("model-engine-debug") << "Build model..." << std::endl;
- d_builder->setEffort( effort );
+ d_builder->d_considerAxioms = effort>=1;
d_builder->buildModel( fm, false );
addedLemmas += (int)d_builder->d_addedLemmas;
//if builder has lemmas, add and return
@@ -81,11 +81,7 @@ void ModelEngine::check( Theory::Effort e ){
Debug("fmf-model-complete") << std::endl;
debugPrint("fmf-model-complete");
//successfully built an acceptable model, now check it
- addedLemmas += checkModel( check_model_full );
- }else if( d_builder->didInstGen() && d_builder->optExhInstNonInstGenQuant() ){
- Trace("model-engine-debug") << "Check model for non-inst gen quantifiers..." << std::endl;
- //check quantifiers that inst-gen didn't apply to
- addedLemmas += checkModel( check_model_no_inst_gen );
+ addedLemmas += checkModel();
}
}
if( addedLemmas==0 ){
@@ -151,7 +147,7 @@ bool ModelEngine::optExhInstEvalSkipMultiple(){
#endif
}
-int ModelEngine::checkModel( int checkOption ){
+int ModelEngine::checkModel(){
int addedLemmas = 0;
FirstOrderModel* fm = d_quantEngine->getModel();
//for debugging
@@ -161,54 +157,61 @@ int ModelEngine::checkModel( int checkOption ){
if( it->first.isSort() ){
Trace("model-engine") << "Cardinality( " << it->first << " )" << " = " << it->second.size() << std::endl;
Trace("model-engine-debug") << " ";
+ Node mbt = d_quantEngine->getTermDatabase()->getModelBasisTerm(it->first);
for( size_t i=0; i<it->second.size(); i++ ){
//Trace("model-engine-debug") << it->second[i] << " ";
Node r = ((EqualityQueryQuantifiersEngine*)d_quantEngine->getEqualityQuery())->getRepresentative( it->second[i] );
Trace("model-engine-debug") << r << " ";
}
Trace("model-engine-debug") << std::endl;
+ Trace("model-engine-debug") << " Model basis term : " << mbt << std::endl;
}
}
}
- //compute the relevant domain if necessary
- if( optUseRelevantDomain() ){
- d_rel_domain.compute();
+ //full model checking: construct models for all functions
+ /*
+ if( d_fmc.isActive() ){
+ for (std::map< Node, uf::UfModelTreeGenerator >::iterator it = fm->d_uf_model_gen.begin(); it != fm->d_uf_model_gen.end(); ++it) {
+ d_fmc.getModel(fm, it->first);
+ }
}
+ */
+ //compute the relevant domain if necessary
+ //if( optUseRelevantDomain() ){
+ //}
d_triedLemmas = 0;
d_testLemmas = 0;
d_relevantLemmas = 0;
d_totalLemmas = 0;
Trace("model-engine-debug") << "Do exhaustive instantiation..." << std::endl;
- for( int i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
- Node f = fm->getAssertedQuantifier( i );
- //keep track of total instantiations for statistics
- int totalInst = 1;
- for( size_t i=0; i<f[0].getNumChildren(); i++ ){
- TypeNode tn = f[0][i].getType();
- if( fm->d_rep_set.hasType( tn ) ){
- totalInst = totalInst * (int)fm->d_rep_set.d_type_reps[ tn ].size();
- }
- }
- d_totalLemmas += totalInst;
- //determine if we should check this quantifiers
- bool checkQuant = false;
- if( checkOption==check_model_full ){
- checkQuant = d_builder->isQuantifierActive( f );
- }else if( checkOption==check_model_no_inst_gen ){
- checkQuant = !d_builder->hasInstGen( f );
- }
- //if we need to consider this quantifier on this iteration
- if( checkQuant ){
- addedLemmas += exhaustiveInstantiate( f, optUseRelevantDomain() );
- if( Trace.isOn("model-engine-warn") ){
- if( addedLemmas>10000 ){
- Debug("fmf-exit") << std::endl;
- debugPrint("fmf-exit");
- exit( 0 );
+ int e_max = options::fmfFullModelCheck() && options::fmfModelBasedInst() ? 2 : 1;
+ for( int e=0; e<e_max; e++) {
+ if (addedLemmas==0) {
+ for( int i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
+ Node f = fm->getAssertedQuantifier( i );
+ //keep track of total instantiations for statistics
+ int totalInst = 1;
+ for( size_t i=0; i<f[0].getNumChildren(); i++ ){
+ TypeNode tn = f[0][i].getType();
+ if( fm->d_rep_set.hasType( tn ) ){
+ totalInst = totalInst * (int)fm->d_rep_set.d_type_reps[ tn ].size();
+ }
+ }
+ d_totalLemmas += totalInst;
+ //determine if we should check this quantifier
+ if( d_builder->isQuantifierActive( f ) ){
+ addedLemmas += exhaustiveInstantiate( f, e );
+ if( Trace.isOn("model-engine-warn") ){
+ if( addedLemmas>10000 ){
+ Debug("fmf-exit") << std::endl;
+ debugPrint("fmf-exit");
+ exit( 0 );
+ }
+ }
+ if( optOneQuantPerRound() && addedLemmas>0 ){
+ break;
+ }
}
- }
- if( optOneQuantPerRound() && addedLemmas>0 ){
- break;
}
}
}
@@ -222,100 +225,108 @@ int ModelEngine::checkModel( int checkOption ){
return addedLemmas;
}
-int ModelEngine::exhaustiveInstantiate( Node f, bool useRelInstDomain ){
+int ModelEngine::exhaustiveInstantiate( Node f, int effort ){
int addedLemmas = 0;
- 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 ) << " ";
- }
- Debug("inst-fmf-ei") << std::endl;
-
- //create a rep set iterator and iterate over the (relevant) domain of the quantifier
- RepSetIterator riter( &(d_quantEngine->getModel()->d_rep_set) );
- if( riter.setQuantifier( f ) ){
- //set the domain for the iterator (the sufficient set of instantiations to try)
- if( useRelInstDomain ){
- riter.setDomain( d_rel_domain.d_quant_inst_domain[f] );
+ if( !d_builder->doExhaustiveInstantiation( d_quantEngine->getModel(), f, effort, addedLemmas ) ){
+ Trace("inst-fmf-ei") << "Exhaustive instantiate " << f << ", effort = " << effort << "..." << 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 ) << " ";
}
- d_quantEngine->getModel()->resetEvaluate();
- int tests = 0;
- int triedLemmas = 0;
- while( !riter.isFinished() && ( addedLemmas==0 || !optOneInstPerQuantRound() ) ){
- d_testLemmas++;
- int eval = 0;
- int depIndex;
- if( d_builder->optUseModel() ){
- //see if instantiation is already true in current model
- Debug("fmf-model-eval") << "Evaluating ";
- riter.debugPrintSmall("fmf-model-eval");
- Debug("fmf-model-eval") << "Done calculating terms." << std::endl;
- tests++;
- //if evaluate(...)==1, then the instantiation is already true in the model
- // depIndex is the index of the least significant variable that this evaluation relies upon
- depIndex = riter.getNumTerms()-1;
- eval = d_quantEngine->getModel()->evaluate( d_quantEngine->getTermDatabase()->getInstConstantBody( f ), depIndex, &riter );
- if( eval==1 ){
- Debug("fmf-model-eval") << " Returned success with depIndex = " << depIndex << std::endl;
- }else{
- Debug("fmf-model-eval") << " Returned " << (eval==-1 ? "failure" : "unknown") << ", depIndex = " << depIndex << std::endl;
- }
+ Debug("inst-fmf-ei") << std::endl;
+ //create a rep set iterator and iterate over the (relevant) domain of the quantifier
+ RepSetIterator riter( d_quantEngine, &(d_quantEngine->getModel()->d_rep_set) );
+ if( riter.setQuantifier( f ) ){
+ FirstOrderModelIG * fmig = NULL;
+ if( !options::fmfFullModelCheck() ){
+ fmig = (FirstOrderModelIG*)d_quantEngine->getModel();
+ Debug("inst-fmf-ei") << "Reset evaluate..." << std::endl;
+ fmig->resetEvaluate();
}
- if( eval==1 ){
- //instantiation is already true -> skip
- riter.increment2( depIndex );
- }else{
- //instantiation was not shown to be true, construct the match
- InstMatch m;
- for( int i=0; i<riter.getNumTerms(); i++ ){
- m.set( d_quantEngine->getTermDatabase()->getInstantiationConstant( f, riter.d_index_order[i] ), riter.getTerm( i ) );
+ Debug("inst-fmf-ei") << "Begin instantiation..." << std::endl;
+ int tests = 0;
+ int triedLemmas = 0;
+ while( !riter.isFinished() && ( addedLemmas==0 || !optOneInstPerQuantRound() ) ){
+ for( int i=0; i<(int)riter.d_index.size(); i++ ){
+ Trace("try") << i << " : " << riter.d_index[i] << " : " << riter.getTerm( i ) << std::endl;
}
- Debug("fmf-model-eval") << "* Add instantiation " << m << std::endl;
- triedLemmas++;
- d_triedLemmas++;
- //add as instantiation
- if( d_quantEngine->addInstantiation( f, m ) ){
- addedLemmas++;
- //if the instantiation is show to be false, and we wish to skip multiple instantiations at once
- if( eval==-1 && optExhInstEvalSkipMultiple() ){
- riter.increment2( depIndex );
+ d_testLemmas++;
+ int eval = 0;
+ int depIndex;
+ if( d_builder->optUseModel() && fmig ){
+ //see if instantiation is already true in current model
+ Debug("fmf-model-eval") << "Evaluating ";
+ riter.debugPrintSmall("fmf-model-eval");
+ Debug("fmf-model-eval") << "Done calculating terms." << std::endl;
+ tests++;
+ //if evaluate(...)==1, then the instantiation is already true in the model
+ // depIndex is the index of the least significant variable that this evaluation relies upon
+ depIndex = riter.getNumTerms()-1;
+ eval = fmig->evaluate( d_quantEngine->getTermDatabase()->getInstConstantBody( f ), depIndex, &riter );
+ if( eval==1 ){
+ Debug("fmf-model-eval") << " Returned success with depIndex = " << depIndex << std::endl;
}else{
- riter.increment();
+ Debug("fmf-model-eval") << " Returned " << (eval==-1 ? "failure" : "unknown") << ", depIndex = " << depIndex << std::endl;
}
+ }
+ if( eval==1 ){
+ //instantiation is already true -> skip
+ riter.increment2( depIndex );
}else{
- Debug("fmf-model-eval") << "* Failed Add instantiation " << m << std::endl;
- riter.increment();
+ //instantiation was not shown to be true, construct the match
+ InstMatch m;
+ for( int i=0; i<riter.getNumTerms(); i++ ){
+ m.set( d_quantEngine, f, riter.d_index_order[i], riter.getTerm( i ) );
+ }
+ Debug("fmf-model-eval") << "* Add instantiation " << m << std::endl;
+ triedLemmas++;
+ d_triedLemmas++;
+ //add as instantiation
+ if( d_quantEngine->addInstantiation( f, m ) ){
+ addedLemmas++;
+ //if the instantiation is show to be false, and we wish to skip multiple instantiations at once
+ if( eval==-1 && optExhInstEvalSkipMultiple() ){
+ riter.increment2( depIndex );
+ }else{
+ riter.increment();
+ }
+ }else{
+ Debug("fmf-model-eval") << "* Failed Add instantiation " << m << std::endl;
+ riter.increment();
+ }
}
}
+ //print debugging information
+ if( fmig ){
+ d_statistics.d_eval_formulas += fmig->d_eval_formulas;
+ d_statistics.d_eval_uf_terms += fmig->d_eval_uf_terms;
+ d_statistics.d_eval_lits += fmig->d_eval_lits;
+ d_statistics.d_eval_lits_unknown += fmig->d_eval_lits_unknown;
+ }
+ int relevantInst = 1;
+ for( size_t i=0; i<f[0].getNumChildren(); i++ ){
+ relevantInst = relevantInst * (int)riter.d_domain[i].size();
+ }
+ d_relevantLemmas += relevantInst;
+ Trace("inst-fmf-ei") << "Finished: " << std::endl;
+ //Debug("inst-fmf-ei") << " Inst Total: " << totalInst << 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;
+ Trace("model-engine-warn") << " Inst Relevant: " << relevantInst << std::endl;
+ Trace("model-engine-warn") << " Inst Tried: " << triedLemmas << std::endl;
+ Trace("model-engine-warn") << " Inst Added: " << addedLemmas << std::endl;
+ Trace("model-engine-warn") << " # Tests: " << tests << std::endl;
+ Trace("model-engine-warn") << std::endl;
+ }
}
- //print debugging information
- d_statistics.d_eval_formulas += d_quantEngine->getModel()->d_eval_formulas;
- d_statistics.d_eval_uf_terms += d_quantEngine->getModel()->d_eval_uf_terms;
- d_statistics.d_eval_lits += d_quantEngine->getModel()->d_eval_lits;
- d_statistics.d_eval_lits_unknown += d_quantEngine->getModel()->d_eval_lits_unknown;
- int relevantInst = 1;
- for( size_t i=0; i<f[0].getNumChildren(); i++ ){
- relevantInst = relevantInst * (int)riter.d_domain[i].size();
- }
- d_relevantLemmas += relevantInst;
- Trace("inst-fmf-ei") << "Finished: " << std::endl;
- //Debug("inst-fmf-ei") << " Inst Total: " << totalInst << 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;
- Trace("model-engine-warn") << " Inst Relevant: " << relevantInst << std::endl;
- Trace("model-engine-warn") << " Inst Tried: " << triedLemmas << std::endl;
- Trace("model-engine-warn") << " Inst Added: " << addedLemmas << std::endl;
- Trace("model-engine-warn") << " # Tests: " << tests << std::endl;
- Trace("model-engine-warn") << std::endl;
- }
+ //if the iterator is incomplete, we will return unknown instead of sat if no instantiations are added this round
+ d_incomplete_check = d_incomplete_check || riter.d_incomplete;
}
- //if the iterator is incomplete, we will return unknown instead of sat if no instantiations are added this round
- d_incomplete_check = d_incomplete_check || riter.d_incomplete;
return addedLemmas;
}
diff --git a/src/theory/quantifiers/model_engine.h b/src/theory/quantifiers/model_engine.h
index 386864164..0f0ab4fe7 100644
--- a/src/theory/quantifiers/model_engine.h
+++ b/src/theory/quantifiers/model_engine.h
@@ -20,7 +20,7 @@
#include "theory/quantifiers_engine.h"
#include "theory/quantifiers/model_builder.h"
#include "theory/model.h"
-#include "theory/quantifiers/relevant_domain.h"
+#include "theory/quantifiers/full_model_check.h"
namespace CVC4 {
namespace theory {
@@ -31,10 +31,8 @@ class ModelEngine : public QuantifiersModule
friend class RepSetIterator;
private:
/** builder class */
- ModelEngineBuilder* d_builder;
+ QModelBuilder* d_builder;
private: //analysis of current model:
- //relevant domain
- RelevantDomain d_rel_domain;
//is the exhaustive instantiation incomplete?
bool d_incomplete_check;
private:
@@ -44,14 +42,10 @@ private:
bool optOneQuantPerRound();
bool optExhInstEvalSkipMultiple();
private:
- enum{
- check_model_full,
- check_model_no_inst_gen,
- };
//check model
- int checkModel( int checkOption );
+ int checkModel();
//exhaustively instantiate quantifier (possibly using mbqi), return number of lemmas produced
- int exhaustiveInstantiate( Node f, bool useRelInstDomain = false );
+ int exhaustiveInstantiate( Node f, int effort = 0 );
private:
//temporary statistics
int d_triedLemmas;
@@ -62,7 +56,7 @@ public:
ModelEngine( context::Context* c, QuantifiersEngine* qe );
~ModelEngine(){}
//get the builder
- ModelEngineBuilder* getModelBuilder() { return d_builder; }
+ QModelBuilder* getModelBuilder() { return d_builder; }
public:
void check( Theory::Effort e );
void registerQuantifier( Node f );
diff --git a/src/theory/quantifiers/options b/src/theory/quantifiers/options
index 60f5a171d..e83014789 100644
--- a/src/theory/quantifiers/options
+++ b/src/theory/quantifiers/options
@@ -47,6 +47,9 @@ option aggressiveMiniscopeQuant --ag-miniscope-quant bool :default false
# Whether to perform quantifier macro expansion
option macrosQuant --macros-quant bool :default false
perform quantifiers macro expansions
+# Whether to perform first-order propagation
+option foPropQuant --fo-prop-quant bool :default false
+ perform first-order propagation on quantifiers
# Whether to use smart triggers
option smartTriggers /--disable-smart-triggers bool :default true
@@ -54,6 +57,8 @@ option smartTriggers /--disable-smart-triggers bool :default true
# Whether to use relevent triggers
option relevantTriggers /--disable-relevant-triggers bool :default true
prefer triggers that are more relevant based on SInE style analysis
+option relationalTriggers --relational-triggers bool :default false
+ choose relational triggers such as x = f(y), x >= f(y)
# Whether to consider terms in the bodies of quantifiers for matching
option registerQuantBodyTerms --register-quant-body-terms bool :default false
@@ -88,6 +93,11 @@ option finiteModelFind --finite-model-find bool :default false
option fmfModelBasedInst /--disable-fmf-mbqi bool :default true
disable model-based quantifier instantiation for finite model finding
+option fmfFullModelCheck --fmf-fmc bool :default false
+ enable full model check for finite model finding
+option fmfFullModelCheckSimple /--disable-fmf-fmc-simple bool :default true
+ disable simple models in full model check for finite model finding
+
option fmfOneInstPerRound --fmf-one-inst-per-round bool :default false
only add one instantiation per quantifier per round for fmf
option fmfOneQuantPerRound --fmf-one-quant-per-round bool :default false
@@ -98,13 +108,17 @@ option fmfRelevantDomain --fmf-relevant-domain bool :default false
use relevant domain computation, similar to complete instantiation (Ge, deMoura 09)
option fmfNewInstGen --fmf-new-inst-gen bool :default false
use new inst gen technique for answering sat without exhaustive instantiation
-option fmfInstGen /--disable-fmf-inst-gen bool :default true
- disable Inst-Gen instantiation techniques for finite model finding
+option fmfInstGen --fmf-inst-gen/--disable-fmf-inst-gen bool :read-write :default true
+ enable Inst-Gen instantiation techniques for finite model finding (default)
+/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 fmfBoundInt --fmf-bound-int bool :default false
+ finite model finding on bounded integer quantification
+
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 36db56d0d..59995a510 100644
--- a/src/theory/quantifiers/quant_util.cpp
+++ b/src/theory/quantifiers/quant_util.cpp
@@ -22,6 +22,102 @@ using namespace CVC4::kind;
using namespace CVC4::context;
using namespace CVC4::theory;
+
+bool QuantArith::getMonomial( Node n, std::map< Node, Node >& msum ) {
+ if ( n.getKind()==MULT ){
+ if( n.getNumChildren()==2 && msum.find(n[1])==msum.end() && n[0].isConst() ){
+ msum[n[1]] = n[0];
+ return true;
+ }
+ }else{
+ if( msum.find(n)==msum.end() ){
+ msum[n] = Node::null();
+ return true;
+ }
+ }
+ return false;
+}
+
+bool QuantArith::getMonomialSum( Node n, std::map< Node, Node >& msum ) {
+ if ( n.getKind()==PLUS ){
+ for( unsigned i=0; i<n.getNumChildren(); i++) {
+ if (!getMonomial( n[i], msum )){
+ return false;
+ }
+ }
+ return true;
+ }else{
+ return getMonomial( n, msum );
+ }
+}
+
+bool QuantArith::getMonomialSumLit( Node lit, std::map< Node, Node >& msum ) {
+ if( lit.getKind()==GEQ || lit.getKind()==EQUAL ){
+ if( getMonomialSum( lit[0], msum ) ){
+ if( lit[1].isConst() ){
+ if( !lit[1].getConst<Rational>().isZero() ){
+ msum[Node::null()] = negate( lit[1] );
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool QuantArith::isolate( Node v, std::map< Node, Node >& msum, Node & veq, Kind k ) {
+ if( msum.find(v)!=msum.end() ){
+ std::vector< Node > children;
+ Rational r = msum[v].isNull() ? Rational(1) : msum[v].getConst<Rational>();
+ if ( r.sgn()!=0 ){
+ for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){
+ if( it->first.isNull() || it->first!=v ){
+ Node m;
+ if( !it->first.isNull() ){
+ if ( !it->second.isNull() ){
+ m = NodeManager::currentNM()->mkNode( MULT, it->second, it->first );
+ }else{
+ m = it->first;
+ }
+ }else{
+ m = it->second;
+ }
+ children.push_back(m);
+ }
+ }
+ veq = children.size()>1 ? NodeManager::currentNM()->mkNode( PLUS, children ) :
+ (children.size()==1 ? children[0] : NodeManager::currentNM()->mkConst( Rational(0) ));
+ if( !r.isNegativeOne() ){
+ if( r.isOne() ){
+ veq = negate(veq);
+ }else{
+ //TODO
+ return false;
+ }
+ }
+ veq = Rewriter::rewrite( veq );
+ veq = NodeManager::currentNM()->mkNode( k, r.sgn()==1 ? v : veq, r.sgn()==1 ? veq : v );
+ return true;
+ }
+ return false;
+ }else{
+ return false;
+ }
+}
+
+Node QuantArith::negate( Node t ) {
+ Node tt = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkConst( Rational(-1) ), t );
+ tt = Rewriter::rewrite( tt );
+ return tt;
+}
+
+Node QuantArith::offset( Node t, int i ) {
+ Node tt = NodeManager::currentNM()->mkNode( PLUS, NodeManager::currentNM()->mkConst( Rational(i) ), t );
+ tt = Rewriter::rewrite( tt );
+ return tt;
+}
+
+
void QuantRelevance::registerQuantifier( Node f ){
//compute symbols in f
std::vector< Node > syms;
@@ -93,13 +189,13 @@ QuantPhaseReq::QuantPhaseReq( Node n, bool 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()) ){
+ if( quantifiers::TermDb::hasInstConstAttr(it->first[0]) ){
+ if( !quantifiers::TermDb::hasInstConstAttr(it->first[1]) ){
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()) ){
+ }else if( quantifiers::TermDb::hasInstConstAttr(it->first[1]) ){
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;
diff --git a/src/theory/quantifiers/quant_util.h b/src/theory/quantifiers/quant_util.h
index 6a5726cc7..86c7bc3a0 100644
--- a/src/theory/quantifiers/quant_util.h
+++ b/src/theory/quantifiers/quant_util.h
@@ -28,6 +28,18 @@ namespace CVC4 {
namespace theory {
+class QuantArith
+{
+public:
+ static bool getMonomial( Node n, std::map< Node, Node >& msum );
+ static bool getMonomialSum( Node n, std::map< Node, Node >& msum );
+ static bool getMonomialSumLit( Node lit, std::map< Node, Node >& msum );
+ static bool isolate( Node v, std::map< Node, Node >& msum, Node & veq, Kind k );
+ static Node negate( Node t );
+ static Node offset( Node t, int i );
+};
+
+
class QuantRelevance
{
private:
diff --git a/src/theory/quantifiers/quantifiers_rewriter.cpp b/src/theory/quantifiers/quantifiers_rewriter.cpp
index 5c71f6e6f..9f156b656 100644
--- a/src/theory/quantifiers/quantifiers_rewriter.cpp
+++ b/src/theory/quantifiers/quantifiers_rewriter.cpp
@@ -211,10 +211,6 @@ RewriteResponse QuantifiersRewriter::postRewrite(TNode in) {
if( in.hasAttribute(NestedQuantAttribute()) ){
setNestedQuantifiers( ret, in.getAttribute(NestedQuantAttribute()) );
}
- if( in.hasAttribute(InstConstantAttribute()) ){
- InstConstantAttribute ica;
- ret.setAttribute(ica,in.getAttribute(InstConstantAttribute()) );
- }
Trace("quantifiers-rewrite") << "*** rewrite " << in << std::endl;
Trace("quantifiers-rewrite") << " to " << std::endl;
Trace("quantifiers-rewrite") << ret << std::endl;
diff --git a/src/theory/quantifiers/relevant_domain.cpp b/src/theory/quantifiers/relevant_domain.cpp
deleted file mode 100644
index 2b011552c..000000000
--- a/src/theory/quantifiers/relevant_domain.cpp
+++ /dev/null
@@ -1,198 +0,0 @@
-/********************* */
-/*! \file relevant_domain.cpp
- ** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-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 relevant domain class
- **/
-
-#include "theory/quantifiers_engine.h"
-#include "theory/quantifiers/relevant_domain.h"
-#include "theory/quantifiers/term_database.h"
-#include "theory/quantifiers/first_order_model.h"
-
-using namespace std;
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::quantifiers;
-
-RelevantDomain::RelevantDomain( QuantifiersEngine* qe, FirstOrderModel* m ) : d_qe( qe ), d_model( m ){
-
-}
-
-void RelevantDomain::compute(){
- Trace("rel-dom") << "compute relevant domain" << std::endl;
- d_quant_inst_domain.clear();
- for( int i=0; i<(int)d_model->getNumAssertedQuantifiers(); i++ ){
- Node f = d_model->getAssertedQuantifier( i );
- d_quant_inst_domain[f].resize( f[0].getNumChildren() );
- }
- Trace("rel-dom") << "account for ground terms" << std::endl;
- //add ground terms to domain (rule 1 of complete instantiation essentially uf fragment)
- for( std::map< Node, uf::UfModelTree >::iterator it = d_model->d_uf_model_tree.begin();
- it != d_model->d_uf_model_tree.end(); ++it ){
- Node op = it->first;
- for( size_t i=0; i<d_model->d_uf_terms[op].size(); i++ ){
- Node n = d_model->d_uf_terms[op][i];
- //add arguments to domain
- for( int j=0; j<(int)n.getNumChildren(); j++ ){
- if( d_model->d_rep_set.hasType( n[j].getType() ) ){
- Node ra = d_model->getRepresentative( n[j] );
- int raIndex = d_model->d_rep_set.getIndexFor( ra );
- if( raIndex==-1 ) Trace("rel-dom-warn") << "WARNING: Ground domain: rep set does not contain : " << ra << std::endl;
- Assert( raIndex!=-1 );
- if( std::find( d_active_domain[op][j].begin(), d_active_domain[op][j].end(), raIndex )==d_active_domain[op][j].end() ){
- d_active_domain[op][j].push_back( raIndex );
- }
- }
- }
- //add to range
- Node r = d_model->getRepresentative( n );
- int raIndex = d_model->d_rep_set.getIndexFor( r );
- if( raIndex==-1 ) Trace("rel-dom-warn") << "WARNING: Ground range: rep set does not contain : " << r << std::endl;
- Assert( raIndex!=-1 );
- if( std::find( d_active_range[op].begin(), d_active_range[op].end(), raIndex )==d_active_range[op].end() ){
- d_active_range[op].push_back( raIndex );
- }
- }
- }
- Trace("rel-dom") << "do quantifiers" << std::endl;
- //find fixed point for relevant domain computation
- bool success;
- do{
- success = true;
- for( int i=0; i<(int)d_model->getNumAssertedQuantifiers(); i++ ){
- Node f = d_model->getAssertedQuantifier( i );
- //compute the domain of relevant instantiations (rule 3 of complete instantiation, essentially uf fragment)
- if( computeRelevantInstantiationDomain( d_qe->getTermDatabase()->getInstConstantBody( f ), Node::null(), -1, f ) ){
- success = false;
- }
- //extend the possible domain for functions (rule 2 of complete instantiation, essentially uf fragment)
- RepDomain range;
- if( extendFunctionDomains( d_qe->getTermDatabase()->getInstConstantBody( f ), range ) ){
- success = false;
- }
- }
- }while( !success );
- Trace("rel-dom") << "done compute relevant domain" << std::endl;
- /*
- //debug printing
- Trace("rel-dom") << "Exhaustive instantiate " << f << std::endl;
- if( useRelInstDomain ){
- Trace("rel-dom") << "Relevant domain : " << std::endl;
- for( size_t i=0; i<d_rel_domain.d_quant_inst_domain[f].size(); i++ ){
- Trace("rel-dom") << " " << i << " : ";
- for( size_t j=0; j<d_rel_domain.d_quant_inst_domain[f][i].size(); j++ ){
- Trace("rel-dom") << d_rel_domain.d_quant_inst_domain[f][i][j] << " ";
- }
- Trace("rel-dom") << std::endl;
- }
- }
- */
-}
-
-bool RelevantDomain::computeRelevantInstantiationDomain( Node n, Node parent, int arg, Node f ){
- bool domainChanged = false;
- if( n.getKind()==INST_CONSTANT ){
- bool domainSet = false;
- int vi = n.getAttribute(InstVarNumAttribute());
- Assert( !parent.isNull() );
- if( parent.getKind()==APPLY_UF ){
- //if the child of APPLY_UF term f( ... ), only consider the active domain of f at given argument
- Node op = parent.getOperator();
- if( d_active_domain.find( op )!=d_active_domain.end() ){
- for( size_t i=0; i<d_active_domain[op][arg].size(); i++ ){
- int d = d_active_domain[op][arg][i];
- if( std::find( d_quant_inst_domain[f][vi].begin(), d_quant_inst_domain[f][vi].end(), d )==
- d_quant_inst_domain[f][vi].end() ){
- d_quant_inst_domain[f][vi].push_back( d );
- domainChanged = true;
- }
- }
- domainSet = true;
- }
- }
- if( !domainSet ){
- //otherwise, we must consider the entire domain
- TypeNode tn = n.getType();
- if( d_quant_inst_domain_complete[f].find( vi )==d_quant_inst_domain_complete[f].end() ){
- if( d_model->d_rep_set.hasType( tn ) ){
- //it is the complete domain
- d_quant_inst_domain[f][vi].clear();
- for( size_t i=0; i<d_model->d_rep_set.d_type_reps[tn].size(); i++ ){
- d_quant_inst_domain[f][vi].push_back( i );
- }
- domainChanged = true;
- }
- d_quant_inst_domain_complete[f][vi] = true;
- }
- }
- }else{
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( computeRelevantInstantiationDomain( n[i], n, i, f ) ){
- domainChanged = true;
- }
- }
- }
- return domainChanged;
-}
-
-bool RelevantDomain::extendFunctionDomains( Node n, RepDomain& range ){
- if( n.getKind()==INST_CONSTANT ){
- Node f = n.getAttribute(InstConstantAttribute());
- int var = n.getAttribute(InstVarNumAttribute());
- range.insert( range.begin(), d_quant_inst_domain[f][var].begin(), d_quant_inst_domain[f][var].end() );
- return false;
- }else{
- Node op;
- if( n.getKind()==APPLY_UF ){
- op = n.getOperator();
- }
- bool domainChanged = false;
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- RepDomain childRange;
- if( extendFunctionDomains( n[i], childRange ) ){
- domainChanged = true;
- }
- if( n.getKind()==APPLY_UF ){
- if( d_active_domain.find( op )!=d_active_domain.end() ){
- for( int j=0; j<(int)childRange.size(); j++ ){
- int v = childRange[j];
- if( std::find( d_active_domain[op][i].begin(), d_active_domain[op][i].end(), v )==d_active_domain[op][i].end() ){
- d_active_domain[op][i].push_back( v );
- domainChanged = true;
- }
- }
- }else{
- //do this?
- }
- }
- }
- //get the range
- if( n.hasAttribute(InstConstantAttribute()) ){
- if( n.getKind()==APPLY_UF && d_active_range.find( op )!=d_active_range.end() ){
- range.insert( range.end(), d_active_range[op].begin(), d_active_range[op].end() );
- }else{
- //infinite range?
- }
- }else{
- Node r = d_model->getRepresentative( n );
- int index = d_model->d_rep_set.getIndexFor( r );
- if( index==-1 ){
- //we consider all ground terms in bodies of quantifiers to be the first ground representative
- range.push_back( 0 );
- }else{
- range.push_back( index );
- }
- }
- return domainChanged;
- }
-} \ No newline at end of file
diff --git a/src/theory/quantifiers/relevant_domain.h b/src/theory/quantifiers/relevant_domain.h
deleted file mode 100644
index 6fc035e8a..000000000
--- a/src/theory/quantifiers/relevant_domain.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/********************* */
-/*! \file relevant_domain.h
- ** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2013 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief relevant domain class
- **/
-
-#include "cvc4_private.h"
-
-#ifndef __CVC4__THEORY__QUANTIFIERS__RELEVANT_DOMAIN_H
-#define __CVC4__THEORY__QUANTIFIERS__RELEVANT_DOMAIN_H
-
-#include "theory/quantifiers/first_order_model.h"
-
-namespace CVC4 {
-namespace theory {
-namespace quantifiers {
-
-class RelevantDomain
-{
-private:
- QuantifiersEngine* d_qe;
- FirstOrderModel* d_model;
-
- //the domain of the arguments for each operator
- std::map< Node, std::map< int, RepDomain > > d_active_domain;
- //the range for each operator
- std::map< Node, RepDomain > d_active_range;
- //for computing relevant instantiation domain, return true if changed
- bool computeRelevantInstantiationDomain( Node n, Node parent, int arg, Node f );
- //for computing extended
- bool extendFunctionDomains( Node n, RepDomain& range );
-public:
- RelevantDomain( QuantifiersEngine* qe, FirstOrderModel* m );
- virtual ~RelevantDomain(){}
- //compute the relevant domain
- void compute();
- //relevant instantiation domain for each quantifier
- std::map< Node, std::vector< RepDomain > > d_quant_inst_domain;
- std::map< Node, std::map< int, bool > > d_quant_inst_domain_complete;
-};/* class RelevantDomain */
-
-}/* CVC4::theory::quantifiers namespace */
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
-
-#endif /* __CVC4__THEORY__QUANTIFIERS__RELEVANT_DOMAIN_H */
diff --git a/src/theory/quantifiers/term_database.cpp b/src/theory/quantifiers/term_database.cpp
index 3153a3c64..dc00b5f95 100644
--- a/src/theory/quantifiers/term_database.cpp
+++ b/src/theory/quantifiers/term_database.cpp
@@ -74,7 +74,7 @@ void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant ){
//if this is an atomic trigger, consider adding it
//Call the children?
if( inst::Trigger::isAtomicTrigger( n ) ){
- if( !n.hasAttribute(InstConstantAttribute()) ){
+ if( !TermDb::hasInstConstAttr(n) ){
Trace("term-db") << "register term in db " << n << std::endl;
//std::cout << "register trigger term " << n << std::endl;
Node op = n.getOperator();
@@ -117,7 +117,7 @@ void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant ){
}
}
}else{
- if( options::efficientEMatching() && !n.hasAttribute(InstConstantAttribute())){
+ if( options::efficientEMatching() && !TermDb::hasInstConstAttr(n)){
//Efficient e-matching must be notified
//The term in triggers are not important here
Debug("term-db") << "New in this branch term " << n << std::endl;
@@ -167,7 +167,7 @@ void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant ){
while( !eqc.isFinished() ){
Node en = (*eqc);
computeModelBasisArgAttribute( en );
- if( en.getKind()==APPLY_UF && !en.hasAttribute(InstConstantAttribute()) ){
+ if( en.getKind()==APPLY_UF && !TermDb::hasInstConstAttr(en) ){
if( !en.getAttribute(NoMatchAttribute()) ){
Node op = en.getOperator();
if( !d_pred_map_trie[i][op].addTerm( d_quantEngine, en ) ){
@@ -254,8 +254,7 @@ void TermDb::computeModelBasisArgAttribute( Node n ){
//determine if it has model basis attribute
for( int j=0; j<(int)n.getNumChildren(); j++ ){
if( n[j].getAttribute(ModelBasisAttribute()) ){
- val = 1;
- break;
+ val++;
}
}
ModelBasisArgAttribute mbaa;
@@ -276,33 +275,75 @@ void TermDb::makeInstantiationConstantsFor( Node f ){
//set the var number attribute
InstVarNumAttribute ivna;
ic.setAttribute(ivna,i);
+ InstConstantAttribute ica;
+ ic.setAttribute(ica,f);
+ //also set the no-match attribute
+ NoMatchAttribute nma;
+ ic.setAttribute(nma,true);
}
}
}
-void TermDb::setInstantiationConstantAttr( Node n, Node f ){
- if( !n.hasAttribute(InstConstantAttribute()) ){
- bool setAttr = false;
- if( n.getKind()==INST_CONSTANT ){
- setAttr = true;
- }else{
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- setInstantiationConstantAttr( n[i], f );
- if( n[i].hasAttribute(InstConstantAttribute()) ){
- setAttr = true;
- }
+
+Node TermDb::getInstConstAttr( Node n ) {
+ if (!n.hasAttribute(InstConstantAttribute()) ){
+ Node f;
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ f = getInstConstAttr(n[i]);
+ if( !f.isNull() ){
+ break;
}
}
- if( setAttr ){
- InstConstantAttribute ica;
- n.setAttribute(ica,f);
+ InstConstantAttribute ica;
+ n.setAttribute(ica,f);
+ if( !f.isNull() ){
//also set the no-match attribute
NoMatchAttribute nma;
n.setAttribute(nma,true);
}
}
+ return n.getAttribute(InstConstantAttribute());
}
+bool TermDb::hasInstConstAttr( Node n ) {
+ return !getInstConstAttr(n).isNull();
+}
+
+bool TermDb::hasBoundVarAttr( Node n ) {
+ if( !n.getAttribute(HasBoundVarComputedAttribute()) ){
+ bool hasBv = false;
+ if( n.getKind()==BOUND_VARIABLE ){
+ hasBv = true;
+ }else{
+ for (unsigned i=0; i<n.getNumChildren(); i++) {
+ if( hasBoundVarAttr(n[i]) ){
+ hasBv = true;
+ break;
+ }
+ }
+ }
+ HasBoundVarAttribute hbva;
+ n.setAttribute(hbva, hasBv);
+ HasBoundVarComputedAttribute hbvca;
+ n.setAttribute(hbvca, true);
+ Trace("bva") << n << " has bva : " << n.getAttribute(HasBoundVarAttribute()) << std::endl;
+ }
+ return n.getAttribute(HasBoundVarAttribute());
+}
+
+void TermDb::getBoundVars( Node n, std::vector< Node >& bvs) {
+ if (n.getKind()==BOUND_VARIABLE ){
+ if ( std::find( bvs.begin(), bvs.end(), n)==bvs.end() ){
+ bvs.push_back( n );
+ }
+ }else{
+ for( unsigned i=0; i<n.getNumChildren(); i++) {
+ getBoundVars(n[i], bvs);
+ }
+ }
+}
+
+
/** get the i^th instantiation constant of f */
Node TermDb::getInstantiationConstant( Node f, int i ) const {
std::map< Node, std::vector< Node > >::const_iterator it = d_inst_constants.find( f );
@@ -348,7 +389,6 @@ Node TermDb::getCounterexampleLiteral( Node f ){
//otherwise, ensure literal
Node ceLit = d_quantEngine->getValuation().ensureLiteral( ceBody.notNode() );
d_ce_lit[ f ] = ceLit;
- setInstantiationConstantAttr( ceLit, f );
}
return d_ce_lit[ f ];
}
@@ -362,7 +402,6 @@ Node TermDb::convertNodeToPattern( Node n, Node f, const std::vector<Node> & var
Node n2 = n.substitute( vars.begin(), vars.end(),
inst_constants.begin(),
inst_constants.end() );
- setInstantiationConstantAttr( n2, f );
return n2;
}
diff --git a/src/theory/quantifiers/term_database.h b/src/theory/quantifiers/term_database.h
index 231d0ee9e..7b5df2ab8 100644
--- a/src/theory/quantifiers/term_database.h
+++ b/src/theory/quantifiers/term_database.h
@@ -59,6 +59,10 @@ typedef expr::Attribute<ModelBasisAttributeId, bool> ModelBasisAttribute;
struct ModelBasisArgAttributeId {};
typedef expr::Attribute<ModelBasisArgAttributeId, uint64_t> ModelBasisArgAttribute;
+struct HasBoundVarAttributeId {};
+typedef expr::Attribute<HasBoundVarAttributeId, bool> HasBoundVarAttribute;
+struct HasBoundVarComputedAttributeId {};
+typedef expr::Attribute<HasBoundVarComputedAttributeId, bool> HasBoundVarComputedAttribute;
class QuantifiersEngine;
@@ -83,10 +87,15 @@ public:
};/* class TermArgTrie */
+namespace fmcheck {
+ class FullModelChecker;
+}
+
class TermDb {
friend class ::CVC4::theory::QuantifiersEngine;
friend class ::CVC4::theory::inst::Trigger;
friend class ::CVC4::theory::rrinst::Trigger;
+ friend class ::CVC4::theory::quantifiers::fmcheck::FullModelChecker;
private:
/** reference to the quantifiers engine */
QuantifiersEngine* d_quantEngine;
@@ -181,9 +190,15 @@ public:
Node convertNodeToPattern( Node n, Node f,
const std::vector<Node> & vars,
const std::vector<Node> & nvars);
- /** set instantiation constant attr */
- void setInstantiationConstantAttr( Node n, Node f );
+ static Node getInstConstAttr( Node n );
+ static bool hasInstConstAttr( Node n );
+//for bound variables
+public:
+ //does n have bound variables?
+ static bool hasBoundVarAttr( Node n );
+ //get bound variables in n
+ static void getBoundVars( Node n, std::vector< Node >& bvs);
//for skolem
private:
/** map from universal quantifiers to the list of skolem constants */
diff --git a/src/theory/quantifiers/theory_quantifiers.cpp b/src/theory/quantifiers/theory_quantifiers.cpp
index 9843cd09e..c68623baa 100644
--- a/src/theory/quantifiers/theory_quantifiers.cpp
+++ b/src/theory/quantifiers/theory_quantifiers.cpp
@@ -65,7 +65,7 @@ void TheoryQuantifiers::notifyEq(TNode lhs, TNode rhs) {
void TheoryQuantifiers::preRegisterTerm(TNode n) {
Debug("quantifiers-prereg") << "TheoryQuantifiers::preRegisterTerm() " << n << endl;
- if( n.getKind()==FORALL && !n.hasAttribute(InstConstantAttribute()) ){
+ if( n.getKind()==FORALL && !TermDb::hasInstConstAttr(n) ){
getQuantifiersEngine()->registerQuantifier( n );
}
}
@@ -149,7 +149,7 @@ Node TheoryQuantifiers::getNextDecisionRequest(){
void TheoryQuantifiers::assertUniversal( Node n ){
Assert( n.getKind()==FORALL );
- if( !n.hasAttribute(InstConstantAttribute()) ){
+ if( !TermDb::hasInstConstAttr(n) ){
getQuantifiersEngine()->registerQuantifier( n );
getQuantifiersEngine()->assertNode( n );
}
@@ -157,7 +157,7 @@ void TheoryQuantifiers::assertUniversal( Node n ){
void TheoryQuantifiers::assertExistential( Node n ){
Assert( n.getKind()== NOT && n[0].getKind()==FORALL );
- if( !n[0].hasAttribute(InstConstantAttribute()) ){
+ if( !TermDb::hasInstConstAttr(n[0]) ){
if( d_skolemized.find( n )==d_skolemized.end() ){
Node body = getQuantifiersEngine()->getTermDatabase()->getSkolemizedBody( n[0] );
NodeBuilder<> nb(kind::OR);
diff --git a/src/theory/quantifiers/trigger.cpp b/src/theory/quantifiers/trigger.cpp
index cab94fb5c..fea8ab6d5 100644
--- a/src/theory/quantifiers/trigger.cpp
+++ b/src/theory/quantifiers/trigger.cpp
@@ -28,8 +28,6 @@ using namespace CVC4::context;
using namespace CVC4::theory;
using namespace CVC4::theory::inst;
-//#define NESTED_PATTERN_SELECTION
-
/** trigger class constructor */
Trigger::Trigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool smartTriggers ) :
d_quantEngine( qe ), d_f( f ){
@@ -126,7 +124,7 @@ Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >&
qe->getTermDatabase()->computeVarContains( temp[i] );
for( int j=0; j<(int)qe->getTermDatabase()->d_var_contains[ temp[i] ].size(); j++ ){
Node v = qe->getTermDatabase()->d_var_contains[ temp[i] ][j];
- if( v.getAttribute(InstConstantAttribute())==f ){
+ if( quantifiers::TermDb::getInstConstAttr(v)==f ){
if( vars.find( v )==vars.end() ){
varCount++;
vars[ v ] = true;
@@ -225,7 +223,7 @@ bool Trigger::isUsableTrigger( std::vector< Node >& nodes, Node f ){
}
bool Trigger::isUsable( Node n, Node f ){
- if( n.getAttribute(InstConstantAttribute())==f ){
+ if( quantifiers::TermDb::getInstConstAttr(n)==f ){
if( isAtomicTrigger( n ) ){
for( int i=0; i<(int)n.getNumChildren(); i++ ){
if( !isUsable( n[i], f ) ){
@@ -249,11 +247,71 @@ bool Trigger::isUsable( Node n, Node f ){
}
}
-bool Trigger::isUsableTrigger( Node n, Node f ){
- //return n.getAttribute(InstConstantAttribute())==f && n.getKind()==APPLY_UF;
- bool usable = n.getAttribute(InstConstantAttribute())==f && isAtomicTrigger( n ) && isUsable( n, f );
+bool nodeContainsVar( Node n, Node v ){
+ if( n==v) {
+ return true;
+ }else{
+ for( unsigned i=0; i<n.getNumChildren(); i++) {
+ if( nodeContainsVar(n[i], v) ){
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+Node Trigger::getIsUsableTrigger( Node n, Node f, bool pol, bool hasPol ) {
+ if( options::relationalTriggers() ){
+ if( n.getKind()==EQUAL || n.getKind()==IFF || n.getKind()==GEQ ){
+ Node rtr;
+ for( unsigned i=0; i<2; i++) {
+ unsigned j = (i==0) ? 1 : 0;
+ if( n[j].getKind()==INST_CONSTANT && isUsableTrigger(n[i], f) && !nodeContainsVar( n[i], n[j] ) ) {
+ rtr = n;
+ break;
+ }
+ }
+ if( n[0].getType().isInteger() ){
+ //try to rearrange?
+ std::map< Node, Node > m;
+ if (QuantArith::getMonomialSumLit(n, m) ){
+ for( std::map< Node, Node >::iterator it = m.begin(); it!=m.end(); ++it ){
+ if( !it->first.isNull() && it->first.getKind()==INST_CONSTANT ){
+ Node veq;
+ if( QuantArith::isolate( it->first, m, veq, n.getKind() ) ){
+ int vti = veq[0]==it->first ? 1 : 0;
+ if( isUsableTrigger(veq[vti], f) && !nodeContainsVar( veq[vti], veq[vti==0 ? 1 : 0]) ){
+ rtr = veq;
+ }
+ }
+ }
+ }
+ }
+ }
+ if( !rtr.isNull() ){
+ Trace("relational-trigger") << "Relational trigger : " << std::endl;
+ Trace("relational-trigger") << " " << rtr << " (from " << n << ")" << std::endl;
+ Trace("relational-trigger") << " in quantifier " << f << std::endl;
+ if( hasPol ){
+ Trace("relational-trigger") << " polarity : " << pol << std::endl;
+ }
+ Node rtr2 = (hasPol && pol) ? rtr.negate() : rtr;
+ return rtr2;
+ }
+ }
+ }
+ bool usable = quantifiers::TermDb::getInstConstAttr(n)==f && isAtomicTrigger( n ) && isUsable( n, f );
Trace("usable") << n << " usable : " << usable << std::endl;
- return usable;
+ if( usable ){
+ return n;
+ }else{
+ return Node::null();
+ }
+}
+
+bool Trigger::isUsableTrigger( Node n, Node f ){
+ Node nu = getIsUsableTrigger(n,f);
+ return !nu.isNull();
}
bool Trigger::isAtomicTrigger( Node n ){
@@ -263,7 +321,7 @@ bool Trigger::isAtomicTrigger( Node n ){
bool Trigger::isSimpleTrigger( Node n ){
if( isAtomicTrigger( n ) ){
for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( n[i].getKind()!=INST_CONSTANT && n[i].hasAttribute(InstConstantAttribute()) ){
+ if( n[i].getKind()!=INST_CONSTANT && quantifiers::TermDb::hasInstConstAttr(n[i]) ){
return false;
}
}
@@ -274,55 +332,51 @@ bool Trigger::isSimpleTrigger( Node n ){
}
-bool Trigger::collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt ){
+bool Trigger::collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt, bool pol, bool hasPol ){
if( patMap.find( n )==patMap.end() ){
patMap[ n ] = false;
+ bool newHasPol = (n.getKind()==IFF || n.getKind()==XOR) ? false : hasPol;
+ bool newPol = n.getKind()==NOT ? !pol : pol;
if( tstrt==TS_MIN_TRIGGER ){
if( n.getKind()==FORALL ){
-#ifdef NESTED_PATTERN_SELECTION
- //return collectPatTerms2( qe, f, qe->getOrCreateCounterexampleBody( n ), patMap, tstrt );
- return collectPatTerms2( qe, f, qe->getBoundBody( n ), patMap, tstrt );
-#else
return false;
-#endif
}else{
bool retVal = false;
for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( collectPatTerms2( qe, f, n[i], patMap, tstrt ) ){
+ bool newPol2 = (n.getKind()==IMPLIES && i==0) ? !newPol : newPol;
+ bool newHasPol2 = (n.getKind()==ITE && i==0) ? false : newHasPol;
+ if( collectPatTerms2( qe, f, n[i], patMap, tstrt, newPol2, newHasPol2 ) ){
retVal = true;
}
}
if( retVal ){
return true;
- }else if( isUsableTrigger( n, f ) ){
- patMap[ n ] = true;
- return true;
}else{
- return false;
+ Node nu = getIsUsableTrigger( n, f, pol, hasPol );
+ if( !nu.isNull() ){
+ patMap[ nu ] = true;
+ return true;
+ }else{
+ return false;
+ }
}
}
}else{
bool retVal = false;
- if( isUsableTrigger( n, f ) ){
- patMap[ n ] = true;
+ Node nu = getIsUsableTrigger( n, f, pol, hasPol );
+ if( !nu.isNull() ){
+ patMap[ nu ] = true;
if( tstrt==TS_MAX_TRIGGER ){
return true;
}else{
retVal = true;
}
}
- if( n.getKind()==FORALL ){
-#ifdef NESTED_PATTERN_SELECTION
- //if( collectPatTerms2( qe, f, qe->getOrCreateCounterexampleBody( n ), patMap, tstrt ) ){
- // retVal = true;
- //}
- if( collectPatTerms2( qe, f, qe->getBoundBody( n ), patMap, tstrt ) ){
- retVal = true;
- }
-#endif
- }else{
+ if( n.getKind()!=FORALL ){
for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( collectPatTerms2( qe, f, n[i], patMap, tstrt ) ){
+ bool newPol2 = (n.getKind()==IMPLIES && i==0) ? !newPol : newPol;
+ bool newHasPol2 = (n.getKind()==ITE && i==0) ? false : newHasPol;
+ if( collectPatTerms2( qe, f, n[i], patMap, tstrt, newPol2, newHasPol2 ) ){
retVal = true;
}
}
@@ -367,7 +421,7 @@ void Trigger::collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vecto
}
}
}
- collectPatTerms2( qe, f, n, patMap, tstrt );
+ collectPatTerms2( qe, f, n, patMap, tstrt, true, true );
for( std::map< Node, bool >::iterator it = patMap.begin(); it != patMap.end(); ++it ){
if( it->second ){
patTerms.push_back( it->first );
@@ -380,9 +434,9 @@ bool Trigger::isArithmeticTrigger( Node f, Node n, std::map< Node, Node >& coeff
Assert( coeffs.empty() );
NodeBuilder<> t(kind::PLUS);
for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( n[i].hasAttribute(InstConstantAttribute()) ){
+ if( quantifiers::TermDb::hasInstConstAttr(n[i]) ){
if( n[i].getKind()==INST_CONSTANT ){
- if( n[i].getAttribute(InstConstantAttribute())==f ){
+ if( quantifiers::TermDb::getInstConstAttr(n[i])==f ){
coeffs[ n[i] ] = Node::null();
}else{
coeffs.clear();
@@ -405,13 +459,13 @@ bool Trigger::isArithmeticTrigger( Node f, Node n, std::map< Node, Node >& coeff
}
return true;
}else if( n.getKind()==MULT ){
- if( n[0].getKind()==INST_CONSTANT && n[0].getAttribute(InstConstantAttribute())==f ){
- if( !n[1].hasAttribute(InstConstantAttribute()) ){
+ if( n[0].getKind()==INST_CONSTANT && quantifiers::TermDb::getInstConstAttr(n[0])==f ){
+ if( !quantifiers::TermDb::hasInstConstAttr(n[1]) ){
coeffs[ n[0] ] = n[1];
return true;
}
- }else if( n[1].getKind()==INST_CONSTANT && n[1].getAttribute(InstConstantAttribute())==f ){
- if( !n[0].hasAttribute(InstConstantAttribute()) ){
+ }else if( n[1].getKind()==INST_CONSTANT && quantifiers::TermDb::getInstConstAttr(n[1])==f ){
+ if( !quantifiers::TermDb::hasInstConstAttr(n[0]) ){
coeffs[ n[1] ] = n[0];
return true;
}
diff --git a/src/theory/quantifiers/trigger.h b/src/theory/quantifiers/trigger.h
index ca9124751..28fb2acda 100644
--- a/src/theory/quantifiers/trigger.h
+++ b/src/theory/quantifiers/trigger.h
@@ -92,8 +92,9 @@ public:
private:
/** is subterm of trigger usable */
static bool isUsable( Node n, Node f );
+ static Node getIsUsableTrigger( Node n, Node f, bool pol = true, bool hasPol = false );
/** collect all APPLY_UF pattern terms for f in n */
- static bool collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt );
+ static bool collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt, bool pol, bool hasPol );
public:
//different strategies for choosing trigger terms
enum {
diff --git a/src/theory/quantifiers_engine.cpp b/src/theory/quantifiers_engine.cpp
index 0bb0f1f79..c663e1aa2 100644
--- a/src/theory/quantifiers_engine.cpp
+++ b/src/theory/quantifiers_engine.cpp
@@ -27,6 +27,7 @@
#include "theory/quantifiers/trigger.h"
#include "theory/rewriterules/efficient_e_matching.h"
#include "theory/rewriterules/rr_trigger.h"
+#include "theory/quantifiers/bounded_integers.h"
using namespace std;
using namespace CVC4;
@@ -47,7 +48,11 @@ d_lemmas_produced_c(u){
d_hasAddedLemma = false;
//the model object
- d_model = new quantifiers::FirstOrderModel( c, "FirstOrderModel" );
+ if( options::fmfFullModelCheck() ){
+ d_model = new quantifiers::fmcheck::FirstOrderModelFmc( this, c, "FirstOrderModelFmc" );
+ }else{
+ d_model = new quantifiers::FirstOrderModelIG( c, "FirstOrderModelIG" );
+ }
//add quantifiers modules
if( !options::finiteModelFind() || options::fmfInstEngine() ){
@@ -60,8 +65,15 @@ d_lemmas_produced_c(u){
if( options::finiteModelFind() ){
d_model_engine = new quantifiers::ModelEngine( c, this );
d_modules.push_back( d_model_engine );
+ if( options::fmfBoundInt() ){
+ d_bint = new quantifiers::BoundedIntegers( c, this );
+ d_modules.push_back( d_bint );
+ }else{
+ d_bint = NULL;
+ }
}else{
d_model_engine = NULL;
+ d_bint = NULL;
}
//options
@@ -251,7 +263,6 @@ void QuantifiersEngine::computeTermVector( Node f, InstMatch& m, std::vector< No
bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& vars, std::vector< Node >& terms ){
Assert( f.getKind()==FORALL );
- Assert( !f.hasAttribute(InstConstantAttribute()) );
Assert( vars.size()==terms.size() );
Node body = getInstantiation( f, vars, terms );
//make the lemma
@@ -266,7 +277,7 @@ bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& vars, std
Trace("inst") << "*** Instantiate " << f << " with " << std::endl;
uint64_t maxInstLevel = 0;
for( int i=0; i<(int)terms.size(); i++ ){
- if( terms[i].hasAttribute(InstConstantAttribute()) ){
+ if( quantifiers::TermDb::hasInstConstAttr(terms[i]) ){
Debug("inst")<< "***& Bad Instantiate " << f << " with " << std::endl;
for( int i=0; i<(int)terms.size(); i++ ){
Debug("inst") << " " << terms[i] << std::endl;
@@ -432,8 +443,6 @@ bool QuantifiersEngine::addSplit( Node n, bool reqPhase, bool reqPhasePol ){
}
bool QuantifiersEngine::addSplitEquality( Node n1, Node n2, bool reqPhase, bool reqPhasePol ){
- //Assert( !n1.hasAttribute(InstConstantAttribute()) );
- //Assert( !n2.hasAttribute(InstConstantAttribute()) );
//Assert( !areEqual( n1, n2 ) );
//Assert( !areDisequal( n1, n2 ) );
Kind knd = n1.getType()==NodeManager::currentNM()->booleanType() ? IFF : EQUAL;
@@ -463,7 +472,6 @@ void QuantifiersEngine::getPhaseReqTerms( Node f, std::vector< Node >& nodes ){
if( d_phase_reqs[f]->isPhaseReq( nodes[i] ) ){
bool preq = d_phase_reqs[f]->getPhaseReq( nodes[i] );
nodes[i] = NodeManager::currentNM()->mkNode( IFF, nodes[i], NodeManager::currentNM()->mkConst<bool>(preq) );
- d_term_db->setInstantiationConstantAttr( nodes[i], f );
nodeChanged = true;
}
//else if( qe->isPhaseReqEquality( f, trNodes[i] ) ){
diff --git a/src/theory/quantifiers_engine.h b/src/theory/quantifiers_engine.h
index bfa19bb98..2ff2100b2 100644
--- a/src/theory/quantifiers_engine.h
+++ b/src/theory/quantifiers_engine.h
@@ -56,7 +56,7 @@ public:
virtual void assertNode( Node n ) = 0;
virtual void propagate( Theory::Effort level ){}
virtual Node getNextDecisionRequest() { return TNode::null(); }
- virtual Node explain(TNode n) = 0;
+ virtual Node explain(TNode n) { return TNode::null(); }
};/* class QuantifiersModule */
namespace quantifiers {
@@ -64,6 +64,7 @@ namespace quantifiers {
class ModelEngine;
class TermDb;
class FirstOrderModel;
+ class BoundedIntegers;
}/* CVC4::theory::quantifiers */
namespace inst {
@@ -99,6 +100,8 @@ private:
std::map< Node, QuantPhaseReq* > d_phase_reqs;
/** efficient e-matcher */
EfficientEMatcher* d_eem;
+ /** bounded integers utility */
+ quantifiers::BoundedIntegers * d_bint;
private:
/** list of all quantifiers seen */
std::vector< Node > d_quants;
@@ -155,6 +158,8 @@ public:
void getPhaseReqTerms( Node f, std::vector< Node >& nodes );
/** get efficient e-matching utility */
EfficientEMatcher* getEfficientEMatcher() { return d_eem; }
+ /** get bounded integers utility */
+ quantifiers::BoundedIntegers * getBoundedIntegers() { return d_bint; }
public:
/** initialize */
void finishInit();
diff --git a/src/theory/rep_set.cpp b/src/theory/rep_set.cpp
index f6da32bbf..99e28714f 100644
--- a/src/theory/rep_set.cpp
+++ b/src/theory/rep_set.cpp
@@ -14,6 +14,7 @@
#include "theory/rep_set.h"
#include "theory/type_enumerator.h"
+#include "theory/quantifiers/bounded_integers.h"
using namespace std;
using namespace CVC4;
@@ -94,26 +95,38 @@ void RepSet::toStream(std::ostream& out){
}
-RepSetIterator::RepSetIterator( RepSet* rs ) : d_rep_set( rs ){
+RepSetIterator::RepSetIterator( QuantifiersEngine * qe, RepSet* rs ) : d_qe(qe), d_rep_set( rs ){
d_incomplete = false;
+}
+int RepSetIterator::domainSize( int i ) {
+ Assert(i>=0);
+ if( d_enum_type[i]==ENUM_DOMAIN_ELEMENTS ){
+ return d_domain[i].size();
+ }else{
+ return d_domain[i][0];
+ }
}
bool RepSetIterator::setQuantifier( Node f ){
+ Trace("rsi") << "Make rsi for " << f << std::endl;
Assert( d_types.empty() );
//store indicies
for( size_t i=0; i<f[0].getNumChildren(); i++ ){
d_types.push_back( f[0][i].getType() );
}
+ d_owner = f;
return initialize();
}
bool RepSetIterator::setFunctionDomain( Node op ){
+ Trace("rsi") << "Make rsi for " << op << std::endl;
Assert( d_types.empty() );
TypeNode tn = op.getType();
for( size_t i=0; i<tn.getNumChildren()-1; i++ ){
d_types.push_back( tn[i] );
}
+ d_owner = op;
return initialize();
}
@@ -126,13 +139,29 @@ bool RepSetIterator::initialize(){
//store default domain
d_domain.push_back( RepDomain() );
TypeNode tn = d_types[i];
+ bool isSet = false;
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() ){
+ }else if( tn.isInteger() ){
+ //check if it is bound
+ if( d_owner.getKind()==FORALL && d_qe && d_qe->getBoundedIntegers() ){
+ if( d_qe->getBoundedIntegers()->isBoundVar( d_owner, d_owner[0][i] ) ){
+ Trace("bound-int-rsi") << "Rep set iterator: variable #" << i << " is bounded integer." << std::endl;
+ d_enum_type.push_back( ENUM_RANGE );
+ isSet = true;
+ }else{
+ Trace("fmf-incomplete") << "Incomplete because of integer quantification, no bounds found." << std::endl;
+ d_incomplete = true;
+ }
+ }else{
+ Trace("fmf-incomplete") << "Incomplete because of integer quantification." << std::endl;
+ d_incomplete = true;
+ }
+ }else if( 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
@@ -142,12 +171,49 @@ bool RepSetIterator::initialize(){
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 );
+ if( !isSet ){
+ d_enum_type.push_back( ENUM_DOMAIN_ELEMENTS );
+ 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;
}
- }else{
- return false;
+ }
+ }
+ //must set a variable index order
+ if (d_owner.getKind()==FORALL && d_qe && d_qe->getBoundedIntegers()) {
+ Trace("bound-int-rsi") << "Calculating variable order..." << std::endl;
+ std::vector< int > varOrder;
+ for( unsigned i=0; i<d_qe->getBoundedIntegers()->getNumBoundVars(d_owner); i++ ){
+ varOrder.push_back(d_qe->getBoundedIntegers()->getBoundVarNum(d_owner,i));
+ }
+ for( unsigned i=0; i<d_owner[0].getNumChildren(); i++) {
+ if( !d_qe->getBoundedIntegers()->isBoundVar(d_owner, d_owner[0][i])) {
+ varOrder.push_back(i);
+ }
+ }
+ Trace("bound-int-rsi") << "Variable order : ";
+ for( unsigned i=0; i<varOrder.size(); i++) {
+ Trace("bound-int-rsi") << varOrder[i] << " ";
+ }
+ Trace("bound-int-rsi") << std::endl;
+ std::vector< int > indexOrder;
+ indexOrder.resize(varOrder.size());
+ for( unsigned i=0; i<varOrder.size(); i++){
+ indexOrder[varOrder[i]] = i;
+ }
+ Trace("bound-int-rsi") << "Will use index order : ";
+ for( unsigned i=0; i<indexOrder.size(); i++) {
+ Trace("bound-int-rsi") << indexOrder[i] << " ";
+ }
+ Trace("bound-int-rsi") << std::endl;
+ setIndexOrder(indexOrder);
+ }
+ for (unsigned i=0; i<d_index.size(); i++) {
+ if (!resetIndex(i, true)){
+ break;
}
}
return true;
@@ -161,7 +227,7 @@ void RepSetIterator::setIndexOrder( std::vector< int >& indexOrder ){
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() );
@@ -172,6 +238,43 @@ void RepSetIterator::setDomain( std::vector< RepDomain >& domain ){
}
}
}
+*/
+bool RepSetIterator::resetIndex( int i, bool initial ) {
+ d_index[i] = 0;
+ int ii = d_index_order[i];
+ Trace("bound-int-rsi") << "Reset " << i << " " << ii << " " << initial << std::endl;
+ //determine the current range
+ if( d_enum_type[ii]==ENUM_RANGE ){
+ if( initial || !d_qe->getBoundedIntegers()->isGroundRange( d_owner, d_owner[0][ii] ) ){
+ Trace("bound-int-rsi") << "Getting range of " << d_owner[0][ii] << std::endl;
+ Node l, u;
+ d_qe->getBoundedIntegers()->getBoundValues( d_owner, d_owner[0][ii], this, l, u );
+ if( l.isNull() || u.isNull() ){
+ //failed, abort the iterator
+ d_index.clear();
+ return false;
+ }else{
+ Trace("bound-int-rsi") << "Can limit bounds of " << d_owner[0][ii] << " to " << l << "..." << u << std::endl;
+ Node range = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MINUS, u, l ) );
+ Node ra = Rewriter::rewrite( NodeManager::currentNM()->mkNode( LEQ, range, NodeManager::currentNM()->mkConst( Rational( 9999 ) ) ) );
+ d_domain[ii].clear();
+ d_lower_bounds[ii] = l;
+ if( ra==NodeManager::currentNM()->mkConst(true) ){
+ long rr = range.getConst<Rational>().getNumerator().getLong()+1;
+ Trace("bound-int-rsi") << "Actual bound range is " << rr << std::endl;
+ d_domain[ii].push_back( (int)rr );
+ }else{
+ Trace("fmf-incomplete") << "Incomplete because of integer quantification, bounds are too big for " << d_owner[0][ii] << "." << std::endl;
+ d_incomplete = true;
+ d_domain[ii].push_back( 0 );
+ }
+ }
+ }else{
+ Trace("bound-int-rsi") << d_owner[0][ii] << " has ground range, skip." << std::endl;
+ }
+ }
+ return true;
+}
void RepSetIterator::increment2( int counter ){
Assert( !isFinished() );
@@ -179,16 +282,24 @@ void RepSetIterator::increment2( int counter ){
counter = (int)d_index.size()-1;
#endif
//increment d_index
- while( counter>=0 && d_index[counter]==(int)(d_domain[counter].size()-1) ){
+ if( counter>=0){
+ Trace("rsi-debug") << "domain size of " << counter << " is " << domainSize(counter) << std::endl;
+ }
+ while( counter>=0 && d_index[counter]>=(int)(domainSize(counter)-1) ){
counter--;
+ if( counter>=0){
+ Trace("rsi-debug") << "domain size of " << counter << " is " << domainSize(counter) << std::endl;
+ }
}
if( counter==-1 ){
d_index.clear();
}else{
+ d_index[counter]++;
for( int i=(int)d_index.size()-1; i>counter; i-- ){
- d_index[i] = 0;
+ if (!resetIndex(i)){
+ break;
+ }
}
- d_index[counter]++;
}
}
@@ -203,10 +314,18 @@ bool RepSetIterator::isFinished(){
}
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]]];
+ if( d_enum_type[index]==ENUM_DOMAIN_ELEMENTS ){
+ TypeNode tn = d_types[index];
+ Assert( d_rep_set->d_type_reps.find( tn )!=d_rep_set->d_type_reps.end() );
+ return d_rep_set->d_type_reps[tn][d_domain[index][d_index[index]]];
+ }else{
+ Trace("rsi-debug") << index << " " << d_lower_bounds[index] << " " << d_index[index] << std::endl;
+ Node t = NodeManager::currentNM()->mkNode(PLUS, d_lower_bounds[index],
+ NodeManager::currentNM()->mkConst( Rational(d_index[index]) ) );
+ t = Rewriter::rewrite( t );
+ return t;
+ }
}
void RepSetIterator::debugPrint( const char* c ){
diff --git a/src/theory/rep_set.h b/src/theory/rep_set.h
index 24fa7473e..fc8db420d 100644
--- a/src/theory/rep_set.h
+++ b/src/theory/rep_set.h
@@ -23,6 +23,8 @@
namespace CVC4 {
namespace theory {
+class QuantifiersEngine;
+
/** this class stores a representative set */
class RepSet {
public:
@@ -53,10 +55,25 @@ typedef std::vector< int > RepDomain;
/** this class iterates over a RepSet */
class RepSetIterator {
private:
+ enum {
+ ENUM_DOMAIN_ELEMENTS,
+ ENUM_RANGE,
+ };
+ QuantifiersEngine * d_qe;
//initialize function
bool initialize();
+ //enumeration type?
+ std::vector< int > d_enum_type;
+ //for enum ranges
+ std::map< int, Node > d_lower_bounds;
+ //domain size
+ int domainSize( int i );
+ //node this is rep set iterator is for
+ Node d_owner;
+ //reset index
+ bool resetIndex( int i, bool initial = false );
public:
- RepSetIterator( RepSet* rs );
+ RepSetIterator( QuantifiersEngine * qe, RepSet* rs );
~RepSetIterator(){}
//set that this iterator will be iterating over instantiations for a quantifier
bool setQuantifier( Node f );
@@ -90,7 +107,7 @@ public:
/** set index order */
void setIndexOrder( std::vector< int >& indexOrder );
/** set domain */
- void setDomain( std::vector< RepDomain >& domain );
+ //void setDomain( std::vector< RepDomain >& domain );
/** increment the iterator at index=counter */
void increment2( int counter );
/** increment the iterator */
diff --git a/src/theory/rewriterules/rr_inst_match.cpp b/src/theory/rewriterules/rr_inst_match.cpp
index a4c111f86..4908e5ec0 100644
--- a/src/theory/rewriterules/rr_inst_match.cpp
+++ b/src/theory/rewriterules/rr_inst_match.cpp
@@ -137,14 +137,13 @@ class DumbPatMatcher: public PatMatcher{
/* The order of the matching is:
reset arg1, nextMatch arg1, reset arg2, nextMatch arg2, ... */
ApplyMatcher::ApplyMatcher( Node pat, QuantifiersEngine* qe): d_pattern(pat){
- // Assert( pat.hasAttribute(InstConstantAttribute()) );
//set-up d_variables, d_constants, d_childrens
for( size_t i=0; i< d_pattern.getNumChildren(); ++i ){
//EqualityQuery* q = qe->getEqualityQuery(d_pattern[i].getType());
EqualityQuery* q = qe->getEqualityQuery();
Assert( q != NULL );
- if( d_pattern[i].hasAttribute(InstConstantAttribute()) ){
+ if( quantifiers::TermDb::hasInstConstAttr(d_pattern[i]) ){
if( d_pattern[i].getKind()==INST_CONSTANT ){
//It's a variable
d_variables.push_back(make_triple((TNode)d_pattern[i],i,q));
@@ -172,7 +171,7 @@ bool ApplyMatcher::reset(TNode t, InstMatch & m, QuantifiersEngine* qe){
//if t is null
Assert( !t.isNull() );
- Assert( !t.hasAttribute(InstConstantAttribute()) );
+ Assert( !quantifiers::TermDb::hasInstConstAttr(t) );
Assert( t.getKind()==d_pattern.getKind() );
Assert( (t.getKind()!=APPLY_UF && t.getKind()!=APPLY_CONSTRUCTOR)
|| t.getOperator()==d_pattern.getOperator() );
@@ -411,7 +410,7 @@ public:
size_t numFreeVar(TNode t){
size_t n = 0;
for( size_t i=0, size =t.getNumChildren(); i < size; ++i ){
- if( t[i].hasAttribute(InstConstantAttribute()) ){
+ if( quantifiers::TermDb::hasInstConstAttr(t[i]) ){
if( t[i].getKind()==INST_CONSTANT ){
//variable
++n;
@@ -958,7 +957,7 @@ Matcher* mkMatcher( Node pat, QuantifiersEngine* qe ){
/** TODO: something simpler to see if the pattern is a good
arithmetic pattern */
std::map< Node, Node > d_arith_coeffs;
- if( !Trigger::getPatternArithmetic( pat.getAttribute(InstConstantAttribute()), pat, d_arith_coeffs ) ){
+ if( !Trigger::getPatternArithmetic( quantifiers::TermDb::getInstConstAttr(pat), pat, d_arith_coeffs ) ){
Message() << "(?) Unknown matching pattern is " << pat << std::endl;
Unimplemented("pattern not implemented");
return new DumbMatcher();
@@ -983,17 +982,17 @@ Matcher* mkMatcher( Node pat, QuantifiersEngine* qe ){
PatMatcher* mkPattern( Node pat, QuantifiersEngine* qe ){
Debug("inst-match-gen") << "Pattern term is " << pat << std::endl;
- Assert( pat.hasAttribute(InstConstantAttribute()) );
+ Assert( quantifiers::TermDb::hasInstConstAttr(pat) );
if( pat.getKind()==kind::NOT && pat[0].getKind() == kind::EQUAL){
/* Difference */
return new UfDeqMatcher(pat, qe);
} else if (pat.getKind() == kind::EQUAL){
- if( !pat[0].hasAttribute(InstConstantAttribute() )){
- Assert(pat[1].hasAttribute(InstConstantAttribute()));
+ if( !quantifiers::TermDb::hasInstConstAttr(pat[0])){
+ Assert(quantifiers::TermDb::hasInstConstAttr(pat[1]));
return new UfCstEqMatcher(pat[1], pat[0], qe);
- }else if( !pat[1].hasAttribute(InstConstantAttribute() )){
- Assert(pat[0].hasAttribute(InstConstantAttribute()));
+ }else if( !quantifiers::TermDb::hasInstConstAttr(pat[1] )){
+ Assert(quantifiers::TermDb::hasInstConstAttr(pat[0]));
return new UfCstEqMatcher(pat[0], pat[1], qe);
}else{
std::vector< Node > pats(pat.begin(),pat.end());
@@ -1009,7 +1008,7 @@ PatMatcher* mkPattern( Node pat, QuantifiersEngine* qe ){
/** TODO: something simpler to see if the pattern is a good
arithmetic pattern */
std::map< Node, Node > d_arith_coeffs;
- if( !Trigger::getPatternArithmetic( pat.getAttribute(InstConstantAttribute()), pat, d_arith_coeffs ) ){
+ if( !Trigger::getPatternArithmetic( quantifiers::TermDb::getInstConstAttr(pat), pat, d_arith_coeffs ) ){
Debug("inst-match-gen") << "(?) Unknown matching pattern is " << pat << std::endl;
Message() << "(?) Unknown matching pattern is " << pat << std::endl;
return new DumbPatMatcher();
@@ -1033,7 +1032,7 @@ PatMatcher* mkPattern( Node pat, QuantifiersEngine* qe ){
ArithMatcher::ArithMatcher(Node pat, QuantifiersEngine* qe): d_pattern(pat){
- if(Trigger::getPatternArithmetic(pat.getAttribute(InstConstantAttribute()), pat, d_arith_coeffs ) )
+ if(Trigger::getPatternArithmetic(quantifiers::TermDb::getInstConstAttr(pat), pat, d_arith_coeffs ) )
{
Debug("inst-match-gen") << "(?) Unknown matching pattern is " << d_pattern << std::endl;
Assert(false);
diff --git a/src/theory/rewriterules/rr_inst_match.h b/src/theory/rewriterules/rr_inst_match.h
index 3ec9438fd..aa89430c1 100644
--- a/src/theory/rewriterules/rr_inst_match.h
+++ b/src/theory/rewriterules/rr_inst_match.h
@@ -67,7 +67,7 @@ public:
/** legal candidate */
static inline bool isLegalCandidate( TNode n ){
return !n.getAttribute(NoMatchAttribute()) &&
- ( !options::cbqi() || !n.hasAttribute(InstConstantAttribute())) &&
+ ( !options::cbqi() || !quantifiers::TermDb::hasInstConstAttr(n)) &&
( !options::efficientEMatching() || n.hasAttribute(AvailableInTermDb()) );
}
diff --git a/src/theory/rewriterules/rr_trigger.cpp b/src/theory/rewriterules/rr_trigger.cpp
index 7e35be7ad..13250cf1b 100644
--- a/src/theory/rewriterules/rr_trigger.cpp
+++ b/src/theory/rewriterules/rr_trigger.cpp
@@ -65,7 +65,7 @@ bool Trigger::getNextMatch(){
int Trigger::addInstantiations( InstMatch& baseMatch ){
int addedLemmas = d_mg->addInstantiations( baseMatch,
- d_nodes[0].getAttribute(InstConstantAttribute()),
+ quantifiers::TermDb::getInstConstAttr(d_nodes[0]),
d_quantEngine);
if( addedLemmas>0 ){
Debug("inst-trigger") << "Added " << addedLemmas << " lemmas, trigger was ";
@@ -91,7 +91,7 @@ Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >&
qe->getTermDatabase()->computeVarContains( temp[i] );
for( int j=0; j<(int)qe->getTermDatabase()->d_var_contains[ temp[i] ].size(); j++ ){
Node v = qe->getTermDatabase()->d_var_contains[ temp[i] ][j];
- if( v.getAttribute(InstConstantAttribute())==f ){
+ if( quantifiers::TermDb::getInstConstAttr(v)==f ){
if( vars.find( v )==vars.end() ){
vars[ v ] = true;
foundVar = true;
@@ -181,7 +181,7 @@ bool Trigger::isUsableTrigger( std::vector< Node >& nodes, Node f ){
}
bool Trigger::isUsable( Node n, Node f ){
- if( n.getAttribute(InstConstantAttribute())==f ){
+ if( quantifiers::TermDb::getInstConstAttr(n)==f ){
if( !isAtomicTrigger( n ) && n.getKind()!=INST_CONSTANT ){
std::map< Node, Node > coeffs;
return getPatternArithmetic( f, n, coeffs );
@@ -201,7 +201,7 @@ bool Trigger::isUsable( Node n, Node f ){
bool Trigger::isSimpleTrigger( Node n ){
if( isAtomicTrigger( n ) ){
for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( n[i].getKind()!=INST_CONSTANT && n[i].hasAttribute(InstConstantAttribute()) ){
+ if( n[i].getKind()!=INST_CONSTANT && quantifiers::TermDb::hasInstConstAttr(n[i]) ){
return false;
}
}
@@ -318,9 +318,9 @@ bool Trigger::getPatternArithmetic( Node f, Node n, std::map< Node, Node >& coef
Assert( coeffs.empty() );
NodeBuilder<> t(kind::PLUS);
for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( n[i].hasAttribute(InstConstantAttribute()) ){
+ if( quantifiers::TermDb::hasInstConstAttr(n[i]) ){
if( n[i].getKind()==INST_CONSTANT ){
- if( n[i].getAttribute(InstConstantAttribute())==f ){
+ if( quantifiers::TermDb::getInstConstAttr(n[i])==f ){
coeffs[ n[i] ] = Node::null();
}else{
coeffs.clear();
@@ -343,12 +343,12 @@ bool Trigger::getPatternArithmetic( Node f, Node n, std::map< Node, Node >& coef
}
return true;
}else if( n.getKind()==MULT ){
- if( n[0].getKind()==INST_CONSTANT && n[0].getAttribute(InstConstantAttribute())==f ){
- Assert( !n[1].hasAttribute(InstConstantAttribute()) );
+ if( n[0].getKind()==INST_CONSTANT && quantifiers::TermDb::getInstConstAttr(n[0])==f ){
+ Assert( !quantifiers::TermDb::hasInstConstAttr(n[1]) );
coeffs[ n[0] ] = n[1];
return true;
- }else if( n[1].getKind()==INST_CONSTANT && n[1].getAttribute(InstConstantAttribute())==f ){
- Assert( !n[0].hasAttribute(InstConstantAttribute()) );
+ }else if( n[1].getKind()==INST_CONSTANT && quantifiers::TermDb::getInstConstAttr(n[1])==f ){
+ Assert( !quantifiers::TermDb::hasInstConstAttr(n[0]) );
coeffs[ n[1] ] = n[0];
return true;
}
diff --git a/src/theory/rewriterules/rr_trigger.h b/src/theory/rewriterules/rr_trigger.h
index f1a37d937..f02f38d0e 100644
--- a/src/theory/rewriterules/rr_trigger.h
+++ b/src/theory/rewriterules/rr_trigger.h
@@ -94,8 +94,7 @@ public:
public:
/** is usable trigger */
static inline bool isUsableTrigger( TNode n, TNode f ){
- //return n.getAttribute(InstConstantAttribute())==f && n.getKind()==APPLY_UF;
- return n.getAttribute(InstConstantAttribute())==f && isAtomicTrigger( n ) && isUsable( n, f );
+ return quantifiers::TermDb::getInstConstAttr(n)==f && isAtomicTrigger( n ) && isUsable( n, f );
}
static inline bool isAtomicTrigger( TNode n ){
return
diff --git a/src/theory/rewriterules/theory_rewriterules.h b/src/theory/rewriterules/theory_rewriterules.h
index 19cb3e987..a542214b2 100644
--- a/src/theory/rewriterules/theory_rewriterules.h
+++ b/src/theory/rewriterules/theory_rewriterules.h
@@ -263,7 +263,7 @@ private:
rewriter::Subst & vars);
//create inst variable
- std::vector<Node> createInstVariable( std::vector<Node> & vars );
+ std::vector<Node> createInstVariable( Node r, std::vector<Node> & vars );
/** statistics class */
class Statistics {
diff --git a/src/theory/rewriterules/theory_rewriterules_rules.cpp b/src/theory/rewriterules/theory_rewriterules_rules.cpp
index 589556802..446d30d21 100644
--- a/src/theory/rewriterules/theory_rewriterules_rules.cpp
+++ b/src/theory/rewriterules/theory_rewriterules_rules.cpp
@@ -151,7 +151,7 @@ void TheoryRewriteRules::addRewriteRule(const Node r)
vars.push_back(*v);
};
/* Instantiation version */
- std::vector<Node> inst_constants = createInstVariable(vars);
+ std::vector<Node> inst_constants = createInstVariable(r,vars);
/* Body/Remove_term/Guards/Triggers */
Node body = r[2][1];
TNode new_terms = r[2][1];
@@ -376,7 +376,7 @@ bool TheoryRewriteRules::addRewritePattern(TNode pattern, TNode body,
}
-std::vector<Node> TheoryRewriteRules::createInstVariable( std::vector<Node> & vars ){
+std::vector<Node> TheoryRewriteRules::createInstVariable( Node r, std::vector<Node> & vars ){
std::vector<Node> inst_constant;
inst_constant.reserve(vars.size());
for( std::vector<Node>::const_iterator v = vars.begin();
@@ -384,6 +384,11 @@ std::vector<Node> TheoryRewriteRules::createInstVariable( std::vector<Node> & va
//make instantiation constants
Node ic = NodeManager::currentNM()->mkInstConstant( (*v).getType() );
inst_constant.push_back( ic );
+ InstConstantAttribute ica;
+ ic.setAttribute(ica,r);
+ //also set the no-match attribute
+ NoMatchAttribute nma;
+ ic.setAttribute(nma,true);
};
return inst_constant;
}
diff --git a/src/theory/uf/options b/src/theory/uf/options
index 33d1255ef..bea11621a 100644
--- a/src/theory/uf/options
+++ b/src/theory/uf/options
@@ -30,5 +30,7 @@ option ufssSimpleCliques --uf-ss-simple-cliques bool :default true
always use simple clique lemmas for uf strong solver
option ufssDiseqPropagation --uf-ss-deq-prop bool :default false
eagerly propagate disequalities for uf strong solver
+option ufssMinimalModel /--disable-uf-ss-min-model bool :default true
+ disable finding a minimal model in uf strong solver
endmodule
diff --git a/src/theory/uf/theory_uf_model.cpp b/src/theory/uf/theory_uf_model.cpp
index 228cfd2c4..2c853a4fa 100644
--- a/src/theory/uf/theory_uf_model.cpp
+++ b/src/theory/uf/theory_uf_model.cpp
@@ -17,6 +17,7 @@
#include "theory/uf/equality_engine.h"
#include "theory/uf/theory_uf.h"
#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/options.h"
#define RECONSIDER_FUNC_DEFAULT_VALUE
#define USE_PARTIAL_DEFAULT_VALUES
@@ -309,19 +310,21 @@ void UfModelTreeGenerator::setValue( TheoryModel* m, Node n, Node v, bool ground
if( !ground ){
int defSize = (int)d_defaults.size();
for( int i=0; i<defSize; i++ ){
- bool isGround;
//for soundness, to allow variable order-independent function interpretations,
// we must ensure that the intersection of all default terms
// is also defined.
//for example, if we have that f( e, a ) = ..., and f( b, e ) = ...,
// then we must define f( b, a ).
- Node ni = getIntersection( m, n, d_defaults[i], isGround );
- if( !ni.isNull() ){
- //if the intersection exists, and is not already defined
- if( d_set_values[0][ isGround ? 1 : 0 ].find( ni )==d_set_values[0][ isGround ? 1 : 0 ].end() &&
- d_set_values[1][ isGround ? 1 : 0 ].find( ni )==d_set_values[1][ isGround ? 1 : 0 ].end() ){
- //use the current value
- setValue( m, ni, v, isGround, false );
+ if (!options::fmfFullModelCheck()) {
+ bool isGround;
+ Node ni = getIntersection( m, n, d_defaults[i], isGround );
+ if( !ni.isNull() ){
+ //if the intersection exists, and is not already defined
+ if( d_set_values[0][ isGround ? 1 : 0 ].find( ni )==d_set_values[0][ isGround ? 1 : 0 ].end() &&
+ d_set_values[1][ isGround ? 1 : 0 ].find( ni )==d_set_values[1][ isGround ? 1 : 0 ].end() ){
+ //use the current value
+ setValue( m, ni, v, isGround, false );
+ }
}
}
}
diff --git a/src/theory/uf/theory_uf_model.h b/src/theory/uf/theory_uf_model.h
index 12c1cf244..2149a6583 100644
--- a/src/theory/uf/theory_uf_model.h
+++ b/src/theory/uf/theory_uf_model.h
@@ -144,18 +144,12 @@ public:
void debugPrint( std::ostream& out, TheoryModel* m, int ind = 0 ){
d_tree.debugPrint( out, m, d_index_order, ind );
}
-private:
- //helper for to ITE function.
- static Node toIte2( Node fm_node, std::vector< Node >& args, int index, Node defaultNode );
-public:
- /** to ITE function for function model nodes */
- static Node toIte( Node fm_node, std::vector< Node >& args ) { return toIte2( fm_node, args, 0, Node::null() ); }
- static Node toIte( TypeNode type, Node fm_node, const char* argPrefix );
};
+
class UfModelTreeGenerator
{
-private:
+public:
//store for set values
Node d_default_value;
std::map< Node, Node > d_set_values[2][2];
diff --git a/src/theory/uf/theory_uf_strong_solver.cpp b/src/theory/uf/theory_uf_strong_solver.cpp
index d64f7df60..e868460f8 100644
--- a/src/theory/uf/theory_uf_strong_solver.cpp
+++ b/src/theory/uf/theory_uf_strong_solver.cpp
@@ -595,9 +595,11 @@ void StrongSolverTheoryUF::SortModel::check( Theory::Effort level, OutputChannel
if( d_regions[i]->d_valid ){
std::vector< Node > clique;
if( d_regions[i]->check( level, d_cardinality, clique ) ){
- //add clique lemma
- addCliqueLemma( clique, out );
- return;
+ if( options::ufssMinimalModel() ){
+ //add clique lemma
+ addCliqueLemma( clique, out );
+ return;
+ }
}else{
Trace("uf-ss-debug") << "No clique in Region #" << i << std::endl;
}
@@ -659,13 +661,17 @@ void StrongSolverTheoryUF::SortModel::check( Theory::Effort level, OutputChannel
//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 ){
- forceCombineRegion( i, false );
- recheck = true;
- break;
+ int fcr = forceCombineRegion( i, false );
+ Trace("uf-ss-debug") << "Combined regions " << i << " " << fcr << std::endl;
+ if( options::ufssMinimalModel() || fcr!=-1 ){
+ recheck = true;
+ break;
+ }
}
}
}
if( recheck ){
+ Trace("uf-ss-debug") << "Must recheck." << std::endl;
check( level, out );
}
}
@@ -869,8 +875,10 @@ void StrongSolverTheoryUF::SortModel::checkRegion( int ri, bool checkCombine ){
//now check if region is in conflict
std::vector< Node > clique;
if( d_regions[ri]->check( Theory::EFFORT_STANDARD, d_cardinality, clique ) ){
- //explain clique
- addCliqueLemma( clique, &d_thss->getOutputChannel() );
+ if( options::ufssMinimalModel() ){
+ //explain clique
+ addCliqueLemma( clique, &d_thss->getOutputChannel() );
+ }
}
}
}
@@ -1013,8 +1021,8 @@ void StrongSolverTheoryUF::SortModel::allocateCardinality( OutputChannel* out ){
}
bool StrongSolverTheoryUF::SortModel::addSplit( Region* r, OutputChannel* out ){
+ Node s;
if( r->hasSplits() ){
- Node s;
if( !options::ufssSmartSplits() ){
//take the first split you find
for( NodeBoolMap::iterator it = r->d_splits.begin(); it != r->d_splits.end(); ++it ){
@@ -1038,8 +1046,26 @@ bool StrongSolverTheoryUF::SortModel::addSplit( Region* r, OutputChannel* out ){
}
}
}
+ Assert( s!=Node::null() );
+ }else{
+ if( !options::ufssMinimalModel() ){
+ //since candidate clique is not reported, we may need to find splits manually
+ for ( std::map< Node, Region::RegionNodeInfo* >::iterator it = r->d_nodes.begin(); it != r->d_nodes.end(); ++it ){
+ if ( it->second->d_valid ){
+ for ( std::map< Node, Region::RegionNodeInfo* >::iterator it2 = r->d_nodes.begin(); it2 != r->d_nodes.end(); ++it2 ){
+ if ( it->second!=it2->second && it2->second->d_valid ){
+ if( !r->isDisequal( it->first, it2->first, 1 ) ){
+ s = NodeManager::currentNM()->mkNode( EQUAL, it->first, it2->first );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (!s.isNull() ){
//add lemma to output channel
- Assert( s!=Node::null() && s.getKind()==EQUAL );
+ Assert( s.getKind()==EQUAL );
s = Rewriter::rewrite( s );
Trace("uf-ss-lemma") << "*** Split on " << s << std::endl;
if( options::sortInference()) {
diff --git a/test/Makefile.am b/test/Makefile.am
index 6cccca05c..0fdc69e03 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -53,6 +53,7 @@ subdirs_to_check = \
regress/regress0/preprocess \
regress/regress0/unconstrained \
regress/regress0/decision \
+ regress/regress0/fmf \
regress/regress1 \
regress/regress2 \
regress/regress3
diff --git a/test/regress/regress0/Makefile.am b/test/regress/regress0/Makefile.am
index 6cdd18403..c51b505bc 100644
--- a/test/regress/regress0/Makefile.am
+++ b/test/regress/regress0/Makefile.am
@@ -1,5 +1,5 @@
-SUBDIRS = . arith precedence uf uflra uflia bv arrays aufbv auflia datatypes quantifiers rewriterules lemmas push-pop preprocess unconstrained decision
-DIST_SUBDIRS = . arith precedence uf uflra uflia bv arrays aufbv auflia datatypes quantifiers rewriterules lemmas push-pop preprocess unconstrained decision
+SUBDIRS = . arith precedence uf uflra uflia bv arrays aufbv auflia datatypes quantifiers rewriterules lemmas push-pop preprocess unconstrained decision fmf
+DIST_SUBDIRS = . arith precedence uf uflra uflia bv arrays aufbv auflia datatypes quantifiers rewriterules lemmas push-pop preprocess unconstrained decision fmf
BINARY = cvc4
LOG_COMPILER = @srcdir@/../run_regression
diff --git a/test/regress/regress0/arith/integers/Makefile.am b/test/regress/regress0/arith/integers/Makefile.am
index efd5aa909..c555ba413 100644
--- a/test/regress/regress0/arith/integers/Makefile.am
+++ b/test/regress/regress0/arith/integers/Makefile.am
@@ -20,9 +20,9 @@ MAKEFLAGS = -k
TESTS = \
arith-int-004.cvc \
- arith-int-007.cvc \
arith-int-011.cvc \
arith-int-012.cvc \
+ arith-int-013.cvc \
arith-int-022.cvc \
arith-int-024.cvc \
arith-int-042.cvc \
@@ -34,7 +34,7 @@ TESTS = \
arith-int-097.cvc \
arith-int-085.cvc
-EXTRA_DIST = $(TESTS)
+EXTRA_DIST = $(TESTS) \
arith-int-001.cvc \
arith-int-002.cvc \
arith-int-003.cvc \
@@ -105,7 +105,6 @@ EXTRA_DIST = $(TESTS)
arith-int-079.cvc \
arith-int-080.cvc \
arith-int-081.cvc \
- arith-int-082.cvc \
arith-int-083.cvc \
arith-int-086.cvc \
arith-int-087.cvc \
@@ -122,9 +121,11 @@ EXTRA_DIST = $(TESTS)
arith-int-099.cvc \
arith-int-100.cvc
+
FAILING_TESTS = \
- arith-int-024.cvc \
- arith-int-013.cvc
+ arith-int-007.cvc \
+ arith-int-082.cvc \
+ arith-int-098.cvc
#if CVC4_BUILD_PROFILE_COMPETITION
#else
diff --git a/test/regress/regress0/fmf/ALG008-1.smt2 b/test/regress/regress0/fmf/ALG008-1.smt2
new file mode 100644
index 000000000..018006f45
--- /dev/null
+++ b/test/regress/regress0/fmf/ALG008-1.smt2
@@ -0,0 +1,73 @@
+; COMMAND-LINE: --finite-model-find
+; EXPECT: sat
+; EXIT: 10
+;%--------------------------------------------------------------------------
+;% File : ALG008-1 : TPTP v5.4.0. Released v2.2.0.
+;% Domain : General Algebra
+;% Problem : TC + right identity does not give RC.
+;% Version : [MP96] (equality) axioms : Especial.
+;% English : An algebra with a right identity satisfying the Thomsen
+;% Closure (RC) condition does not necessarily satisfy the
+;% Reidemeister Closure (RC) condition.
+
+;% Refs : [McC98] McCune (1998), Email to G. Sutcliffe
+;% : [MP96] McCune & Padmanabhan (1996), Automated Deduction in Eq
+;% Source : [McC98]
+;% Names : TC-3 [MP96]
+
+;% Status : Satisfiable
+;% Rating : 0.50 v5.4.0, 0.80 v5.3.0, 0.78 v5.2.0, 0.80 v5.0.0, 0.78 v4.1.0, 0.71 v4.0.1, 0.80 v4.0.0, 0.50 v3.7.0, 0.33 v3.4.0, 0.50 v3.3.0, 0.33 v3.2.0, 0.80 v3.1.0, 0.67 v2.7.0, 0.33 v2.6.0, 0.86 v2.5.0, 0.50 v2.4.0, 0.67 v2.3.0, 1.00 v2.2.1
+;% Syntax : Number of clauses : 6 ( 0 non-Horn; 5 unit; 5 RR)
+;% Number of atoms : 10 ( 10 equality)
+;% Maximal clause size : 5 ( 2 average)
+;% Number of predicates : 1 ( 0 propositional; 2-2 arity)
+;% Number of functors : 9 ( 8 constant; 0-2 arity)
+;% Number of variables : 9 ( 0 singleton)
+;% Maximal term depth : 2 ( 2 average)
+;% SPC : CNF_SAT_RFO_EQU_NUE
+
+;% Comments : The smallest model has 3 elements.
+;%--------------------------------------------------------------------------
+;%----Thomsen Closure (TC) condition:
+(set-logic UF)
+(set-info :status sat)
+(declare-sort sort__smt2 0)
+; functions
+(declare-fun multiply__smt2_2 ( sort__smt2 sort__smt2 ) sort__smt2)
+(declare-fun identity__smt2_0 ( ) sort__smt2)
+(declare-fun c4__smt2_0 ( ) sort__smt2)
+(declare-fun a__smt2_0 ( ) sort__smt2)
+(declare-fun c3__smt2_0 ( ) sort__smt2)
+(declare-fun b__smt2_0 ( ) sort__smt2)
+(declare-fun c2__smt2_0 ( ) sort__smt2)
+(declare-fun c1__smt2_0 ( ) sort__smt2)
+(declare-fun f__smt2_0 ( ) sort__smt2)
+; predicates
+
+; thomsen_closure axiom
+(assert (forall ((?V7 sort__smt2) (?V6 sort__smt2) (?W sort__smt2) (?V sort__smt2) (?U sort__smt2) (?Z sort__smt2) (?Y sort__smt2) (?X sort__smt2))
+ (or (not (= (multiply__smt2_2 ?X ?Y) ?Z))
+ (not (= (multiply__smt2_2 ?U ?V) ?Z))
+ (not (= (multiply__smt2_2 ?X ?W) ?V6))
+ (not (= (multiply__smt2_2 ?V7 ?V) ?V6))
+ (= (multiply__smt2_2 ?U ?W) (multiply__smt2_2 ?V7 ?Y)))) )
+
+;%----Right identity:
+; right_identity axiom
+(assert (forall ((?X sort__smt2)) (= (multiply__smt2_2 ?X identity__smt2_0) ?X)) )
+
+;%----Denial of Reidimeister Closure (RC) condidition.
+; prove_reidimeister1 negated_conjecture
+(assert (= (multiply__smt2_2 c4__smt2_0 a__smt2_0) (multiply__smt2_2 c3__smt2_0 b__smt2_0)) )
+
+; prove_reidimeister2 negated_conjecture
+(assert (= (multiply__smt2_2 c2__smt2_0 a__smt2_0) (multiply__smt2_2 c1__smt2_0 b__smt2_0)) )
+
+; prove_reidimeister3 negated_conjecture
+(assert (= (multiply__smt2_2 c4__smt2_0 f__smt2_0) (multiply__smt2_2 c3__smt2_0 identity__smt2_0)) )
+
+; prove_reidimeister4 negated_conjecture
+(assert (not (= (multiply__smt2_2 c2__smt2_0 f__smt2_0) (multiply__smt2_2 c1__smt2_0 identity__smt2_0))) )
+
+
+(check-sat)
diff --git a/test/regress/regress0/fmf/Arrow_Order-smtlib.778341.smt b/test/regress/regress0/fmf/Arrow_Order-smtlib.778341.smt
new file mode 100644
index 000000000..644d29737
--- /dev/null
+++ b/test/regress/regress0/fmf/Arrow_Order-smtlib.778341.smt
@@ -0,0 +1,265 @@
+% COMMAND-LINE: --finite-model-find
+% EXPECT: unsat
+% EXIT: 20
+(benchmark Isabelle
+:status sat
+:logic AUFLIA
+:extrasorts ( S1 S2 S3 S4 S5 S6 S7 S8 S9 S10 S11 S12 S13 S14 S15 S16 S17 S18 S19 S20 S21 S22 S23 S24 S25 S26 S27 S28 S29 S30 S31 S32 S33 S34 S35 S36 S37)
+:extrafuns (
+ (f1 S1)
+ (f2 S1)
+ (f3 S3 S2 S1)
+ (f4 S4 S2 S3)
+ (f5 S4)
+ (f6 S6 S5 S1)
+ (f7 S7 S5 S6)
+ (f8 S7)
+ (f9 S9 S8 S1)
+ (f10 S10 S8 S9)
+ (f11 S10)
+ (f12 S1)
+ (f13 S12 S1)
+ (f14 S12)
+ (f15 S12 S1)
+ (f16 S2)
+ (f17 S13 S2 S2)
+ (f18 S14 S11 S13)
+ (f19 S14)
+ (f20 S5)
+ (f21 S16 S5 S5)
+ (f22 S17 S15 S16)
+ (f23 S17)
+ (f24 S8)
+ (f25 S18 S8 S8)
+ (f26 S19 S5 S18)
+ (f27 S19)
+ (f28 S20 S2 S13)
+ (f29 S20)
+ (f30 S21 S5 S16)
+ (f31 S21)
+ (f32 S22 S8 S18)
+ (f33 S22)
+ (f34 S14)
+ (f35 S17)
+ (f36 S19)
+ (f37 S24 S23 S2)
+ (f38 S25 S2 S24)
+ (f39 S25)
+ (f40 S26 S23 S1)
+ (f41 S27 Int S26)
+ (f42 S27)
+ (f43 S28 S23 S5)
+ (f44 S29 S5 S28)
+ (f45 S29)
+ (f46 S30 S23 S8)
+ (f47 S31 S8 S30)
+ (f48 S31)
+ (f49 S2 S1)
+ (f50 S5 S1)
+ (f51 S8 S1)
+ (f52 S4)
+ (f53 S7)
+ (f54 S10)
+ (f55 S32 S2 S11)
+ (f56 S32)
+ (f57 S33 S5 S15)
+ (f58 S33)
+ (f59 S34 S8 S5)
+ (f60 S34)
+ (f61 S35 S11 S1)
+ (f62 S2 S35)
+ (f63 S36 S15 S1)
+ (f64 S5 S36)
+ (f65 S8 S6)
+ (f66 S35 S3)
+ (f67 S36 S6)
+ (f68 S6 S9)
+ (f69 S11 S3)
+ (f70 S5 S9)
+ (f71 S15 S6)
+ (f72 S13)
+ (f73 S16)
+ (f74 S18)
+ (f75 S20)
+ (f76 S21)
+ (f77 S22)
+ (f78 S37 S26 Int)
+ (f79 S37)
+)
+:assumption (not (= f1 f2))
+:assumption (forall (?v0 S2) (?v1 S2) (iff (= (f3 (f4 f5 ?v0) ?v1) f1) (= ?v0 ?v1)) )
+:assumption (forall (?v0 S5) (?v1 S5) (iff (= (f6 (f7 f8 ?v0) ?v1) f1) (= ?v0 ?v1)) )
+:assumption (forall (?v0 S8) (?v1 S8) (iff (= (f9 (f10 f11 ?v0) ?v1) f1) (= ?v0 ?v1)) )
+:assumption (not (= f12 f1))
+:assumption (forall (?v0 S11) (?v1 S11) (implies (not (= ?v0 ?v1)) (= f12 f1)))
+:assumption (exists (?v0 S11) (?v1 S11) (?v2 S11) (distinct ?v0 ?v1 ?v2))
+:assumption (exists (?v0 S11) (?v1 S11) (?v2 S11) (distinct ?v0 ?v1 ?v2) )
+:assumption (= (f13 f14) f1)
+:assumption (= (f15 f14) f1)
+:assumption (forall (?v0 S11) (?v1 S11) (implies (not (= ?v0 ?v1)) (exists (?v2 S11) (distinct ?v0 ?v1 ?v2))) )
+:assumption (forall (?v0 S11) (?v1 S2) (not (= f16 (f17 (f18 f19 ?v0) ?v1))) )
+:assumption (forall (?v0 S15) (?v1 S5) (not (= f20 (f21 (f22 f23 ?v0) ?v1))) )
+:assumption (forall (?v0 S5) (?v1 S8) (not (= f24 (f25 (f26 f27 ?v0) ?v1))) )
+:assumption (forall (?v0 S11) (?v1 S2) (not (= (f17 (f18 f19 ?v0) ?v1) f16)) )
+:assumption (forall (?v0 S15) (?v1 S5) (not (= (f21 (f22 f23 ?v0) ?v1) f20)) )
+:assumption (forall (?v0 S5) (?v1 S8) (not (= (f25 (f26 f27 ?v0) ?v1) f24)) )
+:assumption (forall (?v0 S2) (iff (not (= ?v0 f16)) (exists (?v1 S11) (?v2 S2) (= ?v0 (f17 (f18 f19 ?v1) ?v2)))) )
+:assumption (forall (?v0 S5) (iff (not (= ?v0 f20)) (exists (?v1 S15) (?v2 S5) (= ?v0 (f21 (f22 f23 ?v1) ?v2)))) )
+:assumption (forall (?v0 S8) (iff (not (= ?v0 f24)) (exists (?v1 S5) (?v2 S8) (= ?v0 (f25 (f26 f27 ?v1) ?v2)))) )
+:assumption (forall (?v0 S2) (implies (implies (= ?v0 f16) false) (implies (forall (?v1 S11) (?v2 S2) (implies (= ?v0 (f17 (f18 f19 ?v1) ?v2)) false)) false)) )
+:assumption (forall (?v0 S5) (implies (implies (= ?v0 f20) false) (implies (forall (?v1 S15) (?v2 S5) (implies (= ?v0 (f21 (f22 f23 ?v1) ?v2)) false)) false)) )
+:assumption (forall (?v0 S8) (implies (implies (= ?v0 f24) false) (implies (forall (?v1 S5) (?v2 S8) (implies (= ?v0 (f25 (f26 f27 ?v1) ?v2)) false)) false)) )
+:assumption (forall (?v0 S2) (?v1 S11) (not (= ?v0 (f17 (f18 f19 ?v1) ?v0))) )
+:assumption (forall (?v0 S8) (?v1 S5) (not (= ?v0 (f25 (f26 f27 ?v1) ?v0))) )
+:assumption (forall (?v0 S5) (?v1 S15) (not (= ?v0 (f21 (f22 f23 ?v1) ?v0))) )
+:assumption (forall (?v0 S11) (?v1 S2) (not (= (f17 (f18 f19 ?v0) ?v1) ?v1)) )
+:assumption (forall (?v0 S5) (?v1 S8) (not (= (f25 (f26 f27 ?v0) ?v1) ?v1)) )
+:assumption (forall (?v0 S15) (?v1 S5) (not (= (f21 (f22 f23 ?v0) ?v1) ?v1)) )
+:assumption (forall (?v0 S11) (?v1 S2) (?v2 S11) (?v3 S2) (iff (= (f17 (f18 f19 ?v0) ?v1) (f17 (f18 f19 ?v2) ?v3)) (and (= ?v0 ?v2) (= ?v1 ?v3))) )
+:assumption (forall (?v0 S5) (?v1 S8) (?v2 S5) (?v3 S8) (iff (= (f25 (f26 f27 ?v0) ?v1) (f25 (f26 f27 ?v2) ?v3)) (and (= ?v0 ?v2) (= ?v1 ?v3))) )
+:assumption (forall (?v0 S15) (?v1 S5) (?v2 S15) (?v3 S5) (iff (= (f21 (f22 f23 ?v0) ?v1) (f21 (f22 f23 ?v2) ?v3)) (and (= ?v0 ?v2) (= ?v1 ?v3))) )
+:assumption (forall (?v0 S11) (?v1 S2) (= (f17 (f28 f29 (f17 (f18 f19 ?v0) ?v1)) f16) (f17 (f18 f19 ?v0) ?v1)) )
+:assumption (forall (?v0 S15) (?v1 S5) (= (f21 (f30 f31 (f21 (f22 f23 ?v0) ?v1)) f20) (f21 (f22 f23 ?v0) ?v1)) )
+:assumption (forall (?v0 S5) (?v1 S8) (= (f25 (f32 f33 (f25 (f26 f27 ?v0) ?v1)) f24) (f25 (f26 f27 ?v0) ?v1)) )
+:assumption (forall (?v0 S11) (= (f17 (f18 f34 ?v0) f16) (f17 (f18 f19 ?v0) f16)) )
+:assumption (forall (?v0 S15) (= (f21 (f22 f35 ?v0) f20) (f21 (f22 f23 ?v0) f20)) )
+:assumption (forall (?v0 S5) (= (f25 (f26 f36 ?v0) f24) (f25 (f26 f27 ?v0) f24)) )
+:assumption (forall (?v0 S2) (?v1 S3) (implies (not (= ?v0 f16)) (implies (forall (?v2 S11) (= (f3 ?v1 (f17 (f18 f19 ?v2) f16)) f1)) (implies (forall (?v2 S11) (?v3 S2) (implies (not (= ?v3 f16)) (implies (= (f3 ?v1 ?v3) f1) (= (f3 ?v1 (f17 (f18 f19 ?v2) ?v3)) f1)))) (= (f3 ?v1 ?v0) f1)))) )
+:assumption (forall (?v0 S5) (?v1 S6) (implies (not (= ?v0 f20)) (implies (forall (?v2 S15) (= (f6 ?v1 (f21 (f22 f23 ?v2) f20)) f1)) (implies (forall (?v2 S15) (?v3 S5) (implies (not (= ?v3 f20)) (implies (= (f6 ?v1 ?v3) f1) (= (f6 ?v1 (f21 (f22 f23 ?v2) ?v3)) f1)))) (= (f6 ?v1 ?v0) f1)))) )
+:assumption (forall (?v0 S8) (?v1 S9) (implies (not (= ?v0 f24)) (implies (forall (?v2 S5) (= (f9 ?v1 (f25 (f26 f27 ?v2) f24)) f1)) (implies (forall (?v2 S5) (?v3 S8) (implies (not (= ?v3 f24)) (implies (= (f9 ?v1 ?v3) f1) (= (f9 ?v1 (f25 (f26 f27 ?v2) ?v3)) f1)))) (= (f9 ?v1 ?v0) f1)))) )
+:assumption (forall (?v0 S11) (?v1 S23) (= (f37 (f38 f39 (f17 (f18 f19 ?v0) f16)) ?v1) (ite (= (f40 (f41 f42 0) ?v1) f1) (f17 (f18 f19 ?v0) f16) f16)) )
+:assumption (forall (?v0 S15) (?v1 S23) (= (f43 (f44 f45 (f21 (f22 f23 ?v0) f20)) ?v1) (ite (= (f40 (f41 f42 0) ?v1) f1) (f21 (f22 f23 ?v0) f20) f20)) )
+:assumption (forall (?v0 S5) (?v1 S23) (= (f46 (f47 f48 (f25 (f26 f27 ?v0) f24)) ?v1) (ite (= (f40 (f41 f42 0) ?v1) f1) (f25 (f26 f27 ?v0) f24) f24)) )
+:assumption (forall (?v0 S23) (= (f37 (f38 f39 f16) ?v0) f16) )
+:assumption (forall (?v0 S23) (= (f43 (f44 f45 f20) ?v0) f20) )
+:assumption (forall (?v0 S23) (= (f46 (f47 f48 f24) ?v0) f24) )
+:assumption (forall (?v0 S11) (?v1 S2) (?v2 S11) (?v3 S2) (= (f17 (f28 f29 (f17 (f18 f19 ?v0) ?v1)) (f17 (f18 f19 ?v2) ?v3)) (f17 (f18 f19 ?v0) (f17 (f18 f19 ?v2) (f17 (f28 f29 ?v1) ?v3)))) )
+:assumption (forall (?v0 S5) (?v1 S8) (?v2 S5) (?v3 S8) (= (f25 (f32 f33 (f25 (f26 f27 ?v0) ?v1)) (f25 (f26 f27 ?v2) ?v3)) (f25 (f26 f27 ?v0) (f25 (f26 f27 ?v2) (f25 (f32 f33 ?v1) ?v3)))) )
+:assumption (forall (?v0 S15) (?v1 S5) (?v2 S15) (?v3 S5) (= (f21 (f30 f31 (f21 (f22 f23 ?v0) ?v1)) (f21 (f22 f23 ?v2) ?v3)) (f21 (f22 f23 ?v0) (f21 (f22 f23 ?v2) (f21 (f30 f31 ?v1) ?v3)))) )
+:assumption (forall (?v0 S2) (= (f17 (f28 f29 ?v0) f16) ?v0) )
+:assumption (forall (?v0 S5) (= (f21 (f30 f31 ?v0) f20) ?v0) )
+:assumption (forall (?v0 S8) (= (f25 (f32 f33 ?v0) f24) ?v0) )
+:assumption (forall (?v0 S2) (= (f17 (f28 f29 f16) ?v0) ?v0) )
+:assumption (forall (?v0 S5) (= (f21 (f30 f31 f20) ?v0) ?v0) )
+:assumption (forall (?v0 S8) (= (f25 (f32 f33 f24) ?v0) ?v0) )
+:assumption (forall (?v0 S2) (iff (= ?v0 f16) (= (f49 ?v0) f1)) )
+:assumption (forall (?v0 S5) (iff (= ?v0 f20) (= (f50 ?v0) f1)) )
+:assumption (forall (?v0 S8) (iff (= ?v0 f24) (= (f51 ?v0) f1)) )
+:assumption (forall (?v0 S2) (iff (= (f49 ?v0) f1) (= ?v0 f16)) )
+:assumption (forall (?v0 S5) (iff (= (f50 ?v0) f1) (= ?v0 f20)) )
+:assumption (forall (?v0 S8) (iff (= (f51 ?v0) f1) (= ?v0 f24)) )
+:assumption (iff (= (f49 f16) f1) true)
+:assumption (iff (= (f50 f20) f1) true)
+:assumption (iff (= (f51 f24) f1) true)
+:assumption (forall (?v0 S11) (?v1 S2) (iff (= (f49 (f17 (f18 f19 ?v0) ?v1)) f1) false) )
+:assumption (forall (?v0 S5) (?v1 S8) (iff (= (f51 (f25 (f26 f27 ?v0) ?v1)) f1) false) )
+:assumption (forall (?v0 S15) (?v1 S5) (iff (= (f50 (f21 (f22 f23 ?v0) ?v1)) f1) false) )
+:assumption (forall (?v0 S2) (iff (= (f3 (f4 f52 ?v0) f16) f1) (= (f49 ?v0) f1)) )
+:assumption (forall (?v0 S5) (iff (= (f6 (f7 f53 ?v0) f20) f1) (= (f50 ?v0) f1)) )
+:assumption (forall (?v0 S8) (iff (= (f9 (f10 f54 ?v0) f24) f1) (= (f51 ?v0) f1)) )
+:assumption (forall (?v0 S11) (?v1 S2) (= (f55 f56 (f17 (f18 f19 ?v0) ?v1)) (ite (= ?v1 f16) ?v0 (f55 f56 ?v1))) )
+:assumption (forall (?v0 S15) (?v1 S5) (= (f57 f58 (f21 (f22 f23 ?v0) ?v1)) (ite (= ?v1 f20) ?v0 (f57 f58 ?v1))) )
+:assumption (forall (?v0 S5) (?v1 S8) (= (f59 f60 (f25 (f26 f27 ?v0) ?v1)) (ite (= ?v1 f24) ?v0 (f59 f60 ?v1))) )
+:assumption (forall (?v0 S2) (?v1 S11) (implies (not (= ?v0 f16)) (= (f55 f56 (f17 (f18 f19 ?v1) ?v0)) (f55 f56 ?v0))) )
+:assumption (forall (?v0 S5) (?v1 S15) (implies (not (= ?v0 f20)) (= (f57 f58 (f21 (f22 f23 ?v1) ?v0)) (f57 f58 ?v0))) )
+:assumption (forall (?v0 S8) (?v1 S5) (implies (not (= ?v0 f24)) (= (f59 f60 (f25 (f26 f27 ?v1) ?v0)) (f59 f60 ?v0))) )
+:assumption (forall (?v0 S2) (?v1 S11) (implies (= ?v0 f16) (= (f55 f56 (f17 (f18 f19 ?v1) ?v0)) ?v1)) )
+:assumption (forall (?v0 S5) (?v1 S15) (implies (= ?v0 f20) (= (f57 f58 (f21 (f22 f23 ?v1) ?v0)) ?v1)) )
+:assumption (forall (?v0 S8) (?v1 S5) (implies (= ?v0 f24) (= (f59 f60 (f25 (f26 f27 ?v1) ?v0)) ?v1)) )
+:assumption (forall (?v0 S11) (iff (= (f61 (f62 f16) ?v0) f1) false) )
+:assumption (forall (?v0 S15) (iff (= (f63 (f64 f20) ?v0) f1) false) )
+:assumption (forall (?v0 S5) (iff (= (f6 (f65 f24) ?v0) f1) false) )
+:assumption (forall (?v0 S35) (iff (= (f3 (f66 ?v0) f16) f1) false) )
+:assumption (forall (?v0 S36) (iff (= (f6 (f67 ?v0) f20) f1) false) )
+:assumption (forall (?v0 S6) (iff (= (f9 (f68 ?v0) f24) f1) false) )
+:assumption (forall (?v0 S11) (?v1 S2) (= (f3 (f69 ?v0) (f17 (f18 f19 ?v0) ?v1)) f1) )
+:assumption (forall (?v0 S5) (?v1 S8) (= (f9 (f70 ?v0) (f25 (f26 f27 ?v0) ?v1)) f1) )
+:assumption (forall (?v0 S15) (?v1 S5) (= (f6 (f71 ?v0) (f21 (f22 f23 ?v0) ?v1)) f1) )
+:assumption (forall (?v0 S11) (?v1 S2) (?v2 S11) (iff (= (f61 (f62 (f17 (f18 f19 ?v0) ?v1)) ?v2) f1) (or (= ?v0 ?v2) (= (f61 (f62 ?v1) ?v2) f1))) )
+:assumption (forall (?v0 S5) (?v1 S8) (?v2 S5) (iff (= (f6 (f65 (f25 (f26 f27 ?v0) ?v1)) ?v2) f1) (or (= ?v0 ?v2) (= (f6 (f65 ?v1) ?v2) f1))) )
+:assumption (forall (?v0 S15) (?v1 S5) (?v2 S15) (iff (= (f63 (f64 (f21 (f22 f23 ?v0) ?v1)) ?v2) f1) (or (= ?v0 ?v2) (= (f63 (f64 ?v1) ?v2) f1))) )
+:assumption (forall (?v0 S8) (?v1 S8) (iff (= (f9 (f10 f54 ?v0) ?v1) f1) (= ?v0 ?v1)) )
+:assumption (forall (?v0 S5) (?v1 S5) (iff (= (f6 (f7 f53 ?v0) ?v1) f1) (= ?v0 ?v1)) )
+:assumption (forall (?v0 S2) (?v1 S2) (iff (= (f3 (f4 f52 ?v0) ?v1) f1) (= ?v0 ?v1)) )
+:assumption (= (f17 f72 f16) f16)
+:assumption (= (f21 f73 f20) f20)
+:assumption (= (f25 f74 f24) f24)
+:assumption (forall (?v0 S11) (?v1 S2) (= (f17 f72 (f17 (f18 f19 ?v0) ?v1)) (ite (= ?v1 f16) f16 (f17 (f18 f19 ?v0) (f17 f72 ?v1)))) )
+:assumption (forall (?v0 S15) (?v1 S5) (= (f21 f73 (f21 (f22 f23 ?v0) ?v1)) (ite (= ?v1 f20) f20 (f21 (f22 f23 ?v0) (f21 f73 ?v1)))) )
+:assumption (forall (?v0 S5) (?v1 S8) (= (f25 f74 (f25 (f26 f27 ?v0) ?v1)) (ite (= ?v1 f24) f24 (f25 (f26 f27 ?v0) (f25 f74 ?v1)))) )
+:assumption (forall (?v0 S11) (?v1 S2) (?v2 S11) (implies (= (f3 (f69 ?v0) ?v1) f1) (= (f3 (f69 ?v0) (f17 (f18 f19 ?v2) ?v1)) f1)) )
+:assumption (forall (?v0 S5) (?v1 S8) (?v2 S5) (implies (= (f9 (f70 ?v0) ?v1) f1) (= (f9 (f70 ?v0) (f25 (f26 f27 ?v2) ?v1)) f1)) )
+:assumption (forall (?v0 S15) (?v1 S5) (?v2 S15) (implies (= (f6 (f71 ?v0) ?v1) f1) (= (f6 (f71 ?v0) (f21 (f22 f23 ?v2) ?v1)) f1)) )
+:assumption (forall (?v0 S2) (implies (not (= ?v0 f16)) (= (f17 (f28 f75 (f17 f72 ?v0)) (f17 (f18 f19 (f55 f56 ?v0)) f16)) ?v0)) )
+:assumption (forall (?v0 S5) (implies (not (= ?v0 f20)) (= (f21 (f30 f76 (f21 f73 ?v0)) (f21 (f22 f23 (f57 f58 ?v0)) f20)) ?v0)) )
+:assumption (forall (?v0 S8) (implies (not (= ?v0 f24)) (= (f25 (f32 f77 (f25 f74 ?v0)) (f25 (f26 f27 (f59 f60 ?v0)) f24)) ?v0)) )
+:assumption (forall (?v0 S2) (?v1 S11) (?v2 S2) (iff (= (f17 (f28 f75 ?v0) (f17 (f18 f19 ?v1) f16)) ?v2) (and (not (= ?v2 f16)) (and (= (f17 f72 ?v2) ?v0) (= (f55 f56 ?v2) ?v1)))) )
+:assumption (forall (?v0 S5) (?v1 S15) (?v2 S5) (iff (= (f21 (f30 f76 ?v0) (f21 (f22 f23 ?v1) f20)) ?v2) (and (not (= ?v2 f20)) (and (= (f21 f73 ?v2) ?v0) (= (f57 f58 ?v2) ?v1)))) )
+:assumption (forall (?v0 S8) (?v1 S5) (?v2 S8) (iff (= (f25 (f32 f77 ?v0) (f25 (f26 f27 ?v1) f24)) ?v2) (and (not (= ?v2 f24)) (and (= (f25 f74 ?v2) ?v0) (= (f59 f60 ?v2) ?v1)))) )
+:assumption (= f11 f54)
+:assumption (= f8 f53)
+:assumption (= f5 f52)
+:assumption (forall (?v0 S8) (?v1 S8) (iff (= (f9 (f10 f54 ?v0) ?v1) f1) (= ?v0 ?v1)) )
+:assumption (forall (?v0 S5) (?v1 S5) (iff (= (f6 (f7 f53 ?v0) ?v1) f1) (= ?v0 ?v1)) )
+:assumption (forall (?v0 S2) (?v1 S2) (iff (= (f3 (f4 f52 ?v0) ?v1) f1) (= ?v0 ?v1)) )
+:assumption (forall (?v0 S8) (iff (= (f9 (f10 f54 ?v0) ?v0) f1) true) )
+:assumption (forall (?v0 S5) (iff (= (f6 (f7 f53 ?v0) ?v0) f1) true) )
+:assumption (forall (?v0 S2) (iff (= (f3 (f4 f52 ?v0) ?v0) f1) true) )
+:assumption (= f54 f11)
+:assumption (= f53 f8)
+:assumption (= f52 f5)
+:assumption (forall (?v0 S11) (?v1 S2) (iff (= (f3 (f69 ?v0) ?v1) f1) (or (exists (?v2 S11) (?v3 S2) (and (= ?v0 ?v2) (= ?v1 (f17 (f18 f19 ?v2) ?v3)))) (exists (?v2 S11) (?v3 S2) (?v4 S11) (and (= ?v0 ?v2) (and (= ?v1 (f17 (f18 f19 ?v4) ?v3)) (= (f3 (f69 ?v2) ?v3) f1)))))) )
+:assumption (forall (?v0 S5) (?v1 S8) (iff (= (f9 (f70 ?v0) ?v1) f1) (or (exists (?v2 S5) (?v3 S8) (and (= ?v0 ?v2) (= ?v1 (f25 (f26 f27 ?v2) ?v3)))) (exists (?v2 S5) (?v3 S8) (?v4 S5) (and (= ?v0 ?v2) (and (= ?v1 (f25 (f26 f27 ?v4) ?v3)) (= (f9 (f70 ?v2) ?v3) f1)))))) )
+:assumption (forall (?v0 S15) (?v1 S5) (iff (= (f6 (f71 ?v0) ?v1) f1) (or (exists (?v2 S15) (?v3 S5) (and (= ?v0 ?v2) (= ?v1 (f21 (f22 f23 ?v2) ?v3)))) (exists (?v2 S15) (?v3 S5) (?v4 S15) (and (= ?v0 ?v2) (and (= ?v1 (f21 (f22 f23 ?v4) ?v3)) (= (f6 (f71 ?v2) ?v3) f1)))))) )
+:assumption (forall (?v0 S2) (?v1 S11) (= (f55 f56 (f17 (f28 f75 ?v0) (f17 (f18 f19 ?v1) f16))) ?v1) )
+:assumption (forall (?v0 S5) (?v1 S15) (= (f57 f58 (f21 (f30 f76 ?v0) (f21 (f22 f23 ?v1) f20))) ?v1) )
+:assumption (forall (?v0 S8) (?v1 S5) (= (f59 f60 (f25 (f32 f77 ?v0) (f25 (f26 f27 ?v1) f24))) ?v1) )
+:assumption (forall (?v0 S8) (?v1 S8) (?v2 S8) (?v3 S8) (?v4 S8) (implies (= (f25 (f32 f77 ?v0) ?v1) ?v2) (implies (= ?v3 (f25 (f32 f77 ?v1) ?v4)) (= (f25 (f32 f77 ?v0) ?v3) (f25 (f32 f77 ?v2) ?v4)))) )
+:assumption (forall (?v0 S5) (?v1 S5) (?v2 S5) (?v3 S5) (?v4 S5) (implies (= (f21 (f30 f76 ?v0) ?v1) ?v2) (implies (= ?v3 (f21 (f30 f76 ?v1) ?v4)) (= (f21 (f30 f76 ?v0) ?v3) (f21 (f30 f76 ?v2) ?v4)))) )
+:assumption (forall (?v0 S2) (?v1 S2) (?v2 S2) (?v3 S2) (?v4 S2) (implies (= (f17 (f28 f75 ?v0) ?v1) ?v2) (implies (= ?v3 (f17 (f28 f75 ?v1) ?v4)) (= (f17 (f28 f75 ?v0) ?v3) (f17 (f28 f75 ?v2) ?v4)))) )
+:assumption (forall (?v0 S8) (?v1 S8) (?v2 S8) (iff (= (f25 (f32 f77 ?v0) ?v1) (f25 (f32 f77 ?v2) ?v1)) (= ?v0 ?v2)) )
+:assumption (forall (?v0 S5) (?v1 S5) (?v2 S5) (iff (= (f21 (f30 f76 ?v0) ?v1) (f21 (f30 f76 ?v2) ?v1)) (= ?v0 ?v2)) )
+:assumption (forall (?v0 S2) (?v1 S2) (?v2 S2) (iff (= (f17 (f28 f75 ?v0) ?v1) (f17 (f28 f75 ?v2) ?v1)) (= ?v0 ?v2)) )
+:assumption (forall (?v0 S8) (?v1 S8) (?v2 S8) (iff (= (f25 (f32 f77 ?v0) ?v1) (f25 (f32 f77 ?v0) ?v2)) (= ?v1 ?v2)) )
+:assumption (forall (?v0 S5) (?v1 S5) (?v2 S5) (iff (= (f21 (f30 f76 ?v0) ?v1) (f21 (f30 f76 ?v0) ?v2)) (= ?v1 ?v2)) )
+:assumption (forall (?v0 S2) (?v1 S2) (?v2 S2) (iff (= (f17 (f28 f75 ?v0) ?v1) (f17 (f28 f75 ?v0) ?v2)) (= ?v1 ?v2)) )
+:assumption (forall (?v0 S8) (?v1 S8) (?v2 S8) (?v3 S8) (iff (= (f25 (f32 f77 ?v0) ?v1) (f25 (f32 f77 ?v2) ?v3)) (exists (?v4 S8) (or (and (= ?v0 (f25 (f32 f77 ?v2) ?v4)) (= (f25 (f32 f77 ?v4) ?v1) ?v3)) (and (= (f25 (f32 f77 ?v0) ?v4) ?v2) (= ?v1 (f25 (f32 f77 ?v4) ?v3)))))) )
+:assumption (forall (?v0 S5) (?v1 S5) (?v2 S5) (?v3 S5) (iff (= (f21 (f30 f76 ?v0) ?v1) (f21 (f30 f76 ?v2) ?v3)) (exists (?v4 S5) (or (and (= ?v0 (f21 (f30 f76 ?v2) ?v4)) (= (f21 (f30 f76 ?v4) ?v1) ?v3)) (and (= (f21 (f30 f76 ?v0) ?v4) ?v2) (= ?v1 (f21 (f30 f76 ?v4) ?v3)))))) )
+:assumption (forall (?v0 S2) (?v1 S2) (?v2 S2) (?v3 S2) (iff (= (f17 (f28 f75 ?v0) ?v1) (f17 (f28 f75 ?v2) ?v3)) (exists (?v4 S2) (or (and (= ?v0 (f17 (f28 f75 ?v2) ?v4)) (= (f17 (f28 f75 ?v4) ?v1) ?v3)) (and (= (f17 (f28 f75 ?v0) ?v4) ?v2) (= ?v1 (f17 (f28 f75 ?v4) ?v3)))))) )
+:assumption (forall (?v0 S8) (?v1 S8) (?v2 S8) (= (f25 (f32 f77 (f25 (f32 f77 ?v0) ?v1)) ?v2) (f25 (f32 f77 ?v0) (f25 (f32 f77 ?v1) ?v2))) )
+:assumption (forall (?v0 S5) (?v1 S5) (?v2 S5) (= (f21 (f30 f76 (f21 (f30 f76 ?v0) ?v1)) ?v2) (f21 (f30 f76 ?v0) (f21 (f30 f76 ?v1) ?v2))) )
+:assumption (forall (?v0 S2) (?v1 S2) (?v2 S2) (= (f17 (f28 f75 (f17 (f28 f75 ?v0) ?v1)) ?v2) (f17 (f28 f75 ?v0) (f17 (f28 f75 ?v1) ?v2))) )
+:assumption (forall (?v0 S11) (?v1 S2) (?v2 S2) (= (f17 (f28 f75 (f17 (f18 f19 ?v0) ?v1)) ?v2) (f17 (f18 f19 ?v0) (f17 (f28 f75 ?v1) ?v2))) )
+:assumption (forall (?v0 S5) (?v1 S8) (?v2 S8) (= (f25 (f32 f77 (f25 (f26 f27 ?v0) ?v1)) ?v2) (f25 (f26 f27 ?v0) (f25 (f32 f77 ?v1) ?v2))) )
+:assumption (forall (?v0 S15) (?v1 S5) (?v2 S5) (= (f21 (f30 f76 (f21 (f22 f23 ?v0) ?v1)) ?v2) (f21 (f22 f23 ?v0) (f21 (f30 f76 ?v1) ?v2))) )
+:assumption (forall (?v0 S11) (?v1 S2) (?v2 S2) (?v3 S2) (?v4 S2) (implies (= (f17 (f18 f19 ?v0) ?v1) ?v2) (implies (= ?v3 (f17 (f28 f75 ?v1) ?v4)) (= (f17 (f18 f19 ?v0) ?v3) (f17 (f28 f75 ?v2) ?v4)))) )
+:assumption (forall (?v0 S5) (?v1 S8) (?v2 S8) (?v3 S8) (?v4 S8) (implies (= (f25 (f26 f27 ?v0) ?v1) ?v2) (implies (= ?v3 (f25 (f32 f77 ?v1) ?v4)) (= (f25 (f26 f27 ?v0) ?v3) (f25 (f32 f77 ?v2) ?v4)))) )
+:assumption (forall (?v0 S15) (?v1 S5) (?v2 S5) (?v3 S5) (?v4 S5) (implies (= (f21 (f22 f23 ?v0) ?v1) ?v2) (implies (= ?v3 (f21 (f30 f76 ?v1) ?v4)) (= (f21 (f22 f23 ?v0) ?v3) (f21 (f30 f76 ?v2) ?v4)))) )
+:assumption (forall (?v0 S2) (= (f17 (f28 f75 f16) ?v0) ?v0) )
+:assumption (forall (?v0 S5) (= (f21 (f30 f76 f20) ?v0) ?v0) )
+:assumption (forall (?v0 S8) (= (f25 (f32 f77 f24) ?v0) ?v0) )
+:assumption (forall (?v0 S2) (?v1 S2) (iff (= f16 (f17 (f28 f75 ?v0) ?v1)) (and (= ?v0 f16) (= ?v1 f16))) )
+:assumption (forall (?v0 S5) (?v1 S5) (iff (= f20 (f21 (f30 f76 ?v0) ?v1)) (and (= ?v0 f20) (= ?v1 f20))) )
+:assumption (forall (?v0 S8) (?v1 S8) (iff (= f24 (f25 (f32 f77 ?v0) ?v1)) (and (= ?v0 f24) (= ?v1 f24))) )
+:assumption (forall (?v0 S2) (= (f17 (f28 f75 ?v0) f16) ?v0) )
+:assumption (forall (?v0 S5) (= (f21 (f30 f76 ?v0) f20) ?v0) )
+:assumption (forall (?v0 S8) (= (f25 (f32 f77 ?v0) f24) ?v0) )
+:assumption (forall (?v0 S2) (?v1 S2) (iff (= ?v0 (f17 (f28 f75 ?v0) ?v1)) (= ?v1 f16)) )
+:assumption (forall (?v0 S5) (?v1 S5) (iff (= ?v0 (f21 (f30 f76 ?v0) ?v1)) (= ?v1 f20)) )
+:assumption (forall (?v0 S8) (?v1 S8) (iff (= ?v0 (f25 (f32 f77 ?v0) ?v1)) (= ?v1 f24)) )
+:assumption (forall (?v0 S2) (?v1 S2) (iff (= ?v0 (f17 (f28 f75 ?v1) ?v0)) (= ?v1 f16)) )
+:assumption (forall (?v0 S5) (?v1 S5) (iff (= ?v0 (f21 (f30 f76 ?v1) ?v0)) (= ?v1 f20)) )
+:assumption (forall (?v0 S8) (?v1 S8) (iff (= ?v0 (f25 (f32 f77 ?v1) ?v0)) (= ?v1 f24)) )
+:assumption (forall (?v0 S26) (= (f41 f42 (f78 f79 ?v0)) ?v0))
+:assumption (forall (?v0 Int) (implies (<= 0 ?v0) (= (f78 f79 (f41 f42 ?v0)) ?v0)))
+:assumption (forall (?v0 Int) (implies (< ?v0 0) (= (f78 f79 (f41 f42 ?v0)) 0)))
+:formula true)
+; solver: z3
+; timeout: 5.0
+; random seed: 1
+; arguments:
+; DISPLAY_PROOF=true
+; PROOF_MODE=2
+; -rs:1
+; MODEL=true
+; -smt
diff --git a/test/regress/regress0/fmf/Hoare-z3.931718.smt b/test/regress/regress0/fmf/Hoare-z3.931718.smt
new file mode 100644
index 000000000..0b6fd0349
--- /dev/null
+++ b/test/regress/regress0/fmf/Hoare-z3.931718.smt
@@ -0,0 +1,50 @@
+% COMMAND-LINE: --finite-model-find
+% EXPECT: sat
+% EXIT: 10
+(benchmark Isabelle
+:status sat
+:logic AUFLIA
+:extrasorts ( S1 S2 S3 S4 S5 S6 S7 S8 S9 S10 S11)
+:extrafuns (
+ (f1 S1)
+ (f2 S1)
+ (f3 S3 S2 S1)
+ (f4 S4 S2 S3)
+ (f5 S4)
+ (f6 S5 S5 S1)
+ (f7 S5)
+ (f8 S6 S5 S5)
+ (f9 S7 S6)
+ (f10 S8 S4 S7)
+ (f11 S9 S10 S8)
+ (f12 S11 S4 S9)
+ (f13 S11)
+ (f14 S4)
+ (f15 S10)
+ (f16 S4)
+ (f17 S10 S4)
+ (f18 S5 S5 S1)
+)
+:assumption (not (= f1 f2))
+:assumption (forall (?v0 S2) (?v1 S2) (iff (= (f3 (f4 f5 ?v0) ?v1) f1) (= ?v0 ?v1)) )
+:assumption (not (= (f6 f7 (f8 (f9 (f10 (f11 (f12 f13 f14) f15) f16)) f7)) f1))
+:assumption (= (f6 f7 (f8 (f9 (f10 (f11 (f12 f13 f5) f15) (f17 f15))) f7)) f1)
+:assumption (= (f18 f7 (f8 (f9 (f10 (f11 (f12 f13 f14) f15) f16)) f7)) f1)
+:assumption (forall (?v0 S5) (= (f6 ?v0 f7) f1) )
+:assumption (forall (?v0 S4) (?v1 S10) (?v2 S4) (?v3 S4) (?v4 S10) (?v5 S4) (iff (= (f10 (f11 (f12 f13 ?v0) ?v1) ?v2) (f10 (f11 (f12 f13 ?v3) ?v4) ?v5)) (and (= ?v0 ?v3) (and (= ?v1 ?v4) (= ?v2 ?v5)))) )
+:assumption (forall (?v0 S5) (?v1 S5) (implies (= (f6 ?v0 ?v1) f1) (= (f18 ?v0 ?v1) f1)) )
+:assumption (forall (?v0 S5) (?v1 S5) (?v2 S5) (implies (= (f6 ?v0 ?v1) f1) (implies (= (f6 ?v2 ?v0) f1) (= (f6 ?v2 ?v1) f1))) )
+:assumption (forall (?v0 S5) (?v1 S7) (?v2 S5) (implies (= (f6 ?v0 (f8 (f9 ?v1) f7)) f1) (implies (= (f6 ?v0 ?v2) f1) (= (f6 ?v0 (f8 (f9 ?v1) ?v2)) f1))) )
+:assumption (forall (?v0 S5) (?v1 S7) (?v2 S5) (implies (= (f6 ?v0 (f8 (f9 ?v1) ?v2)) f1) (and (= (f6 ?v0 (f8 (f9 ?v1) f7)) f1) (= (f6 ?v0 ?v2) f1))) )
+:assumption (forall (?v0 S5) (?v1 S4) (?v2 S10) (?v3 S4) (?v4 S4) (implies (= (f6 ?v0 (f8 (f9 (f10 (f11 (f12 f13 ?v1) ?v2) ?v3)) f7)) f1) (implies (forall (?v5 S2) (?v6 S2) (implies (= (f3 (f4 ?v3 ?v5) ?v6) f1) (= (f3 (f4 ?v4 ?v5) ?v6) f1))) (= (f6 ?v0 (f8 (f9 (f10 (f11 (f12 f13 ?v1) ?v2) ?v4)) f7)) f1))) )
+:assumption (forall (?v0 S5) (?v1 S4) (?v2 S10) (?v3 S4) (?v4 S4) (implies (= (f6 ?v0 (f8 (f9 (f10 (f11 (f12 f13 ?v1) ?v2) ?v3)) f7)) f1) (implies (forall (?v5 S2) (?v6 S2) (implies (= (f3 (f4 ?v4 ?v5) ?v6) f1) (= (f3 (f4 ?v1 ?v5) ?v6) f1))) (= (f6 ?v0 (f8 (f9 (f10 (f11 (f12 f13 ?v4) ?v2) ?v3)) f7)) f1))) )
+:formula true)
+; solver: z3
+; timeout: 5.0
+; random seed: 1
+; arguments:
+; DISPLAY_PROOF=true
+; PROOF_MODE=2
+; -rs:1
+; MODEL=true
+; -smt
diff --git a/test/regress/regress0/fmf/Makefile.am b/test/regress/regress0/fmf/Makefile.am
new file mode 100755
index 000000000..a367447c9
--- /dev/null
+++ b/test/regress/regress0/fmf/Makefile.am
@@ -0,0 +1,47 @@
+BINARY = cvc4
+LOG_COMPILER = @srcdir@/../../run_regression
+AM_LOG_FLAGS = $(RUN_REGRESSION_ARGS) @top_builddir@/src/main/$(BINARY)$(EXEEXT)
+
+if AUTOMAKE_1_11
+# old-style (pre-automake 1.12) test harness
+TESTS_ENVIRONMENT = \
+ $(TESTS_ENVIRONMENT) $(LOG_COMPILER) \
+ $(AM_LOG_FLAGS) $(LOG_FLAGS)
+endif
+
+MAKEFLAGS = -k
+
+# These are run for all build profiles.
+# If a test shouldn't be run in e.g. competition mode,
+# put it below in "TESTS +="
+TESTS = \
+ agree466.smt2 \
+ ALG008-1.smt2 \
+ german169.smt2 \
+ Hoare-z3.931718.smt \
+ QEpres-uf.855035.smt \
+ agree467.smt2 \
+ Arrow_Order-smtlib.778341.smt \
+ german73.smt2 \
+ PUZ001+1.smt2 \
+ refcount24.cvc.smt2
+
+EXTRA_DIST = $(TESTS)
+
+#if CVC4_BUILD_PROFILE_COMPETITION
+#else
+#TESTS += \
+# error.cvc
+#endif
+#
+# and make sure to distribute it
+#EXTRA_DIST += \
+# error.cvc
+
+# synonyms for "check" in this directory
+.PHONY: regress regress0 test
+regress regress0 test: check
+
+# do nothing in this subdir
+.PHONY: regress1 regress2 regress3
+regress1 regress2 regress3:
diff --git a/test/regress/regress0/fmf/PUZ001+1.smt2 b/test/regress/regress0/fmf/PUZ001+1.smt2
new file mode 100644
index 000000000..4bcbf51c6
--- /dev/null
+++ b/test/regress/regress0/fmf/PUZ001+1.smt2
@@ -0,0 +1,119 @@
+; COMMAND-LINE: --finite-model-find
+; EXPECT: unsat
+; EXIT: 20
+;%------------------------------------------------------------------------------
+;% File : PUZ001+1 : TPTP v5.4.0. Released v2.0.0.
+;% Domain : Puzzles
+;% Problem : Dreadbury Mansion
+;% Version : Especial.
+;% Theorem formulation : Reduced > Complete.
+;% English : Someone who lives in Dreadbury Mansion killed Aunt Agatha.
+;% Agatha, the butler, and Charles live in Dreadbury Mansion,
+;% and are the only people who live therein. A killer always
+;% hates his victim, and is never richer than his victim.
+;% Charles hates no one that Aunt Agatha hates. Agatha hates
+;% everyone except the butler. The butler hates everyone not
+;% richer than Aunt Agatha. The butler hates everyone Aunt
+;% Agatha hates. No one hates everyone. Agatha is not the
+;% butler. Therefore : Agatha killed herself.
+
+;% Refs : [Pel86] Pelletier (1986), Seventy-five Problems for Testing Au
+;% : [Hah94] Haehnle (1994), Email to G. Sutcliffe
+;% Source : [Hah94]
+;% Names : Pelletier 55 [Pel86]
+
+;% Status : Theorem
+;% Rating : 0.07 v5.3.0, 0.19 v5.2.0, 0.00 v5.0.0, 0.08 v4.1.0, 0.13 v4.0.0, 0.12 v3.7.0, 0.14 v3.5.0, 0.00 v3.4.0, 0.08 v3.3.0, 0.11 v3.2.0, 0.22 v3.1.0, 0.17 v2.7.0, 0.00 v2.5.0, 0.33 v2.4.0, 0.33 v2.2.1, 0.00 v2.1.0
+;% Syntax : Number of formulae : 14 ( 6 unit)
+;% Number of atoms : 24 ( 5 equality)
+;% Maximal formula depth : 5 ( 3 average)
+;% Number of connectives : 16 ( 6 ~; 2 |; 1 &)
+;% ( 0 <=>; 7 =>; 0 <=; 0 <~>)
+;% ( 0 ~|; 0 ~&)
+;% Number of predicates : 5 ( 0 propositional; 1-2 arity)
+;% Number of functors : 3 ( 3 constant; 0-0 arity)
+;% Number of variables : 12 ( 0 sgn; 10 !; 2 ?)
+;% Maximal term depth : 1 ( 1 average)
+;% SPC : FOF_THM_RFO_SEQ
+
+;% Comments : Modified by Geoff Sutcliffe.
+;% : Also known as "Who killed Aunt Agatha"
+;%------------------------------------------------------------------------------
+;%----Problem axioms
+(set-logic UF)
+(set-info :status unsat)
+(declare-sort sort__smt2 0)
+; functions
+(declare-fun agatha__smt2_0 ( ) sort__smt2)
+(declare-fun butler__smt2_0 ( ) sort__smt2)
+(declare-fun charles__smt2_0 ( ) sort__smt2)
+; predicates
+(declare-fun lives__smt2_1 ( sort__smt2 ) Bool)
+(declare-fun killed__smt2_2 ( sort__smt2 sort__smt2 ) Bool)
+(declare-fun hates__smt2_2 ( sort__smt2 sort__smt2 ) Bool)
+(declare-fun richer__smt2_2 ( sort__smt2 sort__smt2 ) Bool)
+
+; pel55_1 axiom
+(assert (exists ((?X sort__smt2))
+ (and (lives__smt2_1 ?X)
+ (killed__smt2_2 ?X agatha__smt2_0))))
+
+; pel55_2_1 axiom
+(assert (lives__smt2_1 agatha__smt2_0))
+
+; pel55_2_2 axiom
+(assert (lives__smt2_1 butler__smt2_0))
+
+; pel55_2_3 axiom
+(assert (lives__smt2_1 charles__smt2_0))
+
+; pel55_3 axiom
+(assert (forall ((?X sort__smt2))
+ (=> (lives__smt2_1 ?X)
+ (or (= ?X agatha__smt2_0)
+ (= ?X butler__smt2_0)
+ (= ?X charles__smt2_0)))))
+
+; pel55_4 axiom
+(assert (forall ((?X sort__smt2) (?Y sort__smt2))
+ (=> (killed__smt2_2 ?X ?Y)
+ (hates__smt2_2 ?X ?Y))))
+
+; pel55_5 axiom
+(assert (forall ((?X sort__smt2) (?Y sort__smt2))
+ (=> (killed__smt2_2 ?X ?Y)
+ (not (richer__smt2_2 ?X ?Y)))))
+
+; pel55_6 axiom
+(assert (forall ((?X sort__smt2))
+ (=> (hates__smt2_2 agatha__smt2_0 ?X)
+ (not (hates__smt2_2 charles__smt2_0 ?X)))))
+
+; pel55_7 axiom
+(assert (forall ((?X sort__smt2))
+ (=> (not (= ?X butler__smt2_0))
+ (hates__smt2_2 agatha__smt2_0 ?X))))
+
+; pel55_8 axiom
+(assert (forall ((?X sort__smt2))
+ (=> (not (richer__smt2_2 ?X agatha__smt2_0))
+ (hates__smt2_2 butler__smt2_0 ?X))))
+
+; pel55_9 axiom
+(assert (forall ((?X sort__smt2))
+ (=> (hates__smt2_2 agatha__smt2_0 ?X)
+ (hates__smt2_2 butler__smt2_0 ?X))))
+
+; pel55_10 axiom
+(assert (forall ((?X sort__smt2))
+(exists ((?Y sort__smt2)) (not (hates__smt2_2 ?X ?Y)))))
+
+; pel55_11 axiom
+(assert (not (= agatha__smt2_0 butler__smt2_0)))
+
+;----This is the conjecture with negated conjecture
+; pel55 conjecture
+(assert (not (killed__smt2_2 agatha__smt2_0 agatha__smt2_0)))
+
+
+(check-sat)
diff --git a/test/regress/regress0/fmf/QEpres-uf.855035.smt b/test/regress/regress0/fmf/QEpres-uf.855035.smt
new file mode 100644
index 000000000..95ab0cb34
--- /dev/null
+++ b/test/regress/regress0/fmf/QEpres-uf.855035.smt
@@ -0,0 +1,85 @@
+% COMMAND-LINE: --finite-model-find
+% EXPECT: sat
+% EXIT: 10
+(benchmark Isabelle
+:status sat
+:logic AUFLIA
+:extrasorts ( S1 S2 S3 S4 S5 S6 S7 S8 S9 S10 S11 S12 S13 S14 S15 S16 S17 S18)
+:extrafuns (
+ (f1 S1)
+ (f2 S1)
+ (f3 S2 S3 S4)
+ (f4 S2)
+ (f5 S3)
+ (f6 S4)
+ (f7 S3 S5 S1)
+ (f8 S6 S5)
+ (f9 S6)
+ (f10 S7 S6 S6)
+ (f11 S7)
+ (f12 S8 S4 S4)
+ (f13 S8)
+ (f14 S10 S3 S3)
+ (f15 S11 S9 S10)
+ (f16 S12 S4 S11)
+ (f17 S12)
+ (f18 S4 S13 S1)
+ (f19 S13)
+ (f20 S4 S1)
+ (f21 S2)
+ (f22 S10)
+ (f23 S3 S9 S1)
+ (f24 S14 S9 S9)
+ (f25 S15 S4 S14)
+ (f26 S15)
+ (f27 S13)
+ (f28 S8)
+ (f29 S16 S9 S3)
+ (f30 S17 S4 S16)
+ (f31 S18 S4 S17)
+ (f32 S18)
+ (f33 S18)
+ (f34 S4 S4 S1)
+)
+:assumption (not (= f1 f2))
+:assumption (not (not (= (f3 f4 f5) f6)))
+:assumption (forall (?v0 S3) (implies (= (f7 ?v0 (f8 f9)) f1) (not (= (f3 f4 ?v0) f6))) )
+:assumption (= (f7 f5 (f8 (f10 f11 f9))) f1)
+:assumption (forall (?v0 S4) (iff (= f6 ?v0) (= ?v0 f6)) )
+:assumption (= (f12 f13 f6) f6)
+:assumption (forall (?v0 S4) (iff (= f6 (f12 f13 ?v0)) (= ?v0 f6)) )
+:assumption (forall (?v0 S4) (iff (= (f12 f13 ?v0) f6) (= ?v0 f6)) )
+:assumption (forall (?v0 S4) (?v1 S9) (?v2 S3) (= (f3 f4 (f14 (f15 (f16 f17 ?v0) ?v1) ?v2)) (f3 f4 ?v2)) )
+:assumption (= (f18 f6 f19) f1)
+:assumption (= (f20 f6) f1)
+:assumption (forall (?v0 S4) (iff (= (f20 ?v0) f1) (= ?v0 f6)) )
+:assumption (forall (?v0 S3) (implies (= (f7 ?v0 (f8 f9)) f1) (not (= (f3 f21 ?v0) f6))) )
+:assumption (forall (?v0 S3) (implies (not (not (= (f3 f21 ?v0) f6))) (implies (not (= (f3 f4 ?v0) f6)) (not (= (f3 f4 (f14 f22 ?v0)) f6)))) )
+:assumption (forall (?v0 S4) (?v1 S4) (iff (= (f12 f13 ?v0) (f12 f13 ?v1)) (= ?v0 ?v1)) )
+:assumption (forall (?v0 S6) (?v1 S9) (implies (forall (?v2 S3) (implies (= (f7 ?v2 (f8 ?v0)) f1) (not (= (f3 f21 ?v2) f6)))) (iff (exists (?v2 S4) (forall (?v3 S3) (implies (= (f7 ?v3 (f8 (f10 f11 ?v0))) f1) (= (f23 ?v3 (f24 (f25 f26 ?v2) ?v1)) f1)))) (exists (?v2 S4) (forall (?v3 S3) (implies (= (f7 ?v3 (f8 ?v0)) f1) (= (f23 ?v3 (f24 (f25 f26 ?v2) ?v1)) f1)))))) )
+:assumption (forall (?v0 S4) (= (f18 (f12 f13 ?v0) f27) f1) )
+:assumption (= (f12 f28 f6) f6)
+:assumption (forall (?v0 S4) (?v1 S4) (?v2 S9) (= (f3 f4 (f29 (f30 (f31 f32 ?v0) ?v1) ?v2)) ?v0) )
+:assumption (forall (?v0 S4) (?v1 S4) (?v2 S9) (= (f3 f4 (f29 (f30 (f31 f33 ?v0) ?v1) ?v2)) ?v0) )
+:assumption (= (f18 f6 f27) f1)
+:assumption (forall (?v0 S3) (?v1 S4) (?v2 S9) (implies (not (not (= (f3 f21 ?v0) f6))) (iff (= (f23 ?v0 (f24 (f25 f26 ?v1) ?v2)) f1) (= (f23 (f14 f22 ?v0) ?v2) f1))) )
+:assumption (forall (?v0 S4) (iff (= (f34 (f12 f13 ?v0) f6) f1) (= (f34 ?v0 f6) f1)) )
+:assumption (forall (?v0 S4) (iff (= (f34 f6 (f12 f13 ?v0)) f1) (= (f34 f6 ?v0) f1)) )
+:assumption (forall (?v0 S4) (?v1 S4) (?v2 S9) (?v3 S4) (?v4 S4) (?v5 S9) (not (= (f29 (f30 (f31 f33 ?v0) ?v1) ?v2) (f29 (f30 (f31 f32 ?v3) ?v4) ?v5))) )
+:assumption (forall (?v0 S4) (?v1 S4) (?v2 S9) (?v3 S4) (?v4 S4) (?v5 S9) (not (= (f29 (f30 (f31 f32 ?v0) ?v1) ?v2) (f29 (f30 (f31 f33 ?v3) ?v4) ?v5))) )
+:assumption (forall (?v0 S4) (= (f34 ?v0 ?v0) f1) )
+:assumption (forall (?v0 S4) (?v1 S4) (or (= (f34 ?v0 ?v1) f1) (= (f34 ?v1 ?v0) f1)) )
+:assumption (forall (?v0 S4) (?v1 S4) (?v2 S9) (?v3 S4) (?v4 S4) (?v5 S9) (iff (= (f29 (f30 (f31 f33 ?v0) ?v1) ?v2) (f29 (f30 (f31 f33 ?v3) ?v4) ?v5)) (and (= ?v0 ?v3) (and (= ?v1 ?v4) (= ?v2 ?v5)))) )
+:assumption (forall (?v0 S4) (?v1 S4) (?v2 S9) (?v3 S4) (?v4 S4) (?v5 S9) (iff (= (f29 (f30 (f31 f32 ?v0) ?v1) ?v2) (f29 (f30 (f31 f32 ?v3) ?v4) ?v5)) (and (= ?v0 ?v3) (and (= ?v1 ?v4) (= ?v2 ?v5)))) )
+:assumption (forall (?v0 S4) (?v1 S4) (?v2 S4) (implies (= (f34 ?v0 ?v1) f1) (implies (= (f34 ?v1 ?v2) f1) (= (f34 ?v0 ?v2) f1))) )
+:assumption (forall (?v0 S4) (?v1 S4) (implies (= (f34 ?v0 ?v1) f1) (implies (= (f34 ?v1 ?v0) f1) (= ?v0 ?v1))) )
+:formula true)
+; solver: z3
+; timeout: 1.897
+; random seed: 1
+; arguments:
+; DISPLAY_PROOF=true
+; PROOF_MODE=2
+; -rs:1
+; MODEL=true
+; -smt
diff --git a/test/regress/regress0/fmf/agree466.smt2 b/test/regress/regress0/fmf/agree466.smt2
new file mode 100644
index 000000000..2a021ea9b
--- /dev/null
+++ b/test/regress/regress0/fmf/agree466.smt2
@@ -0,0 +1,475 @@
+; COMMAND-LINE: --finite-model-find
+; EXPECT: sat
+; EXIT: 10
+; Preamble --------------
+(set-logic ALL_SUPPORTED)
+(set-info :status sat)
+(declare-datatypes () ((UNIT (Unit))))
+(declare-datatypes () ((BOOL (Truth) (Falsity))))
+
+; Decls --------------
+(declare-sort node$type 0)
+(declare-sort value$type 0)
+(define-sort Nodes$elem$type () node$type)
+(declare-sort Nodes$t$type 0)
+(declare-fun Nodes$empty () Nodes$t$type)
+(declare-fun Nodes$mem (Nodes$elem$type Nodes$t$type) BOOL)
+(declare-fun Nodes$add (Nodes$elem$type Nodes$t$type) Nodes$t$type)
+(declare-fun Nodes$remove (Nodes$elem$type Nodes$t$type) Nodes$t$type)
+(declare-fun Nodes$cardinality (Nodes$t$type) Int)
+(declare-fun Nodes$union (Nodes$t$type Nodes$t$type) Nodes$t$type)
+(declare-fun Nodes$disjoint (Nodes$t$type Nodes$t$type) BOOL)
+;Nodes$disjoint_empty :
+(assert (forall ((a Nodes$t$type)) (= (Nodes$disjoint a Nodes$empty) Truth)))
+;Nodes$disjoint_comm :
+(assert (forall ((a Nodes$t$type) (b Nodes$t$type)) (= (Nodes$disjoint a b)
+ (Nodes$disjoint b a))))
+;Nodes$mem_empty :
+(assert (forall ((e Nodes$elem$type)) (not (= (Nodes$mem e Nodes$empty)
+ Truth))))
+;Nodes$mem_add :
+(assert (forall ((x Nodes$elem$type) (y Nodes$elem$type) (s Nodes$t$type))
+ (= (Nodes$mem x (Nodes$add y s)) (ite (or (= x y) (= (Nodes$mem x s)
+ Truth)) Truth
+ Falsity))))
+;Nodes$mem_remove :
+(assert (forall ((x Nodes$elem$type) (y Nodes$elem$type) (s Nodes$t$type))
+ (= (Nodes$mem x (Nodes$remove y s)) (ite (and (not (= x y)) (=
+ (Nodes$mem
+ x s)
+ Truth))
+ Truth Falsity))))
+;Nodes$mem_union1 :
+(assert (forall ((x Nodes$elem$type) (a Nodes$t$type)) (=> (= (Nodes$mem x a)
+ Truth) (forall
+ ((b Nodes$t$type))
+ (=
+ (Nodes$mem
+ x (Nodes$union
+ a b))
+ Truth)))))
+;Nodes$mem_union2 :
+(assert (forall ((a Nodes$t$type) (b Nodes$t$type)) (= (Nodes$union a b)
+ (Nodes$union b a))))
+;Nodes$mem_union3 :
+(assert (forall ((x Nodes$elem$type) (a Nodes$t$type) (b Nodes$t$type))
+ (=> (= (Nodes$mem x (Nodes$union a b)) Truth) (or (= (Nodes$mem x a)
+ Truth) (= (Nodes$mem
+ x b)
+ Truth)))))
+;Nodes$mem_union4 :
+(assert (forall ((a Nodes$t$type)) (= (Nodes$union a a) a)))
+;Nodes$mem_union5 :
+(assert (forall ((a Nodes$t$type)) (= (Nodes$union a Nodes$empty) a)))
+;Nodes$empty_union :
+(assert (forall ((a Nodes$t$type) (b Nodes$t$type)) (=> (= (Nodes$union a b)
+ Nodes$empty)
+ (= a Nodes$empty))))
+;Nodes$card_empty :
+(assert (= (Nodes$cardinality Nodes$empty) 0))
+;Nodes$card_zero :
+(assert (forall ((s Nodes$t$type)) (=> (= (Nodes$cardinality s) 0) (=
+ s
+ Nodes$empty))))
+;Nodes$card_non_negative :
+(assert (forall ((s Nodes$t$type)) (>= (Nodes$cardinality s) 0)))
+;Nodes$card_add :
+(assert (forall ((x Nodes$elem$type) (s Nodes$t$type)) (= (Nodes$cardinality
+ (Nodes$add x s))
+ (ite (= (Nodes$mem
+ x s) Truth)
+ (Nodes$cardinality
+ s) (+ (Nodes$cardinality
+ s) 1)))))
+;Nodes$card_remove :
+(assert (forall ((x Nodes$elem$type) (s Nodes$t$type)) (= (Nodes$cardinality
+ (Nodes$remove x s))
+ (ite (= (Nodes$mem
+ x s) Truth) (-
+ (Nodes$cardinality
+ s) 1) (Nodes$cardinality
+ s)))))
+;Nodes$card_union :
+(assert (forall ((a Nodes$t$type) (b Nodes$t$type)) (=> (= (Nodes$disjoint
+ a b) Truth)
+ (= (Nodes$cardinality
+ (Nodes$union a b)) (+
+ (Nodes$cardinality
+ a) (Nodes$cardinality b))))))
+(declare-fun Nodes$eq (Nodes$t$type Nodes$t$type) BOOL)
+;Nodes$eq_is_equality :
+(assert (forall ((a Nodes$t$type) (b Nodes$t$type)) (= (Nodes$eq a b)
+ (ite (= a b) Truth
+ Falsity))))
+;Nodes$equal1 :
+(assert (forall ((a Nodes$t$type) (b Nodes$t$type)) (=> (forall ((x Nodes$elem$type))
+ (= (Nodes$mem x a)
+ (Nodes$mem x b)))
+ (= (Nodes$eq a b)
+ Truth))))
+(define-sort Values$elem$type () value$type)
+(declare-sort Values$t$type 0)
+(declare-fun Values$empty () Values$t$type)
+(declare-fun Values$mem (Values$elem$type Values$t$type) BOOL)
+(declare-fun Values$add (Values$elem$type Values$t$type) Values$t$type)
+(declare-fun Values$remove (Values$elem$type Values$t$type) Values$t$type)
+(declare-fun Values$cardinality (Values$t$type) Int)
+(declare-fun Values$union (Values$t$type Values$t$type) Values$t$type)
+(declare-fun Values$disjoint (Values$t$type Values$t$type) BOOL)
+;Values$disjoint_empty :
+(assert (forall ((a Values$t$type)) (= (Values$disjoint a Values$empty)
+ Truth)))
+;Values$disjoint_comm :
+(assert (forall ((a Values$t$type) (b Values$t$type)) (= (Values$disjoint
+ a b) (Values$disjoint
+ b a))))
+;Values$mem_empty :
+(assert (forall ((e Values$elem$type)) (not (= (Values$mem e Values$empty)
+ Truth))))
+;Values$mem_add :
+(assert (forall ((x Values$elem$type) (y Values$elem$type) (s Values$t$type))
+ (= (Values$mem x (Values$add y s)) (ite (or (= x y) (= (Values$mem
+ x s) Truth))
+ Truth Falsity))))
+;Values$mem_remove :
+(assert (forall ((x Values$elem$type) (y Values$elem$type) (s Values$t$type))
+ (= (Values$mem x (Values$remove y s)) (ite (and (not (= x y))
+ (= (Values$mem x s)
+ Truth)) Truth Falsity))))
+;Values$mem_union1 :
+(assert (forall ((x Values$elem$type) (a Values$t$type)) (=> (= (Values$mem
+ x a)
+ Truth) (forall
+ (
+ (b Values$t$type))
+ (=
+ (Values$mem
+ x
+ (Values$union
+ a b))
+ Truth)))))
+;Values$mem_union2 :
+(assert (forall ((a Values$t$type) (b Values$t$type)) (= (Values$union a b)
+ (Values$union b a))))
+;Values$mem_union3 :
+(assert (forall ((x Values$elem$type) (a Values$t$type) (b Values$t$type))
+ (=> (= (Values$mem x (Values$union a b)) Truth) (or (= (Values$mem
+ x a) Truth)
+ (= (Values$mem x b)
+ Truth)))))
+;Values$mem_union4 :
+(assert (forall ((a Values$t$type)) (= (Values$union a a) a)))
+;Values$mem_union5 :
+(assert (forall ((a Values$t$type)) (= (Values$union a Values$empty) a)))
+;Values$empty_union :
+(assert (forall ((a Values$t$type) (b Values$t$type)) (=> (= (Values$union
+ a b) Values$empty)
+ (= a Values$empty))))
+;Values$card_empty :
+(assert (= (Values$cardinality Values$empty) 0))
+;Values$card_zero :
+(assert (forall ((s Values$t$type)) (=> (= (Values$cardinality s) 0)
+ (= s Values$empty))))
+;Values$card_non_negative :
+(assert (forall ((s Values$t$type)) (>= (Values$cardinality s) 0)))
+;Values$card_add :
+(assert (forall ((x Values$elem$type) (s Values$t$type)) (= (Values$cardinality
+ (Values$add x s))
+ (ite (= (Values$mem
+ x s)
+ Truth)
+ (Values$cardinality
+ s) (+ (Values$cardinality
+ s) 1)))))
+;Values$card_remove :
+(assert (forall ((x Values$elem$type) (s Values$t$type)) (= (Values$cardinality
+ (Values$remove
+ x s)) (ite
+ (=
+ (Values$mem
+ x s)
+ Truth) (-
+ (Values$cardinality
+ s)
+ 1)
+ (Values$cardinality
+ s)))))
+;Values$card_union :
+(assert (forall ((a Values$t$type) (b Values$t$type)) (=> (= (Values$disjoint
+ a b) Truth)
+ (= (Values$cardinality
+ (Values$union a b)) (+
+ (Values$cardinality
+ a) (Values$cardinality
+ b))))))
+(declare-fun Values$eq (Values$t$type Values$t$type) BOOL)
+;Values$eq_is_equality :
+(assert (forall ((a Values$t$type) (b Values$t$type)) (= (Values$eq a b)
+ (ite (= a b) Truth
+ Falsity))))
+;Values$equal1 :
+(assert (forall ((a Values$t$type) (b Values$t$type)) (=> (forall ((x Values$elem$type))
+ (= (Values$mem x a)
+ (Values$mem
+ x b))) (= (Values$eq
+ a b)
+ Truth))))
+(define-sort node_set$type () (Array node$type BOOL))
+(declare-fun mk_array_1 () (Array node$type BOOL))
+;mk_array_1_def :
+(assert (forall ((mk_array_1_index node$type)) (= (select mk_array_1
+ mk_array_1_index) Falsity)))
+(define-fun empty_node_set () node_set$type mk_array_1)
+(define-sort node_pair_set$type () (Array node$type (Array node$type BOOL)))
+(declare-fun mk_array_2 () (Array node$type BOOL))
+;mk_array_2_def :
+(assert (forall ((mk_array_2_index node$type)) (= (select mk_array_2
+ mk_array_2_index) Falsity)))
+(declare-fun mk_array_3 () (Array node$type (Array node$type BOOL)))
+;mk_array_3_def :
+(assert (forall ((mk_array_3_index node$type)) (= (select mk_array_3
+ mk_array_3_index) mk_array_2)))
+(define-fun empty_node_pair_set () node_pair_set$type mk_array_3)
+(declare-fun mk_array_4 () (Array node$type BOOL))
+;mk_array_4_def :
+(assert (forall ((mk_array_4_index node$type)) (= (select mk_array_4
+ mk_array_4_index) Truth)))
+(declare-fun mk_array_5 () (Array node$type (Array node$type BOOL)))
+;mk_array_5_def :
+(assert (forall ((mk_array_5_index node$type)) (= (select mk_array_5
+ mk_array_5_index) mk_array_4)))
+(define-fun full_node_pair_set () node_pair_set$type mk_array_5)
+(declare-fun input () (Array node$type value$type))
+(declare-fun t () Int)
+;positive_bound :
+(assert (> t 0))
+(define-sort message$type () Values$t$type)
+(define-sort message_set$type () (Array node$type message$type))
+(define-sort state$type () Values$t$type)
+(define-sort state_set$type () (Array node$type state$type))
+(define-fun null_message () message$type Values$empty)
+(declare-fun mk_array_6 () (Array node$type message$type))
+;mk_array_6_def :
+(assert (forall ((mk_array_6_index node$type)) (= (select mk_array_6
+ mk_array_6_index) null_message)))
+(define-fun null_message_set () message_set$type mk_array_6)
+(define-fun null_state () state$type Values$empty)
+(declare-fun mk_array_7 () (Array node$type state$type))
+;mk_array_7_def :
+(assert (forall ((mk_array_7_index node$type)) (= (select mk_array_7
+ mk_array_7_index) null_state)))
+(define-fun null_state_set () state_set$type mk_array_7)
+(declare-fun choose (Values$t$type) value$type)
+;choosen_value :
+(assert (forall ((vals Values$t$type)) (or (= vals Values$empty) (= (Values$mem
+ (choose
+ vals)
+ vals)
+ Truth))))
+(define-sort failure_pattern$type () node_pair_set$type)
+(define-fun is_faulty ((p node$type) (deliver failure_pattern$type)) BOOL
+(ite (exists ((q node$type)) (not (= (select (select deliver p) q) Truth)))
+Truth Falsity))
+(define-fun is_silent ((p node$type) (deliver failure_pattern$type)) BOOL
+(ite (forall ((q node$type)) (not (= (select (select deliver p) q) Truth)))
+Truth Falsity))
+(declare-datatypes () ((phase_state$type (init_phase) (send_phase) (recv_phase) (comp_phase))))
+(declare-datatypes () ((clean_state$type (before) (active) (after))))
+
+; Var Decls --------------
+(declare-fun my_compute$result$1 () state$type)
+(declare-fun output$1 () (Array node$type value$type))
+(declare-fun comp_done () node_set$type)
+(declare-fun compute$can_decide$0$1 () BOOL)
+(declare-fun chosen () (Array node$type BOOL))
+(declare-fun recv_done () node_pair_set$type)
+(declare-fun output () (Array node$type value$type))
+(declare-fun phase () phase_state$type)
+(declare-fun global_state () state_set$type)
+(declare-fun my_decide$result$1 () value$type)
+(declare-fun round () Int)
+(declare-fun compute$n () node$type)
+(declare-fun send_done () node_pair_set$type)
+(declare-fun my_can_decide$result$1 () BOOL)
+(declare-fun chosen$1 () (Array node$type BOOL))
+(declare-fun comp_done$1 () node_set$type)
+(declare-fun global_state$1 () state_set$type)
+
+; Asserts --------------
+(assert (not (=> (forall ((n node$type)) (=>
+ (and
+ (=
+ (select
+ chosen
+ n)
+ Truth)
+ (=
+ round (+
+ t
+ 1)))
+ (and
+ (forall
+ (
+ (n node$type) (m node$type))
+ (=
+ (select
+ (select
+ send_done
+ n)
+ m)
+ Truth))
+ (forall
+ (
+ (n node$type) (m node$type))
+ (=
+ (select
+ (select
+ recv_done
+ n)
+ m)
+ Truth)))))
+ (=> (= phase comp_phase) (=>
+ (not
+ (= (select
+ comp_done
+ compute$n)
+ Truth))
+ (=>
+ (= my_compute$result$1
+ (select
+ global_state
+ compute$n))
+ (=>
+ (= global_state$1
+ (store
+ global_state
+ compute$n
+ my_compute$result$1))
+ (=>
+ (= my_can_decide$result$1
+ (ite
+ (= round (+
+ t 1))
+ Truth
+ Falsity))
+ (=>
+ (= compute$can_decide$0$1
+ my_can_decide$result$1)
+ (= (ite
+ (=
+ compute$can_decide$0$1
+ Truth)
+ (ite
+ (=>
+ (=
+ my_decide$result$1
+ (choose
+ (select
+ global_state$1
+ compute$n)))
+ (=>
+ (=
+ output$1
+ (store
+ output
+ compute$n
+ my_decide$result$1))
+ (=>
+ (=
+ chosen$1
+ (store
+ chosen
+ compute$n
+ Truth))
+ (=>
+ (=
+ comp_done$1
+ (store
+ comp_done
+ compute$n
+ Truth))
+ (forall
+ (
+ (n node$type))
+ (=>
+ (and
+ (=
+ (select
+ chosen$1
+ n)
+ Truth)
+ (=
+ round (+
+ t
+ 1)))
+ (and
+ (forall
+ (
+ (n node$type) (m node$type))
+ (=
+ (select
+ (select
+ send_done
+ n)
+ m)
+ Truth))
+ (forall
+ (
+ (n node$type) (m node$type))
+ (=
+ (select
+ (select
+ recv_done
+ n)
+ m)
+ Truth)))))))))
+ Truth
+ Falsity)
+ (ite
+ (=>
+ (=
+ comp_done$1
+ (store
+ comp_done
+ compute$n
+ Truth))
+ (forall
+ (
+ (n node$type))
+ (=>
+ (and
+ (=
+ (select
+ chosen
+ n)
+ Truth)
+ (=
+ round (+
+ t
+ 1)))
+ (and
+ (forall
+ (
+ (n node$type) (m node$type))
+ (=
+ (select
+ (select
+ send_done
+ n)
+ m)
+ Truth))
+ (forall
+ (
+ (n node$type) (m node$type))
+ (=
+ (select
+ (select
+ recv_done
+ n)
+ m)
+ Truth))))))
+ Truth
+ Falsity))
+ Truth))))))))))
+
+(check-sat)
diff --git a/test/regress/regress0/fmf/agree467.smt2 b/test/regress/regress0/fmf/agree467.smt2
new file mode 100644
index 000000000..09e16dfe3
--- /dev/null
+++ b/test/regress/regress0/fmf/agree467.smt2
@@ -0,0 +1,342 @@
+; COMMAND-LINE: --finite-model-find
+; EXPECT: unsat
+; EXIT: 20
+; Preamble --------------
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+(declare-datatypes () ((UNIT (Unit))))
+(declare-datatypes () ((BOOL (Truth) (Falsity))))
+
+; Decls --------------
+(declare-sort node$type 0)
+(declare-sort value$type 0)
+(define-sort Nodes$elem$type () node$type)
+(declare-sort Nodes$t$type 0)
+(declare-fun Nodes$empty () Nodes$t$type)
+(declare-fun Nodes$mem (Nodes$elem$type Nodes$t$type) BOOL)
+(declare-fun Nodes$add (Nodes$elem$type Nodes$t$type) Nodes$t$type)
+(declare-fun Nodes$remove (Nodes$elem$type Nodes$t$type) Nodes$t$type)
+(declare-fun Nodes$cardinality (Nodes$t$type) Int)
+(declare-fun Nodes$union (Nodes$t$type Nodes$t$type) Nodes$t$type)
+(declare-fun Nodes$disjoint (Nodes$t$type Nodes$t$type) BOOL)
+;Nodes$disjoint_empty :
+(assert (forall ((a Nodes$t$type)) (= (Nodes$disjoint a Nodes$empty) Truth)))
+;Nodes$disjoint_comm :
+(assert (forall ((a Nodes$t$type) (b Nodes$t$type)) (= (Nodes$disjoint a b)
+ (Nodes$disjoint b a))))
+;Nodes$mem_empty :
+(assert (forall ((e Nodes$elem$type)) (not (= (Nodes$mem e Nodes$empty)
+ Truth))))
+;Nodes$mem_add :
+(assert (forall ((x Nodes$elem$type) (y Nodes$elem$type) (s Nodes$t$type))
+ (= (Nodes$mem x (Nodes$add y s)) (ite (or (= x y) (= (Nodes$mem x s)
+ Truth)) Truth
+ Falsity))))
+;Nodes$mem_remove :
+(assert (forall ((x Nodes$elem$type) (y Nodes$elem$type) (s Nodes$t$type))
+ (= (Nodes$mem x (Nodes$remove y s)) (ite (and (not (= x y)) (=
+ (Nodes$mem
+ x s)
+ Truth))
+ Truth Falsity))))
+;Nodes$mem_union1 :
+(assert (forall ((x Nodes$elem$type) (a Nodes$t$type)) (=> (= (Nodes$mem x a)
+ Truth) (forall
+ ((b Nodes$t$type))
+ (=
+ (Nodes$mem
+ x (Nodes$union
+ a b))
+ Truth)))))
+;Nodes$mem_union2 :
+(assert (forall ((a Nodes$t$type) (b Nodes$t$type)) (= (Nodes$union a b)
+ (Nodes$union b a))))
+;Nodes$mem_union3 :
+(assert (forall ((x Nodes$elem$type) (a Nodes$t$type) (b Nodes$t$type))
+ (=> (= (Nodes$mem x (Nodes$union a b)) Truth) (or (= (Nodes$mem x a)
+ Truth) (= (Nodes$mem
+ x b)
+ Truth)))))
+;Nodes$mem_union4 :
+(assert (forall ((a Nodes$t$type)) (= (Nodes$union a a) a)))
+;Nodes$mem_union5 :
+(assert (forall ((a Nodes$t$type)) (= (Nodes$union a Nodes$empty) a)))
+;Nodes$empty_union :
+(assert (forall ((a Nodes$t$type) (b Nodes$t$type)) (=> (= (Nodes$union a b)
+ Nodes$empty)
+ (= a Nodes$empty))))
+;Nodes$card_empty :
+(assert (= (Nodes$cardinality Nodes$empty) 0))
+;Nodes$card_zero :
+(assert (forall ((s Nodes$t$type)) (=> (= (Nodes$cardinality s) 0) (=
+ s
+ Nodes$empty))))
+;Nodes$card_non_negative :
+(assert (forall ((s Nodes$t$type)) (>= (Nodes$cardinality s) 0)))
+;Nodes$card_add :
+(assert (forall ((x Nodes$elem$type) (s Nodes$t$type)) (= (Nodes$cardinality
+ (Nodes$add x s))
+ (ite (= (Nodes$mem
+ x s) Truth)
+ (Nodes$cardinality
+ s) (+ (Nodes$cardinality
+ s) 1)))))
+;Nodes$card_remove :
+(assert (forall ((x Nodes$elem$type) (s Nodes$t$type)) (= (Nodes$cardinality
+ (Nodes$remove x s))
+ (ite (= (Nodes$mem
+ x s) Truth) (-
+ (Nodes$cardinality
+ s) 1) (Nodes$cardinality
+ s)))))
+;Nodes$card_union :
+(assert (forall ((a Nodes$t$type) (b Nodes$t$type)) (=> (= (Nodes$disjoint
+ a b) Truth)
+ (= (Nodes$cardinality
+ (Nodes$union a b)) (+
+ (Nodes$cardinality
+ a) (Nodes$cardinality b))))))
+(declare-fun Nodes$eq (Nodes$t$type Nodes$t$type) BOOL)
+;Nodes$eq_is_equality :
+(assert (forall ((a Nodes$t$type) (b Nodes$t$type)) (= (Nodes$eq a b)
+ (ite (= a b) Truth
+ Falsity))))
+;Nodes$equal1 :
+(assert (forall ((a Nodes$t$type) (b Nodes$t$type)) (=> (forall ((x Nodes$elem$type))
+ (= (Nodes$mem x a)
+ (Nodes$mem x b)))
+ (= (Nodes$eq a b)
+ Truth))))
+(define-sort Values$elem$type () value$type)
+(declare-sort Values$t$type 0)
+(declare-fun Values$empty () Values$t$type)
+(declare-fun Values$mem (Values$elem$type Values$t$type) BOOL)
+(declare-fun Values$add (Values$elem$type Values$t$type) Values$t$type)
+(declare-fun Values$remove (Values$elem$type Values$t$type) Values$t$type)
+(declare-fun Values$cardinality (Values$t$type) Int)
+(declare-fun Values$union (Values$t$type Values$t$type) Values$t$type)
+(declare-fun Values$disjoint (Values$t$type Values$t$type) BOOL)
+;Values$disjoint_empty :
+(assert (forall ((a Values$t$type)) (= (Values$disjoint a Values$empty)
+ Truth)))
+;Values$disjoint_comm :
+(assert (forall ((a Values$t$type) (b Values$t$type)) (= (Values$disjoint
+ a b) (Values$disjoint
+ b a))))
+;Values$mem_empty :
+(assert (forall ((e Values$elem$type)) (not (= (Values$mem e Values$empty)
+ Truth))))
+;Values$mem_add :
+(assert (forall ((x Values$elem$type) (y Values$elem$type) (s Values$t$type))
+ (= (Values$mem x (Values$add y s)) (ite (or (= x y) (= (Values$mem
+ x s) Truth))
+ Truth Falsity))))
+;Values$mem_remove :
+(assert (forall ((x Values$elem$type) (y Values$elem$type) (s Values$t$type))
+ (= (Values$mem x (Values$remove y s)) (ite (and (not (= x y))
+ (= (Values$mem x s)
+ Truth)) Truth Falsity))))
+;Values$mem_union1 :
+(assert (forall ((x Values$elem$type) (a Values$t$type)) (=> (= (Values$mem
+ x a)
+ Truth) (forall
+ (
+ (b Values$t$type))
+ (=
+ (Values$mem
+ x
+ (Values$union
+ a b))
+ Truth)))))
+;Values$mem_union2 :
+(assert (forall ((a Values$t$type) (b Values$t$type)) (= (Values$union a b)
+ (Values$union b a))))
+;Values$mem_union3 :
+(assert (forall ((x Values$elem$type) (a Values$t$type) (b Values$t$type))
+ (=> (= (Values$mem x (Values$union a b)) Truth) (or (= (Values$mem
+ x a) Truth)
+ (= (Values$mem x b)
+ Truth)))))
+;Values$mem_union4 :
+(assert (forall ((a Values$t$type)) (= (Values$union a a) a)))
+;Values$mem_union5 :
+(assert (forall ((a Values$t$type)) (= (Values$union a Values$empty) a)))
+;Values$empty_union :
+(assert (forall ((a Values$t$type) (b Values$t$type)) (=> (= (Values$union
+ a b) Values$empty)
+ (= a Values$empty))))
+;Values$card_empty :
+(assert (= (Values$cardinality Values$empty) 0))
+;Values$card_zero :
+(assert (forall ((s Values$t$type)) (=> (= (Values$cardinality s) 0)
+ (= s Values$empty))))
+;Values$card_non_negative :
+(assert (forall ((s Values$t$type)) (>= (Values$cardinality s) 0)))
+;Values$card_add :
+(assert (forall ((x Values$elem$type) (s Values$t$type)) (= (Values$cardinality
+ (Values$add x s))
+ (ite (= (Values$mem
+ x s)
+ Truth)
+ (Values$cardinality
+ s) (+ (Values$cardinality
+ s) 1)))))
+;Values$card_remove :
+(assert (forall ((x Values$elem$type) (s Values$t$type)) (= (Values$cardinality
+ (Values$remove
+ x s)) (ite
+ (=
+ (Values$mem
+ x s)
+ Truth) (-
+ (Values$cardinality
+ s)
+ 1)
+ (Values$cardinality
+ s)))))
+;Values$card_union :
+(assert (forall ((a Values$t$type) (b Values$t$type)) (=> (= (Values$disjoint
+ a b) Truth)
+ (= (Values$cardinality
+ (Values$union a b)) (+
+ (Values$cardinality
+ a) (Values$cardinality
+ b))))))
+(declare-fun Values$eq (Values$t$type Values$t$type) BOOL)
+;Values$eq_is_equality :
+(assert (forall ((a Values$t$type) (b Values$t$type)) (= (Values$eq a b)
+ (ite (= a b) Truth
+ Falsity))))
+;Values$equal1 :
+(assert (forall ((a Values$t$type) (b Values$t$type)) (=> (forall ((x Values$elem$type))
+ (= (Values$mem x a)
+ (Values$mem
+ x b))) (= (Values$eq
+ a b)
+ Truth))))
+(define-sort node_set$type () (Array node$type BOOL))
+(declare-fun mk_array_1 () (Array node$type BOOL))
+;mk_array_1_def :
+(assert (forall ((mk_array_1_index node$type)) (= (select mk_array_1
+ mk_array_1_index) Falsity)))
+(define-fun empty_node_set () node_set$type mk_array_1)
+(define-sort node_pair_set$type () (Array node$type (Array node$type BOOL)))
+(declare-fun mk_array_2 () (Array node$type BOOL))
+;mk_array_2_def :
+(assert (forall ((mk_array_2_index node$type)) (= (select mk_array_2
+ mk_array_2_index) Falsity)))
+(declare-fun mk_array_3 () (Array node$type (Array node$type BOOL)))
+;mk_array_3_def :
+(assert (forall ((mk_array_3_index node$type)) (= (select mk_array_3
+ mk_array_3_index) mk_array_2)))
+(define-fun empty_node_pair_set () node_pair_set$type mk_array_3)
+(declare-fun mk_array_4 () (Array node$type BOOL))
+;mk_array_4_def :
+(assert (forall ((mk_array_4_index node$type)) (= (select mk_array_4
+ mk_array_4_index) Truth)))
+(declare-fun mk_array_5 () (Array node$type (Array node$type BOOL)))
+;mk_array_5_def :
+(assert (forall ((mk_array_5_index node$type)) (= (select mk_array_5
+ mk_array_5_index) mk_array_4)))
+(define-fun full_node_pair_set () node_pair_set$type mk_array_5)
+(declare-fun input () (Array node$type value$type))
+(declare-fun t () Int)
+;positive_bound :
+(assert (> t 0))
+(define-sort message$type () Values$t$type)
+(define-sort message_set$type () (Array node$type message$type))
+(define-sort state$type () Values$t$type)
+(define-sort state_set$type () (Array node$type state$type))
+(define-fun null_message () message$type Values$empty)
+(declare-fun mk_array_6 () (Array node$type message$type))
+;mk_array_6_def :
+(assert (forall ((mk_array_6_index node$type)) (= (select mk_array_6
+ mk_array_6_index) null_message)))
+(define-fun null_message_set () message_set$type mk_array_6)
+(define-fun null_state () state$type Values$empty)
+(declare-fun mk_array_7 () (Array node$type state$type))
+;mk_array_7_def :
+(assert (forall ((mk_array_7_index node$type)) (= (select mk_array_7
+ mk_array_7_index) null_state)))
+(define-fun null_state_set () state_set$type mk_array_7)
+(declare-fun choose (Values$t$type) value$type)
+;choosen_value :
+(assert (forall ((vals Values$t$type)) (or (= vals Values$empty) (= (Values$mem
+ (choose
+ vals)
+ vals)
+ Truth))))
+(define-sort failure_pattern$type () node_pair_set$type)
+(define-fun is_faulty ((p node$type) (deliver failure_pattern$type)) BOOL
+(ite (exists ((q node$type)) (not (= (select (select deliver p) q) Truth)))
+Truth Falsity))
+(define-fun is_silent ((p node$type) (deliver failure_pattern$type)) BOOL
+(ite (forall ((q node$type)) (not (= (select (select deliver p) q) Truth)))
+Truth Falsity))
+(declare-datatypes () ((phase_state$type (init_phase) (send_phase) (recv_phase) (comp_phase))))
+(declare-datatypes () ((clean_state$type (before) (active) (after))))
+
+; Var Decls --------------
+(declare-fun init_done () node_set$type)
+(declare-fun crashed () Nodes$t$type)
+(declare-fun comp_done () node_set$type)
+(declare-fun chosen () (Array node$type BOOL))
+(declare-fun recv_done () node_pair_set$type)
+(declare-fun phase () phase_state$type)
+(declare-fun clean () clean_state$type)
+(declare-fun global_state () state_set$type)
+(declare-fun messages () (Array node$type message_set$type))
+(declare-fun deliver_message () failure_pattern$type)
+(declare-fun crashing () Nodes$t$type)
+(declare-fun round () Int)
+(declare-fun send_done () node_pair_set$type)
+
+; Asserts --------------
+(declare-fun mk_array_8 () (Array node$type BOOL))
+;mk_array_8_def :
+(assert (forall ((mk_array_8_index node$type)) (= (select mk_array_8
+ mk_array_8_index) Falsity)))
+(declare-fun mk_array_9 () (Array node$type message_set$type))
+;mk_array_9_def :
+(assert (forall ((mk_array_9_index node$type)) (= (select mk_array_9
+ mk_array_9_index) null_message_set)))
+(assert (not (=> (and (and (and (and (and (and (and (and (and (and (and
+ (and
+ (=
+ clean
+ before)
+ (=
+ global_state
+ null_state_set))
+ (=
+ messages
+ mk_array_9))
+ (= deliver_message
+ full_node_pair_set))
+ (= comp_done
+ empty_node_set))
+ (= recv_done empty_node_pair_set))
+ (= send_done empty_node_pair_set))
+ (= init_done empty_node_set))
+ (= phase init_phase)) (= crashing
+ Nodes$empty))
+ (= crashed Nodes$empty)) (= round 0)) (= chosen
+ mk_array_8))
+ (forall ((n node$type)) (=> (and (= (select chosen n) Truth)
+ (= round (+ t 1))) (and (forall
+ ((n node$type) (m node$type))
+ (= (select
+ (select
+ send_done
+ n)
+ m)
+ Truth))
+ (forall (
+ (n node$type) (m node$type))
+ (= (select
+ (select
+ recv_done
+ n) m)
+ Truth))))))))
+
+(check-sat)
diff --git a/test/regress/regress0/fmf/german169.smt2 b/test/regress/regress0/fmf/german169.smt2
new file mode 100755
index 000000000..f0906d6b5
--- /dev/null
+++ b/test/regress/regress0/fmf/german169.smt2
@@ -0,0 +1,104 @@
+; COMMAND-LINE: --finite-model-find
+; EXPECT: sat
+; EXIT: 10
+(set-logic ALL_SUPPORTED)
+(set-info :status sat)
+(declare-datatypes () ((UNIT (Unit))))
+(declare-datatypes () ((BOOL (Truth) (Falsity))))
+
+; Decls --------------
+(declare-sort node$type 0)
+(declare-sort data$type 0)
+(declare-datatypes () ((cache_state$type (invalid) (shared) (exclusive))))
+(declare-datatypes () ((cache$type (c_cache$type (c_state cache_state$type) (c_data data$type)))))
+(declare-datatypes () ((msg_cmd$type (empty) (reqs) (reqe) (inv) (invack) (gnts) (gnte))))
+(declare-datatypes () ((msg$type (c_msg$type (m_cmd msg_cmd$type) (m_data data$type)))))
+(declare-fun dummy () data$type)
+
+; Var Decls --------------
+(declare-fun memdata$1 () data$type)
+(declare-fun shrset$1 () (Array node$type BOOL))
+(declare-fun recv_invack$i () node$type)
+(declare-fun exgntd () BOOL)
+(declare-fun chan3$1 () (Array node$type msg$type))
+(declare-fun shrset () (Array node$type BOOL))
+(declare-fun exgntd$1 () BOOL)
+(declare-fun chan2 () (Array node$type msg$type))
+(declare-fun chan3 () (Array node$type msg$type))
+(declare-fun auxnode () node$type)
+(declare-fun curcmd () msg_cmd$type)
+
+; Asserts --------------
+(assert (not (=> (and (and (forall ((n node$type))
+ (=> (= (m_cmd (select
+ chan2
+ n))
+ gnte) (= exgntd
+ Truth)))
+ (forall ((n node$type))
+ (=> (= exgntd Truth)
+ (= (select shrset n)
+ (ite (= n auxnode) Truth
+ Falsity))))) (forall
+ ((n node$type))
+ (=> (=
+ (m_cmd
+ (select
+ chan3
+ n))
+ invack)
+ (= (m_cmd
+ (select
+ chan2
+ n))
+ empty))))
+ (=> (= (m_cmd (select chan3 recv_invack$i))
+ invack) (=> (not (= curcmd empty))
+ (=> (= chan3$1 (store
+ chan3
+ recv_invack$i
+ (let (
+ (vup_228
+ (select
+ chan3
+ recv_invack$i)))
+ (c_msg$type
+ empty
+ (m_data
+ vup_228)))))
+ (=> (= shrset$1 (store
+ shrset
+ recv_invack$i
+ Falsity))
+ (= (ite (= exgntd Truth)
+ (ite (=> (= exgntd$1
+ Falsity)
+ (=> (= memdata$1
+ (m_data
+ (select
+ chan3$1
+ recv_invack$i)))
+ (forall (
+ (n node$type))
+ (=> (= (m_cmd
+ (select
+ chan2
+ n))
+ gnte)
+ (= exgntd$1
+ Truth)))))
+ Truth Falsity)
+ (ite (forall (
+ (n node$type))
+ (=> (= (m_cmd
+ (select
+ chan2
+ n))
+ gnte)
+ (= exgntd
+ Truth)))
+ Truth Falsity))
+ Truth))))))))
+
+(check-sat)
+(exit)
diff --git a/test/regress/regress0/fmf/german73.smt2 b/test/regress/regress0/fmf/german73.smt2
new file mode 100755
index 000000000..388a53624
--- /dev/null
+++ b/test/regress/regress0/fmf/german73.smt2
@@ -0,0 +1,106 @@
+; COMMAND-LINE: --finite-model-find
+; EXPECT: unsat
+; EXIT: 20
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+(declare-datatypes () ((UNIT (Unit))))
+(declare-datatypes () ((BOOL (Truth) (Falsity))))
+
+; Decls --------------
+(declare-sort node$type 0)
+(declare-sort data$type 0)
+(declare-datatypes () ((cache_state$type (invalid) (shared) (exclusive))))
+(declare-datatypes () ((cache$type (c_cache$type (c_state cache_state$type) (c_data data$type)))))
+(declare-datatypes () ((msg_cmd$type (empty) (reqs) (reqe) (inv) (invack) (gnts) (gnte))))
+(declare-datatypes () ((msg$type (c_msg$type (m_cmd msg_cmd$type) (m_data data$type)))))
+(declare-fun dummy () data$type)
+
+; Var Decls --------------
+(declare-fun memdata$1 () data$type)
+(declare-fun shrset$1 () (Array node$type BOOL))
+(declare-fun recv_invack$i () node$type)
+(declare-fun exgntd () BOOL)
+(declare-fun invset () (Array node$type BOOL))
+(declare-fun chan3$1 () (Array node$type msg$type))
+(declare-fun shrset () (Array node$type BOOL))
+(declare-fun exgntd$1 () BOOL)
+(declare-fun chan2 () (Array node$type msg$type))
+(declare-fun chan3 () (Array node$type msg$type))
+(declare-fun curcmd () msg_cmd$type)
+
+; Asserts --------------
+(assert (not (=> (and (forall ((n node$type))
+ (=> (= (select invset n)
+ Truth) (= (select
+ shrset
+ n) Truth)))
+ (forall ((n node$type)) (=>
+ (or
+ (=
+ (m_cmd
+ (select
+ chan2
+ n))
+ inv)
+ (=
+ (m_cmd
+ (select
+ chan3
+ n))
+ invack))
+ (not
+ (=
+ (select
+ invset
+ n)
+ Truth)))))
+ (=> (= (m_cmd (select chan3 recv_invack$i))
+ invack) (=> (not (= curcmd empty))
+ (=> (= chan3$1 (store
+ chan3
+ recv_invack$i
+ (let (
+ (vup_101
+ (select
+ chan3
+ recv_invack$i)))
+ (c_msg$type
+ empty
+ (m_data
+ vup_101)))))
+ (=> (= shrset$1 (store
+ shrset
+ recv_invack$i
+ Falsity))
+ (= (ite (= exgntd Truth)
+ (ite (=> (= exgntd$1
+ Falsity)
+ (=> (= memdata$1
+ (m_data
+ (select
+ chan3$1
+ recv_invack$i)))
+ (forall (
+ (n node$type))
+ (=> (= (select
+ invset
+ n)
+ Truth)
+ (= (select
+ shrset$1
+ n) Truth)))))
+ Truth Falsity)
+ (ite (forall (
+ (n node$type))
+ (=> (= (select
+ invset
+ n)
+ Truth)
+ (= (select
+ shrset$1
+ n) Truth)))
+ Truth Falsity))
+ Truth))))))))
+
+(check-sat)
+(exit)
diff --git a/test/regress/regress0/fmf/refcount24.cvc.smt2 b/test/regress/regress0/fmf/refcount24.cvc.smt2
new file mode 100755
index 000000000..bf042c9b2
--- /dev/null
+++ b/test/regress/regress0/fmf/refcount24.cvc.smt2
@@ -0,0 +1,38 @@
+; COMMAND-LINE: --finite-model-find
+; EXPECT: sat
+; EXIT: 10
+(set-logic ALL_SUPPORTED)
+(set-info :smt-lib-version 2.0)
+(set-info :category "unknown")
+(set-info :status sat)
+(declare-datatypes ()
+((UNIT (Unit))
+))
+(declare-datatypes ()
+((BOOL (Truth) (Falsity))
+))
+(declare-sort resource$type 0)
+(declare-sort process$type 0)
+(declare-fun null () resource$type)
+(declare-sort S$t$type 0)
+(declare-fun S$empty () S$t$type)
+(declare-fun S$mem (process$type S$t$type) BOOL)
+(declare-fun S$add (process$type S$t$type) S$t$type)
+(declare-fun S$remove (process$type S$t$type) S$t$type)
+(declare-fun S$cardinality (S$t$type) Int)
+(assert (forall ((e process$type)) (not (= (S$mem e S$empty) Truth))))
+(assert (forall ((x process$type) (y process$type) (s S$t$type)) (= (S$mem x (S$add y s)) (ite (or (= x y) (= (S$mem x s) Truth)) Truth Falsity))))
+(assert (forall ((x process$type) (y process$type) (s S$t$type)) (= (S$mem x (S$remove y s)) (ite (and (not (= x y)) (= (S$mem x s) Truth)) Truth Falsity))))
+(assert (= (S$cardinality S$empty) 0))
+(assert (forall ((s S$t$type)) (=> (= (S$cardinality s) 0) (= s S$empty))))
+(assert (forall ((s S$t$type)) (>= (S$cardinality s) 0)))
+(assert (forall ((x process$type) (s S$t$type)) (let ((?v_0 (S$cardinality s))) (= (S$cardinality (S$add x s)) (ite (= (S$mem x s) Truth) ?v_0 (+ ?v_0 1))))))
+(assert (forall ((x process$type) (s S$t$type)) (let ((?v_0 (S$cardinality s))) (= (S$cardinality (S$remove x s)) (ite (= (S$mem x s) Truth) (- ?v_0 1) ?v_0)))))
+(declare-fun count () (Array resource$type Int))
+(declare-fun ref () (Array process$type resource$type))
+(declare-fun valid () (Array resource$type BOOL))
+(declare-fun destroy$r () resource$type)
+(declare-fun valid$1 () (Array resource$type BOOL))
+(assert (not (=> (forall ((p process$type)) (let ((?v_0 (select ref p))) (=> (not (= ?v_0 null)) (= (select valid ?v_0) Truth)))) (=> (not (= destroy$r null)) (=> (= (select valid destroy$r) Truth) (=> (= (select count destroy$r) 0) (=> (= valid$1 (store valid destroy$r Falsity)) (forall ((p process$type)) (let ((?v_1 (select ref p))) (=> (not (= ?v_1 null)) (= (select valid$1 ?v_1) Truth)))))))))))
+(check-sat)
+(exit)
diff --git a/test/unit/theory/theory_arith_white.h b/test/unit/theory/theory_arith_white.h
index 844fb57d1..3247b8c73 100644
--- a/test/unit/theory/theory_arith_white.h
+++ b/test/unit/theory/theory_arith_white.h
@@ -60,6 +60,7 @@ class TheoryArithWhite : public CxxTest::TestSuite {
TypeNode* d_booleanType;
TypeNode* d_realType;
+ TypeNode* d_intType;
const Rational d_zero;
const Rational d_one;
@@ -120,10 +121,12 @@ public:
d_booleanType = new TypeNode(d_nm->booleanType());
d_realType = new TypeNode(d_nm->realType());
+ d_intType = new TypeNode(d_nm->integerType());
}
void tearDown() {
+ delete d_intType;
delete d_realType;
delete d_booleanType;
@@ -281,4 +284,37 @@ public:
TS_ASSERT_EQUALS(d_outputChannel.getIthCallType(1), LEMMA);
TS_ASSERT_EQUALS(d_outputChannel.getIthNode(1), geq0OrLeq1);
}
+
+ void testIntNormalForm() {
+ Node x = d_nm->mkVar(*d_intType);
+ Node c0 = d_nm->mkConst<Rational>(d_zero);
+ Node c1 = d_nm->mkConst<Rational>(d_one);
+ Node c2 = d_nm->mkConst<Rational>(Rational(2));
+
+
+ Node geq0 = d_nm->mkNode(GEQ, x, c0);
+ Node geq1 = d_nm->mkNode(GEQ, x, c1);
+ Node geq2 = d_nm->mkNode(GEQ, x, c2);
+
+ TS_ASSERT_EQUALS(Rewriter::rewrite(geq0), geq0);
+ TS_ASSERT_EQUALS(Rewriter::rewrite(geq1), geq1);
+
+ Node gt0 = d_nm->mkNode(GT, x, c0);
+ Node gt1 = d_nm->mkNode(GT, x, c1);
+
+ TS_ASSERT_EQUALS(Rewriter::rewrite(gt0), Rewriter::rewrite(geq1));
+ TS_ASSERT_EQUALS(Rewriter::rewrite(gt1), Rewriter::rewrite(geq2));
+
+ Node lt0 = d_nm->mkNode(LT, x, c0);
+ Node lt1 = d_nm->mkNode(LT, x, c1);
+
+ TS_ASSERT_EQUALS(Rewriter::rewrite(lt0), Rewriter::rewrite(geq0.notNode()));
+ TS_ASSERT_EQUALS(Rewriter::rewrite(lt1), Rewriter::rewrite(geq1.notNode()));
+
+ Node leq0 = d_nm->mkNode(LEQ, x, c0);
+ Node leq1 = d_nm->mkNode(LEQ, x, c1);
+
+ TS_ASSERT_EQUALS(Rewriter::rewrite(leq0), Rewriter::rewrite(geq1.notNode()));
+ TS_ASSERT_EQUALS(Rewriter::rewrite(leq1), Rewriter::rewrite(geq2.notNode()));
+ }
};
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback