summaryrefslogtreecommitdiff
path: root/src/theory
diff options
context:
space:
mode:
authorPaul Meng <baolmeng@gmail.com>2016-10-11 13:54:20 -0500
committerPaul Meng <baolmeng@gmail.com>2016-10-11 13:54:20 -0500
commit3395c5c13cd61d98aec0d9806e3b9bc3d707968a (patch)
tree0eadad9799862ec77d29f7abe03a46c300d80de8 /src/theory
parent773e7d27d606b71ff0f78e84efe1deef2653f016 (diff)
parent5f415d4585134612bc24e9a823289fee35541a01 (diff)
Merge branch 'origin' of https://github.com/CVC4/CVC4.git
Conflicts: src/options/quantifiers_options
Diffstat (limited to 'src/theory')
-rw-r--r--src/theory/arith/cut_log.h2
-rw-r--r--src/theory/arith/theory_arith.h5
-rw-r--r--src/theory/arith/theory_arith_private.cpp21
-rw-r--r--src/theory/arith/theory_arith_private.h4
-rw-r--r--src/theory/arrays/array_proof_reconstruction.cpp13
-rw-r--r--src/theory/bv/bv_inequality_graph.h2
-rw-r--r--src/theory/bv/theory_bv.cpp4
-rw-r--r--src/theory/bv/theory_bv_type_rules.h204
-rw-r--r--src/theory/datatypes/theory_datatypes_type_rules.h278
-rw-r--r--src/theory/fp/theory_fp_type_rules.h298
-rw-r--r--src/theory/ite_utilities.cpp10
-rwxr-xr-xsrc/theory/quantifiers/ambqi_builder.cpp7
-rwxr-xr-xsrc/theory/quantifiers/ambqi_builder.h2
-rwxr-xr-xsrc/theory/quantifiers/anti_skolem.cpp21
-rwxr-xr-xsrc/theory/quantifiers/anti_skolem.h46
-rwxr-xr-xsrc/theory/quantifiers/candidate_generator.cpp1
-rwxr-xr-xsrc/theory/quantifiers/ce_guided_instantiation.cpp60
-rwxr-xr-xsrc/theory/quantifiers/ce_guided_single_inv.cpp46
-rwxr-xr-xsrc/theory/quantifiers/ce_guided_single_inv.h98
-rwxr-xr-xsrc/theory/quantifiers/ceg_instantiator.cpp1388
-rwxr-xr-xsrc/theory/quantifiers/ceg_instantiator.h198
-rw-r--r--src/theory/quantifiers/ceg_t_instantiator.cpp868
-rw-r--r--src/theory/quantifiers/ceg_t_instantiator.h93
-rwxr-xr-xsrc/theory/quantifiers/conjecture_generator.cpp3
-rwxr-xr-xsrc/theory/quantifiers/full_model_check.cpp8
-rwxr-xr-xsrc/theory/quantifiers/full_model_check.h2
-rwxr-xr-xsrc/theory/quantifiers/inst_match.cpp14
-rwxr-xr-xsrc/theory/quantifiers/inst_match_generator.cpp65
-rwxr-xr-xsrc/theory/quantifiers/inst_match_generator.h8
-rwxr-xr-xsrc/theory/quantifiers/inst_propagator.cpp2
-rwxr-xr-xsrc/theory/quantifiers/inst_strategy_cbqi.cpp792
-rwxr-xr-xsrc/theory/quantifiers/inst_strategy_cbqi.h90
-rwxr-xr-xsrc/theory/quantifiers/inst_strategy_e_matching.cpp1
-rwxr-xr-xsrc/theory/quantifiers/instantiation_engine.cpp17
-rwxr-xr-xsrc/theory/quantifiers/instantiation_engine.h2
-rwxr-xr-xsrc/theory/quantifiers/local_theory_ext.h2
-rwxr-xr-xsrc/theory/quantifiers/macros.cpp4
-rwxr-xr-xsrc/theory/quantifiers/macros.h2
-rwxr-xr-xsrc/theory/quantifiers/model_builder.cpp7
-rwxr-xr-xsrc/theory/quantifiers/model_builder.h11
-rwxr-xr-xsrc/theory/quantifiers/model_engine.cpp53
-rwxr-xr-xsrc/theory/quantifiers/model_engine.h14
-rwxr-xr-xsrc/theory/quantifiers/quant_conflict_find.cpp25
-rwxr-xr-xsrc/theory/quantifiers/quant_conflict_find.h2
-rwxr-xr-xsrc/theory/quantifiers/quant_split.cpp7
-rwxr-xr-xsrc/theory/quantifiers/quant_split.h1
-rwxr-xr-xsrc/theory/quantifiers/quant_util.cpp104
-rwxr-xr-xsrc/theory/quantifiers/quant_util.h38
-rwxr-xr-xsrc/theory/quantifiers/quantifiers_rewriter.cpp244
-rwxr-xr-xsrc/theory/quantifiers/quantifiers_rewriter.h11
-rwxr-xr-xsrc/theory/quantifiers/relevant_domain.h6
-rwxr-xr-xsrc/theory/quantifiers/rewrite_engine.cpp7
-rwxr-xr-xsrc/theory/quantifiers/rewrite_engine.h13
-rwxr-xr-xsrc/theory/quantifiers/term_database.cpp92
-rwxr-xr-xsrc/theory/quantifiers/term_database.h30
-rwxr-xr-xsrc/theory/quantifiers/theory_quantifiers.cpp7
-rwxr-xr-xsrc/theory/quantifiers/theory_quantifiers.h1
-rwxr-xr-xsrc/theory/quantifiers/trigger.cpp13
-rwxr-xr-xsrc/theory/quantifiers/trigger.h2
-rw-r--r--src/theory/quantifiers_engine.cpp202
-rw-r--r--src/theory/quantifiers_engine.h24
-rw-r--r--src/theory/sep/theory_sep.cpp466
-rw-r--r--src/theory/sep/theory_sep.h27
-rw-r--r--src/theory/sets/normal_form.h74
-rw-r--r--src/theory/sets/scrutinize.h6
-rw-r--r--src/theory/sets/theory_sets_private.cpp301
-rw-r--r--src/theory/sets/theory_sets_private.h7
-rw-r--r--src/theory/sets/theory_sets_type_enumerator.h10
-rw-r--r--src/theory/shared_terms_database.cpp2
-rw-r--r--src/theory/shared_terms_database.h2
-rw-r--r--src/theory/strings/theory_strings.cpp231
-rw-r--r--src/theory/strings/theory_strings.h6
-rw-r--r--src/theory/strings/theory_strings_rewriter.cpp1
-rw-r--r--src/theory/theory.cpp193
-rw-r--r--src/theory/theory.h75
-rw-r--r--src/theory/theory_engine.cpp18
-rw-r--r--src/theory/theory_engine.h13
-rw-r--r--src/theory/theory_model.h2
-rw-r--r--src/theory/uf/equality_engine.cpp11
-rw-r--r--src/theory/uf/equality_engine.h2
-rw-r--r--src/theory/uf/theory_uf_strong_solver.cpp55
-rw-r--r--src/theory/uf/theory_uf_strong_solver.h105
-rw-r--r--src/theory/uf/theory_uf_type_rules.h110
-rw-r--r--src/theory/unconstrained_simplifier.cpp77
84 files changed, 4335 insertions, 3054 deletions
diff --git a/src/theory/arith/cut_log.h b/src/theory/arith/cut_log.h
index 548035aec..e6475b58e 100644
--- a/src/theory/arith/cut_log.h
+++ b/src/theory/arith/cut_log.h
@@ -234,8 +234,6 @@ std::ostream& operator<<(std::ostream& os, const NodeLog& nl);
class ApproximateSimplex;
class TreeLog {
private:
- ApproximateSimplex* d_generator;
-
int next_exec_ord;
typedef std::map<int, NodeLog> ToNodeMap;
ToNodeMap d_toNode;
diff --git a/src/theory/arith/theory_arith.h b/src/theory/arith/theory_arith.h
index 3e414ca6d..51bbd67f3 100644
--- a/src/theory/arith/theory_arith.h
+++ b/src/theory/arith/theory_arith.h
@@ -25,10 +25,6 @@
namespace CVC4 {
namespace theory {
-namespace quantifiers {
- class InstStrategySimplex;
-}
-
namespace arith {
/**
@@ -38,7 +34,6 @@ namespace arith {
*/
class TheoryArith : public Theory {
private:
- friend class quantifiers::InstStrategySimplex;
friend class TheoryArithPrivate;
TheoryArithPrivate* d_internal;
diff --git a/src/theory/arith/theory_arith_private.cpp b/src/theory/arith/theory_arith_private.cpp
index e47231128..069d3530c 100644
--- a/src/theory/arith/theory_arith_private.cpp
+++ b/src/theory/arith/theory_arith_private.cpp
@@ -2520,34 +2520,37 @@ struct SizeOrd {
return a.size() < b.size();
}
};
-void TheoryArithPrivate::subsumption(std::vector<ConstraintCPVec>& confs) const {
+
+void TheoryArithPrivate::subsumption(
+ std::vector<ConstraintCPVec> &confs) const {
int checks CVC4_UNUSED = 0;
int subsumed CVC4_UNUSED = 0;
- for(size_t i =0, N= confs.size(); i < N; ++i){
- ConstraintCPVec& conf = confs[i];
+ for (size_t i = 0, N = confs.size(); i < N; ++i) {
+ ConstraintCPVec &conf = confs[i];
std::sort(conf.begin(), conf.end());
}
std::sort(confs.begin(), confs.end(), SizeOrd());
- for(size_t i = 0; i < confs.size(); i++){
- ConstraintCPVec& a = confs[i];
+ for (size_t i = 0; i < confs.size(); i++) {
// i is not subsumed
- for(size_t j = i+1; j < confs.size();){
+ for (size_t j = i + 1; j < confs.size();) {
+ ConstraintCPVec& a = confs[i];
ConstraintCPVec& b = confs[j];
checks++;
bool subsumes = std::includes(a.begin(), a.end(), b.begin(), b.end());
- if(subsumes){
+ if (subsumes) {
ConstraintCPVec& back = confs.back();
b.swap(back);
confs.pop_back();
subsumed++;
- }else{
+ } else {
j++;
}
}
}
- Debug("arith::subsumption") << "subsumed " << subsumed << "/" << checks << endl;
+ Debug("arith::subsumption") << "subsumed " << subsumed << "/" << checks
+ << endl;
}
std::vector<ConstraintCPVec> TheoryArithPrivate::replayLogRec(ApproximateSimplex* approx, int nid, ConstraintP bc, int depth){
diff --git a/src/theory/arith/theory_arith_private.h b/src/theory/arith/theory_arith_private.h
index edc3a5bc0..ed7efe008 100644
--- a/src/theory/arith/theory_arith_private.h
+++ b/src/theory/arith/theory_arith_private.h
@@ -70,9 +70,6 @@
namespace CVC4 {
namespace theory {
-namespace quantifiers {
- class InstStrategySimplex;
-}
namespace arith {
class BranchCutInfo;
@@ -93,7 +90,6 @@ class InferBoundsResult;
*/
class TheoryArithPrivate {
private:
- friend class quantifiers::InstStrategySimplex;
static const uint32_t RESET_START = 2;
diff --git a/src/theory/arrays/array_proof_reconstruction.cpp b/src/theory/arrays/array_proof_reconstruction.cpp
index 8dd7fe782..5ecccdd53 100644
--- a/src/theory/arrays/array_proof_reconstruction.cpp
+++ b/src/theory/arrays/array_proof_reconstruction.cpp
@@ -107,7 +107,14 @@ void ArrayProofReconstruction::notify(unsigned reasonType, Node reason, Node a,
// It could be that the guard condition is a constant disequality. In this case,
// we need to change it to a different format.
- if (childProof->d_id == theory::eq::MERGED_THROUGH_CONSTANTS) {
+ bool haveNegChild = false;
+ for (unsigned i = 0; i < childProof->d_children.size(); ++i) {
+ if (childProof->d_children[i]->d_node.getKind() == kind::NOT)
+ haveNegChild = true;
+ }
+
+ if ((childProof->d_children.size() != 0) &&
+ (childProof->d_id == theory::eq::MERGED_THROUGH_CONSTANTS || !haveNegChild)) {
// The proof has two children, explaining why each index is a (different) constant.
Assert(childProof->d_children.size() == 2);
@@ -117,7 +124,7 @@ void ArrayProofReconstruction::notify(unsigned reasonType, Node reason, Node a,
if (childProof->d_children[0]->d_id == theory::eq::MERGED_THROUGH_REFLEXIVITY) {
constantOne = childProof->d_children[0]->d_node;
} else {
- Assert(childProof->d_children[0]->d_id == theory::eq::MERGED_THROUGH_EQUALITY);
+ Assert(childProof->d_children[0]->d_node.getKind() == kind::EQUAL);
if ((childProof->d_children[0]->d_node[0] == indexOne) ||
(childProof->d_children[0]->d_node[0] == indexTwo)) {
constantOne = childProof->d_children[0]->d_node[1];
@@ -129,7 +136,7 @@ void ArrayProofReconstruction::notify(unsigned reasonType, Node reason, Node a,
if (childProof->d_children[1]->d_id == theory::eq::MERGED_THROUGH_REFLEXIVITY) {
constantTwo = childProof->d_children[1]->d_node;
} else {
- Assert(childProof->d_children[1]->d_id == theory::eq::MERGED_THROUGH_EQUALITY);
+ Assert(childProof->d_children[1]->d_node.getKind() == kind::EQUAL);
if ((childProof->d_children[1]->d_node[0] == indexOne) ||
(childProof->d_children[1]->d_node[0] == indexTwo)) {
constantTwo = childProof->d_children[1]->d_node[1];
diff --git a/src/theory/bv/bv_inequality_graph.h b/src/theory/bv/bv_inequality_graph.h
index 452172586..923e1d8c5 100644
--- a/src/theory/bv/bv_inequality_graph.h
+++ b/src/theory/bv/bv_inequality_graph.h
@@ -242,7 +242,7 @@ public:
*/
bool addDisequality(TNode a, TNode b, TNode reason);
void getConflict(std::vector<TNode>& conflict);
- virtual ~InequalityGraph() throw(AssertionException) {}
+ virtual ~InequalityGraph() {}
/**
* Check that the currently asserted disequalities that have not been split on
* are still true in the current model.
diff --git a/src/theory/bv/theory_bv.cpp b/src/theory/bv/theory_bv.cpp
index f0981044b..de596e3d5 100644
--- a/src/theory/bv/theory_bv.cpp
+++ b/src/theory/bv/theory_bv.cpp
@@ -100,8 +100,10 @@ TheoryBV::TheoryBV(context::Context* c, context::UserContext* u,
d_subtheoryMap[SUB_BITBLAST] = bb_solver;
}
-
TheoryBV::~TheoryBV() {
+ if (d_eagerSolver) {
+ delete d_eagerSolver;
+ }
for (unsigned i = 0; i < d_subtheories.size(); ++i) {
delete d_subtheories[i];
}
diff --git a/src/theory/bv/theory_bv_type_rules.h b/src/theory/bv/theory_bv_type_rules.h
index b531129f7..cafa7044a 100644
--- a/src/theory/bv/theory_bv_type_rules.h
+++ b/src/theory/bv/theory_bv_type_rules.h
@@ -26,9 +26,9 @@ namespace theory {
namespace bv {
class BitVectorConstantTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
if (check) {
if (n.getConst<BitVector>().getSize() == 0) {
throw TypeCheckingExceptionPrivate(n, "constant of size 0");
@@ -36,14 +36,13 @@ public:
}
return nodeManager->mkBitVectorType(n.getConst<BitVector>().getSize());
}
-};/* class BitVectorConstantTypeRule */
+}; /* class BitVectorConstantTypeRule */
class BitVectorBitOfTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate) {
-
- if(check) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
+ if (check) {
BitVectorBitOf info = n.getOperator().getConst<BitVectorBitOf>();
TypeNode t = n[0].getType(check);
@@ -51,72 +50,76 @@ public:
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector term");
}
if (info.bitIndex >= t.getBitVectorSize()) {
- throw TypeCheckingExceptionPrivate(n, "extract index is larger than the bitvector size");
+ throw TypeCheckingExceptionPrivate(
+ n, "extract index is larger than the bitvector size");
}
}
return nodeManager->booleanType();
}
-};/* class BitVectorBitOfTypeRule */
+}; /* class BitVectorBitOfTypeRule */
class BitVectorCompTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
- if( check ) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
+ if (check) {
TypeNode lhs = n[0].getType(check);
TypeNode rhs = n[1].getType(check);
if (!lhs.isBitVector() || lhs != rhs) {
- throw TypeCheckingExceptionPrivate(n, "expecting bit-vector terms of the same width");
+ throw TypeCheckingExceptionPrivate(
+ n, "expecting bit-vector terms of the same width");
}
}
return nodeManager->mkBitVectorType(1);
}
-};/* class BitVectorCompTypeRule */
+}; /* class BitVectorCompTypeRule */
class BitVectorFixedWidthTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TNode::iterator it = n.begin();
TypeNode t = (*it).getType(check);
- if( check ) {
+ if (check) {
if (!t.isBitVector()) {
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector terms");
}
TNode::iterator it_end = n.end();
- for (++ it; it != it_end; ++ it) {
+ for (++it; it != it_end; ++it) {
if ((*it).getType(check) != t) {
- throw TypeCheckingExceptionPrivate(n, "expecting bit-vector terms of the same width");
+ throw TypeCheckingExceptionPrivate(
+ n, "expecting bit-vector terms of the same width");
}
}
}
return t;
}
-};/* class BitVectorFixedWidthTypeRule */
+}; /* class BitVectorFixedWidthTypeRule */
class BitVectorPredicateTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
- if( check ) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
+ if (check) {
TypeNode lhsType = n[0].getType(check);
if (!lhsType.isBitVector()) {
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector terms");
}
TypeNode rhsType = n[1].getType(check);
if (lhsType != rhsType) {
- throw TypeCheckingExceptionPrivate(n, "expecting bit-vector terms of the same width");
+ throw TypeCheckingExceptionPrivate(
+ n, "expecting bit-vector terms of the same width");
}
}
return nodeManager->booleanType();
}
-};/* class BitVectorPredicateTypeRule */
+}; /* class BitVectorPredicateTypeRule */
class BitVectorUnaryPredicateTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
- if( check ) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
+ if (check) {
TypeNode type = n[0].getType(check);
if (!type.isBitVector()) {
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector terms");
@@ -124,13 +127,13 @@ public:
}
return nodeManager->booleanType();
}
-};/* class BitVectorUnaryPredicateTypeRule */
+}; /* class BitVectorUnaryPredicateTypeRule */
class BitVectorEagerAtomTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
- if( check ) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
+ if (check) {
TypeNode lhsType = n[0].getType(check);
if (!lhsType.isBoolean()) {
throw TypeCheckingExceptionPrivate(n, "expecting boolean term");
@@ -138,96 +141,98 @@ public:
}
return nodeManager->booleanType();
}
-};/* class BitVectorEagerAtomTypeRule */
+}; /* class BitVectorEagerAtomTypeRule */
class BitVectorAckermanizationUdivTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TypeNode lhsType = n[0].getType(check);
- if( check ) {
+ if (check) {
if (!lhsType.isBitVector()) {
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector term");
}
}
return lhsType;
}
-};/* class BitVectorAckermanizationUdivTypeRule */
+}; /* class BitVectorAckermanizationUdivTypeRule */
class BitVectorAckermanizationUremTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TypeNode lhsType = n[0].getType(check);
- if( check ) {
+ if (check) {
if (!lhsType.isBitVector()) {
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector term");
}
}
return lhsType;
}
-};/* class BitVectorAckermanizationUremTypeRule */
+}; /* class BitVectorAckermanizationUremTypeRule */
class BitVectorExtractTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
BitVectorExtract extractInfo = n.getOperator().getConst<BitVectorExtract>();
// NOTE: We're throwing a type-checking exception here even
// if check is false, bc if we allow high < low the resulting
// type will be illegal
if (extractInfo.high < extractInfo.low) {
- throw TypeCheckingExceptionPrivate(n, "high extract index is smaller than the low extract index");
+ throw TypeCheckingExceptionPrivate(
+ n, "high extract index is smaller than the low extract index");
}
- if( check ) {
+ if (check) {
TypeNode t = n[0].getType(check);
if (!t.isBitVector()) {
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector term");
}
if (extractInfo.high >= t.getBitVectorSize()) {
- throw TypeCheckingExceptionPrivate(n, "high extract index is bigger than the size of the bit-vector");
+ throw TypeCheckingExceptionPrivate(
+ n, "high extract index is bigger than the size of the bit-vector");
}
}
return nodeManager->mkBitVectorType(extractInfo.high - extractInfo.low + 1);
}
-};/* class BitVectorExtractTypeRule */
+}; /* class BitVectorExtractTypeRule */
class BitVectorExtractOpTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
Assert(n.getKind() == kind::BITVECTOR_EXTRACT_OP);
return nodeManager->builtinOperatorType();
}
-};/* class BitVectorExtractOpTypeRule */
+}; /* class BitVectorExtractOpTypeRule */
class BitVectorConcatTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
unsigned size = 0;
TNode::iterator it = n.begin();
TNode::iterator it_end = n.end();
- for (; it != it_end; ++ it) {
- TypeNode t = (*it).getType(check);
- // NOTE: We're throwing a type-checking exception here even
- // when check is false, bc if we don't check that the arguments
- // are bit-vectors the result type will be inaccurate
- if (!t.isBitVector()) {
- throw TypeCheckingExceptionPrivate(n, "expecting bit-vector terms");
- }
- size += t.getBitVectorSize();
+ for (; it != it_end; ++it) {
+ TypeNode t = (*it).getType(check);
+ // NOTE: We're throwing a type-checking exception here even
+ // when check is false, bc if we don't check that the arguments
+ // are bit-vectors the result type will be inaccurate
+ if (!t.isBitVector()) {
+ throw TypeCheckingExceptionPrivate(n, "expecting bit-vector terms");
+ }
+ size += t.getBitVectorSize();
}
return nodeManager->mkBitVectorType(size);
}
-};/* class BitVectorConcatTypeRule */
+}; /* class BitVectorConcatTypeRule */
class BitVectorRepeatTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TypeNode t = n[0].getType(check);
// NOTE: We're throwing a type-checking exception here even
// when check is false, bc if the argument isn't a bit-vector
@@ -238,12 +243,12 @@ public:
unsigned repeatAmount = n.getOperator().getConst<BitVectorRepeat>();
return nodeManager->mkBitVectorType(repeatAmount * t.getBitVectorSize());
}
-};/* class BitVectorRepeatTypeRule */
+}; /* class BitVectorRepeatTypeRule */
class BitVectorExtendTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TypeNode t = n[0].getType(check);
// NOTE: We're throwing a type-checking exception here even
// when check is false, bc if the argument isn't a bit-vector
@@ -251,27 +256,28 @@ public:
if (!t.isBitVector()) {
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector term");
}
- unsigned extendAmount = n.getKind() == kind::BITVECTOR_SIGN_EXTEND ?
- (unsigned) n.getOperator().getConst<BitVectorSignExtend>() :
- (unsigned) n.getOperator().getConst<BitVectorZeroExtend>();
+ unsigned extendAmount =
+ n.getKind() == kind::BITVECTOR_SIGN_EXTEND
+ ? (unsigned)n.getOperator().getConst<BitVectorSignExtend>()
+ : (unsigned)n.getOperator().getConst<BitVectorZeroExtend>();
return nodeManager->mkBitVectorType(extendAmount + t.getBitVectorSize());
}
-};/* class BitVectorExtendTypeRule */
+}; /* class BitVectorExtendTypeRule */
class BitVectorConversionTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
- if(n.getKind() == kind::BITVECTOR_TO_NAT) {
- if(check && !n[0].getType(check).isBitVector()) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
+ if (n.getKind() == kind::BITVECTOR_TO_NAT) {
+ if (check && !n[0].getType(check).isBitVector()) {
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector term");
}
return nodeManager->integerType();
}
- if(n.getKind() == kind::INT_TO_BITVECTOR) {
+ if (n.getKind() == kind::INT_TO_BITVECTOR) {
size_t bvSize = n.getOperator().getConst<IntToBitVector>();
- if(check && !n[0].getType(check).isInteger()) {
+ if (check && !n[0].getType(check).isInteger()) {
throw TypeCheckingExceptionPrivate(n, "expecting integer term");
}
return nodeManager->mkBitVectorType(bvSize);
@@ -279,24 +285,24 @@ public:
InternalError("bv-conversion typerule invoked for non-bv-conversion kind");
}
-};/* class BitVectorConversionTypeRule */
+}; /* class BitVectorConversionTypeRule */
class CardinalityComputer {
-public:
+ public:
inline static Cardinality computeCardinality(TypeNode type) {
Assert(type.getKind() == kind::BITVECTOR_TYPE);
unsigned size = type.getConst<BitVectorSize>();
- if(size == 0) {
+ if (size == 0) {
return 0;
}
Integer i = Integer(2).pow(size);
return i;
}
-};/* class CardinalityComputer */
+}; /* class CardinalityComputer */
-}/* CVC4::theory::bv namespace */
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
+} /* CVC4::theory::bv namespace */
+} /* CVC4::theory namespace */
+} /* CVC4 namespace */
#endif /* __CVC4__THEORY__BV__THEORY_BV_TYPE_RULES_H */
diff --git a/src/theory/datatypes/theory_datatypes_type_rules.h b/src/theory/datatypes/theory_datatypes_type_rules.h
index 9c8387958..8a440974d 100644
--- a/src/theory/datatypes/theory_datatypes_type_rules.h
+++ b/src/theory/datatypes/theory_datatypes_type_rules.h
@@ -25,56 +25,64 @@
namespace CVC4 {
namespace expr {
- namespace attr {
- struct DatatypeConstructorTypeGroundTermTag {};
- }/* CVC4::expr::attr namespace */
-}/* CVC4::expr namespace */
+namespace attr {
+struct DatatypeConstructorTypeGroundTermTag {};
+} /* CVC4::expr::attr namespace */
+} /* CVC4::expr namespace */
namespace theory {
namespace datatypes {
-typedef expr::Attribute<expr::attr::DatatypeConstructorTypeGroundTermTag, Node> GroundTermAttr;
-
+typedef expr::Attribute<expr::attr::DatatypeConstructorTypeGroundTermTag, Node>
+ GroundTermAttr;
struct DatatypeConstructorTypeRule {
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw(TypeCheckingExceptionPrivate, AssertionException) {
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
Assert(n.getKind() == kind::APPLY_CONSTRUCTOR);
TypeNode consType = n.getOperator().getType(check);
Type t = consType.getConstructorRangeType().toType();
- Assert( t.isDatatype() );
+ Assert(t.isDatatype());
DatatypeType dt = DatatypeType(t);
TNode::iterator child_it = n.begin();
TNode::iterator child_it_end = n.end();
TypeNode::iterator tchild_it = consType.begin();
- if( ( dt.isParametric() || check ) && n.getNumChildren() != consType.getNumChildren() - 1 ){
- throw TypeCheckingExceptionPrivate(n, "number of arguments does not match the constructor type");
+ if ((dt.isParametric() || check) &&
+ n.getNumChildren() != consType.getNumChildren() - 1) {
+ throw TypeCheckingExceptionPrivate(
+ n, "number of arguments does not match the constructor type");
}
- if( dt.isParametric() ){
- Debug("typecheck-idt") << "typecheck parameterized datatype " << n << std::endl;
- Matcher m( dt );
- for(; child_it != child_it_end; ++child_it, ++tchild_it) {
+ if (dt.isParametric()) {
+ Debug("typecheck-idt") << "typecheck parameterized datatype " << n
+ << std::endl;
+ Matcher m(dt);
+ for (; child_it != child_it_end; ++child_it, ++tchild_it) {
TypeNode childType = (*child_it).getType(check);
- if( !m.doMatching( *tchild_it, childType ) ){
- throw TypeCheckingExceptionPrivate(n, "matching failed for parameterized constructor");
+ if (!m.doMatching(*tchild_it, childType)) {
+ throw TypeCheckingExceptionPrivate(
+ n, "matching failed for parameterized constructor");
}
}
- std::vector< Type > instTypes;
- m.getMatches( instTypes );
- TypeNode range = TypeNode::fromType( dt.instantiate( instTypes ) );
+ std::vector<Type> instTypes;
+ m.getMatches(instTypes);
+ TypeNode range = TypeNode::fromType(dt.instantiate(instTypes));
Debug("typecheck-idt") << "Return " << range << std::endl;
return range;
- }else{
- if(check) {
- Debug("typecheck-idt") << "typecheck cons: " << n << " " << n.getNumChildren() << std::endl;
- Debug("typecheck-idt") << "cons type: " << consType << " " << consType.getNumChildren() << std::endl;
- for(; child_it != child_it_end; ++child_it, ++tchild_it) {
+ } else {
+ if (check) {
+ Debug("typecheck-idt") << "typecheck cons: " << n << " "
+ << n.getNumChildren() << std::endl;
+ Debug("typecheck-idt") << "cons type: " << consType << " "
+ << consType.getNumChildren() << std::endl;
+ for (; child_it != child_it_end; ++child_it, ++tchild_it) {
TypeNode childType = (*child_it).getType(check);
- Debug("typecheck-idt") << "typecheck cons arg: " << childType << " " << (*tchild_it) << std::endl;
+ Debug("typecheck-idt") << "typecheck cons arg: " << childType << " "
+ << (*tchild_it) << std::endl;
TypeNode argumentType = *tchild_it;
- if(!childType.isComparableTo(argumentType)) {
+ if (!childType.isComparableTo(argumentType)) {
std::stringstream ss;
- ss << "bad type for constructor argument:\nexpected: " << argumentType << "\ngot : " << childType;
+ ss << "bad type for constructor argument:\nexpected: "
+ << argumentType << "\ngot : " << childType;
throw TypeCheckingExceptionPrivate(n, ss.str());
}
}
@@ -83,132 +91,131 @@ struct DatatypeConstructorTypeRule {
}
}
- inline static bool computeIsConst(NodeManager* nodeManager, TNode n)
- throw(AssertionException) {
+ inline static bool computeIsConst(NodeManager* nodeManager, TNode n) {
Assert(n.getKind() == kind::APPLY_CONSTRUCTOR);
NodeManagerScope nms(nodeManager);
- for(TNode::const_iterator i = n.begin(); i != n.end(); ++i) {
- if( ! (*i).isConst() ) {
+ for (TNode::const_iterator i = n.begin(); i != n.end(); ++i) {
+ if (!(*i).isConst()) {
return false;
}
}
return true;
}
-};/* struct DatatypeConstructorTypeRule */
+}; /* struct DatatypeConstructorTypeRule */
struct DatatypeSelectorTypeRule {
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw(TypeCheckingExceptionPrivate) {
- Assert(n.getKind() == kind::APPLY_SELECTOR || n.getKind() == kind::APPLY_SELECTOR_TOTAL );
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
+ Assert(n.getKind() == kind::APPLY_SELECTOR ||
+ n.getKind() == kind::APPLY_SELECTOR_TOTAL);
TypeNode selType = n.getOperator().getType(check);
Type t = selType[0].toType();
- Assert( t.isDatatype() );
+ Assert(t.isDatatype());
DatatypeType dt = DatatypeType(t);
- if( ( dt.isParametric() || check ) && n.getNumChildren() != 1 ){
- throw TypeCheckingExceptionPrivate(n, "number of arguments does not match the selector type");
+ if ((dt.isParametric() || check) && n.getNumChildren() != 1) {
+ throw TypeCheckingExceptionPrivate(
+ n, "number of arguments does not match the selector type");
}
- if( dt.isParametric() ){
- Debug("typecheck-idt") << "typecheck parameterized sel: " << n << std::endl;
- Matcher m( dt );
+ if (dt.isParametric()) {
+ Debug("typecheck-idt") << "typecheck parameterized sel: " << n
+ << std::endl;
+ Matcher m(dt);
TypeNode childType = n[0].getType(check);
- if(! childType.isInstantiatedDatatype()) {
- throw TypeCheckingExceptionPrivate(n, "Datatype type not fully instantiated");
+ if (!childType.isInstantiatedDatatype()) {
+ throw TypeCheckingExceptionPrivate(
+ n, "Datatype type not fully instantiated");
}
- if( !m.doMatching( selType[0], childType ) ){
- throw TypeCheckingExceptionPrivate(n, "matching failed for selector argument of parameterized datatype");
+ if (!m.doMatching(selType[0], childType)) {
+ throw TypeCheckingExceptionPrivate(
+ n,
+ "matching failed for selector argument of parameterized datatype");
}
- std::vector< Type > types, matches;
- m.getTypes( types );
- m.getMatches( matches );
+ std::vector<Type> types, matches;
+ m.getTypes(types);
+ m.getMatches(matches);
Type range = selType[1].toType();
- range = range.substitute( types, matches );
+ range = range.substitute(types, matches);
Debug("typecheck-idt") << "Return " << range << std::endl;
- return TypeNode::fromType( range );
- }else{
- if(check) {
+ return TypeNode::fromType(range);
+ } else {
+ if (check) {
Debug("typecheck-idt") << "typecheck sel: " << n << std::endl;
Debug("typecheck-idt") << "sel type: " << selType << std::endl;
TypeNode childType = n[0].getType(check);
- if(!selType[0].isComparableTo(childType)) {
- Debug("typecheck-idt") << "ERROR: " << selType[0].getKind() << " " << childType.getKind() << std::endl;
- throw TypeCheckingExceptionPrivate(n, "bad type for selector argument");
+ if (!selType[0].isComparableTo(childType)) {
+ Debug("typecheck-idt") << "ERROR: " << selType[0].getKind() << " "
+ << childType.getKind() << std::endl;
+ throw TypeCheckingExceptionPrivate(n,
+ "bad type for selector argument");
}
}
return selType[1];
}
}
-};/* struct DatatypeSelectorTypeRule */
+}; /* struct DatatypeSelectorTypeRule */
struct DatatypeTesterTypeRule {
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw(TypeCheckingExceptionPrivate) {
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
Assert(n.getKind() == kind::APPLY_TESTER);
- if(check) {
- if(n.getNumChildren() != 1) {
- throw TypeCheckingExceptionPrivate(n, "number of arguments does not match the tester type");
+ if (check) {
+ if (n.getNumChildren() != 1) {
+ throw TypeCheckingExceptionPrivate(
+ n, "number of arguments does not match the tester type");
}
TypeNode testType = n.getOperator().getType(check);
TypeNode childType = n[0].getType(check);
Type t = testType[0].toType();
- Assert( t.isDatatype() );
+ Assert(t.isDatatype());
DatatypeType dt = DatatypeType(t);
- if(dt.isParametric()) {
- Debug("typecheck-idt") << "typecheck parameterized tester: " << n << std::endl;
- Matcher m( dt );
- if( !m.doMatching( testType[0], childType ) ){
- throw TypeCheckingExceptionPrivate(n, "matching failed for tester argument of parameterized datatype");
+ if (dt.isParametric()) {
+ Debug("typecheck-idt") << "typecheck parameterized tester: " << n
+ << std::endl;
+ Matcher m(dt);
+ if (!m.doMatching(testType[0], childType)) {
+ throw TypeCheckingExceptionPrivate(
+ n,
+ "matching failed for tester argument of parameterized datatype");
}
} else {
Debug("typecheck-idt") << "typecheck test: " << n << std::endl;
Debug("typecheck-idt") << "test type: " << testType << std::endl;
- if(!testType[0].isComparableTo(childType)) {
+ if (!testType[0].isComparableTo(childType)) {
throw TypeCheckingExceptionPrivate(n, "bad type for tester argument");
}
}
}
return nodeManager->booleanType();
}
-};/* struct DatatypeTesterTypeRule */
+}; /* struct DatatypeTesterTypeRule */
struct DatatypeAscriptionTypeRule {
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw(TypeCheckingExceptionPrivate) {
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
Debug("typecheck-idt") << "typechecking ascription: " << n << std::endl;
Assert(n.getKind() == kind::APPLY_TYPE_ASCRIPTION);
- TypeNode t = TypeNode::fromType(n.getOperator().getConst<AscriptionType>().getType());
- if(check) {
+ TypeNode t = TypeNode::fromType(
+ n.getOperator().getConst<AscriptionType>().getType());
+ if (check) {
TypeNode childType = n[0].getType(check);
- //if(!t.getKind() == kind::DATATYPE_TYPE) {
- // throw TypeCheckingExceptionPrivate(n, "bad type for datatype type ascription");
- //}
- //DatatypeType dt = DatatypeType(childType.toType());
- //if( dt.isParametric() ){
- // Debug("typecheck-idt") << "typecheck parameterized ascription: " << n << std::endl;
- // Matcher m( dt );
- // if( !m.doMatching( childType, t ) ){
- // throw TypeCheckingExceptionPrivate(n, "matching failed for type ascription argument of parameterized datatype");
- // }
- //}else{
- // Debug("typecheck-idt") << "typecheck test: " << n << std::endl;
- // if(t != childType) {
- // throw TypeCheckingExceptionPrivate(n, "bad type for type ascription argument");
- // }
- //}
Matcher m;
- if( childType.getKind() == kind::CONSTRUCTOR_TYPE ){
- m.addTypesFromDatatype( ConstructorType(childType.toType()).getRangeType() );
- }else if( childType.getKind() == kind::DATATYPE_TYPE ){
- m.addTypesFromDatatype( DatatypeType(childType.toType()) );
+ if (childType.getKind() == kind::CONSTRUCTOR_TYPE) {
+ m.addTypesFromDatatype(
+ ConstructorType(childType.toType()).getRangeType());
+ } else if (childType.getKind() == kind::DATATYPE_TYPE) {
+ m.addTypesFromDatatype(DatatypeType(childType.toType()));
}
- if( !m.doMatching( childType, t ) ){
- throw TypeCheckingExceptionPrivate(n, "matching failed for type ascription argument of parameterized datatype");
+ if (!m.doMatching(childType, t)) {
+ throw TypeCheckingExceptionPrivate(n,
+ "matching failed for type "
+ "ascription argument of "
+ "parameterized datatype");
}
-
}
return t;
}
-};/* struct DatatypeAscriptionTypeRule */
+}; /* struct DatatypeAscriptionTypeRule */
struct ConstructorProperties {
inline static Cardinality computeCardinality(TypeNode type) {
@@ -217,24 +224,26 @@ struct ConstructorProperties {
// that of a tuple than that of a function.
AssertArgument(type.isConstructor(), type);
Cardinality c = 1;
- for(unsigned i = 0, i_end = type.getNumChildren(); i < i_end - 1; ++i) {
+ for (unsigned i = 0, i_end = type.getNumChildren(); i < i_end - 1; ++i) {
c *= type[i].getCardinality();
}
return c;
}
-};/* struct ConstructorProperties */
+}; /* struct ConstructorProperties */
struct TupleUpdateTypeRule {
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
Assert(n.getKind() == kind::TUPLE_UPDATE);
const TupleUpdate& tu = n.getOperator().getConst<TupleUpdate>();
TypeNode tupleType = n[0].getType(check);
TypeNode newValue = n[1].getType(check);
- if(check) {
- if(!tupleType.isTuple()) {
- throw TypeCheckingExceptionPrivate(n, "Tuple-update expression formed over non-tuple");
+ if (check) {
+ if (!tupleType.isTuple()) {
+ throw TypeCheckingExceptionPrivate(
+ n, "Tuple-update expression formed over non-tuple");
}
- if(tu.getIndex() >= tupleType.getTupleLength()) {
+ if (tu.getIndex() >= tupleType.getTupleLength()) {
std::stringstream ss;
ss << "Tuple-update expression index `" << tu.getIndex()
<< "' is not a valid index; tuple type only has "
@@ -244,21 +253,23 @@ struct TupleUpdateTypeRule {
}
return tupleType;
}
-};/* struct TupleUpdateTypeRule */
+}; /* struct TupleUpdateTypeRule */
struct RecordUpdateTypeRule {
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
Assert(n.getKind() == kind::RECORD_UPDATE);
NodeManagerScope nms(nodeManager);
const RecordUpdate& ru = n.getOperator().getConst<RecordUpdate>();
TypeNode recordType = n[0].getType(check);
TypeNode newValue = n[1].getType(check);
- if(check) {
- if(!recordType.isRecord()) {
- throw TypeCheckingExceptionPrivate(n, "Record-update expression formed over non-record");
+ if (check) {
+ if (!recordType.isRecord()) {
+ throw TypeCheckingExceptionPrivate(
+ n, "Record-update expression formed over non-record");
}
const Record& rec = recordType.getRecord();
- if(!rec.contains(ru.getField())) {
+ if (!rec.contains(ru.getField())) {
std::stringstream ss;
ss << "Record-update field `" << ru.getField()
<< "' is not a valid field name for the record type";
@@ -267,44 +278,49 @@ struct RecordUpdateTypeRule {
}
return recordType;
}
-};/* struct RecordUpdateTypeRule */
+}; /* struct RecordUpdateTypeRule */
class DtSizeTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
- if( check ) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
+ if (check) {
TypeNode t = n[0].getType(check);
if (!t.isDatatype()) {
- throw TypeCheckingExceptionPrivate(n, "expecting datatype size term to have datatype argument.");
+ throw TypeCheckingExceptionPrivate(
+ n, "expecting datatype size term to have datatype argument.");
}
}
return nodeManager->integerType();
}
-};/* class DtSizeTypeRule */
+}; /* class DtSizeTypeRule */
class DtHeightBoundTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
- if( check ) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
+ if (check) {
TypeNode t = n[0].getType(check);
if (!t.isDatatype()) {
- throw TypeCheckingExceptionPrivate(n, "expecting datatype height bound term to have datatype argument.");
+ throw TypeCheckingExceptionPrivate(
+ n,
+ "expecting datatype height bound term to have datatype argument.");
}
- if( n[1].getKind()!=kind::CONST_RATIONAL ){
- throw TypeCheckingExceptionPrivate(n, "datatype height bound must be a constant");
+ if (n[1].getKind() != kind::CONST_RATIONAL) {
+ throw TypeCheckingExceptionPrivate(
+ n, "datatype height bound must be a constant");
}
- if( n[1].getConst<Rational>().getNumerator().sgn()==-1 ){
- throw TypeCheckingExceptionPrivate(n, "datatype height bound must be non-negative");
+ if (n[1].getConst<Rational>().getNumerator().sgn() == -1) {
+ throw TypeCheckingExceptionPrivate(
+ n, "datatype height bound must be non-negative");
}
}
return nodeManager->booleanType();
}
-};/* class DtHeightBoundTypeRule */
+}; /* class DtHeightBoundTypeRule */
-}/* CVC4::theory::datatypes namespace */
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
+} /* CVC4::theory::datatypes namespace */
+} /* CVC4::theory namespace */
+} /* CVC4 namespace */
#endif /* __CVC4__THEORY__DATATYPES__THEORY_DATATYPES_TYPE_RULES_H */
diff --git a/src/theory/fp/theory_fp_type_rules.h b/src/theory/fp/theory_fp_type_rules.h
index f9bf2e432..edda93de8 100644
--- a/src/theory/fp/theory_fp_type_rules.h
+++ b/src/theory/fp/theory_fp_type_rules.h
@@ -24,34 +24,36 @@ namespace CVC4 {
namespace theory {
namespace fp {
-#define TRACE(FUNCTION) Trace("fp-type") << FUNCTION "::computeType(" << check << "): " << n << std::endl
-
+#define TRACE(FUNCTION) \
+ Trace("fp-type") << FUNCTION "::computeType(" << check << "): " << n \
+ << std::endl
class FloatingPointConstantTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TRACE("FloatingPointConstantTypeRule");
- const FloatingPoint &f = n.getConst<FloatingPoint>();
-
+ const FloatingPoint& f = n.getConst<FloatingPoint>();
+
if (check) {
if (!(validExponentSize(f.t.exponent()))) {
- throw TypeCheckingExceptionPrivate(n, "constant with invalid exponent size");
+ throw TypeCheckingExceptionPrivate(
+ n, "constant with invalid exponent size");
}
if (!(validSignificandSize(f.t.significand()))) {
- throw TypeCheckingExceptionPrivate(n, "constant with invalid significand size");
+ throw TypeCheckingExceptionPrivate(
+ n, "constant with invalid significand size");
}
}
return nodeManager->mkFloatingPointType(f.t);
}
};
-
class RoundingModeConstantTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TRACE("RoundingModeConstantTypeRule");
// Nothing to check!
@@ -59,22 +61,20 @@ public:
}
};
-
-
class FloatingPointFPTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TRACE("FloatingPointFPTypeRule");
TypeNode signType = n[0].getType(check);
TypeNode exponentType = n[1].getType(check);
TypeNode significandType = n[2].getType(check);
- if (!signType.isBitVector() ||
- !exponentType.isBitVector() ||
- !significandType.isBitVector()) {
- throw TypeCheckingExceptionPrivate(n, "arguments to fp must be bit vectors");
+ if (!signType.isBitVector() || !exponentType.isBitVector() ||
+ !significandType.isBitVector()) {
+ throw TypeCheckingExceptionPrivate(n,
+ "arguments to fp must be bit vectors");
}
unsigned signBits = signType.getBitVectorSize();
@@ -82,41 +82,43 @@ public:
unsigned significandBits = significandType.getBitVectorSize();
if (check) {
-
if (signBits != 1) {
- throw TypeCheckingExceptionPrivate(n, "sign bit vector in fp must be 1 bit long");
+ throw TypeCheckingExceptionPrivate(
+ n, "sign bit vector in fp must be 1 bit long");
} else if (!(validExponentSize(exponentBits))) {
- throw TypeCheckingExceptionPrivate(n, "exponent bit vector in fp is an invalid size");
+ throw TypeCheckingExceptionPrivate(
+ n, "exponent bit vector in fp is an invalid size");
} else if (!(validSignificandSize(significandBits))) {
- throw TypeCheckingExceptionPrivate(n, "significand bit vector in fp is an invalid size");
+ throw TypeCheckingExceptionPrivate(
+ n, "significand bit vector in fp is an invalid size");
}
}
// The +1 is for the implicit hidden bit
- return nodeManager->mkFloatingPointType(exponentBits,significandBits + 1);
+ return nodeManager->mkFloatingPointType(exponentBits, significandBits + 1);
}
-
};
-
class FloatingPointTestTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TRACE("FloatingPointTestTypeRule");
if (check) {
TypeNode firstOperand = n[0].getType(check);
if (!firstOperand.isFloatingPoint()) {
- throw TypeCheckingExceptionPrivate(n, "floating-point test applied to a non floating-point sort");
+ throw TypeCheckingExceptionPrivate(
+ n, "floating-point test applied to a non floating-point sort");
}
size_t children = n.getNumChildren();
for (size_t i = 1; i < children; ++i) {
- if (!(n[i].getType(check) == firstOperand)) {
- throw TypeCheckingExceptionPrivate(n, "floating-point test applied to mixed sorts");
- }
+ if (!(n[i].getType(check) == firstOperand)) {
+ throw TypeCheckingExceptionPrivate(
+ n, "floating-point test applied to mixed sorts");
+ }
}
}
@@ -124,25 +126,26 @@ public:
}
};
-
class FloatingPointOperationTypeRule {
-public :
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TRACE("FloatingPointOperationTypeRule");
TypeNode firstOperand = n[0].getType(check);
if (check) {
if (!firstOperand.isFloatingPoint()) {
- throw TypeCheckingExceptionPrivate(n, "floating-point operation applied to a non floating-point sort");
+ throw TypeCheckingExceptionPrivate(
+ n, "floating-point operation applied to a non floating-point sort");
}
size_t children = n.getNumChildren();
for (size_t i = 1; i < children; ++i) {
- if (!(n[i].getType(check) == firstOperand)) {
- throw TypeCheckingExceptionPrivate(n, "floating-point test applied to mixed sorts");
- }
+ if (!(n[i].getType(check) == firstOperand)) {
+ throw TypeCheckingExceptionPrivate(
+ n, "floating-point test applied to mixed sorts");
+ }
}
}
@@ -150,34 +153,35 @@ public :
}
};
-
class FloatingPointRoundingOperationTypeRule {
-public :
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TRACE("FloatingPointRoundingOperationTypeRule");
if (check) {
TypeNode roundingModeType = n[0].getType(check);
if (!roundingModeType.isRoundingMode()) {
- throw TypeCheckingExceptionPrivate(n, "first argument must be a rounding mode");
+ throw TypeCheckingExceptionPrivate(
+ n, "first argument must be a rounding mode");
}
}
-
TypeNode firstOperand = n[1].getType(check);
if (check) {
if (!firstOperand.isFloatingPoint()) {
- throw TypeCheckingExceptionPrivate(n, "floating-point operation applied to a non floating-point sort");
+ throw TypeCheckingExceptionPrivate(
+ n, "floating-point operation applied to a non floating-point sort");
}
size_t children = n.getNumChildren();
for (size_t i = 2; i < children; ++i) {
- if (!(n[i].getType(check) == firstOperand)) {
- throw TypeCheckingExceptionPrivate(n, "floating-point test applied to mixed sorts");
- }
+ if (!(n[i].getType(check) == firstOperand)) {
+ throw TypeCheckingExceptionPrivate(
+ n, "floating-point test applied to mixed sorts");
+ }
}
}
@@ -186,9 +190,9 @@ public :
};
class FloatingPointParametricOpTypeRule {
-public :
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TRACE("FloatingPointParametricOpTypeRule");
return nodeManager->builtinOperatorType();
@@ -196,20 +200,28 @@ public :
};
class FloatingPointToFPIEEEBitVectorTypeRule {
-public :
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TRACE("FloatingPointToFPIEEEBitVectorTypeRule");
- FloatingPointToFPIEEEBitVector info = n.getOperator().getConst<FloatingPointToFPIEEEBitVector>();
+ FloatingPointToFPIEEEBitVector info =
+ n.getOperator().getConst<FloatingPointToFPIEEEBitVector>();
if (check) {
TypeNode operandType = n[0].getType(check);
-
+
if (!(operandType.isBitVector())) {
- throw TypeCheckingExceptionPrivate(n, "conversion to floating-point from bit vector used with sort other than bit vector");
- } else if (!(operandType.getBitVectorSize() == info.t.exponent() + info.t.significand())) {
- throw TypeCheckingExceptionPrivate(n, "conversion to floating-point from bit vector used with bit vector length that does not match floating point parameters");
+ throw TypeCheckingExceptionPrivate(n,
+ "conversion to floating-point from "
+ "bit vector used with sort other "
+ "than bit vector");
+ } else if (!(operandType.getBitVectorSize() ==
+ info.t.exponent() + info.t.significand())) {
+ throw TypeCheckingExceptionPrivate(
+ n,
+ "conversion to floating-point from bit vector used with bit vector "
+ "length that does not match floating point parameters");
}
}
@@ -217,27 +229,30 @@ public :
}
};
-
class FloatingPointToFPFloatingPointTypeRule {
-public :
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TRACE("FloatingPointToFPFloatingPointTypeRule");
- FloatingPointToFPFloatingPoint info = n.getOperator().getConst<FloatingPointToFPFloatingPoint>();
+ FloatingPointToFPFloatingPoint info =
+ n.getOperator().getConst<FloatingPointToFPFloatingPoint>();
if (check) {
TypeNode roundingModeType = n[0].getType(check);
if (!roundingModeType.isRoundingMode()) {
- throw TypeCheckingExceptionPrivate(n, "first argument must be a rounding mode");
+ throw TypeCheckingExceptionPrivate(
+ n, "first argument must be a rounding mode");
}
-
TypeNode operandType = n[1].getType(check);
-
+
if (!(operandType.isFloatingPoint())) {
- throw TypeCheckingExceptionPrivate(n, "conversion to floating-point from floating-point used with sort other than floating-point");
+ throw TypeCheckingExceptionPrivate(n,
+ "conversion to floating-point from "
+ "floating-point used with sort "
+ "other than floating-point");
}
}
@@ -245,27 +260,30 @@ public :
}
};
-
class FloatingPointToFPRealTypeRule {
-public :
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TRACE("FloatingPointToFPRealTypeRule");
- FloatingPointToFPReal info = n.getOperator().getConst<FloatingPointToFPReal>();
+ FloatingPointToFPReal info =
+ n.getOperator().getConst<FloatingPointToFPReal>();
if (check) {
TypeNode roundingModeType = n[0].getType(check);
if (!roundingModeType.isRoundingMode()) {
- throw TypeCheckingExceptionPrivate(n, "first argument must be a rounding mode");
+ throw TypeCheckingExceptionPrivate(
+ n, "first argument must be a rounding mode");
}
-
TypeNode operandType = n[1].getType(check);
-
+
if (!(operandType.isReal())) {
- throw TypeCheckingExceptionPrivate(n, "conversion to floating-point from real used with sort other than real");
+ throw TypeCheckingExceptionPrivate(n,
+ "conversion to floating-point from "
+ "real used with sort other than "
+ "real");
}
}
@@ -273,27 +291,30 @@ public :
}
};
-
class FloatingPointToFPSignedBitVectorTypeRule {
-public :
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TRACE("FloatingPointToFPSignedBitVectorTypeRule");
- FloatingPointToFPSignedBitVector info = n.getOperator().getConst<FloatingPointToFPSignedBitVector>();
+ FloatingPointToFPSignedBitVector info =
+ n.getOperator().getConst<FloatingPointToFPSignedBitVector>();
if (check) {
TypeNode roundingModeType = n[0].getType(check);
if (!roundingModeType.isRoundingMode()) {
- throw TypeCheckingExceptionPrivate(n, "first argument must be a rounding mode");
+ throw TypeCheckingExceptionPrivate(
+ n, "first argument must be a rounding mode");
}
-
TypeNode operandType = n[1].getType(check);
-
+
if (!(operandType.isBitVector())) {
- throw TypeCheckingExceptionPrivate(n, "conversion to floating-point from signed bit vector used with sort other than bit vector");
+ throw TypeCheckingExceptionPrivate(n,
+ "conversion to floating-point from "
+ "signed bit vector used with sort "
+ "other than bit vector");
}
}
@@ -301,27 +322,30 @@ public :
}
};
-
class FloatingPointToFPUnsignedBitVectorTypeRule {
-public :
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TRACE("FloatingPointToFPUnsignedBitVectorTypeRule");
- FloatingPointToFPUnsignedBitVector info = n.getOperator().getConst<FloatingPointToFPUnsignedBitVector>();
+ FloatingPointToFPUnsignedBitVector info =
+ n.getOperator().getConst<FloatingPointToFPUnsignedBitVector>();
if (check) {
TypeNode roundingModeType = n[0].getType(check);
if (!roundingModeType.isRoundingMode()) {
- throw TypeCheckingExceptionPrivate(n, "first argument must be a rounding mode");
+ throw TypeCheckingExceptionPrivate(
+ n, "first argument must be a rounding mode");
}
-
TypeNode operandType = n[1].getType(check);
-
+
if (!(operandType.isBitVector())) {
- throw TypeCheckingExceptionPrivate(n, "conversion to floating-point from unsigned bit vector used with sort other than bit vector");
+ throw TypeCheckingExceptionPrivate(n,
+ "conversion to floating-point from "
+ "unsigned bit vector used with sort "
+ "other than bit vector");
}
}
@@ -329,15 +353,14 @@ public :
}
};
-
-
class FloatingPointToFPGenericTypeRule {
-public :
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TRACE("FloatingPointToFPGenericTypeRule");
- FloatingPointToFPGeneric info = n.getOperator().getConst<FloatingPointToFPGeneric>();
+ FloatingPointToFPGeneric info =
+ n.getOperator().getConst<FloatingPointToFPGeneric>();
if (check) {
/* As this is a generic kind intended only for parsing,
@@ -347,7 +370,7 @@ public :
size_t children = n.getNumChildren();
for (size_t i = 0; i < children; ++i) {
- n[i].getType(check);
+ n[i].getType(check);
}
}
@@ -355,12 +378,10 @@ public :
}
};
-
-
class FloatingPointToUBVTypeRule {
-public :
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TRACE("FloatingPointToUBVTypeRule");
FloatingPointToUBV info = n.getOperator().getConst<FloatingPointToUBV>();
@@ -369,14 +390,17 @@ public :
TypeNode roundingModeType = n[0].getType(check);
if (!roundingModeType.isRoundingMode()) {
- throw TypeCheckingExceptionPrivate(n, "first argument must be a rounding mode");
+ throw TypeCheckingExceptionPrivate(
+ n, "first argument must be a rounding mode");
}
-
TypeNode operandType = n[1].getType(check);
-
+
if (!(operandType.isFloatingPoint())) {
- throw TypeCheckingExceptionPrivate(n, "conversion to unsigned bit vector used with a sort other than floating-point");
+ throw TypeCheckingExceptionPrivate(n,
+ "conversion to unsigned bit vector "
+ "used with a sort other than "
+ "floating-point");
}
}
@@ -384,11 +408,10 @@ public :
}
};
-
class FloatingPointToSBVTypeRule {
-public :
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TRACE("FloatingPointToSBVTypeRule");
FloatingPointToSBV info = n.getOperator().getConst<FloatingPointToSBV>();
@@ -397,14 +420,17 @@ public :
TypeNode roundingModeType = n[0].getType(check);
if (!roundingModeType.isRoundingMode()) {
- throw TypeCheckingExceptionPrivate(n, "first argument must be a rounding mode");
+ throw TypeCheckingExceptionPrivate(
+ n, "first argument must be a rounding mode");
}
-
TypeNode operandType = n[1].getType(check);
-
+
if (!(operandType.isFloatingPoint())) {
- throw TypeCheckingExceptionPrivate(n, "conversion to signed bit vector used with a sort other than floating-point");
+ throw TypeCheckingExceptionPrivate(n,
+ "conversion to signed bit vector "
+ "used with a sort other than "
+ "floating-point");
}
}
@@ -412,25 +438,25 @@ public :
}
};
-
-
class FloatingPointToRealTypeRule {
-public :
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TRACE("FloatingPointToRealTypeRule");
if (check) {
TypeNode roundingModeType = n[0].getType(check);
if (!roundingModeType.isRoundingMode()) {
- throw TypeCheckingExceptionPrivate(n, "first argument must be a rounding mode");
+ throw TypeCheckingExceptionPrivate(
+ n, "first argument must be a rounding mode");
}
TypeNode operand = n[1].getType(check);
if (!operand.isFloatingPoint()) {
- throw TypeCheckingExceptionPrivate(n, "floating-point to real applied to a non floating-point sort");
+ throw TypeCheckingExceptionPrivate(
+ n, "floating-point to real applied to a non floating-point sort");
}
}
@@ -438,10 +464,8 @@ public :
}
};
-
-
-}/* CVC4::theory::fp namespace */
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
+} /* CVC4::theory::fp namespace */
+} /* CVC4::theory namespace */
+} /* CVC4 namespace */
#endif /* __CVC4__THEORY__FP__THEORY_FP_TYPE_RULES_H */
diff --git a/src/theory/ite_utilities.cpp b/src/theory/ite_utilities.cpp
index 6fab100de..126f3bfb8 100644
--- a/src/theory/ite_utilities.cpp
+++ b/src/theory/ite_utilities.cpp
@@ -73,9 +73,9 @@ static bool isTheoryAtom(TNode a){
struct CTIVStackElement {
TNode curr;
unsigned pos;
- CTIVStackElement(){}
- CTIVStackElement(TNode c) : curr(c), pos(0){ }
-};/* CTIVStackElement */
+ CTIVStackElement() : curr(), pos(0) {}
+ CTIVStackElement(TNode c) : curr(c), pos(0) {}
+}; /* CTIVStackElement */
} /* CVC4::theory::ite */
@@ -490,8 +490,8 @@ struct TITEHStackElement {
TNode curr;
unsigned pos;
uint32_t maxChildHeight;
- TITEHStackElement(){}
- TITEHStackElement(TNode c) : curr(c), pos(0), maxChildHeight(0){ }
+ TITEHStackElement() : curr(), pos(0), maxChildHeight(0) {}
+ TITEHStackElement(TNode c) : curr(c), pos(0), maxChildHeight(0) {}
};
} /* namespace ite */
diff --git a/src/theory/quantifiers/ambqi_builder.cpp b/src/theory/quantifiers/ambqi_builder.cpp
index 97116dee4..2ccc17e55 100755
--- a/src/theory/quantifiers/ambqi_builder.cpp
+++ b/src/theory/quantifiers/ambqi_builder.cpp
@@ -836,7 +836,7 @@ void AbsMbqiBuilder::processBuildModel(TheoryModel* m, bool fullModel) {
//--------------------model checking---------------------------------------
//do exhaustive instantiation
-bool AbsMbqiBuilder::doExhaustiveInstantiation( FirstOrderModel * fm, Node q, int effort ) {
+int AbsMbqiBuilder::doExhaustiveInstantiation( FirstOrderModel * fm, Node q, int effort ) {
Trace("ambqi-check") << "Exhaustive instantiation " << q << " " << effort << std::endl;
if (effort==0) {
FirstOrderModelAbs * fma = fm->asFirstOrderModelAbs();
@@ -868,9 +868,10 @@ bool AbsMbqiBuilder::doExhaustiveInstantiation( FirstOrderModel * fm, Node q, in
d_addedLemmas += lem;
Trace("ambqi-inst-debug") << "...Total : " << d_addedLemmas << std::endl;
}
- return quantValid;
+ return quantValid ? 1 : 0;
+ }else{
+ return 1;
}
- return true;
}
bool AbsMbqiBuilder::doCheck( FirstOrderModelAbs * m, TNode q, AbsDef & ad, TNode n ) {
diff --git a/src/theory/quantifiers/ambqi_builder.h b/src/theory/quantifiers/ambqi_builder.h
index 3669d38b7..0adaef638 100755
--- a/src/theory/quantifiers/ambqi_builder.h
+++ b/src/theory/quantifiers/ambqi_builder.h
@@ -93,7 +93,7 @@ public:
//process build model
void processBuildModel(TheoryModel* m, bool fullModel);
//do exhaustive instantiation
- bool doExhaustiveInstantiation( FirstOrderModel * fm, Node q, int effort );
+ int doExhaustiveInstantiation( FirstOrderModel * fm, Node q, int effort );
};
}
diff --git a/src/theory/quantifiers/anti_skolem.cpp b/src/theory/quantifiers/anti_skolem.cpp
index c8d18aced..9ccba38cd 100755
--- a/src/theory/quantifiers/anti_skolem.cpp
+++ b/src/theory/quantifiers/anti_skolem.cpp
@@ -14,18 +14,19 @@
**/
#include "theory/quantifiers/anti_skolem.h"
+
+#include "options/quantifiers_options.h"
+#include "theory/quantifiers/first_order_model.h"
#include "theory/quantifiers/term_database.h"
#include "theory/quantifiers_engine.h"
-#include "theory/quantifiers/first_order_model.h"
-#include "options/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;
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
struct sortTypeOrder {
TermDb* d_tdb;
@@ -74,10 +75,13 @@ bool QuantAntiSkolem::CDSkQuantCache::add( context::Context* c, std::vector< Nod
}
}
-QuantAntiSkolem::QuantAntiSkolem( QuantifiersEngine * qe ) : QuantifiersModule( qe ){
- d_sqc = new CDSkQuantCache( qe->getUserContext() );
+QuantAntiSkolem::QuantAntiSkolem(QuantifiersEngine* qe)
+ : QuantifiersModule(qe) {
+ d_sqc = new CDSkQuantCache(qe->getUserContext());
}
+QuantAntiSkolem::~QuantAntiSkolem() { delete d_sqc; }
+
/* Call during quantifier engine's check */
void QuantAntiSkolem::check( Theory::Effort e, unsigned quant_e ) {
if( quant_e==QuantifiersEngine::QEFFORT_STANDARD ){
@@ -267,3 +271,6 @@ bool QuantAntiSkolem::sendAntiSkolemizeLemma( std::vector< Node >& quants, bool
}
}
+}/* namespace CVC4::theory::quantifiers */
+}/* namespace CVC4::theory */
+}/* namespace CVC4 */
diff --git a/src/theory/quantifiers/anti_skolem.h b/src/theory/quantifiers/anti_skolem.h
index 721371159..48205db9d 100755
--- a/src/theory/quantifiers/anti_skolem.h
+++ b/src/theory/quantifiers/anti_skolem.h
@@ -17,17 +17,39 @@
#ifndef __CVC4__THEORY__QUANT_ANTI_SKOLEM_H
#define __CVC4__THEORY__QUANT_ANTI_SKOLEM_H
-#include "theory/quantifiers_engine.h"
+#include <map>
+#include <vector>
+
+#include "expr/node.h"
+#include "expr/type_node.h"
+#include "context/cdhashset.h"
#include "context/cdo.h"
#include "theory/quantifiers/ce_guided_single_inv.h"
+#include "theory/quantifiers_engine.h"
namespace CVC4 {
namespace theory {
namespace quantifiers {
class QuantAntiSkolem : public QuantifiersModule {
+public:
+ QuantAntiSkolem( QuantifiersEngine * qe );
+ virtual ~QuantAntiSkolem();
+
+ bool sendAntiSkolemizeLemma( std::vector< Node >& quants,
+ bool pconnected = true );
+
+ /* Call during quantifier engine's check */
+ void check( Theory::Effort e, unsigned quant_e );
+ /* Called for new quantifiers */
+ void registerQuantifier( Node q ) {}
+ void assertNode( Node n ) {}
+ /** Identify this module (for debugging, dynamic configuration, etc..) */
+ std::string identify() const { return "QuantAntiSkolem"; }
+
+ private:
typedef context::CDHashSet<Node, NodeHashFunction> NodeSet;
-private:
+
std::map< Node, bool > d_quant_processed;
std::map< Node, SingleInvocationPartition > d_quant_sip;
std::map< Node, std::vector< TypeNode > > d_ask_types;
@@ -54,22 +76,10 @@ private:
bool add( context::Context* c, std::vector< Node >& quants, unsigned index = 0 );
};
CDSkQuantCache * d_sqc;
-public:
- bool sendAntiSkolemizeLemma( std::vector< Node >& quants, bool pconnected = true );
-public:
- QuantAntiSkolem( QuantifiersEngine * qe );
-
- /* Call during quantifier engine's check */
- void check( Theory::Effort e, unsigned quant_e );
- /* Called for new quantifiers */
- void registerQuantifier( Node q ) {}
- void assertNode( Node n ) {}
- /** Identify this module (for debugging, dynamic configuration, etc..) */
- std::string identify() const { return "QuantAntiSkolem"; }
-};
+}; /* class QuantAntiSkolem */
-}
-}
-}
+}/* namespace CVC4::theory::quantifiers */
+}/* namespace CVC4::theory */
+}/* namespace CVC4 */
#endif
diff --git a/src/theory/quantifiers/candidate_generator.cpp b/src/theory/quantifiers/candidate_generator.cpp
index a0d9bda0f..8e8f34cac 100755
--- a/src/theory/quantifiers/candidate_generator.cpp
+++ b/src/theory/quantifiers/candidate_generator.cpp
@@ -264,6 +264,7 @@ CandidateGeneratorQEAll::CandidateGeneratorQEAll( QuantifiersEngine* qe, Node mp
Assert( mpat.getKind()==INST_CONSTANT );
d_f = quantifiers::TermDb::getInstConstAttr( mpat );
d_index = mpat.getAttribute(InstVarNumAttribute());
+ d_firstTime = false;
}
void CandidateGeneratorQEAll::resetInstantiationRound() {
diff --git a/src/theory/quantifiers/ce_guided_instantiation.cpp b/src/theory/quantifiers/ce_guided_instantiation.cpp
index 71bf7c426..54415d974 100755
--- a/src/theory/quantifiers/ce_guided_instantiation.cpp
+++ b/src/theory/quantifiers/ce_guided_instantiation.cpp
@@ -767,7 +767,7 @@ void CegInstantiation::printSynthSolution( std::ostream& out ) {
Assert( dt.isSygus() );
//get the solution
Node sol;
- int status;
+ int status = -1;
if( d_last_inst_si ){
Assert( d_conj->getCegConjectureSingleInv() != NULL );
sol = d_conj->getSingleInvocationSolution( i, tn, status );
@@ -786,39 +786,45 @@ void CegInstantiation::printSynthSolution( std::ostream& out ) {
for( unsigned j=0; j<svl.getNumChildren(); j++ ){
subs.push_back( Node::fromExpr( svl[j] ) );
}
+ bool templIsPost = false;
+ Node templ;
if( options::sygusInvTemplMode() == SYGUS_INV_TEMPL_MODE_PRE ){
- const CegConjectureSingleInv* ceg_si =
- d_conj->getCegConjectureSingleInv();
+ const CegConjectureSingleInv* ceg_si = d_conj->getCegConjectureSingleInv();
if(ceg_si->d_trans_pre.find( prog ) != ceg_si->d_trans_pre.end()){
- std::vector<Node>& templ_vars = d_conj->getProgTempVars(prog);
- Assert(templ_vars.size() == subs.size());
- Node pre = ceg_si->getTransPre(prog);
- pre = pre.substitute( templ_vars.begin(), templ_vars.end(),
- subs.begin(), subs.end() );
- TermDbSygus* sygusDb = getTermDatabase()->getTermDatabaseSygus();
- sol = sygusDb->sygusToBuiltin( sol, sol.getType() );
- Trace("cegqi-inv") << "Builtin version of solution is : "
- << sol << ", type : " << sol.getType()
- << std::endl;
- sol = NodeManager::currentNM()->mkNode( OR, sol, pre );
+ templ = ceg_si->getTransPre(prog);
+ templIsPost = false;
}
}else if(options::sygusInvTemplMode() == SYGUS_INV_TEMPL_MODE_POST){
- const CegConjectureSingleInv* ceg_si =
- d_conj->getCegConjectureSingleInv();
+ const CegConjectureSingleInv* ceg_si = d_conj->getCegConjectureSingleInv();
if(ceg_si->d_trans_post.find(prog) != ceg_si->d_trans_post.end()){
- std::vector<Node>& templ_vars = d_conj->getProgTempVars(prog);
- Assert( templ_vars.size()==subs.size() );
- Node post = ceg_si->getTransPost(prog);
- post = post.substitute( templ_vars.begin(), templ_vars.end(),
- subs.begin(), subs.end() );
- TermDbSygus* sygusDb = getTermDatabase()->getTermDatabaseSygus();
- sol = sygusDb->sygusToBuiltin( sol, sol.getType() );
- Trace("cegqi-inv") << "Builtin version of solution is : "
- << sol << ", type : " << sol.getType()
- << std::endl;
- sol = NodeManager::currentNM()->mkNode( AND, sol, post );
+ templ = ceg_si->getTransPost(prog);
+ templIsPost = true;
}
}
+ if( !templ.isNull() ){
+ std::vector<Node>& templ_vars = d_conj->getProgTempVars(prog);
+
+ //take into consideration Boolean term conversion (this step can be eliminated when boolean term conversion is eliminated)
+ std::vector< Node > vars;
+ vars.insert( vars.end(), templ_vars.begin(), templ_vars.end() );
+ Node vl = Node::fromExpr( dt.getSygusVarList() );
+ Assert(vars.size() == subs.size());
+ for( unsigned j=0; j<templ_vars.size(); j++ ){
+ if( vl[j].getType().isBoolean() ){
+ Node c = NodeManager::currentNM()->mkConst(BitVector(1u, 1u));
+ vars[j] = vars[j].eqNode( c );
+ }
+ Assert( vars[j].getType()==subs[j].getType() );
+ }
+
+ templ = templ.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ TermDbSygus* sygusDb = getTermDatabase()->getTermDatabaseSygus();
+ sol = sygusDb->sygusToBuiltin( sol, sol.getType() );
+ Trace("cegqi-inv") << "Builtin version of solution is : "
+ << sol << ", type : " << sol.getType()
+ << std::endl;
+ sol = NodeManager::currentNM()->mkNode( templIsPost ? AND : OR, sol, templ );
+ }
if( sol==sygus_sol ){
sol = sygus_sol;
status = 1;
diff --git a/src/theory/quantifiers/ce_guided_single_inv.cpp b/src/theory/quantifiers/ce_guided_single_inv.cpp
index 981abea94..e0bbbf8ac 100755
--- a/src/theory/quantifiers/ce_guided_single_inv.cpp
+++ b/src/theory/quantifiers/ce_guided_single_inv.cpp
@@ -45,27 +45,41 @@ bool CegqiOutputSingleInv::addLemma( Node n ) {
return d_out->addLemma( n );
}
+CegConjectureSingleInv::CegConjectureSingleInv(QuantifiersEngine* qe,
+ CegConjecture* p)
+ : d_qe(qe),
+ d_parent(p),
+ d_sip(new SingleInvocationPartition),
+ d_sol(new CegConjectureSingleInvSol(qe)),
+ d_ei(NULL),
+ d_cosi(new CegqiOutputSingleInv(this)),
+ d_cinst(NULL),
+ d_c_inst_match_trie(NULL),
+ d_has_ites(true) {
+ // third and fourth arguments set to (false,false) until we have solution
+ // reconstruction for delta and infinity
+ d_cinst = new CegInstantiator(d_qe, d_cosi, false, false);
-CegConjectureSingleInv::CegConjectureSingleInv( QuantifiersEngine * qe, CegConjecture * p ) : d_qe( qe ), d_parent( p ){
- d_has_ites = true;
- if( options::incrementalSolving() ){
- d_c_inst_match_trie = new inst::CDInstMatchTrie( qe->getUserContext() );
- }else{
- d_c_inst_match_trie = NULL;
+ if (options::incrementalSolving()) {
+ d_c_inst_match_trie = new inst::CDInstMatchTrie(qe->getUserContext());
}
- d_cosi = new CegqiOutputSingleInv( this );
- // third and fourth arguments set to (false,false) until we have solution reconstruction for delta and infinity
- d_cinst = new CegInstantiator( d_qe, d_cosi, false, false );
- d_sol = new CegConjectureSingleInvSol( qe );
-
- d_sip = new SingleInvocationPartition;
+ if (options::cegqiSingleInvPartial()) {
+ d_ei = new CegEntailmentInfer(qe, d_sip);
+ }
+}
- if( options::cegqiSingleInvPartial() ){
- d_ei = new CegEntailmentInfer( qe, d_sip );
- }else{
- d_ei = NULL;
+CegConjectureSingleInv::~CegConjectureSingleInv() {
+ if (d_c_inst_match_trie) {
+ delete d_c_inst_match_trie;
+ }
+ delete d_cinst;
+ delete d_cosi;
+ if (d_ei) {
+ delete d_ei;
}
+ delete d_sol; // (new CegConjectureSingleInvSol(qe)),
+ delete d_sip; // d_sip(new SingleInvocationPartition),
}
void CegConjectureSingleInv::getInitialSingleInvLemma( std::vector< Node >& lems ) {
diff --git a/src/theory/quantifiers/ce_guided_single_inv.h b/src/theory/quantifiers/ce_guided_single_inv.h
index feadeca39..449ab7189 100755
--- a/src/theory/quantifiers/ce_guided_single_inv.h
+++ b/src/theory/quantifiers/ce_guided_single_inv.h
@@ -31,11 +31,10 @@ class CegConjecture;
class CegConjectureSingleInv;
class CegEntailmentInfer;
-class CegqiOutputSingleInv : public CegqiOutput
-{
+class CegqiOutputSingleInv : public CegqiOutput {
public:
CegqiOutputSingleInv( CegConjectureSingleInv * out ) : d_out( out ){}
- ~CegqiOutputSingleInv() {}
+ virtual ~CegqiOutputSingleInv() {}
CegConjectureSingleInv * d_out;
bool doAddInstantiation( std::vector< Node >& subs );
bool isEligibleForInstantiation( Node n );
@@ -45,22 +44,13 @@ public:
class SingleInvocationPartition;
-class CegConjectureSingleInv
-{
+class CegConjectureSingleInv {
+ private:
friend class CegqiOutputSingleInv;
-private:
- SingleInvocationPartition * d_sip;
- QuantifiersEngine * d_qe;
- CegConjecture * d_parent;
- CegConjectureSingleInvSol * d_sol;
- CegEntailmentInfer * d_ei;
- //the instantiator
- CegqiOutputSingleInv * d_cosi;
- CegInstantiator * d_cinst;
- //for recognizing templates for invariant synthesis
+ // for recognizing templates for invariant synthesis
Node substituteInvariantTemplates(
- Node n, std::map< Node, Node >& prog_templ,
- std::map< Node, std::vector< Node > >& prog_templ_vars );
+ Node n, std::map<Node, Node>& prog_templ,
+ std::map<Node, std::vector<Node> >& prog_templ_vars);
// partially single invocation
Node removeDeepEmbedding( Node n, std::vector< Node >& progs,
std::vector< TypeNode >& types, int& type_valid,
@@ -73,42 +63,56 @@ private:
std::vector< Node >& terms,
std::map< Node, std::vector< Node > >& teq,
Node n, std::vector< Node >& conj );
- //constructing solution
- Node constructSolution( std::vector< unsigned >& indices, unsigned i, unsigned index, std::map< Node, Node >& weak_imp );
- Node postProcessSolution( Node n );
-private:
- //list of skolems for each argument of programs
- std::vector< Node > d_single_inv_arg_sk;
- //list of variables/skolems for each program
- std::vector< Node > d_single_inv_var;
- std::vector< Node > d_single_inv_sk;
- std::map< Node, int > d_single_inv_sk_index;
- //program to solution index
- std::map< Node, unsigned > d_prog_to_sol_index;
- //lemmas produced
+ // constructing solution
+ Node constructSolution(std::vector<unsigned>& indices, unsigned i,
+ unsigned index, std::map<Node, Node>& weak_imp);
+ Node postProcessSolution(Node n);
+
+ private:
+ QuantifiersEngine* d_qe;
+ CegConjecture* d_parent;
+ SingleInvocationPartition* d_sip;
+ CegConjectureSingleInvSol* d_sol;
+ CegEntailmentInfer* d_ei;
+ // the instantiator
+ CegqiOutputSingleInv* d_cosi;
+ CegInstantiator* d_cinst;
+
+ // list of skolems for each argument of programs
+ std::vector<Node> d_single_inv_arg_sk;
+ // list of variables/skolems for each program
+ std::vector<Node> d_single_inv_var;
+ std::vector<Node> d_single_inv_sk;
+ std::map<Node, int> d_single_inv_sk_index;
+ // program to solution index
+ std::map<Node, unsigned> d_prog_to_sol_index;
+ // lemmas produced
inst::InstMatchTrie d_inst_match_trie;
- inst::CDInstMatchTrie * d_c_inst_match_trie;
- //original conjecture
+ inst::CDInstMatchTrie* d_c_inst_match_trie;
+ // original conjecture
Node d_orig_conjecture;
// solution
Node d_orig_solution;
Node d_solution;
Node d_sygus_solution;
bool d_has_ites;
-public:
- //lemmas produced
- std::vector< Node > d_lemmas_produced;
- std::vector< std::vector< Node > > d_inst;
-private:
- std::vector< Node > d_curr_lemmas;
- //add instantiation
+
+ public:
+ // lemmas produced
+ std::vector<Node> d_lemmas_produced;
+ std::vector<std::vector<Node> > d_inst;
+
+ private:
+ std::vector<Node> d_curr_lemmas;
+ // add instantiation
bool doAddInstantiation( std::vector< Node >& subs );
//is eligible for instantiation
bool isEligibleForInstantiation( Node n );
// add lemma
bool addLemma( Node lem );
-public:
+ public:
CegConjectureSingleInv( QuantifiersEngine * qe, CegConjecture * p );
+ ~CegConjectureSingleInv();
// original conjecture
Node d_quant;
// single invocation portion of quantified formula
@@ -130,7 +134,7 @@ public:
std::map< Node, Node > d_nsi_op_map;
std::map< Node, Node > d_nsi_op_map_to_prog;
std::map< Node, Node > d_prog_to_eval_op;
-public:
+ public:
//get the single invocation lemma(s)
void getInitialSingleInvLemma( std::vector< Node >& lems );
//initialize
@@ -169,12 +173,12 @@ public:
};
-// partitions any formulas given to it into single invocation/non-single invocation
-// only processes functions having argument types exactly matching "d_arg_types",
-// and all invocations are in the same order across all functions
-class SingleInvocationPartition
-{
-private:
+// partitions any formulas given to it into single invocation/non-single
+// invocation only processes functions having argument types exactly matching
+// "d_arg_types", and all invocations are in the same order across all
+// functions
+class SingleInvocationPartition {
+ private:
//options
Kind d_checkKind;
bool inferArgTypes( Node n, std::vector< TypeNode >& typs, std::map< Node, bool >& visited );
diff --git a/src/theory/quantifiers/ceg_instantiator.cpp b/src/theory/quantifiers/ceg_instantiator.cpp
index 0fe4b98c7..61a20ad42 100755
--- a/src/theory/quantifiers/ceg_instantiator.cpp
+++ b/src/theory/quantifiers/ceg_instantiator.cpp
@@ -11,21 +11,18 @@
**
** \brief Implementation of counterexample-guided quantifier instantiation
**/
+
#include "theory/quantifiers/ceg_instantiator.h"
+#include "theory/quantifiers/ceg_t_instantiator.h"
#include "options/quantifiers_options.h"
#include "smt/ite_removal.h"
-#include "theory/arith/partial_model.h"
-#include "theory/arith/theory_arith.h"
-#include "theory/arith/theory_arith_private.h"
#include "theory/quantifiers/first_order_model.h"
#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/quantifiers_rewriter.h"
+#include "theory/quantifiers/trigger.h"
#include "theory/theory_engine.h"
-#include "theory/bv/theory_bv_utils.h"
-#include "util/bitvector.h"
-
-//#define MBP_STRICT_ASSERTIONS
using namespace std;
using namespace CVC4;
@@ -36,12 +33,15 @@ using namespace CVC4::theory::quantifiers;
CegInstantiator::CegInstantiator( QuantifiersEngine * qe, CegqiOutput * out, bool use_vts_delta, bool use_vts_inf ) :
d_qe( qe ), d_out( out ), d_use_vts_delta( use_vts_delta ), d_use_vts_inf( use_vts_inf ){
- d_zero = NodeManager::currentNM()->mkConst( Rational( 0 ) );
- d_one = NodeManager::currentNM()->mkConst( Rational( 1 ) );
- d_true = NodeManager::currentNM()->mkConst( true );
d_is_nested_quant = false;
}
+CegInstantiator::~CegInstantiator() {
+ for( std::map< Node, Instantiator * >::iterator it = d_instantiator.begin(); it != d_instantiator.end(); ++it ){
+ delete it->second;
+ }
+}
+
void CegInstantiator::computeProgVars( Node n ){
if( d_prog_var.find( n )==d_prog_var.end() ){
d_prog_var[n].clear();
@@ -68,41 +68,108 @@ void CegInstantiator::computeProgVars( Node n ){
}
}
-bool CegInstantiator::doAddInstantiation( SolvedForm& sf, SolvedForm& ssf, std::vector< Node >& vars,
- std::vector< int >& btyp, Node theta, unsigned i, unsigned effort,
- std::map< Node, Node >& cons, std::vector< Node >& curr_var ){
+bool CegInstantiator::isEligible( Node n ) {
+ //compute d_subs_fv, which program variables are contained in n, and determines if eligible
+ computeProgVars( n );
+ return d_inelig.find( n )==d_inelig.end();
+}
+
+bool CegInstantiator::hasVariable( Node n, Node pv ) {
+ computeProgVars( n );
+ return d_prog_var[n].find( pv )!=d_prog_var[n].end();
+}
+
+
+void CegInstantiator::registerInstantiationVariable( Node v, unsigned index ) {
+ if( d_instantiator.find( v )==d_instantiator.end() ){
+ TypeNode tn = v.getType();
+ Instantiator * vinst;
+ if( tn.isReal() ){
+ vinst = new ArithInstantiator( d_qe, tn );
+ }else if( tn.isSort() ){
+ Assert( options::quantEpr() );
+ vinst = new EprInstantiator( d_qe, tn );
+ }else if( tn.isDatatype() ){
+ vinst = new DtInstantiator( d_qe, tn );
+ }else if( tn.isBitVector() ){
+ vinst = new BvInstantiator( d_qe, tn );
+ }else if( tn.isBoolean() ){
+ vinst = new ModelValueInstantiator( d_qe, tn );
+ }else{
+ //default
+ vinst = new Instantiator( d_qe, tn );
+ }
+ d_instantiator[v] = vinst;
+ }
+ d_curr_subs_proc[v].clear();
+ d_curr_index[v] = index;
+}
+
+void CegInstantiator::unregisterInstantiationVariable( Node v ) {
+ d_curr_subs_proc.erase( v );
+ d_curr_index.erase( v );
+}
+
+bool CegInstantiator::doAddInstantiation( SolvedForm& sf, unsigned i, unsigned effort ){
if( i==d_vars.size() ){
//solved for all variables, now construct instantiation
- if( !sf.d_has_coeff.empty() ){
- if( options::cbqiSymLia() ){
- //use symbolic solved forms
- SolvedForm csf;
- csf.copy( ssf );
- return doAddInstantiationCoeff( csf, vars, btyp, 0, cons );
+ bool needsPostprocess = false;
+ std::map< Instantiator *, Node > pp_inst;
+ for( std::map< Node, Instantiator * >::iterator ita = d_active_instantiators.begin(); ita != d_active_instantiators.end(); ++ita ){
+ if( ita->second->needsPostProcessInstantiation( this, sf, ita->first, effort ) ){
+ needsPostprocess = true;
+ pp_inst[ ita->second ] = ita->first;
+ }
+ }
+ if( needsPostprocess ){
+ //must make copy so that backtracking reverts sf
+ SolvedForm sf_tmp;
+ sf_tmp.copy( sf );
+ bool postProcessSuccess = true;
+ for( std::map< Instantiator *, Node >::iterator itp = pp_inst.begin(); itp != pp_inst.end(); ++itp ){
+ if( !itp->first->postProcessInstantiation( this, sf_tmp, itp->second, effort ) ){
+ postProcessSuccess = false;
+ break;
+ }
+ }
+ if( postProcessSuccess ){
+ return doAddInstantiation( sf_tmp.d_subs, sf_tmp.d_vars );
}else{
- return doAddInstantiationCoeff( sf, vars, btyp, 0, cons );
+ return false;
}
}else{
- return doAddInstantiation( sf.d_subs, vars, cons );
+ return doAddInstantiation( sf.d_subs, sf.d_vars );
}
}else{
- std::map< Node, std::map< Node, bool > > subs_proc;
//Node v = d_single_inv_map_to_prog[d_single_inv[0][i]];
bool is_cv = false;
Node pv;
- if( curr_var.empty() ){
+ if( d_stack_vars.empty() ){
pv = d_vars[i];
}else{
- pv = curr_var.back();
+ pv = d_stack_vars.back();
is_cv = true;
+ d_stack_vars.pop_back();
+ }
+ registerInstantiationVariable( pv, i );
+
+ //get the instantiator object
+ Instantiator * vinst = NULL;
+ std::map< Node, Instantiator * >::iterator itin = d_instantiator.find( pv );
+ if( itin!=d_instantiator.end() ){
+ vinst = itin->second;
}
+ Assert( vinst!=NULL );
+ d_active_instantiators[pv] = vinst;
+ vinst->reset( this, sf, pv, effort );
+
TypeNode pvtn = pv.getType();
TypeNode pvtnb = pvtn.getBaseType();
Node pvr = pv;
if( d_qe->getMasterEqualityEngine()->hasTerm( pv ) ){
pvr = d_qe->getMasterEqualityEngine()->getRepresentative( pv );
}
- Trace("cbqi-inst-debug") << "[Find instantiation for " << pv << "], rep=" << pvr << std::endl;
+ Trace("cbqi-inst-debug") << "[Find instantiation for " << pv << "], rep=" << pvr << ", instantiator is " << vinst->identify() << std::endl;
Node pv_value;
if( options::cbqiModel() ){
pv_value = getModelValue( pv );
@@ -116,72 +183,38 @@ bool CegInstantiator::doAddInstantiation( SolvedForm& sf, SolvedForm& ssf, std::
Trace("cbqi-inst-debug") << "[1] try based on equivalence class." << std::endl;
std::map< Node, std::vector< Node > >::iterator it_eqc = d_curr_eqc.find( pvr );
if( it_eqc!=d_curr_eqc.end() ){
+ //std::vector< Node > eq_candidates;
Trace("cbqi-inst-debug2") << "...eqc has size " << it_eqc->second.size() << std::endl;
for( unsigned k=0; k<it_eqc->second.size(); k++ ){
Node n = it_eqc->second[k];
if( n!=pv ){
Trace("cbqi-inst-debug") << "...try based on equal term " << n << std::endl;
- //compute d_subs_fv, which program variables are contained in n
- computeProgVars( n );
//must be an eligible term
- if( d_inelig.find( n )==d_inelig.end() ){
+ if( isEligible( n ) ){
Node ns;
Node pv_coeff; //coefficient of pv in the equality we solve (null is 1)
bool proc = false;
if( !d_prog_var[n].empty() ){
- ns = applySubstitution( pvtn, n, sf, vars, pv_coeff, false );
+ ns = applySubstitution( pvtn, n, sf, pv_coeff, false );
if( !ns.isNull() ){
computeProgVars( ns );
//substituted version must be new and cannot contain pv
- proc = subs_proc[pv_coeff].find( ns )==subs_proc[pv_coeff].end() && d_prog_var[ns].find( pv )==d_prog_var[ns].end();
+ proc = d_prog_var[ns].find( pv )==d_prog_var[ns].end();
}
}else{
ns = n;
proc = true;
}
if( proc ){
- //try the substitution
- subs_proc[ns][pv_coeff] = true;
- if( doAddInstantiationInc( ns, pv, pv_coeff, 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
+ if( vinst->processEqualTerm( this, sf, pv, pv_coeff, ns, effort ) ){
return true;
}
}
}
}
}
- if( pvtn.isDatatype() ){
- Trace("cbqi-inst-debug") << "[2] try based on constructors in equivalence class." << std::endl;
- //[2] look in equivalence class for a constructor
- for( unsigned k=0; k<it_eqc->second.size(); k++ ){
- Node n = it_eqc->second[k];
- if( n.getKind()==APPLY_CONSTRUCTOR ){
- Trace("cbqi-inst-debug") << "... " << i << "...try based on constructor term " << n << std::endl;
- cons[pv] = n.getOperator();
- const Datatype& dt = ((DatatypeType)(pvtn).toType()).getDatatype();
- unsigned cindex = Datatype::indexOf( n.getOperator().toExpr() );
- if( is_cv ){
- curr_var.pop_back();
- }
- //now must solve for selectors applied to pv
- for( unsigned j=0; j<dt[cindex].getNumArgs(); j++ ){
- curr_var.push_back( NodeManager::currentNM()->mkNode( APPLY_SELECTOR_TOTAL, Node::fromExpr( dt[cindex][j].getSelector() ), pv ) );
- }
- if( doAddInstantiation( sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
- return true;
- }else{
- //cleanup
- cons.erase( pv );
- Assert( curr_var.size()>=dt[cindex].getNumArgs() );
- for( unsigned j=0; j<dt[cindex].getNumArgs(); j++ ){
- curr_var.pop_back();
- }
- if( is_cv ){
- curr_var.push_back( pv );
- }
- break;
- }
- }
- }
+ if( vinst->processEqualTerms( this, sf, pv, it_eqc->second, effort ) ){
+ return true;
}
}else{
Trace("cbqi-inst-debug2") << "...eqc not found." << std::endl;
@@ -189,762 +222,246 @@ bool CegInstantiator::doAddInstantiation( SolvedForm& sf, SolvedForm& ssf, std::
//[3] : we can solve an equality for pv
///iterate over equivalence classes to find cases where we can solve for the variable
- Trace("cbqi-inst-debug") << "[3] try based on solving equalities." << std::endl;
- for( unsigned k=0; k<d_curr_type_eqc[pvtnb].size(); k++ ){
- Node r = d_curr_type_eqc[pvtnb][k];
- std::map< Node, std::vector< Node > >::iterator it_reqc = d_curr_eqc.find( r );
- std::vector< Node > lhs;
- std::vector< bool > lhs_v;
- std::vector< Node > lhs_coeff;
- Assert( it_reqc!=d_curr_eqc.end() );
- for( unsigned kk=0; kk<it_reqc->second.size(); kk++ ){
- Node n = it_reqc->second[kk];
- Trace("cbqi-inst-debug2") << "...look at term " << n << std::endl;
- //compute the variables in n
- computeProgVars( n );
- //must be an eligible term
- if( d_inelig.find( n )==d_inelig.end() ){
- Node ns;
- Node pv_coeff;
- if( !d_prog_var[n].empty() ){
- ns = applySubstitution( pvtn, n, sf, vars, pv_coeff );
- if( !ns.isNull() ){
- computeProgVars( ns );
+ if( vinst->hasProcessEquality( this, sf, pv, effort ) ){
+ Trace("cbqi-inst-debug") << "[3] try based on solving equalities." << std::endl;
+ for( unsigned k=0; k<d_curr_type_eqc[pvtnb].size(); k++ ){
+ Node r = d_curr_type_eqc[pvtnb][k];
+ std::map< Node, std::vector< Node > >::iterator it_reqc = d_curr_eqc.find( r );
+ std::vector< Node > lhs;
+ std::vector< bool > lhs_v;
+ std::vector< Node > lhs_coeff;
+ Assert( it_reqc!=d_curr_eqc.end() );
+ for( unsigned kk=0; kk<it_reqc->second.size(); kk++ ){
+ Node n = it_reqc->second[kk];
+ Trace("cbqi-inst-debug2") << "...look at term " << n << std::endl;
+ //must be an eligible term
+ if( isEligible( n ) ){
+ Node ns;
+ Node pv_coeff;
+ if( !d_prog_var[n].empty() ){
+ ns = applySubstitution( pvtn, n, sf, pv_coeff );
+ if( !ns.isNull() ){
+ computeProgVars( ns );
+ }
+ }else{
+ ns = n;
}
- }else{
- ns = n;
- }
- if( !ns.isNull() ){
- bool hasVar = d_prog_var[ns].find( pv )!=d_prog_var[ns].end();
- Trace("cbqi-inst-debug2") << "... " << ns << " has var " << pv << " : " << hasVar << std::endl;
- for( unsigned j=0; j<lhs.size(); j++ ){
- //if this term or the another has pv in it, try to solve for it
- if( hasVar || lhs_v[j] ){
- Trace("cbqi-inst-debug") << "... " << i << "...try based on equality " << lhs[j] << " = " << ns << std::endl;
- Node val;
- Node veq_c;
- bool success = false;
- if( pvtnb.isReal() ){
- Node eq_lhs = lhs[j];
- Node eq_rhs = ns;
- //make the same coefficient
- if( pv_coeff!=lhs_coeff[j] ){
- if( !pv_coeff.isNull() ){
- Trace("cbqi-inst-debug") << "...mult lhs by " << pv_coeff << std::endl;
- eq_lhs = NodeManager::currentNM()->mkNode( MULT, pv_coeff, eq_lhs );
- eq_lhs = Rewriter::rewrite( eq_lhs );
- }
- if( !lhs_coeff[j].isNull() ){
- Trace("cbqi-inst-debug") << "...mult rhs by " << lhs_coeff[j] << std::endl;
- eq_rhs = NodeManager::currentNM()->mkNode( MULT, lhs_coeff[j], eq_rhs );
- eq_rhs = Rewriter::rewrite( eq_rhs );
- }
- }
- Node eq = eq_lhs.eqNode( eq_rhs );
- eq = Rewriter::rewrite( eq );
- Node vts_coeff_inf;
- Node vts_coeff_delta;
- //isolate pv in the equality
- int ires = solve_arith( pv, eq, veq_c, val, vts_coeff_inf, vts_coeff_delta );
- if( ires!=0 ){
- success = true;
- }
- /*
- //cannot contain infinity?
- //if( !d_qe->getTermDatabase()->containsVtsInfinity( eq ) ){
- Trace("cbqi-inst-debug") << "...equality is " << eq << std::endl;
- std::map< Node, Node > msum;
- if( QuantArith::getMonomialSumLit( eq, msum ) ){
- if( Trace.isOn("cbqi-inst-debug") ){
- Trace("cbqi-inst-debug") << "...got monomial sum: " << std::endl;
- QuantArith::debugPrintMonomialSum( msum, "cbqi-inst-debug" );
- Trace("cbqi-inst-debug") << "isolate for " << pv << " : " << pv.getType() << "..." << std::endl;
- }
- Node veq;
- if( QuantArith::isolate( pv, msum, veq, EQUAL, true )!=0 ){
- Trace("cbqi-inst-debug") << "...isolated equality " << veq << "." << std::endl;
- Node veq_c;
- if( veq[0]!=pv ){
- Node veq_v;
- if( QuantArith::getMonomial( veq[0], veq_c, veq_v ) ){
- Assert( veq_v==pv );
- }
- }
- Node val = veq[1];
- if( subs_proc[val].find( veq_c )==subs_proc[val].end() ){
- subs_proc[val][veq_c] = true;
- if( doAddInstantiationInc( val, pv, veq_c, 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
- return true;
- }
- }
- }
- }
- */
- }else if( pvtnb.isDatatype() ){
- val = solve_dt( pv, lhs[j], ns, lhs[j], ns );
- if( !val.isNull() ){
- success = true;
- }
- }
- if( success ){
- if( subs_proc[val].find( veq_c )==subs_proc[val].end() ){
- subs_proc[val][veq_c] = true;
- if( doAddInstantiationInc( val, pv, veq_c, 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
- return true;
- }
+ if( !ns.isNull() ){
+ bool hasVar = d_prog_var[ns].find( pv )!=d_prog_var[ns].end();
+ Trace("cbqi-inst-debug2") << "... " << ns << " has var " << pv << " : " << hasVar << std::endl;
+ std::vector< Node > term_coeffs;
+ std::vector< Node > terms;
+ term_coeffs.push_back( pv_coeff );
+ terms.push_back( ns );
+ for( unsigned j=0; j<lhs.size(); j++ ){
+ //if this term or the another has pv in it, try to solve for it
+ if( hasVar || lhs_v[j] ){
+ Trace("cbqi-inst-debug") << "... " << i << "...try based on equality " << lhs[j] << " = " << ns << std::endl;
+ //processEquality( CegInstantiator * ci, SolvedForm& sf, Node pv, std::vector< Node >& term_coeffs, std::vector< Node >& terms, unsigned effort ) { return false; }
+ term_coeffs.push_back( lhs_coeff[j] );
+ terms.push_back( lhs[j] );
+ if( vinst->processEquality( this, sf, pv, term_coeffs, terms, effort ) ){
+ return true;
}
+ term_coeffs.pop_back();
+ terms.pop_back();
}
}
+ lhs.push_back( ns );
+ lhs_v.push_back( hasVar );
+ lhs_coeff.push_back( pv_coeff );
+ }else{
+ Trace("cbqi-inst-debug2") << "... term " << n << " is ineligible after substitution." << std::endl;
}
- lhs.push_back( ns );
- lhs_v.push_back( hasVar );
- lhs_coeff.push_back( pv_coeff );
}else{
- Trace("cbqi-inst-debug2") << "... term " << n << " is ineligible after substitution." << std::endl;
+ Trace("cbqi-inst-debug2") << "... term " << n << " is ineligible." << std::endl;
}
- }else{
- Trace("cbqi-inst-debug2") << "... term " << n << " is ineligible." << std::endl;
}
}
}
//[4] directly look at assertions
- Trace("cbqi-inst-debug") << "[4] try based on assertions." << std::endl;
- d_vts_sym[0] = d_qe->getTermDatabase()->getVtsInfinity( pvtn, false, false );
- d_vts_sym[1] = d_qe->getTermDatabase()->getVtsDelta( false, false );
- std::vector< Node > mbp_bounds[2];
- std::vector< Node > mbp_coeff[2];
- std::vector< Node > mbp_vts_coeff[2][2];
- std::vector< Node > mbp_lit[2];
- //std::vector< MbpBounds > mbp_bounds[2];
- //unsigned rmax = Theory::theoryOf( pv )==Theory::theoryOf( pv.getType() ) ? 1 : 2;
- for( unsigned r=0; r<2; r++ ){
- TheoryId tid = r==0 ? Theory::theoryOf( pvtn ) : THEORY_UF;
- Trace("cbqi-inst-debug2") << " look at assertions of " << tid << std::endl;
- std::map< TheoryId, std::vector< Node > >::iterator ita = d_curr_asserts.find( tid );
- if( ita!=d_curr_asserts.end() ){
- for (unsigned j = 0; j<ita->second.size(); j++) {
- Node lit = ita->second[j];
- Trace("cbqi-inst-debug2") << " look at " << lit << std::endl;
- Node atom = lit.getKind()==NOT ? lit[0] : lit;
- bool pol = lit.getKind()!=NOT;
- if( pvtn.isReal() ){
- //arithmetic inequalities and disequalities
- if( atom.getKind()==GEQ || ( atom.getKind()==EQUAL && !pol && atom[0].getType().isReal() ) ){
- Assert( atom.getKind()!=GEQ || atom[1].isConst() );
- Node atom_lhs;
- Node atom_rhs;
- if( atom.getKind()==GEQ ){
- atom_lhs = atom[0];
- atom_rhs = atom[1];
- }else{
- atom_lhs = NodeManager::currentNM()->mkNode( MINUS, atom[0], atom[1] );
- atom_lhs = Rewriter::rewrite( atom_lhs );
- atom_rhs = d_zero;
- }
-
- computeProgVars( atom_lhs );
- //must be an eligible term
- if( d_inelig.find( atom_lhs )==d_inelig.end() ){
- //apply substitution to LHS of atom
- if( !d_prog_var[atom_lhs].empty() ){
- Node atom_lhs_coeff;
- atom_lhs = applySubstitution( pvtn, atom_lhs, sf, vars, atom_lhs_coeff );
- if( !atom_lhs.isNull() ){
- computeProgVars( atom_lhs );
- if( !atom_lhs_coeff.isNull() ){
- atom_rhs = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MULT, atom_lhs_coeff, atom_rhs ) );
- }
- }
- }
- //if it contains pv, not infinity
- if( !atom_lhs.isNull() && d_prog_var[atom_lhs].find( pv )!=d_prog_var[atom_lhs].end() ){
- Node satom = NodeManager::currentNM()->mkNode( atom.getKind(), atom_lhs, atom_rhs );
- //cannot contain infinity?
- //if( !d_qe->getTermDatabase()->containsVtsInfinity( atom_lhs ) ){
- Trace("cbqi-inst-debug") << "..[3] From assertion : " << atom << ", pol = " << pol << std::endl;
- Trace("cbqi-inst-debug") << " substituted : " << satom << ", pol = " << pol << std::endl;
- Node vts_coeff_inf;
- Node vts_coeff_delta;
- Node val;
- Node veq_c;
- //isolate pv in the inequality
- int ires = solve_arith( pv, satom, veq_c, val, vts_coeff_inf, vts_coeff_delta );
- if( ires!=0 ){
- //disequalities are either strict upper or lower bounds
- unsigned rmax = ( atom.getKind()==GEQ && options::cbqiModel() ) ? 1 : 2;
- for( unsigned r=0; r<rmax; r++ ){
- int uires = ires;
- Node uval = val;
- if( atom.getKind()==GEQ ){
- //push negation downwards
- if( !pol ){
- uires = -ires;
- if( pvtn.isInteger() ){
- uval = NodeManager::currentNM()->mkNode( PLUS, val, NodeManager::currentNM()->mkConst( Rational( uires ) ) );
- uval = Rewriter::rewrite( uval );
- }else{
- Assert( pvtn.isReal() );
- //now is strict inequality
- uires = uires*2;
- }
- }
- }else{
- bool is_upper = ( r==0 );
- if( options::cbqiModel() ){
- // disequality is a disjunction : only consider the bound in the direction of the model
- //first check if there is an infinity...
- if( !vts_coeff_inf.isNull() ){
- //coefficient or val won't make a difference, just compare with zero
- Trace("cbqi-inst-debug") << "Disequality : check infinity polarity " << vts_coeff_inf << std::endl;
- Assert( vts_coeff_inf.isConst() );
- is_upper = ( vts_coeff_inf.getConst<Rational>().sgn()==1 );
- }else{
- Node rhs_value = getModelValue( val );
- Node lhs_value = pv_value;
- if( !veq_c.isNull() ){
- lhs_value = NodeManager::currentNM()->mkNode( MULT, lhs_value, veq_c );
- lhs_value = Rewriter::rewrite( lhs_value );
- }
- Trace("cbqi-inst-debug") << "Disequality : check model values " << lhs_value << " " << rhs_value << std::endl;
- Assert( lhs_value!=rhs_value );
- Node cmp = NodeManager::currentNM()->mkNode( GEQ, lhs_value, rhs_value );
- cmp = Rewriter::rewrite( cmp );
- Assert( cmp.isConst() );
- is_upper = ( cmp!=d_true );
- }
- }
- Assert( atom.getKind()==EQUAL && !pol );
- if( pvtn.isInteger() ){
- uires = is_upper ? -1 : 1;
- uval = NodeManager::currentNM()->mkNode( PLUS, val, NodeManager::currentNM()->mkConst( Rational( uires ) ) );
- uval = Rewriter::rewrite( uval );
- }else{
- Assert( pvtn.isReal() );
- uires = is_upper ? -2 : 2;
- }
- }
- Trace("cbqi-bound-inf") << "From " << lit << ", got : ";
- if( !veq_c.isNull() ){
- Trace("cbqi-bound-inf") << veq_c << " * ";
- }
- Trace("cbqi-bound-inf") << pv << " -> " << uval << ", styp = " << uires << std::endl;
- //take into account delta
- if( d_use_vts_delta && ( uires==2 || uires==-2 ) ){
- if( options::cbqiModel() ){
- Node delta_coeff = NodeManager::currentNM()->mkConst( Rational( uires > 0 ? 1 : -1 ) );
- if( vts_coeff_delta.isNull() ){
- vts_coeff_delta = delta_coeff;
- }else{
- vts_coeff_delta = NodeManager::currentNM()->mkNode( PLUS, vts_coeff_delta, delta_coeff );
- vts_coeff_delta = Rewriter::rewrite( vts_coeff_delta );
- }
- }else{
- Node delta = d_qe->getTermDatabase()->getVtsDelta();
- uval = NodeManager::currentNM()->mkNode( uires==2 ? PLUS : MINUS, uval, delta );
- uval = Rewriter::rewrite( uval );
- }
- }
- if( options::cbqiModel() ){
- //just store bounds, will choose based on tighest bound
- unsigned index = uires>0 ? 0 : 1;
- mbp_bounds[index].push_back( uval );
- mbp_coeff[index].push_back( veq_c );
- for( unsigned t=0; t<2; t++ ){
- mbp_vts_coeff[index][t].push_back( t==0 ? vts_coeff_inf : vts_coeff_delta );
- }
- mbp_lit[index].push_back( lit );
- }else{
- //try this bound
- if( subs_proc[uval].find( veq_c )==subs_proc[uval].end() ){
- subs_proc[uval][veq_c] = true;
- if( doAddInstantiationInc( uval, pv, veq_c, uires>0 ? 1 : -1, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
- return true;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- /* TODO: algebraic reasoning for bitvector instantiation
- else if( pvtn.isBitVector() ){
- if( atom.getKind()==BITVECTOR_ULT || atom.getKind()==BITVECTOR_ULE ){
- for( unsigned t=0; t<2; t++ ){
- if( atom[t]==pv ){
- computeProgVars( atom[1-t] );
- if( d_inelig.find( atom[1-t] )==d_inelig.end() ){
- //only ground terms TODO: more
- if( d_prog_var[atom[1-t]].empty() ){
- Node veq_c;
- Node uval;
- if( ( !pol && atom.getKind()==BITVECTOR_ULT ) || ( pol && atom.getKind()==BITVECTOR_ULE ) ){
- uval = atom[1-t];
- }else{
- uval = NodeManager::currentNM()->mkNode( (atom.getKind()==BITVECTOR_ULT)==(t==1) ? BITVECTOR_PLUS : BITVECTOR_SUB, atom[1-t],
- bv::utils::mkConst(pvtn.getConst<BitVectorSize>(), 1) );
- }
- if( subs_proc[uval].find( veq_c )==subs_proc[uval].end() ){
- subs_proc[uval][veq_c] = true;
- if( doAddInstantiationInc( uval, pv, veq_c, 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
- return true;
- }
- }
- }
- }
- }
- }
- }
- }
- */
- }
- }
- }
- if( options::cbqiModel() ){
- if( pvtn.isInteger() || pvtn.isReal() ){
- bool use_inf = d_use_vts_inf && ( pvtn.isInteger() ? options::cbqiUseInfInt() : options::cbqiUseInfReal() ) && !options::cbqiMidpoint();
- bool upper_first = false;
- if( options::cbqiMinBounds() ){
- upper_first = mbp_bounds[1].size()<mbp_bounds[0].size();
- }
- int best_used[2];
- std::vector< Node > t_values[3];
- //try optimal bounds
- for( unsigned r=0; r<2; r++ ){
- int rr = upper_first ? (1-r) : r;
- best_used[rr] = -1;
- if( mbp_bounds[rr].empty() ){
- if( use_inf ){
- Trace("cbqi-bound") << "No " << ( rr==0 ? "lower" : "upper" ) << " bounds for " << pv << " (type=" << pvtn << ")" << std::endl;
- //no bounds, we do +- infinity
- Node val = d_qe->getTermDatabase()->getVtsInfinity( pvtn );
- //TODO : rho value for infinity?
- if( rr==0 ){
- val = NodeManager::currentNM()->mkNode( UMINUS, val );
- val = Rewriter::rewrite( val );
- }
- if( doAddInstantiationInc( val, pv, Node::null(), 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
- return true;
- }
- }
- }else{
- Trace("cbqi-bound") << ( rr==0 ? "Lower" : "Upper" ) << " bounds for " << pv << " (type=" << pvtn << ") : " << std::endl;
- int best = -1;
- Node best_bound_value[3];
- for( unsigned j=0; j<mbp_bounds[rr].size(); j++ ){
- Node value[3];
- if( Trace.isOn("cbqi-bound") ){
- Assert( !mbp_bounds[rr][j].isNull() );
- Trace("cbqi-bound") << " " << j << ": " << mbp_bounds[rr][j];
- if( !mbp_vts_coeff[rr][0][j].isNull() ){
- Trace("cbqi-bound") << " (+ " << mbp_vts_coeff[rr][0][j] << " * INF)";
- }
- if( !mbp_vts_coeff[rr][1][j].isNull() ){
- Trace("cbqi-bound") << " (+ " << mbp_vts_coeff[rr][1][j] << " * DELTA)";
- }
- if( !mbp_coeff[rr][j].isNull() ){
- Trace("cbqi-bound") << " (div " << mbp_coeff[rr][j] << ")";
- }
- Trace("cbqi-bound") << ", value = ";
- }
- t_values[rr].push_back( Node::null() );
- //check if it is better than the current best bound : lexicographic order infinite/finite/infinitesimal parts
- bool new_best = true;
- for( unsigned t=0; t<3; t++ ){
- //get the value
- if( t==0 ){
- value[0] = mbp_vts_coeff[rr][0][j];
- if( !value[0].isNull() ){
- Trace("cbqi-bound") << "( " << value[0] << " * INF ) + ";
- }else{
- value[0] = d_zero;
- }
- }else if( t==1 ){
- Node t_value = getModelValue( mbp_bounds[rr][j] );
- t_values[rr][j] = t_value;
- value[1] = t_value;
- Trace("cbqi-bound") << value[1];
- }else{
- value[2] = mbp_vts_coeff[rr][1][j];
- if( !value[2].isNull() ){
- Trace("cbqi-bound") << " + ( " << value[2] << " * DELTA )";
- }else{
- value[2] = d_zero;
- }
- }
- //multiply by coefficient
- if( value[t]!=d_zero && !mbp_coeff[rr][j].isNull() ){
- Assert( mbp_coeff[rr][j].isConst() );
- value[t] = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkConst( Rational(1) / mbp_coeff[rr][j].getConst<Rational>() ), value[t] );
- value[t] = Rewriter::rewrite( value[t] );
- }
- //check if new best
- if( best!=-1 ){
- Assert( !value[t].isNull() && !best_bound_value[t].isNull() );
- if( value[t]!=best_bound_value[t] ){
- Kind k = rr==0 ? GEQ : LEQ;
- Node cmp_bound = NodeManager::currentNM()->mkNode( k, value[t], best_bound_value[t] );
- cmp_bound = Rewriter::rewrite( cmp_bound );
- if( cmp_bound!=d_true ){
- new_best = false;
- break;
- }
- }
- }
- }
- Trace("cbqi-bound") << std::endl;
- if( new_best ){
- for( unsigned t=0; t<3; t++ ){
- best_bound_value[t] = value[t];
- }
- best = j;
- }
- }
- if( best!=-1 ){
- Trace("cbqi-bound") << "...best bound is " << best << " : ";
- if( best_bound_value[0]!=d_zero ){
- Trace("cbqi-bound") << "( " << best_bound_value[0] << " * INF ) + ";
- }
- Trace("cbqi-bound") << best_bound_value[1];
- if( best_bound_value[2]!=d_zero ){
- Trace("cbqi-bound") << " + ( " << best_bound_value[2] << " * DELTA )";
- }
- Trace("cbqi-bound") << std::endl;
- best_used[rr] = best;
- //if using cbqiMidpoint, only add the instance based on one bound if the bound is non-strict
- if( !options::cbqiMidpoint() || pvtn.isInteger() || mbp_vts_coeff[rr][1][best].isNull() ){
- Node val = mbp_bounds[rr][best];
- val = getModelBasedProjectionValue( pv, val, rr==0, mbp_coeff[rr][best], pv_value, t_values[rr][best], theta,
- mbp_vts_coeff[rr][0][best], mbp_vts_coeff[rr][1][best] );
- if( !val.isNull() ){
- if( subs_proc[val].find( mbp_coeff[rr][best] )==subs_proc[val].end() ){
- subs_proc[val][mbp_coeff[rr][best]] = true;
- if( doAddInstantiationInc( val, pv, mbp_coeff[rr][best], rr==0 ? 1 : -1, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
- return true;
- }
- }
- }
- }
- }
- }
- }
- //if not using infinity, use model value of zero
- if( !use_inf && mbp_bounds[0].empty() && mbp_bounds[1].empty() ){
- Node val = d_zero;
- Node c; //null (one) coefficient
- val = getModelBasedProjectionValue( pv, val, true, c, pv_value, d_zero, theta, Node::null(), Node::null() );
- if( !val.isNull() ){
- if( subs_proc[val].find( c )==subs_proc[val].end() ){
- subs_proc[val][c] = true;
- if( doAddInstantiationInc( val, pv, c, 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
- return true;
- }
- }
- }
- }
- if( options::cbqiMidpoint() && !pvtn.isInteger() ){
- Node vals[2];
- bool bothBounds = true;
- Trace("cbqi-bound") << "Try midpoint of bounds..." << std::endl;
- for( unsigned rr=0; rr<2; rr++ ){
- int best = best_used[rr];
- if( best==-1 ){
- bothBounds = false;
- }else{
- vals[rr] = mbp_bounds[rr][best];
- vals[rr] = getModelBasedProjectionValue( pv, vals[rr], rr==0, Node::null(), pv_value, t_values[rr][best], theta,
- mbp_vts_coeff[rr][0][best], Node::null() );
- }
- Trace("cbqi-bound") << "Bound : " << vals[rr] << std::endl;
- }
- Node val;
- if( bothBounds ){
- Assert( !vals[0].isNull() && !vals[1].isNull() );
- if( vals[0]==vals[1] ){
- val = vals[0];
- }else{
- val = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkNode( PLUS, vals[0], vals[1] ),
- NodeManager::currentNM()->mkConst( Rational(1)/Rational(2) ) );
- val = Rewriter::rewrite( val );
- }
- }else{
- if( !vals[0].isNull() ){
- val = NodeManager::currentNM()->mkNode( PLUS, vals[0], d_one );
- val = Rewriter::rewrite( val );
- }else if( !vals[1].isNull() ){
- val = NodeManager::currentNM()->mkNode( MINUS, vals[1], d_one );
- val = Rewriter::rewrite( val );
- }
- }
- Trace("cbqi-bound") << "Midpoint value : " << val << std::endl;
- if( !val.isNull() ){
- if( subs_proc[val].find( Node::null() )==subs_proc[val].end() ){
- subs_proc[val][Node::null()] = true;
- if( doAddInstantiationInc( val, pv, Node::null(), 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
+ if( vinst->hasProcessAssertion( this, sf, pv, effort ) ){
+ Trace("cbqi-inst-debug") << "[4] try based on assertions." << std::endl;
+ std::vector< Node > lits;
+ //unsigned rmax = Theory::theoryOf( pv )==Theory::theoryOf( pv.getType() ) ? 1 : 2;
+ for( unsigned r=0; r<2; r++ ){
+ TheoryId tid = r==0 ? Theory::theoryOf( pvtn ) : THEORY_UF;
+ Trace("cbqi-inst-debug2") << " look at assertions of " << tid << std::endl;
+ std::map< TheoryId, std::vector< Node > >::iterator ita = d_curr_asserts.find( tid );
+ if( ita!=d_curr_asserts.end() ){
+ for (unsigned j = 0; j<ita->second.size(); j++) {
+ Node lit = ita->second[j];
+ if( std::find( lits.begin(), lits.end(), lit )==lits.end() ){
+ lits.push_back( lit );
+ if( vinst->processAssertion( this, sf, pv, lit, effort ) ){
return true;
}
}
}
}
-#ifdef MBP_STRICT_ASSERTIONS
- Assert( false );
-#endif
- if( options::cbqiNopt() ){
- //try non-optimal bounds (heuristic, may help when nested quantification) ?
- Trace("cbqi-bound") << "Try non-optimal bounds..." << std::endl;
- for( unsigned r=0; r<2; r++ ){
- int rr = upper_first ? (1-r) : r;
- for( unsigned j=0; j<mbp_bounds[rr].size(); j++ ){
- if( (int)j!=best_used[rr] && ( !options::cbqiMidpoint() || mbp_vts_coeff[rr][1][j].isNull() ) ){
- Node val = getModelBasedProjectionValue( pv, mbp_bounds[rr][j], rr==0, mbp_coeff[rr][j], pv_value, t_values[rr][j], theta,
- mbp_vts_coeff[rr][0][j], mbp_vts_coeff[rr][1][j] );
- if( !val.isNull() ){
- if( subs_proc[val].find( mbp_coeff[rr][j] )==subs_proc[val].end() ){
- subs_proc[val][mbp_coeff[rr][j]] = true;
- if( doAddInstantiationInc( val, pv, mbp_coeff[rr][j], rr==0 ? 1 : -1, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
- return true;
- }
- }
- }
- }
- }
- }
- }
+ }
+ if( vinst->processAssertions( this, sf, pv, lits, effort ) ){
+ return true;
}
}
}
//[5] resort to using value in model
// do so if we are in effort=1, or if the variable is boolean, or if we are solving for a subfield of a datatype
- if( ( effort>0 || pvtn.isBoolean() || pvtn.isBitVector() || !curr_var.empty() ) && d_qe->getTermDatabase()->isClosedEnumerableType( pvtn ) ){
+ bool use_model_value = vinst->useModelValue( this, sf, pv, effort );
+ if( ( effort>0 || use_model_value || is_cv ) && vinst->allowModelValue( this, sf, pv, effort ) ){
+#ifdef CVC4_ASSERTIONS
+ if( pvtn.isReal() && options::cbqiNestedQE() && !options::cbqiAll() ){
+ Trace("cbqi-warn") << "Had to resort to model value." << std::endl;
+ Assert( false );
+ }
+#endif
Node mv = getModelValue( pv );
Node pv_coeff_m;
Trace("cbqi-inst-debug") << "[5] " << i << "...try model value " << mv << std::endl;
- int new_effort = pvtn.isBoolean() ? effort : 1;
-#ifdef MBP_STRICT_ASSERTIONS
- //we only resort to values in the case of booleans
- Assert( ( pvtn.isInteger() ? !options::cbqiUseInfInt() : !options::cbqiUseInfReal() ) || pvtn.isBoolean() );
-#endif
- if( doAddInstantiationInc( mv, pv, pv_coeff_m, 0, sf, ssf, vars, btyp, theta, i, new_effort, cons, curr_var ) ){
+ int new_effort = use_model_value ? effort : 1;
+ if( doAddInstantiationInc( pv, mv, pv_coeff_m, 0, sf, new_effort ) ){
return true;
}
}
Trace("cbqi-inst-debug") << "[No instantiation found for " << pv << "]" << std::endl;
+ if( is_cv ){
+ d_stack_vars.push_back( pv );
+ }
+ d_active_instantiators.erase( pv );
+ unregisterInstantiationVariable( pv );
return false;
}
}
+void CegInstantiator::pushStackVariable( Node v ) {
+ d_stack_vars.push_back( v );
+}
-bool CegInstantiator::doAddInstantiationInc( Node n, Node pv, Node pv_coeff, int bt, SolvedForm& sf, SolvedForm& ssf, std::vector< Node >& vars,
- std::vector< int >& btyp, Node theta, unsigned i, unsigned effort,
- std::map< Node, Node >& cons, std::vector< Node >& curr_var ) {
- if( Trace.isOn("cbqi-inst") ){
- for( unsigned j=0; j<sf.d_subs.size(); j++ ){
- Trace("cbqi-inst") << " ";
- }
- Trace("cbqi-inst") << sf.d_subs.size() << ": ";
- if( !pv_coeff.isNull() ){
- Trace("cbqi-inst") << pv_coeff << " * ";
- }
- Trace("cbqi-inst") << pv << " -> " << n << std::endl;
- Assert( n.getType().isSubtypeOf( pv.getType() ) );
- }
- //must ensure variables have been computed for n
- computeProgVars( n );
- Assert( d_inelig.find( n )==d_inelig.end() );
+void CegInstantiator::popStackVariable() {
+ Assert( !d_stack_vars.empty() );
+ d_stack_vars.pop_back();
+}
- //substitute into previous substitutions, when applicable
- std::vector< Node > a_subs;
- a_subs.push_back( n );
- std::vector< Node > a_var;
- a_var.push_back( pv );
- std::vector< Node > a_coeff;
- std::vector< Node > a_has_coeff;
- if( !pv_coeff.isNull() ){
- a_coeff.push_back( pv_coeff );
- a_has_coeff.push_back( pv );
- }
- bool success = true;
- std::map< int, Node > prev_subs;
- std::map< int, Node > prev_coeff;
- std::map< int, Node > prev_sym_subs;
- std::vector< Node > new_has_coeff;
- Trace("cbqi-inst-debug2") << "Applying substitutions..." << std::endl;
- for( unsigned j=0; j<sf.d_subs.size(); j++ ){
- Trace("cbqi-inst-debug2") << " Apply for " << sf.d_subs[j] << std::endl;
- Assert( d_prog_var.find( sf.d_subs[j] )!=d_prog_var.end() );
- if( d_prog_var[sf.d_subs[j]].find( pv )!=d_prog_var[sf.d_subs[j]].end() ){
- prev_subs[j] = sf.d_subs[j];
- TNode tv = pv;
- TNode ts = n;
- Node a_pv_coeff;
- Node new_subs = applySubstitution( vars[j].getType(), sf.d_subs[j], a_subs, a_coeff, a_has_coeff, a_var, a_pv_coeff, true );
- if( !new_subs.isNull() ){
- sf.d_subs[j] = new_subs;
- if( !a_pv_coeff.isNull() ){
- prev_coeff[j] = sf.d_coeff[j];
- if( sf.d_coeff[j].isNull() ){
- Assert( std::find( sf.d_has_coeff.begin(), sf.d_has_coeff.end(), vars[j] )==sf.d_has_coeff.end() );
- //now has coefficient
- new_has_coeff.push_back( vars[j] );
- sf.d_has_coeff.push_back( vars[j] );
- sf.d_coeff[j] = a_pv_coeff;
- }else{
- sf.d_coeff[j] = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MULT, sf.d_coeff[j], a_pv_coeff ) );
+bool CegInstantiator::doAddInstantiationInc( Node pv, Node n, Node pv_coeff, int bt, SolvedForm& sf, unsigned effort ) {
+ if( d_curr_subs_proc[pv][n].find( pv_coeff )==d_curr_subs_proc[pv][n].end() ){
+ d_curr_subs_proc[pv][n][pv_coeff] = true;
+ if( Trace.isOn("cbqi-inst") ){
+ for( unsigned j=0; j<sf.d_subs.size(); j++ ){
+ Trace("cbqi-inst") << " ";
+ }
+ Trace("cbqi-inst") << sf.d_subs.size() << ": ";
+ if( !pv_coeff.isNull() ){
+ Trace("cbqi-inst") << pv_coeff << " * ";
+ }
+ Trace("cbqi-inst") << pv << " -> " << n << std::endl;
+ Assert( n.getType().isSubtypeOf( pv.getType() ) );
+ }
+ //must ensure variables have been computed for n
+ computeProgVars( n );
+ Assert( d_inelig.find( n )==d_inelig.end() );
+
+ //substitute into previous substitutions, when applicable
+ std::vector< Node > a_subs;
+ a_subs.push_back( n );
+ std::vector< Node > a_var;
+ a_var.push_back( pv );
+ std::vector< Node > a_coeff;
+ std::vector< Node > a_has_coeff;
+ if( !pv_coeff.isNull() ){
+ a_coeff.push_back( pv_coeff );
+ a_has_coeff.push_back( pv );
+ }
+ bool success = true;
+ std::map< int, Node > prev_subs;
+ std::map< int, Node > prev_coeff;
+ std::map< int, Node > prev_sym_subs;
+ std::vector< Node > new_has_coeff;
+ Trace("cbqi-inst-debug2") << "Applying substitutions..." << std::endl;
+ for( unsigned j=0; j<sf.d_subs.size(); j++ ){
+ Trace("cbqi-inst-debug2") << " Apply for " << sf.d_subs[j] << std::endl;
+ Assert( d_prog_var.find( sf.d_subs[j] )!=d_prog_var.end() );
+ if( d_prog_var[sf.d_subs[j]].find( pv )!=d_prog_var[sf.d_subs[j]].end() ){
+ prev_subs[j] = sf.d_subs[j];
+ TNode tv = pv;
+ TNode ts = n;
+ Node a_pv_coeff;
+ Node new_subs = applySubstitution( sf.d_vars[j].getType(), sf.d_subs[j], a_subs, a_coeff, a_has_coeff, a_var, a_pv_coeff, true );
+ if( !new_subs.isNull() ){
+ sf.d_subs[j] = new_subs;
+ if( !a_pv_coeff.isNull() ){
+ prev_coeff[j] = sf.d_coeff[j];
+ if( sf.d_coeff[j].isNull() ){
+ Assert( std::find( sf.d_has_coeff.begin(), sf.d_has_coeff.end(), sf.d_vars[j] )==sf.d_has_coeff.end() );
+ //now has coefficient
+ new_has_coeff.push_back( sf.d_vars[j] );
+ sf.d_has_coeff.push_back( sf.d_vars[j] );
+ sf.d_coeff[j] = a_pv_coeff;
+ }else{
+ sf.d_coeff[j] = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MULT, sf.d_coeff[j], a_pv_coeff ) );
+ }
}
+ if( sf.d_subs[j]!=prev_subs[j] ){
+ computeProgVars( sf.d_subs[j] );
+ Assert( d_inelig.find( sf.d_subs[j] )==d_inelig.end() );
+ }
+ Trace("cbqi-inst-debug2") << "Subs " << j << " " << sf.d_subs[j] << std::endl;
+ }else{
+ Trace("cbqi-inst-debug2") << "...failed to apply substitution to " << sf.d_subs[j] << std::endl;
+ success = false;
+ break;
}
- if( sf.d_subs[j]!=prev_subs[j] ){
- computeProgVars( sf.d_subs[j] );
- Assert( d_inelig.find( sf.d_subs[j] )==d_inelig.end() );
- }
- Trace("cbqi-inst-debug2") << "Subs " << j << " " << sf.d_subs[j] << std::endl;
}else{
- Trace("cbqi-inst-debug2") << "...failed to apply substitution to " << sf.d_subs[j] << std::endl;
- success = false;
- break;
+ Trace("cbqi-inst-debug2") << "Skip " << j << " " << sf.d_subs[j] << std::endl;
}
- }else{
- Trace("cbqi-inst-debug2") << "Skip " << j << " " << sf.d_subs[j] << std::endl;
- }
- if( options::cbqiSymLia() && pv_coeff.isNull() ){
- //apply simple substitutions also to sym_subs
- prev_sym_subs[j] = ssf.d_subs[j];
- ssf.d_subs[j] = ssf.d_subs[j].substitute( a_var.begin(), a_var.end(), a_subs.begin(), a_subs.end() );
- ssf.d_subs[j] = Rewriter::rewrite( ssf.d_subs[j] );
}
- }
- if( success ){
- Trace("cbqi-inst-debug2") << "Adding to vectors..." << std::endl;
- vars.push_back( pv );
- btyp.push_back( bt );
- sf.push_back( pv, n, pv_coeff );
- ssf.push_back( pv, n, pv_coeff );
- Node new_theta = theta;
- if( !pv_coeff.isNull() ){
- if( new_theta.isNull() ){
- new_theta = pv_coeff;
- }else{
- new_theta = NodeManager::currentNM()->mkNode( MULT, new_theta, pv_coeff );
- new_theta = Rewriter::rewrite( new_theta );
+ if( success ){
+ Trace("cbqi-inst-debug2") << "Adding to vectors..." << std::endl;
+ sf.push_back( pv, n, pv_coeff, bt );
+ Node prev_theta = sf.d_theta;
+ Node new_theta = sf.d_theta;
+ if( !pv_coeff.isNull() ){
+ if( new_theta.isNull() ){
+ new_theta = pv_coeff;
+ }else{
+ new_theta = NodeManager::currentNM()->mkNode( MULT, new_theta, pv_coeff );
+ new_theta = Rewriter::rewrite( new_theta );
+ }
}
- }
- bool is_cv = false;
- if( !curr_var.empty() ){
- Assert( curr_var.back()==pv );
- curr_var.pop_back();
- is_cv = true;
- }
- Trace("cbqi-inst-debug2") << "Recurse..." << std::endl;
- success = doAddInstantiation( sf, ssf, vars, btyp, new_theta, curr_var.empty() ? i+1 : i, effort, cons, curr_var );
- if( !success ){
- Trace("cbqi-inst-debug2") << "Removing from vectors..." << std::endl;
- if( is_cv ){
- curr_var.push_back( pv );
+ sf.d_theta = new_theta;
+ Trace("cbqi-inst-debug2") << "Recurse..." << std::endl;
+ unsigned i = d_curr_index[pv];
+ success = doAddInstantiation( sf, d_stack_vars.empty() ? i+1 : i, effort );
+ sf.d_theta = prev_theta;
+ if( !success ){
+ Trace("cbqi-inst-debug2") << "Removing from vectors..." << std::endl;
+ sf.pop_back( pv, n, pv_coeff, bt );
}
- sf.pop_back( pv, n, pv_coeff );
- ssf.pop_back( pv, n, pv_coeff );
- vars.pop_back();
- btyp.pop_back();
- }
- }
- if( success ){
- return true;
- }else{
- Trace("cbqi-inst-debug2") << "Revert substitutions..." << std::endl;
- //revert substitution information
- for( std::map< int, Node >::iterator it = prev_subs.begin(); it != prev_subs.end(); it++ ){
- sf.d_subs[it->first] = it->second;
- }
- for( std::map< int, Node >::iterator it = prev_coeff.begin(); it != prev_coeff.end(); it++ ){
- sf.d_coeff[it->first] = it->second;
- }
- for( unsigned i=0; i<new_has_coeff.size(); i++ ){
- sf.d_has_coeff.pop_back();
- }
- for( std::map< int, Node >::iterator it = prev_sym_subs.begin(); it != prev_sym_subs.end(); it++ ){
- ssf.d_subs[it->first] = it->second;
}
- return false;
- }
-}
-
-bool CegInstantiator::doAddInstantiationCoeff( SolvedForm& sf, std::vector< Node >& vars, std::vector< int >& btyp,
- unsigned j, std::map< Node, Node >& cons ) {
-
-
- if( j==sf.d_has_coeff.size() ){
- return doAddInstantiation( sf.d_subs, vars, cons );
- }else{
- Assert( std::find( vars.begin(), vars.end(), sf.d_has_coeff[j] )!=vars.end() );
- unsigned index = std::find( vars.begin(), vars.end(), sf.d_has_coeff[j] )-vars.begin();
- Node prev = sf.d_subs[index];
- Assert( !sf.d_coeff[index].isNull() );
- Trace("cbqi-inst-debug") << "Normalize substitution for " << sf.d_coeff[index] << " * " << vars[index] << " = " << sf.d_subs[index] << std::endl;
- Assert( vars[index].getType().isInteger() );
- //must ensure that divisibility constraints are met
- //solve updated rewritten equality for vars[index], if coefficient is one, then we are successful
- Node eq_lhs = NodeManager::currentNM()->mkNode( MULT, sf.d_coeff[index], vars[index] );
- Node eq_rhs = sf.d_subs[index];
- Node eq = eq_lhs.eqNode( eq_rhs );
- eq = Rewriter::rewrite( eq );
- Trace("cbqi-inst-debug") << "...equality is " << eq << std::endl;
- std::map< Node, Node > msum;
- if( QuantArith::getMonomialSumLit( eq, msum ) ){
- Node veq;
- if( QuantArith::isolate( vars[index], msum, veq, EQUAL, true )!=0 ){
- Node veq_c;
- if( veq[0]!=vars[index] ){
- Node veq_v;
- if( QuantArith::getMonomial( veq[0], veq_c, veq_v ) ){
- Assert( veq_v==vars[index] );
- }
- }
- sf.d_subs[index] = veq[1];
- if( !veq_c.isNull() ){
- sf.d_subs[index] = NodeManager::currentNM()->mkNode( INTS_DIVISION_TOTAL, veq[1], veq_c );
- Trace("cbqi-inst-debug") << "...bound type is : " << btyp[index] << std::endl;
- //intger division rounding up if from a lower bound
- if( btyp[index]==1 && options::cbqiRoundUpLowerLia() ){
- sf.d_subs[index] = NodeManager::currentNM()->mkNode( PLUS, sf.d_subs[index],
- NodeManager::currentNM()->mkNode( ITE,
- NodeManager::currentNM()->mkNode( EQUAL,
- NodeManager::currentNM()->mkNode( INTS_MODULUS_TOTAL, veq[1], veq_c ),
- d_zero ),
- d_zero, d_one )
- );
- }
- }
- Trace("cbqi-inst-debug") << "...normalize integers : " << vars[index] << " -> " << sf.d_subs[index] << std::endl;
- if( options::cbqiSymLia() ){
- //must apply substitution to previous subs
- std::vector< Node > curr_var;
- std::vector< Node > curr_subs;
- curr_var.push_back( vars[index] );
- curr_subs.push_back( sf.d_subs[index] );
- for( unsigned k=0; k<index; k++ ){
- Node prevs = sf.d_subs[k];
- sf.d_subs[k] = sf.d_subs[k].substitute( curr_var.begin(), curr_var.end(), curr_subs.begin(), curr_subs.end() );
- if( prevs!=sf.d_subs[k] ){
- Trace("cbqi-inst-debug2") << " rewrite " << vars[k] << " -> " << prevs << " to ";
- sf.d_subs[k] = Rewriter::rewrite( sf.d_subs[k] );
- Trace("cbqi-inst-debug2") << sf.d_subs[k] << std::endl;
- }
- }
- }
- if( doAddInstantiationCoeff( sf, vars, btyp, j+1, cons ) ){
- return true;
- }
+ if( success ){
+ return true;
+ }else{
+ Trace("cbqi-inst-debug2") << "Revert substitutions..." << std::endl;
+ //revert substitution information
+ for( std::map< int, Node >::iterator it = prev_subs.begin(); it != prev_subs.end(); it++ ){
+ sf.d_subs[it->first] = it->second;
+ }
+ for( std::map< int, Node >::iterator it = prev_coeff.begin(); it != prev_coeff.end(); it++ ){
+ sf.d_coeff[it->first] = it->second;
+ }
+ for( unsigned i=0; i<new_has_coeff.size(); i++ ){
+ sf.d_has_coeff.pop_back();
}
+ return false;
}
- sf.d_subs[index] = prev;
- Trace("cbqi-inst-debug") << "...failed." << std::endl;
+ }else{
+ //already tried this substitution
return false;
}
}
-bool CegInstantiator::doAddInstantiation( std::vector< Node >& subs, std::vector< Node >& vars, std::map< Node, Node >& cons ) {
+bool CegInstantiator::doAddInstantiation( std::vector< Node >& subs, std::vector< Node >& vars ) {
if( vars.size()>d_vars.size() ){
Trace("cbqi-inst-debug") << "Reconstructing instantiations...." << std::endl;
std::map< Node, Node > subs_map;
@@ -953,7 +470,9 @@ bool CegInstantiator::doAddInstantiation( std::vector< Node >& subs, std::vector
}
subs.clear();
for( unsigned i=0; i<d_vars.size(); i++ ){
- Node n = constructInstantiation( d_vars[i], subs_map, cons );
+ std::map< Node, Node >::iterator it = subs_map.find( d_vars[i] );
+ Assert( it!=subs_map.end() );
+ Node n = it->second;
Trace("cbqi-inst-debug") << " " << d_vars[i] << " -> " << n << std::endl;
subs.push_back( n );
}
@@ -967,32 +486,9 @@ bool CegInstantiator::doAddInstantiation( std::vector< Node >& subs, std::vector
}
}
bool ret = d_out->doAddInstantiation( subs );
-#ifdef MBP_STRICT_ASSERTIONS
- Assert( ret );
-#endif
return ret;
}
-Node CegInstantiator::constructInstantiation( Node n, std::map< Node, Node >& subs_map, std::map< Node, Node >& cons ) {
- std::map< Node, Node >::iterator it = subs_map.find( n );
- if( it!=subs_map.end() ){
- return it->second;
- }else{
- it = cons.find( n );
- Assert( it!=cons.end() );
- std::vector< Node > children;
- children.push_back( it->second );
- const Datatype& dt = Datatype::datatypeOf( it->second.toExpr() );
- unsigned cindex = Datatype::indexOf( it->second.toExpr() );
- for( unsigned i=0; i<dt[cindex].getNumArgs(); i++ ){
- Node nn = NodeManager::currentNM()->mkNode( APPLY_SELECTOR_TOTAL, Node::fromExpr( dt[cindex][i].getSelector() ), n );
- Node nc = constructInstantiation( nn, subs_map, cons );
- children.push_back( nc );
- }
- return NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, children );
- }
-}
-
Node CegInstantiator::applySubstitution( TypeNode tn, Node n, std::vector< Node >& subs, std::vector< Node >& coeff, std::vector< Node >& has_coeff,
std::vector< Node >& vars, Node& pv_coeff, bool try_coeff ) {
Assert( d_prog_var.find( n )!=d_prog_var.end() );
@@ -1097,66 +593,6 @@ Node CegInstantiator::applySubstitution( TypeNode tn, Node n, std::vector< Node
}
}
-Node CegInstantiator::getModelBasedProjectionValue( Node e, Node t, bool isLower, Node c, Node me, Node mt, Node theta, Node inf_coeff, Node delta_coeff ) {
- Node val = t;
- Trace("cbqi-bound2") << "Value : " << val << std::endl;
- Assert( !e.getType().isInteger() || t.getType().isInteger() );
- Assert( !e.getType().isInteger() || mt.getType().isInteger() );
- //add rho value
- //get the value of c*e
- Node ceValue = me;
- Node new_theta = theta;
- if( !c.isNull() ){
- Assert( c.getType().isInteger() );
- ceValue = NodeManager::currentNM()->mkNode( MULT, ceValue, c );
- ceValue = Rewriter::rewrite( ceValue );
- if( new_theta.isNull() ){
- new_theta = c;
- }else{
- new_theta = NodeManager::currentNM()->mkNode( MULT, new_theta, c );
- new_theta = Rewriter::rewrite( new_theta );
- }
- Trace("cbqi-bound2") << "...c*e = " << ceValue << std::endl;
- Trace("cbqi-bound2") << "...theta = " << new_theta << std::endl;
- }
- if( !new_theta.isNull() && e.getType().isInteger() ){
- Node rho;
- //if( !mt.getType().isInteger() ){
- //round up/down
- //mt = NodeManager::currentNM()->mkNode(
- //}
- if( isLower ){
- rho = NodeManager::currentNM()->mkNode( MINUS, ceValue, mt );
- }else{
- rho = NodeManager::currentNM()->mkNode( MINUS, mt, ceValue );
- }
- rho = Rewriter::rewrite( rho );
- Trace("cbqi-bound2") << "...rho = " << me << " - " << mt << " = " << rho << std::endl;
- Trace("cbqi-bound2") << "..." << rho << " mod " << new_theta << " = ";
- rho = NodeManager::currentNM()->mkNode( INTS_MODULUS_TOTAL, rho, new_theta );
- rho = Rewriter::rewrite( rho );
- Trace("cbqi-bound2") << rho << std::endl;
- Kind rk = isLower ? PLUS : MINUS;
- val = NodeManager::currentNM()->mkNode( rk, val, rho );
- val = Rewriter::rewrite( val );
- Trace("cbqi-bound2") << "(after rho) : " << val << std::endl;
- }
- if( !inf_coeff.isNull() ){
- Assert( !d_vts_sym[0].isNull() );
- val = NodeManager::currentNM()->mkNode( PLUS, val, NodeManager::currentNM()->mkNode( MULT, inf_coeff, d_vts_sym[0] ) );
- val = Rewriter::rewrite( val );
- }
- if( !delta_coeff.isNull() ){
- //create delta here if necessary
- if( d_vts_sym[1].isNull() ){
- d_vts_sym[1] = d_qe->getTermDatabase()->getVtsDelta();
- }
- val = NodeManager::currentNM()->mkNode( PLUS, val, NodeManager::currentNM()->mkNode( MULT, delta_coeff, d_vts_sym[1] ) );
- val = Rewriter::rewrite( val );
- }
- return val;
-}
-
bool CegInstantiator::check() {
if( d_qe->getTheoryEngine()->needCheck() ){
Trace("cbqi-engine") << " CEGQI instantiator : wait until all ground theories are finished." << std::endl;
@@ -1165,14 +601,9 @@ bool CegInstantiator::check() {
processAssertions();
for( unsigned r=0; r<2; r++ ){
SolvedForm sf;
- SolvedForm ssf;
- std::vector< Node > vars;
- std::vector< int > btyp;
- Node theta;
- std::map< Node, Node > cons;
- std::vector< Node > curr_var;
+ d_stack_vars.clear();
//try to add an instantiation
- if( doAddInstantiation( sf, ssf, vars, btyp, theta, 0, r==0 ? 0 : 2, cons, curr_var ) ){
+ if( doAddInstantiation( sf, 0, r==0 ? 0 : 2 ) ){
return true;
}
}
@@ -1222,25 +653,27 @@ void getPresolveEqConjuncts( std::vector< Node >& vars, std::vector< Node >& ter
}
void CegInstantiator::presolve( Node q ) {
- Trace("cbqi-presolve") << "CBQI presolve " << q << std::endl;
//at preregister time, add proxy of obvious instantiations up front, which helps learning during preprocessing
- std::vector< Node > vars;
- std::map< Node, std::vector< Node > > teq;
- for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
- vars.push_back( q[0][i] );
- teq[q[0][i]].clear();
- }
- collectPresolveEqTerms( q[1], teq );
- std::vector< Node > terms;
- std::vector< Node > conj;
- getPresolveEqConjuncts( vars, terms, teq, q, conj );
-
- if( !conj.empty() ){
- Node lem = conj.size()==1 ? conj[0] : NodeManager::currentNM()->mkNode( AND, conj );
- Node g = NodeManager::currentNM()->mkSkolem( "g", NodeManager::currentNM()->booleanType() );
- lem = NodeManager::currentNM()->mkNode( OR, g, lem );
- Trace("cbqi-presolve-debug") << "Presolve lemma : " << lem << std::endl;
- d_qe->getOutputChannel().lemma( lem, false, true );
+ //only if no nested quantifiers
+ if( !QuantifiersRewriter::containsQuantifiers( q[1] ) ){
+ std::vector< Node > ps_vars;
+ std::map< Node, std::vector< Node > > teq;
+ for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
+ ps_vars.push_back( q[0][i] );
+ teq[q[0][i]].clear();
+ }
+ collectPresolveEqTerms( q[1], teq );
+ std::vector< Node > terms;
+ std::vector< Node > conj;
+ getPresolveEqConjuncts( ps_vars, terms, teq, q, conj );
+
+ if( !conj.empty() ){
+ Node lem = conj.size()==1 ? conj[0] : NodeManager::currentNM()->mkNode( AND, conj );
+ Node g = NodeManager::currentNM()->mkSkolem( "g", NodeManager::currentNM()->booleanType() );
+ lem = NodeManager::currentNM()->mkNode( OR, g, lem );
+ Trace("cbqi-presolve-debug") << "Presolve lemma : " << lem << std::endl;
+ d_qe->getOutputChannel().lemma( lem, false, true );
+ }
}
}
@@ -1362,9 +795,7 @@ void CegInstantiator::processAssertions() {
addToAuxVarSubstitution( subs_lhs, subs_rhs, r, it->second );
}else{
Trace("cbqi-proc") << "....no substitution found for auxiliary variable " << r << "!!!" << std::endl;
-#ifdef MBP_STRICT_ASSERTIONS
Assert( false );
-#endif
}
}
@@ -1397,10 +828,8 @@ void CegInstantiator::processAssertions() {
std::vector< Node > akeep;
for( unsigned i=0; i<it->second.size(); i++ ){
Node n = it->second[i];
- //compute the variables in assertion
- computeProgVars( n );
//must be an eligible term
- if( d_inelig.find( n )==d_inelig.end() ){
+ if( isEligible( n ) ){
//must contain at least one variable
if( !d_prog_var[n].empty() ){
Trace("cbqi-proc") << "...literal[" << it->first << "] : " << n << std::endl;
@@ -1453,17 +882,16 @@ Node CegInstantiator::getModelValue( Node n ) {
void CegInstantiator::collectCeAtoms( Node n, std::map< Node, bool >& visited ) {
if( n.getKind()==FORALL ){
d_is_nested_quant = true;
- }else{
- if( visited.find( n )==visited.end() ){
- visited[n] = true;
- if( TermDb::isBoolConnective( n.getKind() ) ){
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- collectCeAtoms( n[i], visited );
- }
- }else{
- if( std::find( d_ce_atoms.begin(), d_ce_atoms.end(), n )==d_ce_atoms.end() ){
- d_ce_atoms.push_back( n );
- }
+ }else if( visited.find( n )==visited.end() ){
+ visited[n] = true;
+ if( TermDb::isBoolConnective( n.getKind() ) ){
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ collectCeAtoms( n[i], visited );
+ }
+ }else{
+ if( std::find( d_ce_atoms.begin(), d_ce_atoms.end(), n )==d_ce_atoms.end() ){
+ Trace("cbqi-ce-atoms") << "CE atoms : " << n << std::endl;
+ d_ce_atoms.push_back( n );
}
}
}
@@ -1479,7 +907,8 @@ struct sortCegVarOrder {
void CegInstantiator::registerCounterexampleLemma( std::vector< Node >& lems, std::vector< Node >& ce_vars ) {
- Assert( d_vars.empty() );
+ //Assert( d_vars.empty() );
+ d_vars.clear();
d_vars.insert( d_vars.end(), ce_vars.begin(), ce_vars.end() );
//determine variable order: must do Reals before Ints
@@ -1512,7 +941,9 @@ void CegInstantiator::registerCounterexampleLemma( std::vector< Node >& lems, st
//remove ITEs
IteSkolemMap iteSkolemMap;
d_qe->getTheoryEngine()->getIteRemover()->run(lems, iteSkolemMap);
- Assert( d_aux_vars.empty() );
+ //Assert( d_aux_vars.empty() );
+ d_aux_vars.clear();
+ d_aux_eq.clear();
for(IteSkolemMap::iterator i = iteSkolemMap.begin(); i != iteSkolemMap.end(); ++i) {
Trace("cbqi-debug") << " Auxiliary var (from ITE) : " << i->first << std::endl;
d_aux_vars.push_back( i->first );
@@ -1544,159 +975,14 @@ void CegInstantiator::registerCounterexampleLemma( std::vector< Node >& lems, st
}
}
-//this isolates the atom into solved form
-// veq_c * pv <> val + vts_coeff_delta * delta + vts_coeff_inf * inf
-// ensures val is Int if pv is Int, and val does not contain vts symbols
-int CegInstantiator::solve_arith( Node pv, Node atom, Node& veq_c, Node& val, Node& vts_coeff_inf, Node& vts_coeff_delta ) {
- int ires = 0;
- Trace("cbqi-inst-debug") << "isolate for " << pv << " in " << atom << std::endl;
- std::map< Node, Node > msum;
- if( QuantArith::getMonomialSumLit( atom, msum ) ){
- Trace("cbqi-inst-debug") << "got monomial sum: " << std::endl;
- if( Trace.isOn("cbqi-inst-debug") ){
- QuantArith::debugPrintMonomialSum( msum, "cbqi-inst-debug" );
- }
- TypeNode pvtn = pv.getType();
- //remove vts symbols from polynomial
- Node vts_coeff[2];
- for( unsigned t=0; t<2; t++ ){
- if( !d_vts_sym[t].isNull() ){
- std::map< Node, Node >::iterator itminf = msum.find( d_vts_sym[t] );
- if( itminf!=msum.end() ){
- vts_coeff[t] = itminf->second;
- if( vts_coeff[t].isNull() ){
- vts_coeff[t] = NodeManager::currentNM()->mkConst( Rational( 1 ) );
- }
- //negate if coefficient on variable is positive
- std::map< Node, Node >::iterator itv = msum.find( pv );
- if( itv!=msum.end() ){
- //multiply by the coefficient we will isolate for
- if( itv->second.isNull() ){
- vts_coeff[t] = QuantArith::negate(vts_coeff[t]);
- }else{
- if( !pvtn.isInteger() ){
- vts_coeff[t] = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkConst( Rational(-1) / itv->second.getConst<Rational>() ), vts_coeff[t] );
- vts_coeff[t] = Rewriter::rewrite( vts_coeff[t] );
- }else if( itv->second.getConst<Rational>().sgn()==1 ){
- vts_coeff[t] = QuantArith::negate(vts_coeff[t]);
- }
- }
- }
- Trace("cbqi-inst-debug") << "vts[" << t << "] coefficient is " << vts_coeff[t] << std::endl;
- msum.erase( d_vts_sym[t] );
- }
- }
- }
- ires = QuantArith::isolate( pv, msum, veq_c, val, atom.getKind() );
- if( ires!=0 ){
- Node realPart;
- if( Trace.isOn("cbqi-inst-debug") ){
- Trace("cbqi-inst-debug") << "Isolate : ";
- if( !veq_c.isNull() ){
- Trace("cbqi-inst-debug") << veq_c << " * ";
- }
- Trace("cbqi-inst-debug") << pv << " " << atom.getKind() << " " << val << std::endl;
- }
- if( options::cbqiAll() ){
- // when not pure LIA/LRA, we must check whether the lhs contains pv
- if( TermDb::containsTerm( val, pv ) ){
- return 0;
- }
- }
- if( pvtn.isInteger() && ( ( !veq_c.isNull() && !veq_c.getType().isInteger() ) || !val.getType().isInteger() ) ){
- //redo, split integer/non-integer parts
- bool useCoeff = false;
- Integer coeff = d_one.getConst<Rational>().getNumerator();
- for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){
- if( it->first.isNull() || it->first.getType().isInteger() ){
- if( !it->second.isNull() ){
- coeff = coeff.lcm( it->second.getConst<Rational>().getDenominator() );
- useCoeff = true;
- }
- }
- }
- //multiply everything by this coefficient
- Node rcoeff = NodeManager::currentNM()->mkConst( Rational( coeff ) );
- std::vector< Node > real_part;
- for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){
- if( useCoeff ){
- if( it->second.isNull() ){
- msum[it->first] = rcoeff;
- }else{
- msum[it->first] = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MULT, it->second, rcoeff ) );
- }
- }
- if( !it->first.isNull() && !it->first.getType().isInteger() ){
- real_part.push_back( msum[it->first].isNull() ? it->first : NodeManager::currentNM()->mkNode( MULT, msum[it->first], it->first ) );
- }
- }
- //remove delta TODO: check this
- vts_coeff[1] = Node::null();
- //multiply inf
- if( !vts_coeff[0].isNull() ){
- vts_coeff[0] = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MULT, rcoeff, vts_coeff[0] ) );
- }
- realPart = real_part.empty() ? d_zero : ( real_part.size()==1 ? real_part[0] : NodeManager::currentNM()->mkNode( PLUS, real_part ) );
- Assert( d_out->isEligibleForInstantiation( realPart ) );
- //re-isolate
- Trace("cbqi-inst-debug") << "Re-isolate..." << std::endl;
- ires = QuantArith::isolate( pv, msum, veq_c, val, atom.getKind() );
- Trace("cbqi-inst-debug") << "Isolate for mixed Int/Real : " << veq_c << " * " << pv << " " << atom.getKind() << " " << val << std::endl;
- Trace("cbqi-inst-debug") << " real part : " << realPart << std::endl;
- if( ires!=0 ){
- int ires_use = ( msum[pv].isNull() || msum[pv].getConst<Rational>().sgn()==1 ) ? 1 : -1;
- val = Rewriter::rewrite( NodeManager::currentNM()->mkNode( ires_use==-1 ? PLUS : MINUS,
- NodeManager::currentNM()->mkNode( ires_use==-1 ? MINUS : PLUS, val, realPart ),
- NodeManager::currentNM()->mkNode( TO_INTEGER, realPart ) ) ); //TODO: round up for upper bounds?
- Trace("cbqi-inst-debug") << "result : " << val << std::endl;
- Assert( val.getType().isInteger() );
- }
- }
- }
- vts_coeff_inf = vts_coeff[0];
- vts_coeff_delta = vts_coeff[1];
- }
- return ires;
+Instantiator::Instantiator( QuantifiersEngine * qe, TypeNode tn ) : d_type( tn ){
+ d_closed_enum_type = qe->getTermDatabase()->isClosedEnumerableType( tn );
}
-Node CegInstantiator::solve_dt( Node v, Node a, Node b, Node sa, Node sb ) {
- Trace("cbqi-inst-debug2") << "Solve dt : " << v << " " << a << " " << b << " " << sa << " " << sb << std::endl;
- Node ret;
- if( !a.isNull() && a==v ){
- ret = sb;
- }else if( !b.isNull() && b==v ){
- ret = sa;
- }else if( !a.isNull() && a.getKind()==APPLY_CONSTRUCTOR ){
- if( !b.isNull() && b.getKind()==APPLY_CONSTRUCTOR ){
- if( a.getOperator()==b.getOperator() ){
- for( unsigned i=0; i<a.getNumChildren(); i++ ){
- Node s = solve_dt( v, a[i], b[i], sa[i], sb[i] );
- if( !s.isNull() ){
- return s;
- }
- }
- }
- }else{
- unsigned cindex = Datatype::indexOf( a.getOperator().toExpr() );
- TypeNode tn = a.getType();
- const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
- for( unsigned i=0; i<a.getNumChildren(); i++ ){
- Node nn = NodeManager::currentNM()->mkNode( APPLY_SELECTOR_TOTAL, Node::fromExpr( dt[cindex][i].getSelector() ), sb );
- Node s = solve_dt( v, a[i], Node::null(), sa[i], nn );
- if( !s.isNull() ){
- return s;
- }
- }
- }
- }else if( !b.isNull() && b.getKind()==APPLY_CONSTRUCTOR ){
- return solve_dt( v, b, a, sb, sa );
- }
- if( !ret.isNull() ){
- //ensure does not contain
- if( TermDb::containsTerm( ret, v ) ){
- ret = Node::null();
- }
- }
- return ret;
+
+bool Instantiator::processEqualTerm( CegInstantiator * ci, SolvedForm& sf, Node pv, Node pv_coeff, Node n, unsigned effort ) {
+ return ci->doAddInstantiationInc( pv, n, pv_coeff, 0, sf, effort );
}
+
+
diff --git a/src/theory/quantifiers/ceg_instantiator.h b/src/theory/quantifiers/ceg_instantiator.h
index 3d7bbcb55..94d02de9b 100755
--- a/src/theory/quantifiers/ceg_instantiator.h
+++ b/src/theory/quantifiers/ceg_instantiator.h
@@ -38,17 +38,52 @@ public:
virtual bool addLemma( Node lem ) = 0;
};
+class Instantiator;
+
+
+//solved form, involves substitution with coefficients
+class SolvedForm {
+public:
+ std::vector< Node > d_vars;
+ std::vector< Node > d_subs;
+ std::vector< Node > d_coeff;
+ std::vector< int > d_btyp;
+ std::vector< Node > d_has_coeff;
+ Node d_theta;
+ void copy( SolvedForm& sf ){
+ d_vars.insert( d_vars.end(), sf.d_vars.begin(), sf.d_vars.end() );
+ d_subs.insert( d_subs.end(), sf.d_subs.begin(), sf.d_subs.end() );
+ d_coeff.insert( d_coeff.end(), sf.d_coeff.begin(), sf.d_coeff.end() );
+ d_btyp.insert( d_btyp.end(), sf.d_btyp.begin(), sf.d_btyp.end() );
+ d_has_coeff.insert( d_has_coeff.end(), sf.d_has_coeff.begin(), sf.d_has_coeff.end() );
+ d_theta = sf.d_theta;
+ }
+ void push_back( Node pv, Node n, Node pv_coeff, int bt ){
+ d_vars.push_back( pv );
+ d_subs.push_back( n );
+ d_coeff.push_back( pv_coeff );
+ d_btyp.push_back( bt );
+ if( !pv_coeff.isNull() ){
+ d_has_coeff.push_back( pv );
+ }
+ }
+ void pop_back( Node pv, Node n, Node pv_coeff, int bt ){
+ d_vars.pop_back();
+ d_subs.pop_back();
+ d_coeff.pop_back();
+ d_btyp.pop_back();
+ if( !pv_coeff.isNull() ){
+ d_has_coeff.pop_back();
+ }
+ }
+};
+
class CegInstantiator {
private:
QuantifiersEngine * d_qe;
CegqiOutput * d_out;
- //constants
- Node d_zero;
- Node d_one;
- Node d_true;
bool d_use_vts_delta;
bool d_use_vts_inf;
- Node d_vts_sym[2];
//program variable contains cache
std::map< Node, std::map< Node, bool > > d_prog_var;
std::map< Node, bool > d_inelig;
@@ -67,81 +102,116 @@ private:
//atoms of the CE lemma
bool d_is_nested_quant;
std::vector< Node > d_ce_atoms;
-private:
//collect atoms
- void collectCeAtoms( Node n, std::map< Node, bool >& visited );
+ void collectCeAtoms( Node n, std::map< Node, bool >& visited );
+private:
+ //map from variables to their instantiators
+ std::map< Node, Instantiator * > d_instantiator;
+ //cache of current substitutions tried between register/unregister
+ std::map< Node, std::map< Node, std::map< Node, bool > > > d_curr_subs_proc;
+ std::map< Node, unsigned > d_curr_index;
+ //stack of temporary variables we are solving (e.g. subfields of datatypes)
+ std::vector< Node > d_stack_vars;
+ //used instantiators
+ std::map< Node, Instantiator * > d_active_instantiators;
+ //register variable
+ void registerInstantiationVariable( Node v, unsigned index );
+ void unregisterInstantiationVariable( Node v );
+private:
//for adding instantiations during check
void computeProgVars( Node n );
- //solved form, involves substitution with coefficients
- class SolvedForm {
- public:
- std::vector< Node > d_subs;
- std::vector< Node > d_coeff;
- std::vector< Node > d_has_coeff;
- void copy( SolvedForm& sf ){
- d_subs.insert( d_subs.end(), sf.d_subs.begin(), sf.d_subs.end() );
- d_coeff.insert( d_coeff.end(), sf.d_coeff.begin(), sf.d_coeff.end() );
- d_has_coeff.insert( d_has_coeff.end(), sf.d_has_coeff.begin(), sf.d_has_coeff.end() );
- }
- void push_back( Node pv, Node n, Node pv_coeff ){
- d_subs.push_back( n );
- d_coeff.push_back( pv_coeff );
- if( !pv_coeff.isNull() ){
- d_has_coeff.push_back( pv );
- }
- }
- void pop_back( Node pv, Node n, Node pv_coeff ){
- d_subs.pop_back();
- d_coeff.pop_back();
- if( !pv_coeff.isNull() ){
- d_has_coeff.pop_back();
- }
- }
- };
- /*
- class MbpBound {
- public:
- Node d_bound;
- Node d_coeff;
- Node d_vts_coeff[2];
- Node d_lit;
- };
- */
// effort=0 : do not use model value, 1: use model value, 2: one must use model value
- bool doAddInstantiation( SolvedForm& sf, SolvedForm& ssf, std::vector< Node >& vars,
- std::vector< int >& btyp, Node theta, unsigned i, unsigned effort,
- std::map< Node, Node >& cons, std::vector< Node >& curr_var );
- bool doAddInstantiationInc( Node n, Node pv, Node pv_coeff, int bt, SolvedForm& sf, SolvedForm& ssf, std::vector< Node >& vars,
- std::vector< int >& btyp, Node theta, unsigned i, unsigned effort,
- std::map< Node, Node >& cons, std::vector< Node >& curr_var );
- bool doAddInstantiationCoeff( SolvedForm& sf,
- std::vector< Node >& vars, std::vector< int >& btyp,
- unsigned j, std::map< Node, Node >& cons );
- bool doAddInstantiation( std::vector< Node >& subs, std::vector< Node >& vars, std::map< Node, Node >& cons );
- Node constructInstantiation( Node n, std::map< Node, Node >& subs_map, std::map< Node, Node >& cons );
- Node applySubstitution( TypeNode tn, Node n, SolvedForm& sf, std::vector< Node >& vars, Node& pv_coeff, bool try_coeff = true ) {
- return applySubstitution( tn, n, sf.d_subs, sf.d_coeff, sf.d_has_coeff, vars, pv_coeff, try_coeff );
- }
- Node applySubstitution( TypeNode tn, Node n, std::vector< Node >& subs, std::vector< Node >& coeff, std::vector< Node >& has_coeff,
- std::vector< Node >& vars, Node& pv_coeff, bool try_coeff = true );
- Node getModelBasedProjectionValue( Node e, Node t, bool isLower, Node c, Node me, Node mt, Node theta, Node inf_coeff, Node delta_coeff );
+ bool doAddInstantiation( SolvedForm& sf, unsigned i, unsigned effort );
+ bool doAddInstantiation( std::vector< Node >& subs, std::vector< Node >& vars );
+ //process
void processAssertions();
void addToAuxVarSubstitution( std::vector< Node >& subs_lhs, std::vector< Node >& subs_rhs, Node l, Node r );
- //get model value
- Node getModelValue( Node n );
-private:
- int solve_arith( Node v, Node atom, Node & veq_c, Node & val, Node& vts_coeff_inf, Node& vts_coeff_delta );
- Node solve_dt( Node v, Node a, Node b, Node sa, Node sb );
public:
CegInstantiator( QuantifiersEngine * qe, CegqiOutput * out, bool use_vts_delta = true, bool use_vts_inf = true );
+ virtual ~CegInstantiator();
//check : add instantiations based on valuation of d_vars
bool check();
//presolve for quantified formula
void presolve( Node q );
//register the counterexample lemma (stored in lems), modify vector
void registerCounterexampleLemma( std::vector< Node >& lems, std::vector< Node >& ce_vars );
+ //output
+ CegqiOutput * getOutput() { return d_out; }
+ //get quantifiers engine
+ QuantifiersEngine* getQuantifiersEngine() { return d_qe; }
+
+//interface for instantiators
+public:
+ void pushStackVariable( Node v );
+ void popStackVariable();
+ bool doAddInstantiationInc( Node pv, Node n, Node pv_coeff, int bt, SolvedForm& sf, unsigned effort );
+ Node getModelValue( Node n );
+ // TODO: move to solved form?
+ Node applySubstitution( TypeNode tn, Node n, SolvedForm& sf, Node& pv_coeff, bool try_coeff = true ) {
+ return applySubstitution( tn, n, sf.d_subs, sf.d_coeff, sf.d_has_coeff, sf.d_vars, pv_coeff, try_coeff );
+ }
+ Node applySubstitution( TypeNode tn, Node n, std::vector< Node >& subs, std::vector< Node >& coeff, std::vector< Node >& has_coeff,
+ std::vector< Node >& vars, Node& pv_coeff, bool try_coeff = true );
+public:
+ unsigned getNumCEAtoms() { return d_ce_atoms.size(); }
+ Node getCEAtom( unsigned i ) { return d_ce_atoms[i]; }
+ // is eligible
+ bool isEligible( Node n );
+ // has variable
+ bool hasVariable( Node n, Node pv );
+ bool useVtsDelta() { return d_use_vts_delta; }
+ bool useVtsInfinity() { return d_use_vts_inf; }
+ bool hasNestedQuantification() { return d_is_nested_quant; }
};
+
+
+// an instantiator for individual variables
+// will make calls into CegInstantiator::doAddInstantiationInc
+class Instantiator {
+protected:
+ TypeNode d_type;
+ bool d_closed_enum_type;
+public:
+ Instantiator( QuantifiersEngine * qe, TypeNode tn );
+ virtual ~Instantiator(){}
+ virtual void reset( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) {}
+
+ //called when pv_coeff * pv = n, and n is eligible for instantiation
+ virtual bool processEqualTerm( CegInstantiator * ci, SolvedForm& sf, Node pv, Node pv_coeff, Node n, unsigned effort );
+ //eqc is the equivalence class of pv
+ virtual bool processEqualTerms( CegInstantiator * ci, SolvedForm& sf, Node pv, std::vector< Node >& eqc, unsigned effort ) { return false; }
+
+ //term_coeffs.size() = terms.size() = 2, called when term_coeff[0] * terms[0] = term_coeff[1] * terms[1], terms are eligible, and at least one of these terms contains pv
+ virtual bool hasProcessEquality( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) { return false; }
+ virtual bool processEquality( CegInstantiator * ci, SolvedForm& sf, Node pv, std::vector< Node >& term_coeffs, std::vector< Node >& terms, unsigned effort ) { return false; }
+
+ //called when assertion lit holds. note that lit is unsubstituted, first must substitute/solve/check eligible
+ virtual bool hasProcessAssertion( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) { return false; }
+ virtual bool processAssertion( CegInstantiator * ci, SolvedForm& sf, Node pv, Node lit, unsigned effort ) { return false; }
+ virtual bool processAssertions( CegInstantiator * ci, SolvedForm& sf, Node pv, std::vector< Node >& lits, unsigned effort ) { return false; }
+
+ //do we allow instantiation for the model value of pv
+ virtual bool useModelValue( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) { return false; }
+ virtual bool allowModelValue( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) { return d_closed_enum_type; }
+
+ //do we need to postprocess the solved form? did we successfully postprocess
+ virtual bool needsPostProcessInstantiation( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) { return false; }
+ virtual bool postProcessInstantiation( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) { return true; }
+
+ /** Identify this module (for debugging) */
+ virtual std::string identify() const { return "Default"; }
+};
+
+class ModelValueInstantiator : public Instantiator {
+public:
+ ModelValueInstantiator( QuantifiersEngine * qe, TypeNode tn ) : Instantiator( qe, tn ){}
+ virtual ~ModelValueInstantiator(){}
+ bool useModelValue( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) { return true; }
+ std::string identify() const { return "ModelValue"; }
+};
+
+
}
}
}
diff --git a/src/theory/quantifiers/ceg_t_instantiator.cpp b/src/theory/quantifiers/ceg_t_instantiator.cpp
new file mode 100644
index 000000000..3282872d6
--- /dev/null
+++ b/src/theory/quantifiers/ceg_t_instantiator.cpp
@@ -0,0 +1,868 @@
+/********************* */
+/*! \file ceg_t_instantiator.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Implementation of theory-specific counterexample-guided quantifier instantiation
+ **/
+
+#include "theory/quantifiers/ceg_t_instantiator.h"
+
+#include "options/quantifiers_options.h"
+#include "theory/quantifiers/first_order_model.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/quantifiers_rewriter.h"
+#include "theory/quantifiers/trigger.h"
+
+#include "theory/arith/partial_model.h"
+#include "theory/arith/theory_arith.h"
+#include "theory/arith/theory_arith_private.h"
+#include "theory/bv/theory_bv_utils.h"
+#include "util/bitvector.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+
+Node ArithInstantiator::getModelBasedProjectionValue( CegInstantiator * ci, Node e, Node t, bool isLower, Node c, Node me, Node mt, Node theta, Node inf_coeff, Node delta_coeff ) {
+ Node val = t;
+ Trace("cbqi-bound2") << "Value : " << val << std::endl;
+ Assert( !e.getType().isInteger() || t.getType().isInteger() );
+ Assert( !e.getType().isInteger() || mt.getType().isInteger() );
+ //add rho value
+ //get the value of c*e
+ Node ceValue = me;
+ Node new_theta = theta;
+ if( !c.isNull() ){
+ Assert( c.getType().isInteger() );
+ ceValue = NodeManager::currentNM()->mkNode( MULT, ceValue, c );
+ ceValue = Rewriter::rewrite( ceValue );
+ if( new_theta.isNull() ){
+ new_theta = c;
+ }else{
+ new_theta = NodeManager::currentNM()->mkNode( MULT, new_theta, c );
+ new_theta = Rewriter::rewrite( new_theta );
+ }
+ Trace("cbqi-bound2") << "...c*e = " << ceValue << std::endl;
+ Trace("cbqi-bound2") << "...theta = " << new_theta << std::endl;
+ }
+ if( !new_theta.isNull() && e.getType().isInteger() ){
+ Node rho;
+ //if( !mt.getType().isInteger() ){
+ //round up/down
+ //mt = NodeManager::currentNM()->mkNode(
+ //}
+ if( isLower ){
+ rho = NodeManager::currentNM()->mkNode( MINUS, ceValue, mt );
+ }else{
+ rho = NodeManager::currentNM()->mkNode( MINUS, mt, ceValue );
+ }
+ rho = Rewriter::rewrite( rho );
+ Trace("cbqi-bound2") << "...rho = " << me << " - " << mt << " = " << rho << std::endl;
+ Trace("cbqi-bound2") << "..." << rho << " mod " << new_theta << " = ";
+ rho = NodeManager::currentNM()->mkNode( INTS_MODULUS_TOTAL, rho, new_theta );
+ rho = Rewriter::rewrite( rho );
+ Trace("cbqi-bound2") << rho << std::endl;
+ Kind rk = isLower ? PLUS : MINUS;
+ val = NodeManager::currentNM()->mkNode( rk, val, rho );
+ val = Rewriter::rewrite( val );
+ Trace("cbqi-bound2") << "(after rho) : " << val << std::endl;
+ }
+ if( !inf_coeff.isNull() ){
+ Assert( !d_vts_sym[0].isNull() );
+ val = NodeManager::currentNM()->mkNode( PLUS, val, NodeManager::currentNM()->mkNode( MULT, inf_coeff, d_vts_sym[0] ) );
+ val = Rewriter::rewrite( val );
+ }
+ if( !delta_coeff.isNull() ){
+ //create delta here if necessary
+ val = NodeManager::currentNM()->mkNode( PLUS, val, NodeManager::currentNM()->mkNode( MULT, delta_coeff, ci->getQuantifiersEngine()->getTermDatabase()->getVtsDelta() ) );
+ val = Rewriter::rewrite( val );
+ }
+ return val;
+}
+
+//this isolates the atom into solved form
+// veq_c * pv <> val + vts_coeff_delta * delta + vts_coeff_inf * inf
+// ensures val is Int if pv is Int, and val does not contain vts symbols
+int ArithInstantiator::solve_arith( CegInstantiator * ci, Node pv, Node atom, Node& veq_c, Node& val, Node& vts_coeff_inf, Node& vts_coeff_delta ) {
+ int ires = 0;
+ Trace("cbqi-inst-debug") << "isolate for " << pv << " in " << atom << std::endl;
+ std::map< Node, Node > msum;
+ if( QuantArith::getMonomialSumLit( atom, msum ) ){
+ Trace("cbqi-inst-debug") << "got monomial sum: " << std::endl;
+ if( Trace.isOn("cbqi-inst-debug") ){
+ QuantArith::debugPrintMonomialSum( msum, "cbqi-inst-debug" );
+ }
+ TypeNode pvtn = pv.getType();
+ //remove vts symbols from polynomial
+ Node vts_coeff[2];
+ for( unsigned t=0; t<2; t++ ){
+ if( !d_vts_sym[t].isNull() ){
+ std::map< Node, Node >::iterator itminf = msum.find( d_vts_sym[t] );
+ if( itminf!=msum.end() ){
+ vts_coeff[t] = itminf->second;
+ if( vts_coeff[t].isNull() ){
+ vts_coeff[t] = NodeManager::currentNM()->mkConst( Rational( 1 ) );
+ }
+ //negate if coefficient on variable is positive
+ std::map< Node, Node >::iterator itv = msum.find( pv );
+ if( itv!=msum.end() ){
+ //multiply by the coefficient we will isolate for
+ if( itv->second.isNull() ){
+ vts_coeff[t] = QuantArith::negate(vts_coeff[t]);
+ }else{
+ if( !pvtn.isInteger() ){
+ vts_coeff[t] = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkConst( Rational(-1) / itv->second.getConst<Rational>() ), vts_coeff[t] );
+ vts_coeff[t] = Rewriter::rewrite( vts_coeff[t] );
+ }else if( itv->second.getConst<Rational>().sgn()==1 ){
+ vts_coeff[t] = QuantArith::negate(vts_coeff[t]);
+ }
+ }
+ }
+ Trace("cbqi-inst-debug") << "vts[" << t << "] coefficient is " << vts_coeff[t] << std::endl;
+ msum.erase( d_vts_sym[t] );
+ }
+ }
+ }
+
+ ires = QuantArith::isolate( pv, msum, veq_c, val, atom.getKind() );
+ if( ires!=0 ){
+ Node realPart;
+ if( Trace.isOn("cbqi-inst-debug") ){
+ Trace("cbqi-inst-debug") << "Isolate : ";
+ if( !veq_c.isNull() ){
+ Trace("cbqi-inst-debug") << veq_c << " * ";
+ }
+ Trace("cbqi-inst-debug") << pv << " " << atom.getKind() << " " << val << std::endl;
+ }
+ if( options::cbqiAll() ){
+ // when not pure LIA/LRA, we must check whether the lhs contains pv
+ if( TermDb::containsTerm( val, pv ) ){
+ Trace("cbqi-inst-debug") << "fail : contains bad term" << std::endl;
+ return 0;
+ }
+ }
+ if( pvtn.isInteger() && ( ( !veq_c.isNull() && !veq_c.getType().isInteger() ) || !val.getType().isInteger() ) ){
+ //redo, split integer/non-integer parts
+ bool useCoeff = false;
+ Integer coeff = ci->getQuantifiersEngine()->getTermDatabase()->d_one.getConst<Rational>().getNumerator();
+ for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){
+ if( it->first.isNull() || it->first.getType().isInteger() ){
+ if( !it->second.isNull() ){
+ coeff = coeff.lcm( it->second.getConst<Rational>().getDenominator() );
+ useCoeff = true;
+ }
+ }
+ }
+ //multiply everything by this coefficient
+ Node rcoeff = NodeManager::currentNM()->mkConst( Rational( coeff ) );
+ std::vector< Node > real_part;
+ for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){
+ if( useCoeff ){
+ if( it->second.isNull() ){
+ msum[it->first] = rcoeff;
+ }else{
+ msum[it->first] = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MULT, it->second, rcoeff ) );
+ }
+ }
+ if( !it->first.isNull() && !it->first.getType().isInteger() ){
+ real_part.push_back( msum[it->first].isNull() ? it->first : NodeManager::currentNM()->mkNode( MULT, msum[it->first], it->first ) );
+ }
+ }
+ //remove delta TODO: check this
+ vts_coeff[1] = Node::null();
+ //multiply inf
+ if( !vts_coeff[0].isNull() ){
+ vts_coeff[0] = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MULT, rcoeff, vts_coeff[0] ) );
+ }
+ realPart = real_part.empty() ? ci->getQuantifiersEngine()->getTermDatabase()->d_zero : ( real_part.size()==1 ? real_part[0] : NodeManager::currentNM()->mkNode( PLUS, real_part ) );
+ Assert( ci->getOutput()->isEligibleForInstantiation( realPart ) );
+ //re-isolate
+ Trace("cbqi-inst-debug") << "Re-isolate..." << std::endl;
+ ires = QuantArith::isolate( pv, msum, veq_c, val, atom.getKind() );
+ Trace("cbqi-inst-debug") << "Isolate for mixed Int/Real : " << veq_c << " * " << pv << " " << atom.getKind() << " " << val << std::endl;
+ Trace("cbqi-inst-debug") << " real part : " << realPart << std::endl;
+ if( ires!=0 ){
+ int ires_use = ( msum[pv].isNull() || msum[pv].getConst<Rational>().sgn()==1 ) ? 1 : -1;
+ val = Rewriter::rewrite( NodeManager::currentNM()->mkNode( ires_use==-1 ? PLUS : MINUS,
+ NodeManager::currentNM()->mkNode( ires_use==-1 ? MINUS : PLUS, val, realPart ),
+ NodeManager::currentNM()->mkNode( TO_INTEGER, realPart ) ) ); //TODO: round up for upper bounds?
+ Trace("cbqi-inst-debug") << "result : " << val << std::endl;
+ Assert( val.getType().isInteger() );
+ }
+ }
+ }
+ vts_coeff_inf = vts_coeff[0];
+ vts_coeff_delta = vts_coeff[1];
+ Trace("cbqi-inst-debug") << "Return " << veq_c << " * " << pv << " " << atom.getKind() << " " << val << ", vts = (" << vts_coeff_inf << ", " << vts_coeff_delta << ")" << std::endl;
+ }else{
+ Trace("cbqi-inst-debug") << "fail : could not get monomial sum" << std::endl;
+ }
+ return ires;
+}
+
+void ArithInstantiator::reset( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) {
+ d_vts_sym[0] = ci->getQuantifiersEngine()->getTermDatabase()->getVtsInfinity( d_type, false, false );
+ d_vts_sym[1] = ci->getQuantifiersEngine()->getTermDatabase()->getVtsDelta( false, false );
+ for( unsigned i=0; i<2; i++ ){
+ d_mbp_bounds[i].clear();
+ d_mbp_coeff[i].clear();
+ for( unsigned j=0; j<2; j++ ){
+ d_mbp_vts_coeff[i][j].clear();
+ }
+ d_mbp_lit[i].clear();
+ }
+}
+
+bool ArithInstantiator::processEquality( CegInstantiator * ci, SolvedForm& sf, Node pv, std::vector< Node >& term_coeffs, std::vector< Node >& terms, unsigned effort ) {
+ Node eq_lhs = terms[0];
+ Node eq_rhs = terms[1];
+ Node lhs_coeff = term_coeffs[0];
+ Node rhs_coeff = term_coeffs[1];
+ //make the same coefficient
+ if( rhs_coeff!=lhs_coeff ){
+ if( !rhs_coeff.isNull() ){
+ Trace("cbqi-inst-debug") << "...mult lhs by " << rhs_coeff << std::endl;
+ eq_lhs = NodeManager::currentNM()->mkNode( MULT, rhs_coeff, eq_lhs );
+ eq_lhs = Rewriter::rewrite( eq_lhs );
+ }
+ if( !lhs_coeff.isNull() ){
+ Trace("cbqi-inst-debug") << "...mult rhs by " << lhs_coeff << std::endl;
+ eq_rhs = NodeManager::currentNM()->mkNode( MULT, lhs_coeff, eq_rhs );
+ eq_rhs = Rewriter::rewrite( eq_rhs );
+ }
+ }
+ Node eq = eq_lhs.eqNode( eq_rhs );
+ eq = Rewriter::rewrite( eq );
+ Node val;
+ Node veq_c;
+ Node vts_coeff_inf;
+ Node vts_coeff_delta;
+ //isolate pv in the equality
+ int ires = solve_arith( ci, pv, eq, veq_c, val, vts_coeff_inf, vts_coeff_delta );
+ if( ires!=0 ){
+ if( ci->doAddInstantiationInc( pv, val, veq_c, 0, sf, effort ) ){
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ArithInstantiator::processAssertion( CegInstantiator * ci, SolvedForm& sf, Node pv, Node lit, unsigned effort ) {
+ Trace("cbqi-inst-debug2") << " look at " << lit << std::endl;
+ Node atom = lit.getKind()==NOT ? lit[0] : lit;
+ bool pol = lit.getKind()!=NOT;
+ //arithmetic inequalities and disequalities
+ if( atom.getKind()==GEQ || ( atom.getKind()==EQUAL && !pol && atom[0].getType().isReal() ) ){
+ Assert( atom.getKind()!=GEQ || atom[1].isConst() );
+ Node atom_lhs;
+ Node atom_rhs;
+ if( atom.getKind()==GEQ ){
+ atom_lhs = atom[0];
+ atom_rhs = atom[1];
+ }else{
+ atom_lhs = NodeManager::currentNM()->mkNode( MINUS, atom[0], atom[1] );
+ atom_lhs = Rewriter::rewrite( atom_lhs );
+ atom_rhs = ci->getQuantifiersEngine()->getTermDatabase()->d_zero;
+ }
+ //must be an eligible term
+ if( ci->isEligible( atom_lhs ) ){
+ //apply substitution to LHS of atom
+ Node atom_lhs_coeff;
+ atom_lhs = ci->applySubstitution( d_type, atom_lhs, sf, atom_lhs_coeff );
+ if( !atom_lhs.isNull() ){
+ if( !atom_lhs_coeff.isNull() ){
+ atom_rhs = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MULT, atom_lhs_coeff, atom_rhs ) );
+ }
+ }
+ //if it contains pv, not infinity
+ if( !atom_lhs.isNull() && ci->hasVariable( atom_lhs, pv ) ){
+ Node pv_value = ci->getModelValue( pv );
+ Node satom = NodeManager::currentNM()->mkNode( atom.getKind(), atom_lhs, atom_rhs );
+ //cannot contain infinity?
+ Trace("cbqi-inst-debug") << "..[3] From assertion : " << atom << ", pol = " << pol << std::endl;
+ Trace("cbqi-inst-debug") << " substituted : " << satom << ", pol = " << pol << std::endl;
+ Node vts_coeff_inf;
+ Node vts_coeff_delta;
+ Node val;
+ Node veq_c;
+ //isolate pv in the inequality
+ int ires = solve_arith( ci, pv, satom, veq_c, val, vts_coeff_inf, vts_coeff_delta );
+ if( ires!=0 ){
+ //disequalities are either strict upper or lower bounds
+ unsigned rmax = ( atom.getKind()==GEQ || options::cbqiModel() ) ? 1 : 2;
+ for( unsigned r=0; r<rmax; r++ ){
+ int uires = ires;
+ Node uval = val;
+ if( atom.getKind()==GEQ ){
+ //push negation downwards
+ if( !pol ){
+ uires = -ires;
+ if( d_type.isInteger() ){
+ uval = NodeManager::currentNM()->mkNode( PLUS, val, NodeManager::currentNM()->mkConst( Rational( uires ) ) );
+ uval = Rewriter::rewrite( uval );
+ }else{
+ Assert( d_type.isReal() );
+ //now is strict inequality
+ uires = uires*2;
+ }
+ }
+ }else{
+ bool is_upper;
+ if( options::cbqiModel() ){
+ // disequality is a disjunction : only consider the bound in the direction of the model
+ //first check if there is an infinity...
+ if( !vts_coeff_inf.isNull() ){
+ //coefficient or val won't make a difference, just compare with zero
+ Trace("cbqi-inst-debug") << "Disequality : check infinity polarity " << vts_coeff_inf << std::endl;
+ Assert( vts_coeff_inf.isConst() );
+ is_upper = ( vts_coeff_inf.getConst<Rational>().sgn()==1 );
+ }else{
+ Node rhs_value = ci->getModelValue( val );
+ Node lhs_value = pv_value;
+ if( !veq_c.isNull() ){
+ lhs_value = NodeManager::currentNM()->mkNode( MULT, lhs_value, veq_c );
+ lhs_value = Rewriter::rewrite( lhs_value );
+ }
+ Trace("cbqi-inst-debug") << "Disequality : check model values " << lhs_value << " " << rhs_value << std::endl;
+ Assert( lhs_value!=rhs_value );
+ Node cmp = NodeManager::currentNM()->mkNode( GEQ, lhs_value, rhs_value );
+ cmp = Rewriter::rewrite( cmp );
+ Assert( cmp.isConst() );
+ is_upper = ( cmp!=ci->getQuantifiersEngine()->getTermDatabase()->d_true );
+ }
+ }else{
+ is_upper = (r==0);
+ }
+ Assert( atom.getKind()==EQUAL && !pol );
+ if( d_type.isInteger() ){
+ uires = is_upper ? -1 : 1;
+ uval = NodeManager::currentNM()->mkNode( PLUS, val, NodeManager::currentNM()->mkConst( Rational( uires ) ) );
+ uval = Rewriter::rewrite( uval );
+ }else{
+ Assert( d_type.isReal() );
+ uires = is_upper ? -2 : 2;
+ }
+ }
+ Trace("cbqi-bound-inf") << "From " << lit << ", got : ";
+ if( !veq_c.isNull() ){
+ Trace("cbqi-bound-inf") << veq_c << " * ";
+ }
+ Trace("cbqi-bound-inf") << pv << " -> " << uval << ", styp = " << uires << std::endl;
+ //take into account delta
+ if( ci->useVtsDelta() && ( uires==2 || uires==-2 ) ){
+ if( options::cbqiModel() ){
+ Node delta_coeff = NodeManager::currentNM()->mkConst( Rational( uires > 0 ? 1 : -1 ) );
+ if( vts_coeff_delta.isNull() ){
+ vts_coeff_delta = delta_coeff;
+ }else{
+ vts_coeff_delta = NodeManager::currentNM()->mkNode( PLUS, vts_coeff_delta, delta_coeff );
+ vts_coeff_delta = Rewriter::rewrite( vts_coeff_delta );
+ }
+ }else{
+ Node delta = ci->getQuantifiersEngine()->getTermDatabase()->getVtsDelta();
+ uval = NodeManager::currentNM()->mkNode( uires==2 ? PLUS : MINUS, uval, delta );
+ uval = Rewriter::rewrite( uval );
+ }
+ }
+ if( options::cbqiModel() ){
+ //just store bounds, will choose based on tighest bound
+ unsigned index = uires>0 ? 0 : 1;
+ d_mbp_bounds[index].push_back( uval );
+ d_mbp_coeff[index].push_back( veq_c );
+ Trace("cbqi-inst-debug") << "Store bound " << index << " " << uval << " " << veq_c << " " << vts_coeff_inf << " " << vts_coeff_delta << " " << lit << std::endl;
+ for( unsigned t=0; t<2; t++ ){
+ d_mbp_vts_coeff[index][t].push_back( t==0 ? vts_coeff_inf : vts_coeff_delta );
+ }
+ d_mbp_lit[index].push_back( lit );
+ }else{
+ //try this bound
+ if( ci->doAddInstantiationInc( pv, uval, veq_c, uires>0 ? 1 : -1, sf, effort ) ){
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ return false;
+}
+
+bool ArithInstantiator::processAssertions( CegInstantiator * ci, SolvedForm& sf, Node pv, std::vector< Node >& lits, unsigned effort ) {
+ if( options::cbqiModel() ){
+ bool use_inf = ci->useVtsInfinity() && ( d_type.isInteger() ? options::cbqiUseInfInt() : options::cbqiUseInfReal() );
+ bool upper_first = false;
+ if( options::cbqiMinBounds() ){
+ upper_first = d_mbp_bounds[1].size()<d_mbp_bounds[0].size();
+ }
+ int best_used[2];
+ std::vector< Node > t_values[3];
+ Node zero = ci->getQuantifiersEngine()->getTermDatabase()->d_zero;
+ Node one = ci->getQuantifiersEngine()->getTermDatabase()->d_one;
+ Node pv_value = ci->getModelValue( pv );
+ //try optimal bounds
+ for( unsigned r=0; r<2; r++ ){
+ int rr = upper_first ? (1-r) : r;
+ best_used[rr] = -1;
+ if( d_mbp_bounds[rr].empty() ){
+ if( use_inf ){
+ Trace("cbqi-bound") << "No " << ( rr==0 ? "lower" : "upper" ) << " bounds for " << pv << " (type=" << d_type << ")" << std::endl;
+ //no bounds, we do +- infinity
+ Node val = ci->getQuantifiersEngine()->getTermDatabase()->getVtsInfinity( d_type );
+ //TODO : rho value for infinity?
+ if( rr==0 ){
+ val = NodeManager::currentNM()->mkNode( UMINUS, val );
+ val = Rewriter::rewrite( val );
+ }
+ if( ci->doAddInstantiationInc( pv, val, Node::null(), 0, sf, effort ) ){
+ return true;
+ }
+ }
+ }else{
+ Trace("cbqi-bound") << ( rr==0 ? "Lower" : "Upper" ) << " bounds for " << pv << " (type=" << d_type << ") : " << std::endl;
+ int best = -1;
+ Node best_bound_value[3];
+ for( unsigned j=0; j<d_mbp_bounds[rr].size(); j++ ){
+ Node value[3];
+ if( Trace.isOn("cbqi-bound") ){
+ Assert( !d_mbp_bounds[rr][j].isNull() );
+ Trace("cbqi-bound") << " " << j << ": " << d_mbp_bounds[rr][j];
+ if( !d_mbp_vts_coeff[rr][0][j].isNull() ){
+ Trace("cbqi-bound") << " (+ " << d_mbp_vts_coeff[rr][0][j] << " * INF)";
+ }
+ if( !d_mbp_vts_coeff[rr][1][j].isNull() ){
+ Trace("cbqi-bound") << " (+ " << d_mbp_vts_coeff[rr][1][j] << " * DELTA)";
+ }
+ if( !d_mbp_coeff[rr][j].isNull() ){
+ Trace("cbqi-bound") << " (div " << d_mbp_coeff[rr][j] << ")";
+ }
+ Trace("cbqi-bound") << ", value = ";
+ }
+ t_values[rr].push_back( Node::null() );
+ //check if it is better than the current best bound : lexicographic order infinite/finite/infinitesimal parts
+ bool new_best = true;
+ for( unsigned t=0; t<3; t++ ){
+ //get the value
+ if( t==0 ){
+ value[0] = d_mbp_vts_coeff[rr][0][j];
+ if( !value[0].isNull() ){
+ Trace("cbqi-bound") << "( " << value[0] << " * INF ) + ";
+ }else{
+ value[0] = zero;
+ }
+ }else if( t==1 ){
+ Node t_value = ci->getModelValue( d_mbp_bounds[rr][j] );
+ t_values[rr][j] = t_value;
+ value[1] = t_value;
+ Trace("cbqi-bound") << value[1];
+ }else{
+ value[2] = d_mbp_vts_coeff[rr][1][j];
+ if( !value[2].isNull() ){
+ Trace("cbqi-bound") << " + ( " << value[2] << " * DELTA )";
+ }else{
+ value[2] = zero;
+ }
+ }
+ //multiply by coefficient
+ if( value[t]!=zero && !d_mbp_coeff[rr][j].isNull() ){
+ Assert( d_mbp_coeff[rr][j].isConst() );
+ value[t] = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkConst( Rational(1) / d_mbp_coeff[rr][j].getConst<Rational>() ), value[t] );
+ value[t] = Rewriter::rewrite( value[t] );
+ }
+ //check if new best
+ if( best!=-1 ){
+ Assert( !value[t].isNull() && !best_bound_value[t].isNull() );
+ if( value[t]!=best_bound_value[t] ){
+ Kind k = rr==0 ? GEQ : LEQ;
+ Node cmp_bound = NodeManager::currentNM()->mkNode( k, value[t], best_bound_value[t] );
+ cmp_bound = Rewriter::rewrite( cmp_bound );
+ if( cmp_bound!=ci->getQuantifiersEngine()->getTermDatabase()->d_true ){
+ new_best = false;
+ break;
+ }
+ }
+ }
+ }
+ Trace("cbqi-bound") << std::endl;
+ if( new_best ){
+ for( unsigned t=0; t<3; t++ ){
+ best_bound_value[t] = value[t];
+ }
+ best = j;
+ }
+ }
+ if( best!=-1 ){
+ Trace("cbqi-bound") << "...best bound is " << best << " : ";
+ if( best_bound_value[0]!=zero ){
+ Trace("cbqi-bound") << "( " << best_bound_value[0] << " * INF ) + ";
+ }
+ Trace("cbqi-bound") << best_bound_value[1];
+ if( best_bound_value[2]!=zero ){
+ Trace("cbqi-bound") << " + ( " << best_bound_value[2] << " * DELTA )";
+ }
+ Trace("cbqi-bound") << std::endl;
+ best_used[rr] = best;
+ //if using cbqiMidpoint, only add the instance based on one bound if the bound is non-strict
+ if( !options::cbqiMidpoint() || d_type.isInteger() || d_mbp_vts_coeff[rr][1][best].isNull() ){
+ Node val = d_mbp_bounds[rr][best];
+ val = getModelBasedProjectionValue( ci, pv, val, rr==0, d_mbp_coeff[rr][best], pv_value, t_values[rr][best], sf.d_theta,
+ d_mbp_vts_coeff[rr][0][best], d_mbp_vts_coeff[rr][1][best] );
+ if( !val.isNull() ){
+ if( ci->doAddInstantiationInc( pv, val, d_mbp_coeff[rr][best], rr==0 ? 1 : -1, sf, effort ) ){
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ //if not using infinity, use model value of zero
+ if( !use_inf && d_mbp_bounds[0].empty() && d_mbp_bounds[1].empty() ){
+ Node val = zero;
+ Node c; //null (one) coefficient
+ val = getModelBasedProjectionValue( ci, pv, val, true, c, pv_value, zero, sf.d_theta, Node::null(), Node::null() );
+ if( !val.isNull() ){
+ if( ci->doAddInstantiationInc( pv, val, c, 0, sf, effort ) ){
+ return true;
+ }
+ }
+ }
+ if( options::cbqiMidpoint() && !d_type.isInteger() ){
+ Node vals[2];
+ bool bothBounds = true;
+ Trace("cbqi-bound") << "Try midpoint of bounds..." << std::endl;
+ for( unsigned rr=0; rr<2; rr++ ){
+ int best = best_used[rr];
+ if( best==-1 ){
+ bothBounds = false;
+ }else{
+ vals[rr] = d_mbp_bounds[rr][best];
+ vals[rr] = getModelBasedProjectionValue( ci, pv, vals[rr], rr==0, Node::null(), pv_value, t_values[rr][best], sf.d_theta,
+ d_mbp_vts_coeff[rr][0][best], Node::null() );
+ }
+ Trace("cbqi-bound") << "Bound : " << vals[rr] << std::endl;
+ }
+ Node val;
+ if( bothBounds ){
+ Assert( !vals[0].isNull() && !vals[1].isNull() );
+ if( vals[0]==vals[1] ){
+ val = vals[0];
+ }else{
+ val = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkNode( PLUS, vals[0], vals[1] ),
+ NodeManager::currentNM()->mkConst( Rational(1)/Rational(2) ) );
+ val = Rewriter::rewrite( val );
+ }
+ }else{
+ if( !vals[0].isNull() ){
+ val = NodeManager::currentNM()->mkNode( PLUS, vals[0], one );
+ val = Rewriter::rewrite( val );
+ }else if( !vals[1].isNull() ){
+ val = NodeManager::currentNM()->mkNode( MINUS, vals[1], one );
+ val = Rewriter::rewrite( val );
+ }
+ }
+ Trace("cbqi-bound") << "Midpoint value : " << val << std::endl;
+ if( !val.isNull() ){
+ if( ci->doAddInstantiationInc( pv, val, Node::null(), 0, sf, effort ) ){
+ return true;
+ }
+ }
+ }
+ //generally should not make it to this point FIXME: write proper assertion
+ //Assert( ( ci->hasNestedQuantification() && !options::cbqiNestedQE() ) || options::cbqiAll() );
+
+ if( options::cbqiNopt() ){
+ //try non-optimal bounds (heuristic, may help when nested quantification) ?
+ Trace("cbqi-bound") << "Try non-optimal bounds..." << std::endl;
+ for( unsigned r=0; r<2; r++ ){
+ int rr = upper_first ? (1-r) : r;
+ for( unsigned j=0; j<d_mbp_bounds[rr].size(); j++ ){
+ if( (int)j!=best_used[rr] && ( !options::cbqiMidpoint() || d_mbp_vts_coeff[rr][1][j].isNull() ) ){
+ Node val = getModelBasedProjectionValue( ci, pv, d_mbp_bounds[rr][j], rr==0, d_mbp_coeff[rr][j], pv_value, t_values[rr][j], sf.d_theta,
+ d_mbp_vts_coeff[rr][0][j], d_mbp_vts_coeff[rr][1][j] );
+ if( !val.isNull() ){
+ if( ci->doAddInstantiationInc( pv, val, d_mbp_coeff[rr][j], rr==0 ? 1 : -1, sf, effort ) ){
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool ArithInstantiator::needsPostProcessInstantiation( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) {
+ return std::find( sf.d_has_coeff.begin(), sf.d_has_coeff.end(), pv )!=sf.d_has_coeff.end();
+}
+
+bool ArithInstantiator::postProcessInstantiation( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) {
+ Assert( std::find( sf.d_has_coeff.begin(), sf.d_has_coeff.end(), pv )!=sf.d_has_coeff.end() );
+ Assert( std::find( sf.d_vars.begin(), sf.d_vars.end(), pv )!=sf.d_vars.end() );
+ unsigned index = std::find( sf.d_vars.begin(), sf.d_vars.end(), pv )-sf.d_vars.begin();
+ Assert( !sf.d_coeff[index].isNull() );
+ Trace("cbqi-inst-debug") << "Normalize substitution for " << sf.d_coeff[index] << " * " << sf.d_vars[index] << " = " << sf.d_subs[index] << std::endl;
+ Assert( sf.d_vars[index].getType().isInteger() );
+ //must ensure that divisibility constraints are met
+ //solve updated rewritten equality for vars[index], if coefficient is one, then we are successful
+ Node eq_lhs = NodeManager::currentNM()->mkNode( MULT, sf.d_coeff[index], sf.d_vars[index] );
+ Node eq_rhs = sf.d_subs[index];
+ Node eq = eq_lhs.eqNode( eq_rhs );
+ eq = Rewriter::rewrite( eq );
+ Trace("cbqi-inst-debug") << "...equality is " << eq << std::endl;
+ std::map< Node, Node > msum;
+ if( QuantArith::getMonomialSumLit( eq, msum ) ){
+ Node veq;
+ if( QuantArith::isolate( sf.d_vars[index], msum, veq, EQUAL, true )!=0 ){
+ Node veq_c;
+ if( veq[0]!=sf.d_vars[index] ){
+ Node veq_v;
+ if( QuantArith::getMonomial( veq[0], veq_c, veq_v ) ){
+ Assert( veq_v==sf.d_vars[index] );
+ }
+ }
+ sf.d_subs[index] = veq[1];
+ if( !veq_c.isNull() ){
+ sf.d_subs[index] = NodeManager::currentNM()->mkNode( INTS_DIVISION_TOTAL, veq[1], veq_c );
+ Trace("cbqi-inst-debug") << "...bound type is : " << sf.d_btyp[index] << std::endl;
+ //intger division rounding up if from a lower bound
+ if( sf.d_btyp[index]==1 && options::cbqiRoundUpLowerLia() ){
+ sf.d_subs[index] = NodeManager::currentNM()->mkNode( PLUS, sf.d_subs[index],
+ NodeManager::currentNM()->mkNode( ITE,
+ NodeManager::currentNM()->mkNode( EQUAL,
+ NodeManager::currentNM()->mkNode( INTS_MODULUS_TOTAL, veq[1], veq_c ),
+ ci->getQuantifiersEngine()->getTermDatabase()->d_zero ),
+ ci->getQuantifiersEngine()->getTermDatabase()->d_zero, ci->getQuantifiersEngine()->getTermDatabase()->d_one )
+ );
+ }
+ }
+ Trace("cbqi-inst-debug") << "...normalize integers : " << sf.d_vars[index] << " -> " << sf.d_subs[index] << std::endl;
+ }else{
+ Trace("cbqi-inst-debug") << "...failed to isolate." << std::endl;
+ return false;
+ }
+ }else{
+ Trace("cbqi-inst-debug") << "...failed to get monomial sum." << std::endl;
+ return false;
+ }
+ return true;
+}
+
+void DtInstantiator::reset( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) {
+
+}
+
+Node DtInstantiator::solve_dt( Node v, Node a, Node b, Node sa, Node sb ) {
+ Trace("cbqi-inst-debug2") << "Solve dt : " << v << " " << a << " " << b << " " << sa << " " << sb << std::endl;
+ Node ret;
+ if( !a.isNull() && a==v ){
+ ret = sb;
+ }else if( !b.isNull() && b==v ){
+ ret = sa;
+ }else if( !a.isNull() && a.getKind()==APPLY_CONSTRUCTOR ){
+ if( !b.isNull() && b.getKind()==APPLY_CONSTRUCTOR ){
+ if( a.getOperator()==b.getOperator() ){
+ for( unsigned i=0; i<a.getNumChildren(); i++ ){
+ Node s = solve_dt( v, a[i], b[i], sa[i], sb[i] );
+ if( !s.isNull() ){
+ return s;
+ }
+ }
+ }
+ }else{
+ unsigned cindex = Datatype::indexOf( a.getOperator().toExpr() );
+ TypeNode tn = a.getType();
+ const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ for( unsigned i=0; i<a.getNumChildren(); i++ ){
+ Node nn = NodeManager::currentNM()->mkNode( APPLY_SELECTOR_TOTAL, Node::fromExpr( dt[cindex][i].getSelector() ), sb );
+ Node s = solve_dt( v, a[i], Node::null(), sa[i], nn );
+ if( !s.isNull() ){
+ return s;
+ }
+ }
+ }
+ }else if( !b.isNull() && b.getKind()==APPLY_CONSTRUCTOR ){
+ return solve_dt( v, b, a, sb, sa );
+ }
+ if( !ret.isNull() ){
+ //ensure does not contain
+ if( TermDb::containsTerm( ret, v ) ){
+ ret = Node::null();
+ }
+ }
+ return ret;
+}
+
+bool DtInstantiator::processEqualTerms( CegInstantiator * ci, SolvedForm& sf, Node pv, std::vector< Node >& eqc, unsigned effort ) {
+ Trace("cbqi-inst-debug") << "[2] try based on constructors in equivalence class." << std::endl;
+ //[2] look in equivalence class for a constructor
+ for( unsigned k=0; k<eqc.size(); k++ ){
+ Node n = eqc[k];
+ if( n.getKind()==APPLY_CONSTRUCTOR ){
+ Trace("cbqi-inst-debug") << "...try based on constructor term " << n << std::endl;
+ std::vector< Node > children;
+ children.push_back( n.getOperator() );
+ const Datatype& dt = ((DatatypeType)(d_type).toType()).getDatatype();
+ unsigned cindex = Datatype::indexOf( n.getOperator().toExpr() );
+ //now must solve for selectors applied to pv
+ for( unsigned j=0; j<dt[cindex].getNumArgs(); j++ ){
+ Node c = NodeManager::currentNM()->mkNode( APPLY_SELECTOR_TOTAL, Node::fromExpr( dt[cindex][j].getSelector() ), pv );
+ ci->pushStackVariable( c );
+ children.push_back( c );
+ }
+ Node val = NodeManager::currentNM()->mkNode( kind::APPLY_CONSTRUCTOR, children );
+ if( ci->doAddInstantiationInc( pv, val, Node::null(), 0, sf, effort ) ){
+ return true;
+ }else{
+ //cleanup
+ for( unsigned j=0; j<dt[cindex].getNumArgs(); j++ ){
+ ci->popStackVariable();
+ }
+ break;
+ }
+ }
+ }
+ return false;
+}
+
+bool DtInstantiator::processEquality( CegInstantiator * ci, SolvedForm& sf, Node pv, std::vector< Node >& term_coeffs, std::vector< Node >& terms, unsigned effort ) {
+ Node val = solve_dt( pv, terms[0], terms[1], terms[0], terms[1] );
+ if( !val.isNull() ){
+ Node veq_c;
+ if( ci->doAddInstantiationInc( pv, val, veq_c, 0, sf, effort ) ){
+ return true;
+ }
+ }
+ return false;
+}
+
+void EprInstantiator::reset( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) {
+ d_equal_terms.clear();
+}
+
+bool EprInstantiator::processEqualTerm( CegInstantiator * ci, SolvedForm& sf, Node pv, Node pv_coeff, Node n, unsigned effort ) {
+ if( options::quantEprMatching() ){
+ Assert( pv_coeff.isNull() );
+ d_equal_terms.push_back( n );
+ return false;
+ }else{
+ return ci->doAddInstantiationInc( pv, n, pv_coeff, 0, sf, effort );
+ }
+}
+
+void EprInstantiator::computeMatchScore( CegInstantiator * ci, Node pv, Node catom, std::vector< Node >& arg_reps, TermArgTrie * tat, unsigned index, std::map< Node, int >& match_score ) {
+ if( index==catom.getNumChildren() ){
+ Assert( tat->hasNodeData() );
+ Node gcatom = tat->getNodeData();
+ Trace("epr-inst") << "Matched : " << catom << " and " << gcatom << std::endl;
+ for( unsigned i=0; i<catom.getNumChildren(); i++ ){
+ if( catom[i]==pv ){
+ Trace("epr-inst") << "...increment " << gcatom[i] << std::endl;
+ match_score[gcatom[i]]++;
+ }else{
+ //recursive matching
+ computeMatchScore( ci, pv, catom[i], gcatom[i], match_score );
+ }
+ }
+ }else{
+ std::map< TNode, TermArgTrie >::iterator it = tat->d_data.find( arg_reps[index] );
+ if( it!=tat->d_data.end() ){
+ computeMatchScore( ci, pv, catom, arg_reps, &it->second, index+1, match_score );
+ }
+ }
+}
+
+void EprInstantiator::computeMatchScore( CegInstantiator * ci, Node pv, Node catom, Node eqc, std::map< Node, int >& match_score ) {
+ if( inst::Trigger::isAtomicTrigger( catom ) && TermDb::containsTerm( catom, pv ) ){
+ Trace("epr-inst") << "Find matches for " << catom << "..." << std::endl;
+ std::vector< Node > arg_reps;
+ for( unsigned j=0; j<catom.getNumChildren(); j++ ){
+ arg_reps.push_back( ci->getQuantifiersEngine()->getMasterEqualityEngine()->getRepresentative( catom[j] ) );
+ }
+ if( ci->getQuantifiersEngine()->getMasterEqualityEngine()->hasTerm( eqc ) ){
+ Node rep = ci->getQuantifiersEngine()->getMasterEqualityEngine()->getRepresentative( eqc );
+ Node op = ci->getQuantifiersEngine()->getTermDatabase()->getMatchOperator( catom );
+ TermArgTrie * tat = ci->getQuantifiersEngine()->getTermDatabase()->getTermArgTrie( rep, op );
+ Trace("epr-inst") << "EPR instantiation match term : " << catom << ", check ground terms=" << (tat!=NULL) << std::endl;
+ if( tat ){
+ computeMatchScore( ci, pv, catom, arg_reps, tat, 0, match_score );
+ }
+ }
+ }
+}
+
+struct sortEqTermsMatch {
+ std::map< Node, int > d_match_score;
+ bool operator() (Node i, Node j) {
+ int match_score_i = d_match_score[i];
+ int match_score_j = d_match_score[j];
+ return match_score_i>match_score_j || ( match_score_i==match_score_j && i<j );
+ }
+};
+
+
+bool EprInstantiator::processEqualTerms( CegInstantiator * ci, SolvedForm& sf, Node pv, std::vector< Node >& eqc, unsigned effort ) {
+ if( options::quantEprMatching() ){
+ //heuristic for best matching constant
+ sortEqTermsMatch setm;
+ for( unsigned i=0; i<ci->getNumCEAtoms(); i++ ){
+ Node catom = ci->getCEAtom( i );
+ computeMatchScore( ci, pv, catom, catom, setm.d_match_score );
+ }
+ //sort by match score
+ std::sort( d_equal_terms.begin(), d_equal_terms.end(), setm );
+ Node pv_coeff;
+ for( unsigned i=0; i<d_equal_terms.size(); i++ ){
+ if( ci->doAddInstantiationInc( pv, d_equal_terms[i], pv_coeff, 0, sf, effort ) ){
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool BvInstantiator::processAssertion( CegInstantiator * ci, SolvedForm& sf, Node pv, Node lit, unsigned effort ) {
+ /* TODO: algebraic reasoning for bitvector instantiation
+ if( atom.getKind()==BITVECTOR_ULT || atom.getKind()==BITVECTOR_ULE ){
+ for( unsigned t=0; t<2; t++ ){
+ if( atom[t]==pv ){
+ computeProgVars( atom[1-t] );
+ if( d_inelig.find( atom[1-t] )==d_inelig.end() ){
+ //only ground terms TODO: more
+ if( d_prog_var[atom[1-t]].empty() ){
+ Node veq_c;
+ Node uval;
+ if( ( !pol && atom.getKind()==BITVECTOR_ULT ) || ( pol && atom.getKind()==BITVECTOR_ULE ) ){
+ uval = atom[1-t];
+ }else{
+ uval = NodeManager::currentNM()->mkNode( (atom.getKind()==BITVECTOR_ULT)==(t==1) ? BITVECTOR_PLUS : BITVECTOR_SUB, atom[1-t],
+ bv::utils::mkConst(pvtn.getConst<BitVectorSize>(), 1) );
+ }
+ if( doAddInstantiationInc( pv, uval, veq_c, 0, sf, effort ) ){
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ */
+
+ return false;
+}
+
+
diff --git a/src/theory/quantifiers/ceg_t_instantiator.h b/src/theory/quantifiers/ceg_t_instantiator.h
new file mode 100644
index 000000000..2df7946d5
--- /dev/null
+++ b/src/theory/quantifiers/ceg_t_instantiator.h
@@ -0,0 +1,93 @@
+/********************* */
+/*! \file ceg_t_instantiator.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief theory-specific counterexample-guided quantifier instantiation
+ **/
+
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__CEG_T_INSTANTIATOR_H
+#define __CVC4__CEG_T_INSTANTIATOR_H
+
+#include "theory/quantifiers/ceg_instantiator.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+class ArithInstantiator : public Instantiator {
+private:
+ Node d_vts_sym[2];
+ std::vector< Node > d_mbp_bounds[2];
+ std::vector< Node > d_mbp_coeff[2];
+ std::vector< Node > d_mbp_vts_coeff[2][2];
+ std::vector< Node > d_mbp_lit[2];
+ int solve_arith( CegInstantiator * ci, Node v, Node atom, Node & veq_c, Node & val, Node& vts_coeff_inf, Node& vts_coeff_delta );
+ Node getModelBasedProjectionValue( CegInstantiator * ci, Node e, Node t, bool isLower, Node c, Node me, Node mt, Node theta, Node inf_coeff, Node delta_coeff );
+public:
+ ArithInstantiator( QuantifiersEngine * qe, TypeNode tn ) : Instantiator( qe, tn ){}
+ virtual ~ArithInstantiator(){}
+ void reset( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort );
+ bool hasProcessEquality( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) { return true; }
+ bool processEquality( CegInstantiator * ci, SolvedForm& sf, Node pv, std::vector< Node >& term_coeffs, std::vector< Node >& terms, unsigned effort );
+ bool hasProcessAssertion( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) { return true; }
+ bool processAssertion( CegInstantiator * ci, SolvedForm& sf, Node pv, Node lit, unsigned effort );
+ bool processAssertions( CegInstantiator * ci, SolvedForm& sf, Node pv, std::vector< Node >& lits, unsigned effort );
+ bool needsPostProcessInstantiation( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort );
+ bool postProcessInstantiation( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort );
+ std::string identify() const { return "Arith"; }
+};
+
+class DtInstantiator : public Instantiator {
+private:
+ Node solve_dt( Node v, Node a, Node b, Node sa, Node sb );
+public:
+ DtInstantiator( QuantifiersEngine * qe, TypeNode tn ) : Instantiator( qe, tn ){}
+ virtual ~DtInstantiator(){}
+ void reset( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort );
+ bool processEqualTerms( CegInstantiator * ci, SolvedForm& sf, Node pv, std::vector< Node >& eqc, unsigned effort );
+ bool hasProcessEquality( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) { return true; }
+ bool processEquality( CegInstantiator * ci, SolvedForm& sf, Node pv, std::vector< Node >& term_coeffs, std::vector< Node >& terms, unsigned effort );
+ std::string identify() const { return "Dt"; }
+};
+
+class TermArgTrie;
+
+class EprInstantiator : public Instantiator {
+private:
+ std::vector< Node > d_equal_terms;
+ void computeMatchScore( CegInstantiator * ci, Node pv, Node catom, std::vector< Node >& arg_reps, TermArgTrie * tat, unsigned index, std::map< Node, int >& match_score );
+ void computeMatchScore( CegInstantiator * ci, Node pv, Node catom, Node eqc, std::map< Node, int >& match_score );
+public:
+ EprInstantiator( QuantifiersEngine * qe, TypeNode tn ) : Instantiator( qe, tn ){}
+ virtual ~EprInstantiator(){}
+ void reset( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort );
+ bool processEqualTerm( CegInstantiator * ci, SolvedForm& sf, Node pv, Node pv_coeff, Node n, unsigned effort );
+ bool processEqualTerms( CegInstantiator * ci, SolvedForm& sf, Node pv, std::vector< Node >& eqc, unsigned effort );
+ std::string identify() const { return "Epr"; }
+};
+
+class BvInstantiator : public Instantiator {
+public:
+ BvInstantiator( QuantifiersEngine * qe, TypeNode tn ) : Instantiator( qe, tn ){}
+ virtual ~BvInstantiator(){}
+ bool processAssertion( CegInstantiator * ci, SolvedForm& sf, Node pv, Node lit, unsigned effort );
+ bool useModelValue( CegInstantiator * ci, SolvedForm& sf, Node pv, unsigned effort ) { return true; }
+ std::string identify() const { return "Bv"; }
+};
+
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/conjecture_generator.cpp b/src/theory/quantifiers/conjecture_generator.cpp
index f4eb67d74..11adc61fd 100755
--- a/src/theory/quantifiers/conjecture_generator.cpp
+++ b/src/theory/quantifiers/conjecture_generator.cpp
@@ -84,6 +84,9 @@ d_notify( *this ),
d_uequalityEngine(d_notify, c, "ConjectureGenerator::ee", false),
d_ee_conjectures( c ){
d_fullEffortCount = 0;
+ d_conj_count = 0;
+ d_subs_confirmCount = 0;
+ d_subs_unkCount = 0;
d_uequalityEngine.addFunctionKind( kind::APPLY_UF );
d_uequalityEngine.addFunctionKind( kind::APPLY_CONSTRUCTOR );
diff --git a/src/theory/quantifiers/full_model_check.cpp b/src/theory/quantifiers/full_model_check.cpp
index be608aeaa..72057e734 100755
--- a/src/theory/quantifiers/full_model_check.cpp
+++ b/src/theory/quantifiers/full_model_check.cpp
@@ -589,7 +589,7 @@ void FullModelChecker::debugPrint(const char * tr, Node n, bool dispStar) {
}
-bool FullModelChecker::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) {
+int FullModelChecker::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) {
Trace("fmc") << "Full model check " << f << ", effort = " << effort << "..." << std::endl;
Assert( !d_qe->inConflict() );
if( optUseModel() ){
@@ -723,15 +723,15 @@ bool FullModelChecker::doExhaustiveInstantiation( FirstOrderModel * fm, Node f,
if( temp.addEntry(fmfmc, d_quant_models[f].d_cond[j], d_quant_models[f].d_value[j] ) ){
if( !exhaustiveInstantiate(fmfmc, f, d_quant_models[f].d_cond[j], j ) ){
//something went wrong, resort to exhaustive instantiation
- return false;
+ return 0;
}
}
}
}
}
- return true;
+ return 1;
}else{
- return false;
+ return 0;
}
}
diff --git a/src/theory/quantifiers/full_model_check.h b/src/theory/quantifiers/full_model_check.h
index 411b7a5eb..7d21b4185 100755
--- a/src/theory/quantifiers/full_model_check.h
+++ b/src/theory/quantifiers/full_model_check.h
@@ -139,7 +139,7 @@ public:
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 doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort );
Node getFunctionValue(FirstOrderModelFmc * fm, Node op, const char* argPrefix );
diff --git a/src/theory/quantifiers/inst_match.cpp b/src/theory/quantifiers/inst_match.cpp
index 7e5424d9c..12e15d353 100755
--- a/src/theory/quantifiers/inst_match.cpp
+++ b/src/theory/quantifiers/inst_match.cpp
@@ -258,7 +258,11 @@ void InstMatchTrie::getInstantiations( std::vector< Node >& insts, Node q, std::
}
}
}else{
- insts.push_back( qe->getInstantiation( q, terms, true ) );
+ if( hasInstLemma() ){
+ insts.push_back( getInstLemma() );
+ }else{
+ insts.push_back( qe->getInstantiation( q, terms, true ) );
+ }
}
}else{
for( std::map< Node, InstMatchTrie >::const_iterator it = d_data.begin(); it != d_data.end(); ++it ){
@@ -428,13 +432,17 @@ void CDInstMatchTrie::getInstantiations( std::vector< Node >& insts, Node q, std
if( terms.size()==q[0].getNumChildren() ){
if( useActive ){
if( hasInstLemma() ){
- Node lem;
+ Node lem = getInstLemma();
if( std::find( active.begin(), active.end(), lem )!=active.end() ){
insts.push_back( lem );
}
}
}else{
- insts.push_back( qe->getInstantiation( q, terms, true ) );
+ if( hasInstLemma() ){
+ insts.push_back( getInstLemma() );
+ }else{
+ insts.push_back( qe->getInstantiation( q, terms, true ) );
+ }
}
}else{
for( std::map< Node, CDInstMatchTrie* >::const_iterator it = d_data.begin(); it != d_data.end(); ++it ){
diff --git a/src/theory/quantifiers/inst_match_generator.cpp b/src/theory/quantifiers/inst_match_generator.cpp
index b3df9ca5d..2a940f1fd 100755
--- a/src/theory/quantifiers/inst_match_generator.cpp
+++ b/src/theory/quantifiers/inst_match_generator.cpp
@@ -388,23 +388,6 @@ int InstMatchGenerator::addInstantiations( Node f, InstMatch& baseMatch, Quantif
return addedLemmas;
}
-int InstMatchGenerator::addTerm( Node f, Node t, QuantifiersEngine* qe ){
- Assert( options::eagerInstQuant() );
- if( !d_match_pattern.isNull() ){
- InstMatch m( f );
- if( getMatch( f, t, m, qe ) ){
- if( qe->addInstantiation( f, m ) ){
- return 1;
- }
- }
- }else{
- for( unsigned i=0; i<d_children.size(); i++ ){
- d_children[i]->addTerm( f, t, qe );
- }
- }
- return 0;
-}
-
InstMatchGenerator* InstMatchGenerator::mkInstMatchGenerator( Node q, Node pat, QuantifiersEngine* qe ) {
std::vector< Node > pats;
@@ -716,22 +699,6 @@ void InstMatchGeneratorMulti::processNewInstantiations2( QuantifiersEngine* qe,
}
}
-int InstMatchGeneratorMulti::addTerm( Node q, Node t, QuantifiersEngine* qe ){
- Assert( options::eagerInstQuant() );
- int addedLemmas = 0;
- for( int i=0; i<(int)d_children.size(); i++ ){
- Node t_op = qe->getTermDatabase()->getMatchOperator( t );
- if( ((InstMatchGenerator*)d_children[i])->d_match_pattern_op==t_op ){
- InstMatch m( q );
- //if it produces a match, then process it with the rest
- if( ((InstMatchGenerator*)d_children[i])->getMatch( q, t, m, qe ) ){
- processNewMatch( qe, m, i, addedLemmas );
- }
- }
- }
- return addedLemmas;
-}
-
InstMatchGeneratorSimple::InstMatchGeneratorSimple( Node q, Node pat, QuantifiersEngine* qe ) : d_f( q ), d_match_pattern( pat ) {
if( d_match_pattern.getKind()==NOT ){
d_match_pattern = d_match_pattern[0];
@@ -774,17 +741,19 @@ int InstMatchGeneratorSimple::addInstantiations( Node q, InstMatch& baseMatch, Q
Node r = qe->getEqualityQuery()->getRepresentative( d_eqc );
//iterate over all classes except r
tat = qe->getTermDatabase()->getTermArgTrie( Node::null(), d_op );
- for( std::map< TNode, quantifiers::TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
- if( it->first!=r ){
- InstMatch m( q );
- m.add( baseMatch );
- addInstantiations( m, qe, addedLemmas, 0, &(it->second) );
- if( qe->inConflict() ){
- break;
+ if( tat ){
+ for( std::map< TNode, quantifiers::TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
+ if( it->first!=r ){
+ InstMatch m( q );
+ m.add( baseMatch );
+ addInstantiations( m, qe, addedLemmas, 0, &(it->second) );
+ if( qe->inConflict() ){
+ break;
+ }
}
}
+ tat = NULL;
}
- tat = NULL;
}
}
Debug("simple-trigger-debug") << "Adding instantiations based on " << tat << " from " << d_op << " " << d_eqc << std::endl;
@@ -841,20 +810,6 @@ void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngin
}
}
-int InstMatchGeneratorSimple::addTerm( Node q, Node t, QuantifiersEngine* qe ){
- //for eager instantiation only
- Assert( options::eagerInstQuant() );
- InstMatch m( q );
- for( unsigned i=0; i<t.getNumChildren(); i++ ){
- if( d_match_pattern[i].getKind()==INST_CONSTANT ){
- m.setValue(d_var_num[i], t[i]);
- }else if( !qe->getEqualityQuery()->areEqual( d_match_pattern[i], t[i] ) ){
- return 0;
- }
- }
- return qe->addInstantiation( q, m ) ? 1 : 0;
-}
-
int InstMatchGeneratorSimple::getActiveScore( QuantifiersEngine * qe ) {
Node f = qe->getTermDatabase()->getMatchOperator( d_match_pattern );
unsigned ngt = qe->getTermDatabase()->getNumGroundTerms( f );
diff --git a/src/theory/quantifiers/inst_match_generator.h b/src/theory/quantifiers/inst_match_generator.h
index 65c5a1427..c238e3c4e 100755
--- a/src/theory/quantifiers/inst_match_generator.h
+++ b/src/theory/quantifiers/inst_match_generator.h
@@ -42,8 +42,6 @@ public:
virtual bool getNextMatch( Node q, InstMatch& m, QuantifiersEngine* qe ) = 0;
/** add instantiations directly */
virtual int addInstantiations( Node q, InstMatch& baseMatch, QuantifiersEngine* qe ) = 0;
- /** add ground term t, called when t is added to term db */
- virtual int addTerm( Node q, Node t, QuantifiersEngine* qe ) { return 0; }
/** set active add */
virtual void setActiveAdd( bool val ) {}
/** get active score */
@@ -113,8 +111,6 @@ public:
bool getNextMatch( Node q, InstMatch& m, QuantifiersEngine* qe );
/** add instantiations */
int addInstantiations( Node q, InstMatch& baseMatch, QuantifiersEngine* qe );
- /** add ground term t */
- int addTerm( Node q, Node t, QuantifiersEngine* qe );
bool d_active_add;
void setActiveAdd( bool val );
@@ -205,8 +201,6 @@ public:
bool getNextMatch( Node q, InstMatch& m, QuantifiersEngine* qe ) { return false; }
/** add instantiations */
int addInstantiations( Node q, InstMatch& baseMatch, QuantifiersEngine* qe );
- /** add ground term t */
- int addTerm( Node q, Node t, QuantifiersEngine* qe );
};/* class InstMatchGeneratorMulti */
/** smart (single)-trigger implementation */
@@ -240,8 +234,6 @@ public:
bool getNextMatch( Node q, InstMatch& m, QuantifiersEngine* qe ) { return false; }
/** add instantiations */
int addInstantiations( Node q, InstMatch& baseMatch, QuantifiersEngine* qe );
- /** add ground term t, possibly add instantiations */
- int addTerm( Node q, Node t, QuantifiersEngine* qe );
/** get active score */
int getActiveScore( QuantifiersEngine * qe );
};/* class InstMatchGeneratorSimple */
diff --git a/src/theory/quantifiers/inst_propagator.cpp b/src/theory/quantifiers/inst_propagator.cpp
index 41c9c40c8..1f68fb787 100755
--- a/src/theory/quantifiers/inst_propagator.cpp
+++ b/src/theory/quantifiers/inst_propagator.cpp
@@ -597,6 +597,8 @@ void InstPropagator::InstInfo::init( Node q, Node lem, std::vector< Node >& term
InstPropagator::InstPropagator( QuantifiersEngine* qe ) :
d_qe( qe ), d_notify(*this), d_qy( qe ){
+ d_icount = 1;
+ d_conflict = false;
}
bool InstPropagator::reset( Theory::Effort e ) {
diff --git a/src/theory/quantifiers/inst_strategy_cbqi.cpp b/src/theory/quantifiers/inst_strategy_cbqi.cpp
index 523d868b5..ac6e1edbe 100755
--- a/src/theory/quantifiers/inst_strategy_cbqi.cpp
+++ b/src/theory/quantifiers/inst_strategy_cbqi.cpp
@@ -21,6 +21,7 @@
#include "theory/quantifiers/first_order_model.h"
#include "theory/quantifiers/term_database.h"
#include "theory/quantifiers/trigger.h"
+#include "theory/quantifiers/quantifiers_rewriter.h"
#include "theory/theory_engine.h"
using namespace std;
@@ -34,9 +35,13 @@ using namespace CVC4::theory::arith;
#define ARITH_INSTANTIATOR_USE_MINUS_DELTA
InstStrategyCbqi::InstStrategyCbqi( QuantifiersEngine * qe )
- : QuantifiersModule( qe ), d_added_cbqi_lemma( qe->getUserContext() )
+ : QuantifiersModule( qe ), d_added_cbqi_lemma( qe->getUserContext() ),
+d_elim_quants( qe->getSatContext() ),
+d_nested_qe_waitlist_size( qe->getUserContext() ),
+d_nested_qe_waitlist_proc( qe->getUserContext() )
//, d_added_inst( qe->getUserContext() )
{
+ d_qid_count = 0;
}
InstStrategyCbqi::~InstStrategyCbqi() throw(){}
@@ -55,34 +60,117 @@ unsigned InstStrategyCbqi::needsModel( Theory::Effort e ) {
return QuantifiersEngine::QEFFORT_NONE;
}
+bool InstStrategyCbqi::registerCbqiLemma( Node q ) {
+ if( !hasAddedCbqiLemma( q ) ){
+ d_added_cbqi_lemma.insert( q );
+ Trace("cbqi-debug") << "Do cbqi for " << q << std::endl;
+ //add cbqi lemma
+ //get the counterexample literal
+ Node ceLit = d_quantEngine->getTermDatabase()->getCounterexampleLiteral( q );
+ Node ceBody = d_quantEngine->getTermDatabase()->getInstConstantBody( q );
+ if( !ceBody.isNull() ){
+ //add counterexample lemma
+ Node lem = NodeManager::currentNM()->mkNode( OR, ceLit.negate(), ceBody.negate() );
+ //require any decision on cel to be phase=true
+ d_quantEngine->addRequirePhase( ceLit, true );
+ Debug("cbqi-debug") << "Require phase " << ceLit << " = true." << std::endl;
+ //add counterexample lemma
+ lem = Rewriter::rewrite( lem );
+ Trace("cbqi-lemma") << "Counterexample lemma : " << lem << std::endl;
+ registerCounterexampleLemma( q, lem );
+
+ //totality lemmas for EPR
+ QuantEPR * qepr = d_quantEngine->getQuantEPR();
+ if( qepr!=NULL ){
+ for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
+ TypeNode tn = q[0][i].getType();
+ if( tn.isSort() ){
+ if( qepr->isEPR( tn ) ){
+ //add totality lemma
+ std::map< TypeNode, std::vector< Node > >::iterator itc = qepr->d_consts.find( tn );
+ if( itc!=qepr->d_consts.end() ){
+ Assert( !itc->second.empty() );
+ Node ic = d_quantEngine->getTermDatabase()->getInstantiationConstant( q, i );
+ std::vector< Node > disj;
+ for( unsigned j=0; j<itc->second.size(); j++ ){
+ disj.push_back( ic.eqNode( itc->second[j] ) );
+ }
+ Node tlem = disj.size()==1 ? disj[0] : NodeManager::currentNM()->mkNode( kind::OR, disj );
+ Trace("cbqi-lemma") << "EPR totality lemma : " << tlem << std::endl;
+ d_quantEngine->getOutputChannel().lemma( tlem );
+ }else{
+ Assert( false );
+ }
+ }else{
+ Assert( !options::cbqiAll() );
+ }
+ }
+ }
+ }
+
+ //compute dependencies between quantified formulas
+ if( options::cbqiLitDepend() || options::cbqiInnermost() ){
+ std::vector< Node > ics;
+ TermDb::computeVarContains( q, ics );
+ d_parent_quant[q].clear();
+ d_children_quant[q].clear();
+ std::vector< Node > dep;
+ for( unsigned i=0; i<ics.size(); i++ ){
+ Node qi = ics[i].getAttribute(InstConstantAttribute());
+ if( std::find( d_parent_quant[q].begin(), d_parent_quant[q].end(), qi )==d_parent_quant[q].end() ){
+ d_parent_quant[q].push_back( qi );
+ d_children_quant[qi].push_back( q );
+ Node qicel = d_quantEngine->getTermDatabase()->getCounterexampleLiteral( qi );
+ dep.push_back( qi );
+ dep.push_back( qicel );
+ }
+ }
+ if( !dep.empty() ){
+ Node dep_lemma = NodeManager::currentNM()->mkNode( kind::IMPLIES, ceLit, NodeManager::currentNM()->mkNode( kind::AND, dep ) );
+ Trace("cbqi-lemma") << "Counterexample dependency lemma : " << dep_lemma << std::endl;
+ d_quantEngine->getOutputChannel().lemma( dep_lemma );
+ }
+ }
+
+ //must register all sub-quantifiers of counterexample lemma, register their lemmas
+ std::vector< Node > quants;
+ TermDb::computeQuantContains( lem, quants );
+ for( unsigned i=0; i<quants.size(); i++ ){
+ if( doCbqi( quants[i] ) ){
+ registerCbqiLemma( quants[i] );
+ }
+ if( options::cbqiNestedQE() ){
+ //record these as counterexample quantifiers
+ QAttributes qa;
+ TermDb::computeQuantAttributes( quants[i], qa );
+ if( !qa.d_qid_num.isNull() ){
+ d_id_to_ce_quant[ qa.d_qid_num ] = quants[i];
+ d_ce_quant_to_id[ quants[i] ] = qa.d_qid_num;
+ Trace("cbqi-nqe") << "CE quant id = " << qa.d_qid_num << " is " << quants[i] << std::endl;
+ }
+ }
+ }
+ }
+ return true;
+ }else{
+ return false;
+ }
+}
+
void InstStrategyCbqi::reset_round( Theory::Effort effort ) {
d_cbqi_set_quant_inactive = false;
d_incomplete_check = false;
+ d_active_quant.clear();
//check if any cbqi lemma has not been added yet
for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
Node q = d_quantEngine->getModel()->getAssertedQuantifier( i );
//it is not active if it corresponds to a rewrite rule: we will process in rewrite engine
if( doCbqi( q ) ){
- if( !hasAddedCbqiLemma( q ) ){
- d_added_cbqi_lemma.insert( q );
- Trace("cbqi") << "Do cbqi for " << q << std::endl;
- //add cbqi lemma
- //get the counterexample literal
- Node ceLit = d_quantEngine->getTermDatabase()->getCounterexampleLiteral( q );
- Node ceBody = d_quantEngine->getTermDatabase()->getInstConstantBody( q );
- if( !ceBody.isNull() ){
- //add counterexample lemma
- Node lem = NodeManager::currentNM()->mkNode( OR, ceLit.negate(), ceBody.negate() );
- //require any decision on cel to be phase=true
- d_quantEngine->addRequirePhase( ceLit, true );
- Debug("cbqi-debug") << "Require phase " << ceLit << " = true." << std::endl;
- //add counterexample lemma
- lem = Rewriter::rewrite( lem );
- Trace("cbqi") << "Counterexample lemma : " << lem << std::endl;
- registerCounterexampleLemma( q, lem );
- }
+ if( registerCbqiLemma( q ) ){
+ Debug("cbqi-debug") << "Registered cbqi lemma." << std::endl;
//set inactive the quantified formulas whose CE literals are asserted false
}else if( d_quantEngine->getModel()->isQuantifierActive( q ) ){
+ d_active_quant[q] = true;
Debug("cbqi-debug") << "Check quantified formula " << q << "..." << std::endl;
Node cel = d_quantEngine->getTermDatabase()->getCounterexampleLiteral( q );
bool value;
@@ -92,8 +180,24 @@ void InstStrategyCbqi::reset_round( Theory::Effort effort ) {
if( d_quantEngine->getValuation().isDecision( cel ) ){
Trace("cbqi-warn") << "CBQI WARNING: Bad decision on CE Literal." << std::endl;
}else{
+ Trace("cbqi") << "Inactive : " << q << std::endl;
d_quantEngine->getModel()->setQuantifierActive( q, false );
d_cbqi_set_quant_inactive = true;
+ d_active_quant.erase( q );
+ d_elim_quants.insert( q );
+ Trace("cbqi-nqe") << "Inactive, waitlist proc/size = " << d_nested_qe_waitlist_proc[q].get() << "/" << d_nested_qe_waitlist_size[q].get() << std::endl;
+ //process from waitlist
+ while( d_nested_qe_waitlist_proc[q]<d_nested_qe_waitlist_size[q] ){
+ int index = d_nested_qe_waitlist_proc[q];
+ Assert( index>=0 );
+ Assert( index<(int)d_nested_qe_waitlist[q].size() );
+ Node nq = d_nested_qe_waitlist[q][index];
+ Node nqeqn = doNestedQENode( d_nested_qe_info[nq].d_q, q, nq, d_nested_qe_info[nq].d_inst_terms, d_nested_qe_info[nq].d_doVts );
+ Node dqelem = nq.iffNode( nqeqn );
+ Trace("cbqi-lemma") << "Delayed nested quantifier elimination lemma : " << dqelem << std::endl;
+ d_quantEngine->getOutputChannel().lemma( dqelem );
+ d_nested_qe_waitlist_proc[q] = index + 1;
+ }
}
}
}else{
@@ -102,6 +206,34 @@ void InstStrategyCbqi::reset_round( Theory::Effort effort ) {
}
}
}
+
+ //refinement: only consider innermost active quantified formulas
+ if( options::cbqiInnermost() ){
+ if( !d_children_quant.empty() && !d_active_quant.empty() ){
+ Trace("cbqi-debug") << "Find non-innermost quantifiers..." << std::endl;
+ std::vector< Node > ninner;
+ for( std::map< Node, bool >::iterator it = d_active_quant.begin(); it != d_active_quant.end(); ++it ){
+ std::map< Node, std::vector< Node > >::iterator itc = d_children_quant.find( it->first );
+ if( itc!=d_children_quant.end() ){
+ for( unsigned j=0; j<itc->second.size(); j++ ){
+ if( d_active_quant.find( itc->second[j] )!=d_active_quant.end() ){
+ Trace("cbqi-debug") << "Do not consider " << it->first << " since it is not innermost (" << itc->second[j] << std::endl;
+ ninner.push_back( it->first );
+ break;
+ }
+ }
+ }
+ }
+ Trace("cbqi-debug") << "Found " << ninner.size() << " non-innermost." << std::endl;
+ for( unsigned i=0; i<ninner.size(); i++ ){
+ Assert( d_active_quant.find( ninner[i] )!=d_active_quant.end() );
+ d_active_quant.erase( ninner[i] );
+ }
+ Assert( !d_active_quant.empty() );
+ Trace("cbqi-debug") << "...done removing." << std::endl;
+ }
+ }
+
processResetInstantiationRound( effort );
}
@@ -115,13 +247,20 @@ void InstStrategyCbqi::check( Theory::Effort e, unsigned quant_e ) {
}
unsigned lastWaiting = d_quantEngine->getNumLemmasWaiting();
for( int ee=0; ee<=1; ee++ ){
- for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
- Node q = d_quantEngine->getModel()->getAssertedQuantifier( i );
- if( doCbqi( q ) && d_quantEngine->getModel()->isQuantifierActive( q ) ){
+ //for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ // Node q = d_quantEngine->getModel()->getAssertedQuantifier( i );
+ // if( doCbqi( q ) && d_quantEngine->getModel()->isQuantifierActive( q ) ){
+ for( std::map< Node, bool >::iterator it = d_active_quant.begin(); it != d_active_quant.end(); ++it ){
+ Node q = it->first;
+ Trace("cbqi") << "CBQI : Process quantifier " << q[0] << " at effort " << ee << std::endl;
+ if( d_nested_qe.find( q )==d_nested_qe.end() ){
process( q, e, ee );
if( d_quantEngine->inConflict() ){
break;
}
+ }else{
+ Trace("cbqi-warn") << "CBQI : Cannot process already eliminated quantified formula " << q << std::endl;
+ Assert( false );
}
}
if( d_quantEngine->inConflict() || d_quantEngine->getNumLemmasWaiting()>lastWaiting ){
@@ -146,11 +285,88 @@ bool InstStrategyCbqi::checkComplete() {
}
}
+bool InstStrategyCbqi::checkCompleteFor( Node q ) {
+ std::map< Node, int >::iterator it = d_do_cbqi.find( q );
+ if( it!=d_do_cbqi.end() ){
+ return it->second>0;
+ }else{
+ return false;
+ }
+}
+
+Node InstStrategyCbqi::getIdMarkedQuantNode( Node n, std::map< Node, Node >& visited ){
+ std::map< Node, Node >::iterator it = visited.find( n );
+ if( it==visited.end() ){
+ Node ret = n;
+ if( n.getKind()==FORALL ){
+ QAttributes qa;
+ TermDb::computeQuantAttributes( n, qa );
+ if( qa.d_qid_num.isNull() ){
+ std::vector< Node > rc;
+ rc.push_back( n[0] );
+ rc.push_back( getIdMarkedQuantNode( n[1], visited ) );
+ Node avar = NodeManager::currentNM()->mkSkolem( "id", NodeManager::currentNM()->booleanType() );
+ QuantIdNumAttribute ida;
+ avar.setAttribute(ida,d_qid_count);
+ d_qid_count++;
+ std::vector< Node > iplc;
+ iplc.push_back( NodeManager::currentNM()->mkNode( INST_ATTRIBUTE, avar ) );
+ if( n.getNumChildren()==3 ){
+ for( unsigned i=0; i<n[2].getNumChildren(); i++ ){
+ iplc.push_back( n[2][i] );
+ }
+ }
+ rc.push_back( NodeManager::currentNM()->mkNode( INST_PATTERN_LIST, iplc ) );
+ ret = NodeManager::currentNM()->mkNode( FORALL, rc );
+ }
+ }else if( n.getNumChildren()>0 ){
+ std::vector< Node > children;
+ if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ children.push_back( n.getOperator() );
+ }
+ bool childChanged = false;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ Node nc = getIdMarkedQuantNode( n[i], visited );
+ childChanged = childChanged || nc!=n[i];
+ children.push_back( nc );
+ }
+ if( childChanged ){
+ ret = NodeManager::currentNM()->mkNode( n.getKind(), children );
+ }
+ }
+ visited[n] = ret;
+ return ret;
+ }else{
+ return it->second;
+ }
+}
+
void InstStrategyCbqi::preRegisterQuantifier( Node q ) {
if( d_quantEngine->getOwner( q )==NULL && doCbqi( q ) ){
- if( !options::cbqiAll() && !options::cbqiSplx() ){
+ if( d_do_cbqi[q]==2 ){
//take full ownership of the quantified formula
d_quantEngine->setOwner( q, this );
+
+ //mark all nested quantifiers with id
+ if( options::cbqiNestedQE() ){
+ std::map< Node, Node > visited;
+ Node mq = getIdMarkedQuantNode( q[1], visited );
+ if( mq!=q[1] ){
+ //do not do cbqi
+ d_do_cbqi[q] = false;
+ //instead do reduction
+ std::vector< Node > qqc;
+ qqc.push_back( q[0] );
+ qqc.push_back( mq );
+ if( q.getNumChildren()==3 ){
+ qqc.push_back( q[2] );
+ }
+ Node qq = NodeManager::currentNM()->mkNode( FORALL, qqc );
+ Node mlem = NodeManager::currentNM()->mkNode( IMPLIES, q, qq );
+ Trace("cbqi-lemma") << "Mark quant id lemma : " << mlem << std::endl;
+ d_quantEngine->getOutputChannel().lemma( mlem );
+ }
+ }
}
}
}
@@ -159,6 +375,98 @@ void InstStrategyCbqi::registerQuantifier( Node q ) {
}
+Node InstStrategyCbqi::doNestedQENode( Node q, Node ceq, Node n, std::vector< Node >& inst_terms, bool doVts ) {
+ // there is a nested quantified formula (forall y. nq[y,x]) such that
+ // q is (forall y. nq[y,t]) for ground terms t,
+ // ceq is (forall y. nq[y,e]) for CE variables e.
+ // we call this function when we know (forall y. nq[y,e]) is equivalent to quantifier-free formula C[e].
+ // in this case, q is equivalent to the quantifier-free formula C[t].
+ if( d_nested_qe.find( ceq )==d_nested_qe.end() ){
+ d_nested_qe[ceq] = d_quantEngine->getInstantiatedConjunction( ceq );
+ Trace("cbqi-nqe") << "CE quantifier elimination : " << std::endl;
+ Trace("cbqi-nqe") << " " << ceq << std::endl;
+ Trace("cbqi-nqe") << " " << d_nested_qe[ceq] << std::endl;
+ //should not contain quantifiers
+ Assert( !QuantifiersRewriter::containsQuantifiers( d_nested_qe[ceq] ) );
+ }
+ Assert( d_quantEngine->getTermDatabase()->d_inst_constants[q].size()==inst_terms.size() );
+ //replace inst constants with instantiation
+ Node ret = d_nested_qe[ceq].substitute( d_quantEngine->getTermDatabase()->d_inst_constants[q].begin(),
+ d_quantEngine->getTermDatabase()->d_inst_constants[q].end(),
+ inst_terms.begin(), inst_terms.end() );
+ if( doVts ){
+ //do virtual term substitution
+ ret = Rewriter::rewrite( ret );
+ ret = d_quantEngine->getTermDatabase()->rewriteVtsSymbols( ret );
+ }
+ Trace("cbqi-nqe") << "Nested quantifier elimination: " << std::endl;
+ Trace("cbqi-nqe") << " " << n << std::endl;
+ Trace("cbqi-nqe") << " " << ret << std::endl;
+ return ret;
+}
+
+Node InstStrategyCbqi::doNestedQERec( Node q, Node n, std::map< Node, Node >& visited, std::vector< Node >& inst_terms, bool doVts ) {
+ if( visited.find( n )==visited.end() ){
+ Node ret = n;
+ if( n.getKind()==FORALL ){
+ QAttributes qa;
+ TermDb::computeQuantAttributes( n, qa );
+ if( !qa.d_qid_num.isNull() ){
+ //if it has an id, check whether we have done quantifier elimination for this id
+ std::map< Node, Node >::iterator it = d_id_to_ce_quant.find( qa.d_qid_num );
+ if( it!=d_id_to_ce_quant.end() ){
+ Node ceq = it->second;
+ bool doNestedQe = d_elim_quants.contains( ceq );
+ if( doNestedQe ){
+ ret = doNestedQENode( q, ceq, n, inst_terms, doVts );
+ }else{
+ Trace("cbqi-nqe") << "Add to nested qe waitlist : " << std::endl;
+ Node nr = Rewriter::rewrite( n );
+ Trace("cbqi-nqe") << " " << ceq << std::endl;
+ Trace("cbqi-nqe") << " " << nr << std::endl;
+ int wlsize = d_nested_qe_waitlist_size[ceq] + 1;
+ d_nested_qe_waitlist_size[ceq] = wlsize;
+ if( wlsize<(int)d_nested_qe_waitlist[ceq].size() ){
+ d_nested_qe_waitlist[ceq][wlsize] = nr;
+ }else{
+ d_nested_qe_waitlist[ceq].push_back( nr );
+ }
+ d_nested_qe_info[nr].d_q = q;
+ d_nested_qe_info[nr].d_inst_terms.clear();
+ d_nested_qe_info[nr].d_inst_terms.insert( d_nested_qe_info[nr].d_inst_terms.end(), inst_terms.begin(), inst_terms.end() );
+ d_nested_qe_info[nr].d_doVts = doVts;
+ //TODO: ensure this holds by restricting prenex when cbqiNestedQe is true.
+ Assert( !options::cbqiInnermost() );
+ }
+ }
+ }
+ }else if( n.getNumChildren()>0 ){
+ std::vector< Node > children;
+ if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ children.push_back( n.getOperator() );
+ }
+ bool childChanged = false;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ Node nc = doNestedQERec( q, n[i], visited, inst_terms, doVts );
+ childChanged = childChanged || nc!=n[i];
+ children.push_back( nc );
+ }
+ if( childChanged ){
+ ret = NodeManager::currentNM()->mkNode( n.getKind(), children );
+ }
+ }
+ visited[n] = ret;
+ return ret;
+ }else{
+ return n;
+ }
+}
+
+Node InstStrategyCbqi::doNestedQE( Node q, std::vector< Node >& inst_terms, Node lem, bool doVts ) {
+ std::map< Node, Node > visited;
+ return doNestedQERec( q, lem, visited, inst_terms, doVts );
+}
+
void InstStrategyCbqi::registerCounterexampleLemma( Node q, Node lem ){
Trace("cbqi-debug") << "Counterexample lemma : " << lem << std::endl;
d_quantEngine->addLemma( lem, false );
@@ -187,57 +495,91 @@ bool InstStrategyCbqi::hasNonCbqiOperator( Node n, std::map< Node, bool >& visit
}
return false;
}
-bool InstStrategyCbqi::hasNonCbqiVariable( Node q ){
+int InstStrategyCbqi::hasNonCbqiVariable( Node q ){
+ int hmin = 1;
for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
TypeNode tn = q[0][i].getType();
- if( !tn.isInteger() && !tn.isReal() && !tn.isBoolean() && !tn.isBitVector() ){
- if( options::cbqiSplx() ){
- return true;
- }else{
- //datatypes supported in new implementation
- if( !tn.isDatatype() ){
- return true;
- }
+ int handled = -1;
+ if( tn.isInteger() || tn.isReal() || tn.isBoolean() || tn.isBitVector() ){
+ handled = 0;
+ }else if( tn.isDatatype() ){
+ handled = 0;
+ }else if( tn.isSort() ){
+ QuantEPR * qepr = d_quantEngine->getQuantEPR();
+ if( qepr!=NULL ){
+ handled = qepr->isEPR( tn ) ? 1 : -1;
}
}
+ if( handled==-1 ){
+ return -1;
+ }else if( handled<hmin ){
+ hmin = handled;
+ }
}
- return false;
+ return hmin;
}
bool InstStrategyCbqi::doCbqi( Node q ){
- std::map< Node, bool >::iterator it = d_do_cbqi.find( q );
+ std::map< Node, int >::iterator it = d_do_cbqi.find( q );
if( it==d_do_cbqi.end() ){
- bool ret = false;
- if( d_quantEngine->getTermDatabase()->isQAttrQuantElim( q ) ){
- ret = true;
- }else{
+ int ret = 2;
+ if( !d_quantEngine->getTermDatabase()->isQAttrQuantElim( q ) ){
//if has an instantiation pattern, don't do it
if( q.getNumChildren()==3 && options::eMatching() && options::userPatternsQuant()!=USER_PAT_MODE_IGNORE ){
- ret = false;
- }else{
- if( options::cbqiAll() ){
- ret = true;
- }else{
- //if quantifier has a non-arithmetic variable, then do not use cbqi
- //if quantifier has an APPLY_UF term, then do not use cbqi
- //Node cb = d_quantEngine->getTermDatabase()->getInstConstantBody( q );
+ for( unsigned i=0; i<q[2].getNumChildren(); i++ ){
+ if( q[2][i].getKind()==INST_PATTERN ){
+ ret = 0;
+ }
+ }
+ }
+ if( ret!=0 ){
+ //if quantifier has a non-handled variable, then do not use cbqi
+ //if quantifier has an APPLY_UF term, then do not use cbqi unless EPR
+ int ncbqiv = hasNonCbqiVariable( q );
+ if( ncbqiv==0 || ncbqiv==1 ){
std::map< Node, bool > visited;
- ret = !hasNonCbqiVariable( q ) && !hasNonCbqiOperator( q[1], visited );
+ if( hasNonCbqiOperator( q[1], visited ) ){
+ if( ncbqiv==1 ){
+ //all variables are fully handled, this implies this will be handlable regardless of body (e.g. for EPR)
+ // so, try but not exclusively
+ ret = 1;
+ }else{
+ //cannot be handled
+ ret = 0;
+ }
+ }
+ }else{
+ // unhandled variable type
+ ret = 0;
+ }
+ if( ret==0 && options::cbqiAll() ){
+ //try but not exclusively
+ ret = 1;
}
}
}
- Trace("cbqi") << "doCbqi " << q << " returned " << ret << std::endl;
+ Trace("cbqi-quant") << "doCbqi " << q << " returned " << ret << std::endl;
d_do_cbqi[q] = ret;
- return ret;
+ return ret!=0;
}else{
- return it->second;
+ return it->second!=0;
}
}
-Node InstStrategyCbqi::getNextDecisionRequest(){
- // all counterexample literals that are not asserted
- for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
- Node q = d_quantEngine->getModel()->getAssertedQuantifier( i );
+Node InstStrategyCbqi::getNextDecisionRequestProc( Node q, std::map< Node, bool >& proc ) {
+ if( proc.find( q )==proc.end() ){
+ proc[q] = true;
+ //first check children
+ std::map< Node, std::vector< Node > >::iterator itc = d_children_quant.find( q );
+ if( itc!=d_children_quant.end() ){
+ for( unsigned j=0; j<itc->second.size(); j++ ){
+ Node d = getNextDecisionRequestProc( itc->second[j], proc );
+ if( !d.isNull() ){
+ return d;
+ }
+ }
+ }
+ //then check self
if( hasAddedCbqiLemma( q ) ){
Node cel = d_quantEngine->getTermDatabase()->getCounterexampleLiteral( q );
bool value;
@@ -245,328 +587,21 @@ Node InstStrategyCbqi::getNextDecisionRequest(){
Trace("cbqi-dec") << "CBQI: get next decision " << cel << std::endl;
return cel;
}
- }
+ }
}
- return Node::null();
+ return Node::null();
}
-
-
-
-//old implementation
-
-InstStrategySimplex::InstStrategySimplex( TheoryArith* th, QuantifiersEngine* ie ) : InstStrategyCbqi( ie ), d_th( th ), d_counter( 0 ){
- d_negOne = NodeManager::currentNM()->mkConst( Rational(-1) );
- d_zero = NodeManager::currentNM()->mkConst( Rational(0) );
-}
-
-void getInstantiationConstants( Node n, std::vector< Node >& ics ){
- if( n.getKind()==INST_CONSTANT ){
- if( std::find( ics.begin(), ics.end(), n )==ics.end() ){
- ics.push_back( n );
- }
- }else{
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- getInstantiationConstants( n[i], ics );
- }
- }
-}
-
-
-void InstStrategySimplex::processResetInstantiationRound( Theory::Effort effort ){
- Debug("quant-arith") << "Setting up simplex for instantiator... " << std::endl;
- d_quantActive.clear();
- d_instRows.clear();
- d_tableaux_term.clear();
- d_tableaux.clear();
- d_ceTableaux.clear();
- //search for instantiation rows in simplex tableaux
- ArithVariables& avnm = d_th->d_internal->d_partialModel;
- ArithVariables::var_iterator vi, vend;
- for(vi = avnm.var_begin(), vend = avnm.var_end(); vi != vend; ++vi ){
- ArithVar x = *vi;
- Node n = avnm.asNode(x);
-
- //collect instantiation constants
- std::vector< Node > ics;
- getInstantiationConstants( n, ics );
- for( unsigned i=0; i<ics.size(); i++ ){
- NodeBuilder<> t(kind::PLUS);
- if( n.getKind()==PLUS ){
- for( int j=0; j<(int)n.getNumChildren(); j++ ){
- addTermToRow( ics[i], x, n[j], t );
- }
- }else{
- addTermToRow( ics[i], x, n, t );
- }
- d_instRows[ics[i]].push_back( x );
- //this theory has constraints from f
- Node f = TermDb::getInstConstAttr(ics[i]);
- Debug("quant-arith") << "Has constraints from " << f << std::endl;
- //set that we should process it
- d_quantActive[ f ] = true;
- //set tableaux term
- if( t.getNumChildren()==0 ){
- d_tableaux_term[ics[i]][x] = d_zero;
- }else if( t.getNumChildren()==1 ){
- d_tableaux_term[ics[i]][x] = t.getChild( 0 );
- }else{
- d_tableaux_term[ics[i]][x] = t;
- }
- }
- }
- //print debug
- if( Debug.isOn("quant-arith-debug") ){
- Debug("quant-arith-debug") << std::endl;
- debugPrint( "quant-arith-debug" );
- }
- d_counter++;
-}
-
-void InstStrategySimplex::addTermToRow( Node i, ArithVar x, Node n, NodeBuilder<>& t ){
- if( n.getKind()==MULT ){
- if( TermDb::hasInstConstAttr(n[1]) && n[0].getKind()==CONST_RATIONAL ){
- if( n[1]==i ){
- d_ceTableaux[i][x][ n[1] ] = n[0];
- }else{
- d_tableaux_ce_term[i][x][ n[1] ] = n[0];
- }
- }else{
- d_tableaux[i][x][ n[1] ] = n[0];
- t << n;
- }
- }else{
- if( TermDb::hasInstConstAttr(n) ){
- if( n==i ){
- d_ceTableaux[i][x][ n ] = Node::null();
- }else{
- d_tableaux_ce_term[i][x][ n ] = NodeManager::currentNM()->mkConst( Rational(1) );
- }
- }else{
- d_tableaux[i][x][ n ] = NodeManager::currentNM()->mkConst( Rational(1) );
- t << n;
- }
- }
-}
-
-void InstStrategySimplex::process( Node f, Theory::Effort effort, int e ){
- if( e==0 ){
- if( d_quantActive.find( f )!=d_quantActive.end() ){
- //the point instantiation
- InstMatch m_point( f );
- bool m_point_valid = true;
- int lem = 0;
- //scan over all instantiation rows
- for( unsigned i=0; i<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
- Node ic = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i );
- Debug("quant-arith-simplex") << "InstStrategySimplex check " << ic << ", rows = " << d_instRows[ic].size() << std::endl;
- for( unsigned j=0; j<d_instRows[ic].size(); j++ ){
- ArithVar x = d_instRows[ic][j];
- if( !d_ceTableaux[ic][x].empty() ){
- if( Debug.isOn("quant-arith-simplex") ){
- Debug("quant-arith-simplex") << "--- Check row " << ic << " " << x << std::endl;
- Debug("quant-arith-simplex") << " ";
- for( std::map< Node, Node >::iterator it = d_ceTableaux[ic][x].begin(); it != d_ceTableaux[ic][x].end(); ++it ){
- if( it!=d_ceTableaux[ic][x].begin() ){ Debug("quant-arith-simplex") << " + "; }
- Debug("quant-arith-simplex") << it->first << " * " << it->second;
- }
- Debug("quant-arith-simplex") << " = ";
- Node v = getTableauxValue( x, false );
- Debug("quant-arith-simplex") << v << std::endl;
- Debug("quant-arith-simplex") << " term : " << d_tableaux_term[ic][x] << std::endl;
- Debug("quant-arith-simplex") << " ce-term : ";
- for( std::map< Node, Node >::iterator it = d_tableaux_ce_term[ic][x].begin(); it != d_tableaux_ce_term[ic][x].end(); it++ ){
- if( it!=d_tableaux_ce_term[ic][x].begin() ){ Debug("quant-arith-simplex") << " + "; }
- Debug("quant-arith-simplex") << it->first << " * " << it->second;
- }
- Debug("quant-arith-simplex") << std::endl;
- }
- //instantiation row will be A*e + B*t = beta,
- // where e is a vector of terms , and t is vector of ground terms.
- // Say one term in A*e is coeff*e_i, where e_i is an instantiation constant
- // We will construct the term ( beta - B*t)/coeff to use for e_i.
- InstMatch m( f );
- for( unsigned k=0; k<f[0].getNumChildren(); k++ ){
- if( f[0][k].getType().isInteger() ){
- m.setValue( k, d_zero );
- }
- }
- //By default, choose the first instantiation constant to be e_i.
- Node var = d_ceTableaux[ic][x].begin()->first;
- //if it is integer, we need to find variable with coefficent +/- 1
- if( var.getType().isInteger() ){
- std::map< Node, Node >::iterator it = d_ceTableaux[ic][x].begin();
- while( !var.isNull() && !d_ceTableaux[ic][x][var].isNull() && d_ceTableaux[ic][x][var]!=d_negOne ){
- ++it;
- if( it==d_ceTableaux[ic][x].end() ){
- var = Node::null();
- }else{
- var = it->first;
- }
- }
- //Otherwise, try one that divides all ground term coefficients?
- // Might be futile, if rewrite ensures gcd of coeffs is 1.
- }
- if( !var.isNull() ){
- //add to point instantiation if applicable
- if( d_tableaux_ce_term[ic][x].empty() && d_tableaux_term[ic][x]==d_zero ){
- Debug("quant-arith-simplex") << "*** Row contributes to point instantiation." << std::endl;
- Node v = getTableauxValue( x, false );
- if( !var.getType().isInteger() || v.getType().isInteger() ){
- m_point.setValue( i, v );
- }else{
- m_point_valid = false;
- }
- }
- Debug("quant-arith-simplex") << "Instantiate with var " << var << std::endl;
- if( doInstantiation( f, ic, d_tableaux_term[ic][x], x, m, var ) ){
- lem++;
- }
- }else{
- Debug("quant-arith-simplex") << "Could not find var." << std::endl;
- }
- }
- }
- }
- if( lem==0 && m_point_valid ){
- if( d_quantEngine->addInstantiation( f, m_point ) ){
- Debug("quant-arith-simplex") << "...added point instantiation." << std::endl;
- }
- }
- }
- }
-}
-
-
-void InstStrategySimplex::debugPrint( const char* c ){
- ArithVariables& avnm = d_th->d_internal->d_partialModel;
- ArithVariables::var_iterator vi, vend;
- for(vi = avnm.var_begin(), vend = avnm.var_end(); vi != vend; ++vi ){
- ArithVar x = *vi;
- Node n = avnm.asNode(x);
- //if( ((TheoryArith*)getTheory())->d_partialModel.hasEitherBound( x ) ){
- Debug(c) << x << " : " << n << ", bounds = ";
- if( d_th->d_internal->d_partialModel.hasLowerBound( x ) ){
- Debug(c) << d_th->d_internal->d_partialModel.getLowerBound( x );
- }else{
- Debug(c) << "-infty";
- }
- Debug(c) << " <= ";
- Debug(c) << d_th->d_internal->d_partialModel.getAssignment( x );
- Debug(c) << " <= ";
- if( d_th->d_internal->d_partialModel.hasUpperBound( x ) ){
- Debug(c) << d_th->d_internal->d_partialModel.getUpperBound( x );
- }else{
- Debug(c) << "+infty";
- }
- Debug(c) << std::endl;
- //Debug(c) << " Term = " << d_tableaux_term[x] << std::endl;
- //Debug(c) << " ";
- //for( std::map< Node, Node >::iterator it2 = d_tableaux[x].begin(); it2 != d_tableaux[x].end(); ++it2 ){
- // Debug(c) << "( " << it2->first << ", " << it2->second << " ) ";
- //}
- //for( std::map< Node, Node >::iterator it2 = d_ceTableaux[x].begin(); it2 != d_ceTableaux[x].end(); ++it2 ){
- // Debug(c) << "(CE)( " << it2->first << ", " << it2->second << " ) ";
- //}
- //for( std::map< Node, Node >::iterator it2 = d_tableaux_ce_term[x].begin(); it2 != d_tableaux_ce_term[x].end(); ++it2 ){
- // Debug(c) << "(CE-term)( " << it2->first << ", " << it2->second << " ) ";
- //}
- //Debug(c) << std::endl;
- //}
- }
- Debug(c) << std::endl;
-
+Node InstStrategyCbqi::getNextDecisionRequest(){
+ std::map< Node, bool > proc;
for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
- Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
- Debug(c) << f << std::endl;
- Debug(c) << " Inst constants: ";
- for( unsigned j=0; j<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
- if( j>0 ){
- Debug( c ) << ", ";
- }
- Debug( c ) << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i );
- }
- Debug(c) << std::endl;
- for( unsigned j=0; j<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); j++ ){
- Node ic = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );
- Debug(c) << " Instantiation rows for " << ic << " : ";
- for( unsigned k=0; k<d_instRows[ic].size(); k++ ){
- if( k>0 ){
- Debug(c) << ", ";
- }
- Debug(c) << d_instRows[ic][k];
- }
- Debug(c) << std::endl;
- }
- }
-}
-
-//say instantiation row x for quantifier f is coeff*var + A*t[e] + term = beta,
-// where var is an instantiation constant from f,
-// t[e] is a vector of terms containing instantiation constants from f,
-// and term is a ground term (c1*t1 + ... + cn*tn).
-// We construct the term ( beta - term )/coeff to use as an instantiation for var.
-bool InstStrategySimplex::doInstantiation( Node f, Node ic, Node term, ArithVar x, InstMatch& m, Node var ){
- //first try +delta
- if( doInstantiation2( f, ic, term, x, m, var ) ){
- ++(d_quantEngine->d_statistics.d_instantiations_cbqi_arith);
- return true;
- }else{
-#ifdef ARITH_INSTANTIATOR_USE_MINUS_DELTA
- //otherwise try -delta
- if( doInstantiation2( f, ic, term, x, m, var, true ) ){
- ++(d_quantEngine->d_statistics.d_instantiations_cbqi_arith);
- return true;
- }else{
- return false;
- }
-#else
- return false;
-#endif
- }
-}
-
-bool InstStrategySimplex::doInstantiation2( Node f, Node ic, Node term, ArithVar x, InstMatch& m, Node var, bool minus_delta ){
- // make term ( beta - term )/coeff
- bool vIsInteger = var.getType().isInteger();
- Node beta = getTableauxValue( x, minus_delta );
- if( !vIsInteger || beta.getType().isInteger() ){
- Node instVal = NodeManager::currentNM()->mkNode( MINUS, beta, term );
- if( !d_ceTableaux[ic][x][var].isNull() ){
- if( vIsInteger ){
- Assert( d_ceTableaux[ic][x][var]==NodeManager::currentNM()->mkConst( Rational(-1) ) );
- instVal = NodeManager::currentNM()->mkNode( MULT, d_ceTableaux[ic][x][var], instVal );
- }else{
- Assert( d_ceTableaux[ic][x][var].getKind()==CONST_RATIONAL );
- Node coeff = NodeManager::currentNM()->mkConst( Rational(1) / d_ceTableaux[ic][x][var].getConst<Rational>() );
- instVal = NodeManager::currentNM()->mkNode( MULT, coeff, instVal );
- }
+ Node q = d_quantEngine->getModel()->getAssertedQuantifier( i );
+ Node d = getNextDecisionRequestProc( q, proc );
+ if( !d.isNull() ){
+ return d;
}
- instVal = Rewriter::rewrite( instVal );
- //use as instantiation value for var
- int vn = var.getAttribute(InstVarNumAttribute());
- m.setValue( vn, instVal );
- Debug("quant-arith") << "Add instantiation " << m << std::endl;
- return d_quantEngine->addInstantiation( f, m );
- }else{
- return false;
- }
-}
-/*
-Node InstStrategySimplex::getTableauxValue( Node n, bool minus_delta ){
- if( d_th->d_internal->d_partialModel.hasArithVar(n) ){
- ArithVar v = d_th->d_internal->d_partialModel.asArithVar( n );
- return getTableauxValue( v, minus_delta );
- }else{
- return NodeManager::currentNM()->mkConst( Rational(0) );
}
-}
-*/
-Node InstStrategySimplex::getTableauxValue( ArithVar v, bool minus_delta ){
- const Rational& delta = d_th->d_internal->d_partialModel.getDelta();
- DeltaRational drv = d_th->d_internal->d_partialModel.getAssignment( v );
- Rational qmodel = drv.substituteDelta( minus_delta ? -delta : delta );
- return mkRationalNode(qmodel);
+ return Node::null();
}
@@ -590,6 +625,7 @@ InstStrategyCegqi::InstStrategyCegqi( QuantifiersEngine * qe )
: InstStrategyCbqi( qe ) {
d_out = new CegqiOutputInstStrategy( this );
d_small_const = NodeManager::currentNM()->mkConst( Rational(1)/Rational(1000000) );
+ d_check_vts_lemma_lc = false;
}
InstStrategyCegqi::~InstStrategyCegqi() throw () {
@@ -654,9 +690,13 @@ bool InstStrategyCegqi::doAddInstantiation( std::vector< Node >& subs ) {
//check if we need virtual term substitution (if used delta or infinity)
bool used_vts = d_quantEngine->getTermDatabase()->containsVtsTerm( subs, false );
if( d_quantEngine->addInstantiation( d_curr_quant, subs, false, false, used_vts ) ){
+ ++(d_quantEngine->d_statistics.d_instantiations_cbqi);
//d_added_inst.insert( d_curr_quant );
return true;
}else{
+ //this should never happen for monotonic selection strategies
+ Trace("cbqi-warn") << "WARNING: Existing instantiation" << std::endl;
+ Assert( !options::cbqiNestedQE() || options::cbqiAll() );
return false;
}
}
@@ -671,6 +711,16 @@ bool InstStrategyCegqi::isEligibleForInstantiation( Node n ) {
if( n.getKind()==SKOLEM && d_quantEngine->getTermDatabase()->containsVtsTerm( n ) ){
return true;
}else{
+ TypeNode tn = n.getType();
+ if( tn.isSort() ){
+ QuantEPR * qepr = d_quantEngine->getQuantEPR();
+ if( qepr!=NULL ){
+ //legal if in the finite set of constants of type tn
+ if( qepr->isEPRConstant( tn, n ) ){
+ return true;
+ }
+ }
+ }
//only legal if current quantified formula contains n
return TermDb::containsTerm( d_curr_quant, n );
}
@@ -719,7 +769,9 @@ void InstStrategyCegqi::registerCounterexampleLemma( Node q, Node lem ) {
void InstStrategyCegqi::presolve() {
if( options::cbqiPreRegInst() ){
for( std::map< Node, CegInstantiator * >::iterator it = d_cinst.begin(); it != d_cinst.end(); ++it ){
+ Trace("cbqi-presolve") << "Presolve " << it->first << std::endl;
it->second->presolve( it->first );
}
}
}
+
diff --git a/src/theory/quantifiers/inst_strategy_cbqi.h b/src/theory/quantifiers/inst_strategy_cbqi.h
index 8ed59778b..c9f62243f 100755
--- a/src/theory/quantifiers/inst_strategy_cbqi.h
+++ b/src/theory/quantifiers/inst_strategy_cbqi.h
@@ -34,25 +34,64 @@ namespace quantifiers {
class InstStrategyCbqi : public QuantifiersModule {
typedef context::CDHashSet<Node, NodeHashFunction> NodeSet;
+ typedef context::CDHashMap< Node, int, NodeHashFunction> NodeIntMap;
protected:
bool d_cbqi_set_quant_inactive;
bool d_incomplete_check;
/** whether we have added cbqi lemma */
NodeSet d_added_cbqi_lemma;
+ /** whether we have added cbqi lemma */
+ NodeSet d_elim_quants;
+ /** parent guards */
+ std::map< Node, std::vector< Node > > d_parent_quant;
+ std::map< Node, std::vector< Node > > d_children_quant;
+ std::map< Node, bool > d_active_quant;
/** whether we have instantiated quantified formulas */
//NodeSet d_added_inst;
- /** whether to do cbqi for this quantified formula */
- std::map< Node, bool > d_do_cbqi;
+ /** whether to do cbqi for this quantified formula 0 : no, 2 : yes, 1 : yes but not exclusively, -1 : heuristically */
+ std::map< Node, int > d_do_cbqi;
/** register ce lemma */
+ bool registerCbqiLemma( Node q );
virtual void registerCounterexampleLemma( Node q, Node lem );
/** has added cbqi lemma */
bool hasAddedCbqiLemma( Node q ) { return d_added_cbqi_lemma.find( q )!=d_added_cbqi_lemma.end(); }
/** helper functions */
- bool hasNonCbqiVariable( Node q );
+ int hasNonCbqiVariable( Node q );
bool hasNonCbqiOperator( Node n, std::map< Node, bool >& visited );
+ /** get next decision request with dependency checking */
+ Node getNextDecisionRequestProc( Node q, std::map< Node, bool >& proc );
/** process functions */
virtual void processResetInstantiationRound( Theory::Effort effort ) = 0;
virtual void process( Node q, Theory::Effort effort, int e ) = 0;
+protected:
+ //for identification
+ uint64_t d_qid_count;
+ //nested qe map
+ std::map< Node, Node > d_nested_qe;
+ //mark ids on quantifiers
+ Node getIdMarkedQuantNode( Node n, std::map< Node, Node >& visited );
+ // id to ce quant
+ std::map< Node, Node > d_id_to_ce_quant;
+ std::map< Node, Node > d_ce_quant_to_id;
+ //do nested quantifier elimination recursive
+ Node doNestedQENode( Node q, Node ceq, Node n, std::vector< Node >& inst_terms, bool doVts );
+ Node doNestedQERec( Node q, Node n, std::map< Node, Node >& visited, std::vector< Node >& inst_terms, bool doVts );
+ //elimination information (for delayed elimination)
+ class NestedQEInfo {
+ public:
+ NestedQEInfo() : d_doVts(false){}
+ ~NestedQEInfo(){}
+ Node d_q;
+ std::vector< Node > d_inst_terms;
+ bool d_doVts;
+ };
+ std::map< Node, NestedQEInfo > d_nested_qe_info;
+ NodeIntMap d_nested_qe_waitlist_size;
+ NodeIntMap d_nested_qe_waitlist_proc;
+ std::map< Node, std::vector< Node > > d_nested_qe_waitlist;
+public:
+ //do nested quantifier elimination
+ Node doNestedQE( Node q, std::vector< Node >& inst_terms, Node lem, bool doVts );
public:
InstStrategyCbqi( QuantifiersEngine * qe );
~InstStrategyCbqi() throw();
@@ -64,56 +103,13 @@ public:
void reset_round( Theory::Effort e );
void check( Theory::Effort e, unsigned quant_e );
bool checkComplete();
+ bool checkCompleteFor( Node q );
void preRegisterQuantifier( Node q );
void registerQuantifier( Node q );
/** get next decision request */
Node getNextDecisionRequest();
};
-
-class InstStrategySimplex : public InstStrategyCbqi {
-protected:
- /** reference to theory arithmetic */
- arith::TheoryArith* d_th;
- /** quantifiers we should process */
- std::map< Node, bool > d_quantActive;
- /** delta */
- std::map< TypeNode, Node > d_deltas;
- /** for each quantifier, simplex rows */
- std::map< Node, std::vector< arith::ArithVar > > d_instRows;
- /** tableaux */
- std::map< Node, std::map< arith::ArithVar, Node > > d_tableaux_term;
- std::map< Node, std::map< arith::ArithVar, std::map< Node, Node > > > d_tableaux_ce_term;
- std::map< Node, std::map< arith::ArithVar, std::map< Node, Node > > > d_tableaux;
- /** ce tableaux */
- std::map< Node, std::map< arith::ArithVar, std::map< Node, Node > > > d_ceTableaux;
- /** get value */
- //Node getTableauxValue( Node n, bool minus_delta = false );
- Node getTableauxValue( arith::ArithVar v, bool minus_delta = false );
- /** do instantiation */
- bool doInstantiation( Node f, Node ic, Node term, arith::ArithVar x, InstMatch& m, Node var );
- bool doInstantiation2( Node f, Node ic, Node term, arith::ArithVar x, InstMatch& m, Node var, bool minus_delta = false );
- /** add term to row */
- void addTermToRow( Node ic, arith::ArithVar x, Node n, NodeBuilder<>& t );
- /** print debug */
- void debugPrint( const char* c );
-private:
- /** */
- int d_counter;
- /** constants */
- Node d_zero;
- Node d_negOne;
- /** process functions */
- void processResetInstantiationRound( Theory::Effort effort );
- void process( Node f, Theory::Effort effort, int e );
-public:
- InstStrategySimplex( arith::TheoryArith* th, QuantifiersEngine* ie );
- ~InstStrategySimplex() throw() {}
- /** identify */
- std::string identify() const { return std::string("Simplex"); }
-};
-
-
//generalized counterexample guided quantifier instantiation
class InstStrategyCegqi;
diff --git a/src/theory/quantifiers/inst_strategy_e_matching.cpp b/src/theory/quantifiers/inst_strategy_e_matching.cpp
index 49e0a698f..c4bf61b28 100755
--- a/src/theory/quantifiers/inst_strategy_e_matching.cpp
+++ b/src/theory/quantifiers/inst_strategy_e_matching.cpp
@@ -155,6 +155,7 @@ InstStrategyAutoGenTriggers::InstStrategyAutoGenTriggers( QuantifiersEngine* qe
d_regenerate_frequency = 3;
d_regenerate = true;
}else{
+ d_regenerate_frequency = 1;
d_regenerate = false;
}
}
diff --git a/src/theory/quantifiers/instantiation_engine.cpp b/src/theory/quantifiers/instantiation_engine.cpp
index db597d031..afeed1e5d 100755
--- a/src/theory/quantifiers/instantiation_engine.cpp
+++ b/src/theory/quantifiers/instantiation_engine.cpp
@@ -114,6 +114,7 @@ void InstantiationEngine::reset_round( Theory::Effort e ){
}
void InstantiationEngine::check( Theory::Effort e, unsigned quant_e ){
+ CodeTimer codeTimer(d_quantEngine->d_statistics.d_ematching_time);
if( quant_e==QuantifiersEngine::QEFFORT_STANDARD ){
double clSet = 0;
if( Trace.isOn("inst-engine") ){
@@ -151,19 +152,9 @@ void InstantiationEngine::check( Theory::Effort e, unsigned quant_e ){
}
}
-bool InstantiationEngine::checkComplete() {
- if( !options::finiteModelFind() ){
- for( unsigned i=0; i<d_quants.size(); i++ ){
- if( isIncomplete( d_quants[i] ) ){
- return false;
- }
- }
- }
- return true;
-}
-
-bool InstantiationEngine::isIncomplete( Node q ) {
- return true;
+bool InstantiationEngine::checkCompleteFor( Node q ) {
+ //TODO?
+ return false;
}
void InstantiationEngine::preRegisterQuantifier( Node q ) {
diff --git a/src/theory/quantifiers/instantiation_engine.h b/src/theory/quantifiers/instantiation_engine.h
index d2b3740a1..79963cb45 100755
--- a/src/theory/quantifiers/instantiation_engine.h
+++ b/src/theory/quantifiers/instantiation_engine.h
@@ -78,7 +78,7 @@ public:
bool needsCheck( Theory::Effort e );
void reset_round( Theory::Effort e );
void check( Theory::Effort e, unsigned quant_e );
- bool checkComplete();
+ bool checkCompleteFor( Node q );
void preRegisterQuantifier( Node q );
void registerQuantifier( Node q );
Node explain(TNode n){ return Node::null(); }
diff --git a/src/theory/quantifiers/local_theory_ext.h b/src/theory/quantifiers/local_theory_ext.h
index 94abf3c90..04a6bc9c8 100755
--- a/src/theory/quantifiers/local_theory_ext.h
+++ b/src/theory/quantifiers/local_theory_ext.h
@@ -66,6 +66,8 @@ public:
void check( Theory::Effort e, unsigned quant_e );
/* Called for new quantifiers */
void registerQuantifier( Node q ) {}
+ /* check complete */
+ bool checkComplete() { return !d_wasInvoked; }
void assertNode( Node n ) {}
/** Identify this module (for debugging, dynamic configuration, etc..) */
std::string identify() const { return "LtePartialInst"; }
diff --git a/src/theory/quantifiers/macros.cpp b/src/theory/quantifiers/macros.cpp
index 582599680..976b81e60 100755
--- a/src/theory/quantifiers/macros.cpp
+++ b/src/theory/quantifiers/macros.cpp
@@ -33,6 +33,10 @@ using namespace CVC4::theory::quantifiers;
using namespace CVC4::kind;
+QuantifierMacros::QuantifierMacros( QuantifiersEngine * qe ) : d_qe( qe ){
+ d_ground_macros = false;
+}
+
bool QuantifierMacros::simplify( std::vector< Node >& assertions, bool doRewrite ){
unsigned rmax = options::macrosQuantMode()==MACROS_QUANT_MODE_ALL ? 2 : 1;
for( unsigned r=0; r<rmax; r++ ){
diff --git a/src/theory/quantifiers/macros.h b/src/theory/quantifiers/macros.h
index 39ec2f0a1..60af7ad0a 100755
--- a/src/theory/quantifiers/macros.h
+++ b/src/theory/quantifiers/macros.h
@@ -60,7 +60,7 @@ private:
void addMacro( Node op, Node n, std::vector< Node >& opc );
void debugMacroDefinition( Node oo, Node n );
public:
- QuantifierMacros( QuantifiersEngine * qe ) : d_qe( qe ){}
+ QuantifierMacros( QuantifiersEngine * qe );
~QuantifierMacros(){}
bool simplify( std::vector< Node >& assertions, bool doRewrite = false );
diff --git a/src/theory/quantifiers/model_builder.cpp b/src/theory/quantifiers/model_builder.cpp
index 7bbe06108..b30c2addb 100755
--- a/src/theory/quantifiers/model_builder.cpp
+++ b/src/theory/quantifiers/model_builder.cpp
@@ -391,7 +391,7 @@ bool QModelBuilderIG::isTermActive( Node n ){
//do exhaustive instantiation
-bool QModelBuilderIG::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) {
+int QModelBuilderIG::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) {
if( optUseModel() ){
RepSetIterator riter( d_qe, &(d_qe->getModel()->d_rep_set) );
if( riter.setQuantifier( f ) ){
@@ -470,10 +470,9 @@ bool QModelBuilderIG::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, i
}
}
//if the iterator is incomplete, we will return unknown instead of sat if no instantiations are added this round
- d_incomplete_check = riter.isIncomplete();
- return true;
+ return riter.isIncomplete() ? -1 : 1;
}else{
- return false;
+ return 0;
}
}
diff --git a/src/theory/quantifiers/model_builder.h b/src/theory/quantifiers/model_builder.h
index e4f9529a8..9b89e5ef6 100755
--- a/src/theory/quantifiers/model_builder.h
+++ b/src/theory/quantifiers/model_builder.h
@@ -38,13 +38,14 @@ public:
virtual ~QModelBuilder() throw() {}
// is quantifier active?
virtual bool isQuantifierActive( Node f );
- //do exhaustive instantiation
- virtual bool doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) { return false; }
+ //do exhaustive instantiation
+ // 0 : failed, but resorting to true exhaustive instantiation may work
+ // >0 : success
+ // <0 : failed
+ virtual int doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) { return false; }
//whether to construct model
virtual bool optUseModel();
/** number of lemmas generated while building model */
- //is the exhaustive instantiation incomplete?
- bool d_incomplete_check;
int d_addedLemmas;
int d_triedLemmas;
/** exist instantiation ? */
@@ -142,7 +143,7 @@ public:
// is quantifier active?
bool isQuantifierActive( Node f );
//do exhaustive instantiation
- bool doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort );
+ int doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort );
//temporary stats
int d_numQuantSat;
diff --git a/src/theory/quantifiers/model_engine.cpp b/src/theory/quantifiers/model_engine.cpp
index 7658f2b6b..9c09371c4 100755
--- a/src/theory/quantifiers/model_engine.cpp
+++ b/src/theory/quantifiers/model_engine.cpp
@@ -73,7 +73,6 @@ void ModelEngine::check( Theory::Effort e, unsigned quant_e ){
Trace("model-engine") << "---Model Engine Round---" << std::endl;
clSet = double(clock())/double(CLOCKS_PER_SEC);
}
- ++(d_statistics.d_inst_rounds);
Trace("model-engine-debug") << "Verify uf ss is minimal..." << std::endl;
//let the strong solver verify that the model is minimal
@@ -99,7 +98,7 @@ void ModelEngine::check( Theory::Effort e, unsigned quant_e ){
}
if( addedLemmas==0 ){
- Trace("model-engine-debug") << "No lemmas added, incomplete = " << d_incomplete_check << std::endl;
+ Trace("model-engine-debug") << "No lemmas added, incomplete = " << ( d_incomplete_check || !d_incomplete_quants.empty() ) << std::endl;
//CVC4 will answer SAT or unknown
if( Trace.isOn("fmf-consistent") ){
Trace("fmf-consistent") << std::endl;
@@ -113,6 +112,10 @@ bool ModelEngine::checkComplete() {
return !d_incomplete_check;
}
+bool ModelEngine::checkCompleteFor( Node q ) {
+ return std::find( d_incomplete_quants.begin(), d_incomplete_quants.end(), q )==d_incomplete_quants.end();
+}
+
void ModelEngine::registerQuantifier( Node f ){
if( Trace.isOn("fmf-warn") ){
bool canHandle = true;
@@ -195,17 +198,18 @@ int ModelEngine::checkModel(){
// FMC uses two sub-effort levels
int e_max = options::mbqiMode()==MBQI_FMC || options::mbqiMode()==MBQI_FMC_INTERVAL ? 2 : ( options::mbqiMode()==MBQI_TRUST ? 0 : 1 );
for( int e=0; e<e_max; e++) {
+ d_incomplete_quants.clear();
for( unsigned i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
- Node f = fm->getAssertedQuantifier( i, true );
- Trace("fmf-exh-inst") << "-> Exhaustive instantiate " << f << ", effort = " << e << "..." << std::endl;
+ Node q = fm->getAssertedQuantifier( i, true );
+ Trace("fmf-exh-inst") << "-> Exhaustive instantiate " << q << ", effort = " << e << "..." << std::endl;
//determine if we should check this quantifier
- if( considerQuantifiedFormula( f ) ){
- exhaustiveInstantiate( f, e );
+ if( considerQuantifiedFormula( q ) ){
+ exhaustiveInstantiate( q, e );
if( d_quantEngine->inConflict() || ( optOneQuantPerRound() && d_addedLemmas>0 ) ){
break;
}
}else{
- Trace("fmf-exh-inst") << "-> Inactive : " << f << std::endl;
+ Trace("fmf-exh-inst") << "-> Inactive : " << q << std::endl;
}
}
if( d_addedLemmas>0 ){
@@ -260,13 +264,17 @@ void ModelEngine::exhaustiveInstantiate( Node f, int effort ){
quantifiers::QModelBuilder * mb = d_quantEngine->getModelBuilder();
mb->d_triedLemmas = 0;
mb->d_addedLemmas = 0;
- mb->d_incomplete_check = false;
- if( mb->doExhaustiveInstantiation( d_quantEngine->getModel(), f, effort ) ){
- Trace("fmf-exh-inst") << "-> Builder determined instantiation(s)." << std::endl;
+ int retEi = mb->doExhaustiveInstantiation( d_quantEngine->getModel(), f, effort );
+ if( retEi!=0 ){
+ if( retEi<0 ){
+ Trace("fmf-exh-inst") << "-> Builder determined complete instantiation was impossible." << std::endl;
+ d_incomplete_quants.push_back( f );
+ }else{
+ Trace("fmf-exh-inst") << "-> Builder determined instantiation(s)." << std::endl;
+ }
d_triedLemmas += mb->d_triedLemmas;
d_addedLemmas += mb->d_addedLemmas;
- d_incomplete_check = d_incomplete_check || mb->d_incomplete_check;
- d_statistics.d_mbqi_inst_lemmas += mb->d_addedLemmas;
+ d_quantEngine->d_statistics.d_instantiations_fmf_mbqi += mb->d_addedLemmas;
}else{
if( Trace.isOn("fmf-exh-inst-debug") ){
Trace("fmf-exh-inst-debug") << " Instantiation Constants: ";
@@ -303,13 +311,15 @@ void ModelEngine::exhaustiveInstantiate( Node f, int effort ){
}
d_addedLemmas += addedLemmas;
d_triedLemmas += triedLemmas;
- d_statistics.d_exh_inst_lemmas += addedLemmas;
+ d_quantEngine->d_statistics.d_instantiations_fmf_exh += addedLemmas;
}
}else{
Trace("fmf-exh-inst") << "...exhaustive instantiation did set, incomplete=" << riter.isIncomplete() << "..." << 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.isIncomplete();
+ if( riter.isIncomplete() ){
+ d_incomplete_quants.push_back( f );
+ }
}
}
@@ -328,18 +338,3 @@ void ModelEngine::debugPrint( const char* c ){
//d_quantEngine->getModel()->debugPrint( c );
}
-ModelEngine::Statistics::Statistics():
- d_inst_rounds("ModelEngine::Inst_Rounds", 0),
- d_exh_inst_lemmas("ModelEngine::Instantiations_Exhaustive", 0 ),
- d_mbqi_inst_lemmas("ModelEngine::Instantiations_Mbqi", 0 )
-{
- smtStatisticsRegistry()->registerStat(&d_inst_rounds);
- smtStatisticsRegistry()->registerStat(&d_exh_inst_lemmas);
- smtStatisticsRegistry()->registerStat(&d_mbqi_inst_lemmas);
-}
-
-ModelEngine::Statistics::~Statistics(){
- smtStatisticsRegistry()->unregisterStat(&d_inst_rounds);
- smtStatisticsRegistry()->unregisterStat(&d_exh_inst_lemmas);
- smtStatisticsRegistry()->unregisterStat(&d_mbqi_inst_lemmas);
-}
diff --git a/src/theory/quantifiers/model_engine.h b/src/theory/quantifiers/model_engine.h
index 12f18aa08..e89be8d2b 100755
--- a/src/theory/quantifiers/model_engine.h
+++ b/src/theory/quantifiers/model_engine.h
@@ -42,6 +42,8 @@ private:
//temporary statistics
//is the exhaustive instantiation incomplete?
bool d_incomplete_check;
+ // set of quantified formulas for which check was incomplete
+ std::vector< Node > d_incomplete_quants;
int d_addedLemmas;
int d_triedLemmas;
int d_totalLemmas;
@@ -54,21 +56,11 @@ public:
void reset_round( Theory::Effort e );
void check( Theory::Effort e, unsigned quant_e );
bool checkComplete();
+ bool checkCompleteFor( Node q );
void registerQuantifier( Node f );
void assertNode( Node f );
Node explain(TNode n){ return Node::null(); }
void debugPrint( const char* c );
-public:
- /** statistics class */
- class Statistics {
- public:
- IntStat d_inst_rounds;
- IntStat d_exh_inst_lemmas;
- IntStat d_mbqi_inst_lemmas;
- Statistics();
- ~Statistics();
- };
- Statistics d_statistics;
/** Identify this module */
std::string identify() const { return "ModelEngine"; }
};/* class ModelEngine */
diff --git a/src/theory/quantifiers/quant_conflict_find.cpp b/src/theory/quantifiers/quant_conflict_find.cpp
index bac2aa35c..1e484311c 100755
--- a/src/theory/quantifiers/quant_conflict_find.cpp
+++ b/src/theory/quantifiers/quant_conflict_find.cpp
@@ -108,7 +108,7 @@ void QuantInfo::initialize( QuantConflictFind * p, Node q, Node qn ) {
}
Trace("qcf-qregister-summary") << "QCF register : " << ( d_mg->isValid() ? "VALID " : "INVALID" ) << " : " << q << std::endl;
- if( d_mg->isValid() ){
+ if( d_mg->isValid() && options::qcfEagerCheckRd() ){
//optimization : record variable argument positions for terms that must be matched
std::vector< TNode > vars;
//TODO: revisit this, makes QCF faster, but misses conflicts due to caring about paths that may not be relevant (starExec jobs 14136/14137)
@@ -967,7 +967,11 @@ MatchGen::MatchGen()
d_n(),
d_type( typ_invalid ),
d_type_not()
-{}
+{
+ d_qni_size = 0;
+ d_child_counter = -1;
+ d_use_children = true;
+}
MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar )
@@ -980,6 +984,10 @@ MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar )
d_type(),
d_type_not()
{
+ //initialize temporary
+ d_child_counter = -1;
+ d_use_children = true;
+
Trace("qcf-qregister-debug") << "Make match gen for " << n << ", isVar = " << isVar << std::endl;
std::vector< Node > qni_apps;
d_qni_size = 0;
@@ -1853,7 +1861,7 @@ void MatchGen::setInvalid() {
}
bool MatchGen::isHandledBoolConnective( TNode n ) {
- return TermDb::isBoolConnective( n.getKind() ) && ( n.getKind()!=ITE || n.getType().isBoolean() );
+ return TermDb::isBoolConnective( n.getKind() ) && ( n.getKind()!=ITE || n.getType().isBoolean() ) && n.getKind()!=SEP_STAR;
}
bool MatchGen::isHandledUfTerm( TNode n ) {
@@ -2024,6 +2032,7 @@ void QuantConflictFind::setIrrelevantFunction( TNode f ) {
/** check */
void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
+ CodeTimer codeTimer(d_quantEngine->d_statistics.d_qcf_time);
if( quant_e==QuantifiersEngine::QEFFORT_CONFLICT ){
Trace("qcf-check") << "QCF : check : " << level << std::endl;
if( d_conflict ){
@@ -2098,7 +2107,7 @@ void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
++addedLemmas;
if( e==effort_conflict ){
d_quantEngine->markRelevant( q );
- ++(d_statistics.d_conflict_inst);
+ ++(d_quantEngine->d_statistics.d_instantiations_qcf);
if( options::qcfAllConflict() ){
isConflict = true;
}else{
@@ -2107,7 +2116,7 @@ void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
break;
}else if( e==effort_prop_eq ){
d_quantEngine->markRelevant( q );
- ++(d_statistics.d_prop_inst);
+ ++(d_quantEngine->d_statistics.d_instantiations_qcf);
}
}else{
Trace("qcf-inst") << " ... Failed to add instantiation" << std::endl;
@@ -2234,20 +2243,14 @@ void QuantConflictFind::debugPrintQuantBody( const char * c, Node q, Node n, boo
QuantConflictFind::Statistics::Statistics():
d_inst_rounds("QuantConflictFind::Inst_Rounds", 0),
- d_conflict_inst("QuantConflictFind::Instantiations_Conflict_Find", 0 ),
- d_prop_inst("QuantConflictFind::Instantiations_Prop", 0 ),
d_entailment_checks("QuantConflictFind::Entailment_Checks",0)
{
smtStatisticsRegistry()->registerStat(&d_inst_rounds);
- smtStatisticsRegistry()->registerStat(&d_conflict_inst);
- smtStatisticsRegistry()->registerStat(&d_prop_inst);
smtStatisticsRegistry()->registerStat(&d_entailment_checks);
}
QuantConflictFind::Statistics::~Statistics(){
smtStatisticsRegistry()->unregisterStat(&d_inst_rounds);
- smtStatisticsRegistry()->unregisterStat(&d_conflict_inst);
- smtStatisticsRegistry()->unregisterStat(&d_prop_inst);
smtStatisticsRegistry()->unregisterStat(&d_entailment_checks);
}
diff --git a/src/theory/quantifiers/quant_conflict_find.h b/src/theory/quantifiers/quant_conflict_find.h
index 47a66b1b1..dc8a9acb2 100755
--- a/src/theory/quantifiers/quant_conflict_find.h
+++ b/src/theory/quantifiers/quant_conflict_find.h
@@ -260,8 +260,6 @@ public:
class Statistics {
public:
IntStat d_inst_rounds;
- IntStat d_conflict_inst;
- IntStat d_prop_inst;
IntStat d_entailment_checks;
Statistics();
~Statistics();
diff --git a/src/theory/quantifiers/quant_split.cpp b/src/theory/quantifiers/quant_split.cpp
index 5aff1a848..df8533135 100755
--- a/src/theory/quantifiers/quant_split.cpp
+++ b/src/theory/quantifiers/quant_split.cpp
@@ -48,7 +48,7 @@ void QuantDSplit::preRegisterQuantifier( Node q ) {
}else{
int score = -1;
if( options::quantDynamicSplit()==quantifiers::QUANT_DSPLIT_MODE_AGG ){
- score = dt.isInterpretedFinite() ? 1 : -1;
+ score = dt.isInterpretedFinite() ? 1 : 0;
}else if( options::quantDynamicSplit()==quantifiers::QUANT_DSPLIT_MODE_DEFAULT ){
score = dt.isInterpretedFinite() ? 1 : -1;
}
@@ -73,6 +73,11 @@ bool QuantDSplit::needsCheck( Theory::Effort e ) {
return e>=Theory::EFFORT_FULL && !d_quant_to_reduce.empty();
}
+bool QuantDSplit::checkCompleteFor( Node q ) {
+ // true if we split q
+ return d_added_split.find( q )!=d_added_split.end();
+}
+
/* Call during quantifier engine's check */
void QuantDSplit::check( Theory::Effort e, unsigned quant_e ) {
//add lemmas ASAP (they are a reduction)
diff --git a/src/theory/quantifiers/quant_split.h b/src/theory/quantifiers/quant_split.h
index d36824998..3e3b08814 100755
--- a/src/theory/quantifiers/quant_split.h
+++ b/src/theory/quantifiers/quant_split.h
@@ -43,6 +43,7 @@ public:
/* Called for new quantifiers */
void registerQuantifier( Node q ) {}
void assertNode( Node n ) {}
+ bool checkCompleteFor( Node q );
/** Identify this module (for debugging, dynamic configuration, etc..) */
std::string identify() const { return "QuantDSplit"; }
};
diff --git a/src/theory/quantifiers/quant_util.cpp b/src/theory/quantifiers/quant_util.cpp
index b9aab0236..f4284a8ab 100755
--- a/src/theory/quantifiers/quant_util.cpp
+++ b/src/theory/quantifiers/quant_util.cpp
@@ -419,3 +419,107 @@ void QuantPhaseReq::getEntailPolarity( Node n, int child, bool hasPol, bool pol,
}
}
+void QuantEPR::registerNode( Node n, std::map< int, std::map< Node, bool > >& visited, bool beneathQuant, bool hasPol, bool pol ) {
+ int vindex = hasPol ? ( pol ? 1 : -1 ) : 0;
+ if( visited[vindex].find( n )==visited[vindex].end() ){
+ visited[vindex][n] = true;
+ Trace("quant-epr-debug") << "QuantEPR::registerNode " << n << std::endl;
+ if( n.getKind()==FORALL ){
+ if( beneathQuant || !hasPol || !pol ){
+ for( unsigned i=0; i<n[0].getNumChildren(); i++ ){
+ TypeNode tn = n[0][i].getType();
+ if( d_non_epr.find( tn )==d_non_epr.end() ){
+ Trace("quant-epr") << "Sort " << tn << " is non-EPR because of nested or possible existential quantification." << std::endl;
+ d_non_epr[tn] = true;
+ }
+ }
+ }else{
+ beneathQuant = true;
+ }
+ }
+ TypeNode tn = n.getType();
+
+ if( n.getNumChildren()>0 ){
+ if( tn.isSort() ){
+ if( d_non_epr.find( tn )==d_non_epr.end() ){
+ Trace("quant-epr") << "Sort " << tn << " is non-EPR because of " << n << std::endl;
+ d_non_epr[tn] = true;
+ }
+ }
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ bool newHasPol;
+ bool newPol;
+ QuantPhaseReq::getPolarity( n, i, hasPol, pol, newHasPol, newPol );
+ registerNode( n[i], visited, beneathQuant, newHasPol, newPol );
+ }
+ }else if( tn.isSort() ){
+ if( n.getKind()==BOUND_VARIABLE ){
+ if( d_consts.find( tn )==d_consts.end() ){
+ //mark that at least one constant must occur
+ d_consts[tn].clear();
+ }
+ }else if( std::find( d_consts[tn].begin(), d_consts[tn].end(), n )==d_consts[tn].end() ){
+ d_consts[tn].push_back( n );
+ Trace("quant-epr") << "...constant of type " << tn << " : " << n << std::endl;
+ }
+ }
+ }
+}
+
+void QuantEPR::registerAssertion( Node assertion ) {
+ std::map< int, std::map< Node, bool > > visited;
+ registerNode( assertion, visited, false, true, true );
+}
+
+void QuantEPR::finishInit() {
+ Trace("quant-epr-debug") << "QuantEPR::finishInit" << std::endl;
+ for( std::map< TypeNode, std::vector< Node > >::iterator it = d_consts.begin(); it != d_consts.end(); ++it ){
+ Assert( d_epr_axiom.find( it->first )==d_epr_axiom.end() );
+ Trace("quant-epr-debug") << "process " << it->first << std::endl;
+ if( d_non_epr.find( it->first )!=d_non_epr.end() ){
+ Trace("quant-epr-debug") << "...non-epr" << std::endl;
+ it->second.clear();
+ }else{
+ Trace("quant-epr-debug") << "...epr, #consts = " << it->second.size() << std::endl;
+ if( it->second.empty() ){
+ it->second.push_back( NodeManager::currentNM()->mkSkolem( "e", it->first, "EPR base constant" ) );
+ }
+ if( Trace.isOn("quant-epr") ){
+ Trace("quant-epr") << "Type " << it->first << " is EPR, with constants : " << std::endl;
+ for( unsigned i=0; i<it->second.size(); i++ ){
+ Trace("quant-epr") << " " << it->second[i] << std::endl;
+ }
+ }
+ }
+ }
+}
+
+bool QuantEPR::isEPRConstant( TypeNode tn, Node k ) {
+ return std::find( d_consts[tn].begin(), d_consts[tn].end(), k )!=d_consts[tn].end();
+}
+
+void QuantEPR::addEPRConstant( TypeNode tn, Node k ) {
+ Assert( isEPR( tn ) );
+ Assert( d_epr_axiom.find( tn )==d_epr_axiom.end() );
+ if( !isEPRConstant( tn, k ) ){
+ d_consts[tn].push_back( k );
+ }
+}
+
+Node QuantEPR::mkEPRAxiom( TypeNode tn ) {
+ Assert( isEPR( tn ) );
+ std::map< TypeNode, Node >::iterator ita = d_epr_axiom.find( tn );
+ if( ita==d_epr_axiom.end() ){
+ std::vector< Node > disj;
+ Node x = NodeManager::currentNM()->mkBoundVar( tn );
+ for( unsigned i=0; i<d_consts[tn].size(); i++ ){
+ disj.push_back( NodeManager::currentNM()->mkNode( tn.isBoolean() ? IFF : EQUAL, x, d_consts[tn][i] ) );
+ }
+ Assert( !disj.empty() );
+ d_epr_axiom[tn] = NodeManager::currentNM()->mkNode( FORALL, NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, x ), disj.size()==1 ? disj[0] : NodeManager::currentNM()->mkNode( OR, disj ) );
+ return d_epr_axiom[tn];
+ }else{
+ return ita->second;
+ }
+}
+
diff --git a/src/theory/quantifiers/quant_util.h b/src/theory/quantifiers/quant_util.h
index 79cdae437..3ff21aa6e 100755
--- a/src/theory/quantifiers/quant_util.h
+++ b/src/theory/quantifiers/quant_util.h
@@ -51,8 +51,10 @@ public:
virtual void reset_round( Theory::Effort e ){}
/* Call during quantifier engine's check */
virtual void check( Theory::Effort e, unsigned quant_e ) = 0;
- /* check was complete (e.g. no lemmas implies a model) */
+ /* check was complete, return false if there is no way to answer "SAT", true if maybe can answer "SAT" */
virtual bool checkComplete() { return true; }
+ /* check was complete for quantified formula q (e.g. no lemmas implies a model) */
+ virtual bool checkCompleteFor( Node q ) { return false; }
/* Called for new quantified formulas */
virtual void preRegisterQuantifier( Node q ) { }
/* Called for new quantifiers after owners are finalized */
@@ -149,7 +151,7 @@ public:
};
-class EqualityQuery : public QuantifiersUtil{
+class EqualityQuery : public QuantifiersUtil {
public:
EqualityQuery(){}
virtual ~EqualityQuery(){};
@@ -171,6 +173,38 @@ public:
virtual TNode getCongruentTerm( Node f, std::vector< TNode >& args ) = 0;
};/* class EqualityQuery */
+class QuantEPR
+{
+private:
+ void registerNode( Node n, std::map< int, std::map< Node, bool > >& visited, bool beneathQuant, bool hasPol, bool pol );
+ /** non-epr */
+ std::map< TypeNode, bool > d_non_epr;
+ /** axioms for epr */
+ std::map< TypeNode, Node > d_epr_axiom;
+public:
+ QuantEPR(){}
+ virtual ~QuantEPR(){}
+ /** constants per type */
+ std::map< TypeNode, std::vector< Node > > d_consts;
+ /* reset */
+ //bool reset( Theory::Effort e ) {}
+ /** identify */
+ //std::string identify() const { return "QuantEPR"; }
+ /** register assertion */
+ void registerAssertion( Node assertion );
+ /** finish init */
+ void finishInit();
+ /** is EPR */
+ bool isEPR( TypeNode tn ) const { return d_non_epr.find( tn )==d_non_epr.end(); }
+ /** is EPR constant */
+ bool isEPRConstant( TypeNode tn, Node k );
+ /** add EPR constant */
+ void addEPRConstant( TypeNode tn, Node k );
+ /** get EPR axiom */
+ Node mkEPRAxiom( TypeNode tn );
+ /** has EPR axiom */
+ bool hasEPRAxiom( TypeNode tn ) const { return d_epr_axiom.find( tn )!=d_epr_axiom.end(); }
+};
}
}
diff --git a/src/theory/quantifiers/quantifiers_rewriter.cpp b/src/theory/quantifiers/quantifiers_rewriter.cpp
index 963889a85..de8875ae3 100755
--- a/src/theory/quantifiers/quantifiers_rewriter.cpp
+++ b/src/theory/quantifiers/quantifiers_rewriter.cpp
@@ -20,11 +20,12 @@
#include "theory/quantifiers/trigger.h"
using namespace std;
-using namespace CVC4;
using namespace CVC4::kind;
using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::quantifiers;
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
bool QuantifiersRewriter::isClause( Node n ){
if( isLiteral( n ) ){
@@ -1074,9 +1075,9 @@ Node QuantifiersRewriter::computeVarElimination( Node body, std::vector< Node >&
return body;
}
-Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, bool pol ){
+Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, std::vector< Node >& nargs, bool pol, bool prenexAgg ){
if( body.getKind()==FORALL ){
- if( pol && ( options::prenexQuant()==PRENEX_ALL || body.getNumChildren()==2 ) ){
+ if( ( pol || prenexAgg ) && ( options::prenexQuantUser() || body.getNumChildren()==2 ) ){
std::vector< Node > terms;
std::vector< Node > subs;
//for doing prenexing of same-signed quantifiers
@@ -1085,14 +1086,27 @@ Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, b
terms.push_back( body[0][i] );
subs.push_back( NodeManager::currentNM()->mkBoundVar( body[0][i].getType() ) );
}
- args.insert( args.end(), subs.begin(), subs.end() );
+ if( pol ){
+ args.insert( args.end(), subs.begin(), subs.end() );
+ }else{
+ nargs.insert( nargs.end(), subs.begin(), subs.end() );
+ }
Node newBody = body[1];
newBody = newBody.substitute( terms.begin(), terms.end(), subs.begin(), subs.end() );
return newBody;
- }else{
- return body;
}
- }else{
+ //must remove structure
+ }else if( prenexAgg && body.getKind()==kind::ITE && body.getType().isBoolean() ){
+ Node nn = NodeManager::currentNM()->mkNode( kind::AND,
+ NodeManager::currentNM()->mkNode( kind::OR, body[0].notNode(), body[1] ),
+ NodeManager::currentNM()->mkNode( kind::OR, body[0], body[2] ) );
+ return computePrenex( nn, args, nargs, pol, prenexAgg );
+ }else if( prenexAgg && body.getKind()==kind::IFF ){
+ Node nn = NodeManager::currentNM()->mkNode( kind::AND,
+ NodeManager::currentNM()->mkNode( kind::OR, body[0].notNode(), body[1] ),
+ NodeManager::currentNM()->mkNode( kind::OR, body[0], body[1].notNode() ) );
+ return computePrenex( nn, args, nargs, pol, prenexAgg );
+ }else if( body.getType().isBoolean() ){
Assert( body.getKind()!=EXISTS );
bool childrenChanged = false;
std::vector< Node > newChildren;
@@ -1101,7 +1115,7 @@ Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, b
bool newPol;
QuantPhaseReq::getPolarity( body, i, true, pol, newHasPol, newPol );
if( newHasPol ){
- Node n = computePrenex( body[i], args, newPol );
+ Node n = computePrenex( body[i], args, nargs, newPol, prenexAgg );
newChildren.push_back( n );
if( n!=body[i] ){
childrenChanged = true;
@@ -1116,10 +1130,98 @@ Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, b
}else{
return NodeManager::currentNM()->mkNode( body.getKind(), newChildren );
}
+ }
+ }
+ return body;
+}
+
+Node QuantifiersRewriter::computePrenexAgg( Node n, bool topLevel ){
+ if( containsQuantifiers( n ) ){
+ if( topLevel && options::prenexQuant()==PRENEX_QUANT_DISJ_NORMAL && ( n.getKind()==AND || ( n.getKind()==NOT && n[0].getKind()==OR ) ) ){
+ std::vector< Node > children;
+ Node nc = n.getKind()==NOT ? n[0] : n;
+ for( unsigned i=0; i<nc.getNumChildren(); i++ ){
+ Node ncc = computePrenexAgg( nc[i], true );
+ if( n.getKind()==NOT ){
+ ncc = ncc.negate();
+ }
+ children.push_back( ncc );
+ }
+ return NodeManager::currentNM()->mkNode( AND, children );
+ }else if( n.getKind()==NOT ){
+ return computePrenexAgg( n[0], false ).negate();
+ }else if( n.getKind()==FORALL ){
+ /*
+ Node nn = computePrenexAgg( n[1], false );
+ if( nn!=n[1] ){
+ if( n.getNumChildren()==2 ){
+ return NodeManager::currentNM()->mkNode( FORALL, n[0], nn );
+ }else{
+ return NodeManager::currentNM()->mkNode( FORALL, n[0], nn, n[2] );
+ }
+ }
+ */
+ std::vector< Node > children;
+ if( n[1].getKind()==OR && options::prenexQuant()==PRENEX_QUANT_DISJ_NORMAL ){
+ for( unsigned i=0; i<n[1].getNumChildren(); i++ ){
+ children.push_back( computePrenexAgg( n[1][i], false ) );
+ }
+ }else{
+ children.push_back( computePrenexAgg( n[1], false ) );
+ }
+ std::vector< Node > args;
+ for( unsigned i=0; i<n[0].getNumChildren(); i++ ){
+ args.push_back( n[0][i] );
+ }
+ std::vector< Node > nargs;
+ //for each child, strip top level quant
+ for( unsigned i=0; i<children.size(); i++ ){
+ if( children[i].getKind()==FORALL ){
+ for( unsigned j=0; j<children[i][0].getNumChildren(); j++ ){
+ args.push_back( children[i][0][j] );
+ }
+ children[i] = children[i][1];
+ }
+ }
+ Node nb = children.size()==1 ? children[0] : NodeManager::currentNM()->mkNode( OR, children );
+ return mkForall( args, nb, true );
}else{
- return body;
+ std::vector< Node > args;
+ std::vector< Node > nargs;
+ Node nn = computePrenex( n, args, nargs, true, true );
+ if( n!=nn ){
+ Node nnn = computePrenexAgg( nn, false );
+ //merge prenex
+ if( nnn.getKind()==FORALL ){
+ for( unsigned i=0; i<nnn[0].getNumChildren(); i++ ){
+ args.push_back( nnn[0][i] );
+ }
+ nnn = nnn[1];
+ //pos polarity variables are inner
+ if( !args.empty() ){
+ nnn = mkForall( args, nnn, true );
+ }
+ args.clear();
+ }else if( nnn.getKind()==NOT && nnn[0].getKind()==FORALL ){
+ for( unsigned i=0; i<nnn[0][0].getNumChildren(); i++ ){
+ nargs.push_back( nnn[0][0][i] );
+ }
+ nnn = nnn[0][1].negate();
+ }
+ if( !nargs.empty() ){
+ nnn = mkForall( nargs, nnn.negate(), true ).negate();
+ }
+ if( !args.empty() ){
+ nnn = mkForall( args, nnn, true );
+ }
+ return nnn;
+ }else{
+ Assert( args.empty() );
+ Assert( nargs.empty() );
+ }
}
}
+ return n;
}
Node QuantifiersRewriter::computeSplit( std::vector< Node >& args, Node body, QAttributes& qa ) {
@@ -1237,6 +1339,26 @@ Node QuantifiersRewriter::mkForAll( std::vector< Node >& args, Node body, QAttri
return NodeManager::currentNM()->mkNode( kind::FORALL, children );
}
}
+Node QuantifiersRewriter::mkForall( std::vector< Node >& args, Node body, bool marked ) {
+ if( args.empty() ){
+ return body;
+ }else{
+ std::vector< Node > children;
+ children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, args ) );
+ children.push_back( body );
+ std::vector< Node > iplc;
+ if( marked ){
+ Node avar = NodeManager::currentNM()->mkSkolem( "id", NodeManager::currentNM()->booleanType() );
+ QuantIdNumAttribute ida;
+ avar.setAttribute(ida,0);
+ iplc.push_back( NodeManager::currentNM()->mkNode( INST_ATTRIBUTE, avar ) );
+ }
+ if( !iplc.empty() ){
+ children.push_back( NodeManager::currentNM()->mkNode( INST_PATTERN_LIST, iplc ) );
+ }
+ return NodeManager::currentNM()->mkNode( FORALL, children );
+ }
+}
//computes miniscoping, also eliminates variables that do not occur free in body
Node QuantifiersRewriter::computeMiniscoping( std::vector< Node >& args, Node body, QAttributes& qa ){
@@ -1294,21 +1416,25 @@ Node QuantifiersRewriter::computeMiniscoping( std::vector< Node >& args, Node bo
}
Node QuantifiersRewriter::computeAggressiveMiniscoping( std::vector< Node >& args, Node body ){
- std::map< Node, std::vector< Node > > varLits;
- std::map< Node, std::vector< Node > > litVars;
- if( body.getKind()==OR ){
+ std::map<Node, std::vector<Node> > varLits;
+ std::map<Node, std::vector<Node> > litVars;
+ if (body.getKind() == OR) {
Trace("ag-miniscope") << "compute aggressive miniscoping on " << body << std::endl;
- for( size_t i=0; i<body.getNumChildren(); i++ ){
- std::vector< Node > activeArgs;
- computeArgVec( args, activeArgs, body[i] );
- for (unsigned j=0; j<activeArgs.size(); j++ ){
- varLits[activeArgs[j]].push_back( body[i] );
- }
- litVars[body[i]].insert( litVars[body[i]].begin(), activeArgs.begin(), activeArgs.end() );
+ for (size_t i = 0; i < body.getNumChildren(); i++) {
+ std::vector<Node> activeArgs;
+ computeArgVec(args, activeArgs, body[i]);
+ for (unsigned j = 0; j < activeArgs.size(); j++) {
+ varLits[activeArgs[j]].push_back(body[i]);
+ }
+ std::vector<Node>& lit_body_i = litVars[body[i]];
+ std::vector<Node>::iterator lit_body_i_begin = lit_body_i.begin();
+ std::vector<Node>::const_iterator active_begin = activeArgs.begin();
+ std::vector<Node>::const_iterator active_end = activeArgs.end();
+ lit_body_i.insert(lit_body_i_begin, active_begin, active_end);
}
//find the variable in the least number of literals
Node bestVar;
- for( std::map< Node, std::vector< Node > >::iterator it = varLits.begin(); it != varLits.end(); ++it ){
+ for( std::map< Node, std::vector<Node> >::iterator it = varLits.begin(); it != varLits.end(); ++it ){
if( bestVar.isNull() || varLits[bestVar].size()>it->second.size() ){
bestVar = it->first;
}
@@ -1318,9 +1444,9 @@ Node QuantifiersRewriter::computeAggressiveMiniscoping( std::vector< Node >& arg
//we can miniscope
Trace("ag-miniscope") << "Miniscope on " << bestVar << std::endl;
//make the bodies
- std::vector< Node > qlit1;
+ std::vector<Node> qlit1;
qlit1.insert( qlit1.begin(), varLits[bestVar].begin(), varLits[bestVar].end() );
- std::vector< Node > qlitt;
+ std::vector<Node> qlitt;
//for all literals not containing bestVar
for( size_t i=0; i<body.getNumChildren(); i++ ){
if( std::find( qlit1.begin(), qlit1.end(), body[i] )==qlit1.end() ){
@@ -1328,9 +1454,9 @@ Node QuantifiersRewriter::computeAggressiveMiniscoping( std::vector< Node >& arg
}
}
//make the variable lists
- std::vector< Node > qvl1;
- std::vector< Node > qvl2;
- std::vector< Node > qvsh;
+ std::vector<Node> qvl1;
+ std::vector<Node> qvl2;
+ std::vector<Node> qvsh;
for( unsigned i=0; i<args.size(); i++ ){
bool found1 = false;
bool found2 = false;
@@ -1358,8 +1484,8 @@ Node QuantifiersRewriter::computeAggressiveMiniscoping( std::vector< Node >& arg
Assert( !qvl1.empty() );
Assert( !qvl2.empty() || !qvsh.empty() );
//check for literals that only contain shared variables
- std::vector< Node > qlitsh;
- std::vector< Node > qlit2;
+ std::vector<Node> qlitsh;
+ std::vector<Node> qlit2;
for( size_t i=0; i<qlitt.size(); i++ ){
bool hasVar2 = false;
for( size_t j=0; j<litVars[qlitt[i]].size(); j++ ){
@@ -1413,7 +1539,7 @@ bool QuantifiersRewriter::doOperation( Node q, int computeOption, QAttributes& q
}else if( computeOption==COMPUTE_COND_SPLIT ){
return ( options::iteDtTesterSplitQuant() || options::condVarSplitQuant() ) && !is_strict_trigger;
}else if( computeOption==COMPUTE_PRENEX ){
- return options::prenexQuant()!=PRENEX_NONE && !options::aggressiveMiniscopeQuant() && is_std;
+ return options::prenexQuant()!=PRENEX_QUANT_NONE && !options::aggressiveMiniscopeQuant() && is_std;
}else if( computeOption==COMPUTE_VAR_ELIMINATION ){
return ( options::varElimQuant() || options::dtVarExpandQuant() ) && is_std;
}else{
@@ -1423,7 +1549,7 @@ bool QuantifiersRewriter::doOperation( Node q, int computeOption, QAttributes& q
//general method for computing various rewrites
Node QuantifiersRewriter::computeOperation( Node f, int computeOption, QAttributes& qa ){
- Trace("quantifiers-rewrite-debug") << "Compute operation " << computeOption << " on " << f << std::endl;
+ Trace("quantifiers-rewrite-debug") << "Compute operation " << computeOption << " on " << f << " " << qa.d_qid_num << std::endl;
std::vector< Node > args;
for( unsigned i=0; i<f[0].getNumChildren(); i++ ){
args.push_back( f[0][i] );
@@ -1432,6 +1558,12 @@ Node QuantifiersRewriter::computeOperation( Node f, int computeOption, QAttribut
if( computeOption==COMPUTE_ELIM_SYMBOLS ){
n = computeElimSymbols( n );
}else if( computeOption==COMPUTE_MINISCOPING ){
+ if( options::prenexQuant()==PRENEX_QUANT_DISJ_NORMAL || options::prenexQuant()==PRENEX_QUANT_NORMAL ){
+ if( !qa.d_qid_num.isNull() ){
+ //already processed this, return self
+ return f;
+ }
+ }
//return directly
return computeMiniscoping( args, n, qa );
}else if( computeOption==COMPUTE_AGGRESSIVE_MINISCOPING ){
@@ -1446,7 +1578,14 @@ Node QuantifiersRewriter::computeOperation( Node f, int computeOption, QAttribut
}else if( computeOption==COMPUTE_COND_SPLIT ){
n = computeCondSplit( n, qa );
}else if( computeOption==COMPUTE_PRENEX ){
- n = computePrenex( n, args, true );
+ if( options::prenexQuant()==PRENEX_QUANT_DISJ_NORMAL || options::prenexQuant()==PRENEX_QUANT_NORMAL ){
+ //will rewrite at preprocess time
+ return f;
+ }else{
+ std::vector< Node > nargs;
+ n = computePrenex( n, args, nargs, true, false );
+ Assert( nargs.empty() );
+ }
}else if( computeOption==COMPUTE_VAR_ELIMINATION ){
n = computeVarElimination( n, args, qa );
}
@@ -1592,6 +1731,15 @@ bool QuantifiersRewriter::containsQuantifiers( Node n ){
return cq;
}
}
+bool QuantifiersRewriter::isPrenexNormalForm( Node n ) {
+ if( n.getKind()==FORALL ){
+ return n[1].getKind()!=FORALL && isPrenexNormalForm( n[1] );
+ }else if( n.getKind()==NOT ){
+ return n[0].getKind()!=NOT && isPrenexNormalForm( n[0] );
+ }else{
+ return !containsQuantifiers( n );
+ }
+}
Node QuantifiersRewriter::preSkolemizeQuantifiers( Node n, bool polarity, std::vector< TypeNode >& fvTypes, std::vector< TNode >& fvs ){
Trace("pre-sk") << "Pre-skolem " << n << " " << polarity << " " << fvs.size() << endl;
@@ -1662,21 +1810,37 @@ Node QuantifiersRewriter::preSkolemizeQuantifiers( Node n, bool polarity, std::v
return n;
}
+
Node QuantifiersRewriter::preprocess( Node n, bool isInst ) {
Node prev = n;
- if( options::preSkolemQuant() ){
- if( !isInst || !options::preSkolemQuantNested() ){
- Trace("quantifiers-preprocess-debug") << "Pre-skolemize " << n << "..." << std::endl;
- //apply pre-skolemization to existential quantifiers
- std::vector< TypeNode > fvTypes;
- std::vector< TNode > fvs;
- n = quantifiers::QuantifiersRewriter::preSkolemizeQuantifiers( prev, true, fvTypes, fvs );
+ if( n.getKind() == kind::REWRITE_RULE ){
+ n = quantifiers::QuantifiersRewriter::rewriteRewriteRule( n );
+ }else{
+ if( options::preSkolemQuant() ){
+ if( !isInst || !options::preSkolemQuantNested() ){
+ Trace("quantifiers-preprocess-debug") << "Pre-skolemize " << n << "..." << std::endl;
+ //apply pre-skolemization to existential quantifiers
+ std::vector< TypeNode > fvTypes;
+ std::vector< TNode > fvs;
+ n = quantifiers::QuantifiersRewriter::preSkolemizeQuantifiers( prev, true, fvTypes, fvs );
+ }
}
}
+ //pull all quantifiers globally
+ if( options::prenexQuant()==PRENEX_QUANT_DISJ_NORMAL || options::prenexQuant()==PRENEX_QUANT_NORMAL ){
+ Trace("quantifiers-prenex") << "Prenexing : " << n << std::endl;
+ n = quantifiers::QuantifiersRewriter::computePrenexAgg( n, true );
+ n = Rewriter::rewrite( n );
+ Trace("quantifiers-prenex") << "Prenexing returned : " << n << std::endl;
+ //Assert( isPrenexNormalForm( n ) );
+ }
if( n!=prev ){
- Trace("quantifiers-preprocess") << "Preprocess " << prev<< std::endl;
+ Trace("quantifiers-preprocess") << "Preprocess " << prev << std::endl;
Trace("quantifiers-preprocess") << "..returned " << n << std::endl;
}
return n;
}
+}/* CVC4::theory::quantifiers namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
diff --git a/src/theory/quantifiers/quantifiers_rewriter.h b/src/theory/quantifiers/quantifiers_rewriter.h
index 60dc8ab10..90a22f4b7 100755
--- a/src/theory/quantifiers/quantifiers_rewriter.h
+++ b/src/theory/quantifiers/quantifiers_rewriter.h
@@ -38,7 +38,6 @@ public:
private:
static bool addCheckElimChild( std::vector< Node >& children, Node c, Kind k, std::map< Node, bool >& lit_pol, bool& childrenChanged );
static void addNodeToOrBuilder( Node n, NodeBuilder<>& t );
- static Node mkForAll( std::vector< Node >& args, Node body, QAttributes& qa );
static void computeArgs( std::vector< Node >& args, std::map< Node, bool >& activeMap, Node n, std::map< Node, bool >& visited );
static void computeArgVec( std::vector< Node >& args, std::vector< Node >& activeArgs, Node n );
static void computeArgVec2( std::vector< Node >& args, std::vector< Node >& activeArgs, Node n, Node ipl );
@@ -53,14 +52,15 @@ private:
static bool computeVariableElimLit( Node n, bool pol, std::vector< Node >& args, std::vector< Node >& var, std::vector< Node >& subs,
std::map< Node, std::map< bool, std::map< Node, bool > > >& num_bounds );
static Node computeVarElimination2( Node body, std::vector< Node >& args, QAttributes& qa );
-private:
+public:
static Node computeElimSymbols( Node body );
static Node computeMiniscoping( std::vector< Node >& args, Node body, QAttributes& qa );
static Node computeAggressiveMiniscoping( std::vector< Node >& args, Node body );
//cache is dependent upon currCond, icache is not, new_conds are negated conditions
static Node computeProcessTerms( Node body, std::vector< Node >& new_vars, std::vector< Node >& new_conds, Node q, QAttributes& qa );
static Node computeCondSplit( Node body, QAttributes& qa );
- static Node computePrenex( Node body, std::vector< Node >& args, bool pol );
+ static Node computePrenex( Node body, std::vector< Node >& args, std::vector< Node >& nargs, bool pol, bool prenexAgg );
+ static Node computePrenexAgg( Node n, bool topLevel );
static Node computeSplit( std::vector< Node >& args, Node body, QAttributes& qa );
static Node computeVarElimination( Node body, std::vector< Node >& args, QAttributes& qa );
private:
@@ -89,8 +89,11 @@ private:
static Node preSkolemizeQuantifiers(Node n, bool polarity, std::vector< TypeNode >& fvTypes, std::vector<TNode>& fvs);
public:
static Node rewriteRewriteRule( Node r );
- static bool containsQuantifiers(Node n);
+ static bool containsQuantifiers( Node n );
+ static bool isPrenexNormalForm( Node n );
static Node preprocess( Node n, bool isInst = false );
+ static Node mkForAll( std::vector< Node >& args, Node body, QAttributes& qa );
+ static Node mkForall( std::vector< Node >& args, Node body, bool marked = false );
};/* class QuantifiersRewriter */
}/* CVC4::theory::quantifiers namespace */
diff --git a/src/theory/quantifiers/relevant_domain.h b/src/theory/quantifiers/relevant_domain.h
index 2b90520fd..aae8f6c5b 100755
--- a/src/theory/quantifiers/relevant_domain.h
+++ b/src/theory/quantifiers/relevant_domain.h
@@ -51,7 +51,10 @@ private:
//what each literal does
class RDomainLit {
public:
- RDomainLit() : d_merge(false){}
+ RDomainLit() : d_merge(false){
+ d_rd[0] = NULL;
+ d_rd[1] = NULL;
+ }
~RDomainLit(){}
bool d_merge;
RDomain * d_rd[2];
@@ -72,6 +75,7 @@ public:
RDomain * getRDomain( Node n, int i, bool getParent = true );
};/* class RelevantDomain */
+
}/* CVC4::theory::quantifiers namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/quantifiers/rewrite_engine.cpp b/src/theory/quantifiers/rewrite_engine.cpp
index 2c58b8f77..ec1b41a98 100755
--- a/src/theory/quantifiers/rewrite_engine.cpp
+++ b/src/theory/quantifiers/rewrite_engine.cpp
@@ -20,6 +20,7 @@
#include "theory/quantifiers/first_order_model.h"
#include "theory/quantifiers/inst_match_generator.h"
#include "theory/quantifiers/model_engine.h"
+#include "theory/quantifiers/quant_conflict_find.h"
#include "theory/quantifiers/quant_util.h"
#include "theory/quantifiers/term_database.h"
#include "theory/theory_engine.h"
@@ -204,6 +205,7 @@ int RewriteEngine::checkRewriteRule( Node f, Theory::Effort e ) {
Trace("rewrite-engine-inst-debug") << "...No qinfo." << std::endl;
}
}
+ d_quantEngine->d_statistics.d_instantiations_rr += addedLemmas;
Trace("rewrite-engine-inst") << "-> Generated " << addedLemmas << " lemmas." << std::endl;
return addedLemmas;
}
@@ -294,6 +296,11 @@ void RewriteEngine::assertNode( Node n ) {
}
+bool RewriteEngine::checkCompleteFor( Node q ) {
+ // by semantics of rewrite rules, saturation -> SAT
+ return std::find( d_rr_quant.begin(), d_rr_quant.end(), q )!=d_rr_quant.end();
+}
+
Node RewriteEngine::getInstConstNode( Node n, Node q ) {
std::map< Node, Node >::iterator it = d_inst_const_node[q].find( n );
if( it==d_inst_const_node[q].end() ){
diff --git a/src/theory/quantifiers/rewrite_engine.h b/src/theory/quantifiers/rewrite_engine.h
index 424530696..ef3337e53 100755
--- a/src/theory/quantifiers/rewrite_engine.h
+++ b/src/theory/quantifiers/rewrite_engine.h
@@ -18,19 +18,17 @@
#ifndef __CVC4__REWRITE_ENGINE_H
#define __CVC4__REWRITE_ENGINE_H
-#include "theory/quantifiers_engine.h"
-#include "theory/quantifiers/trigger.h"
-
+#include "context/cdchunk_list.h"
#include "context/context.h"
#include "context/context_mm.h"
-#include "context/cdchunk_list.h"
+#include "theory/quantifiers/trigger.h"
+#include "theory/quantifiers/quant_conflict_find.h"
+#include "theory/quantifiers_engine.h"
namespace CVC4 {
namespace theory {
namespace quantifiers {
-class QuantInfo;
-
class RewriteEngine : public QuantifiersModule
{
typedef context::CDHashMap<Node, bool, NodeHashFunction> NodeBoolMap;
@@ -57,7 +55,8 @@ public:
bool needsCheck( Theory::Effort e );
void check( Theory::Effort e, unsigned quant_e );
void registerQuantifier( Node f );
- void assertNode( Node n );
+ void assertNode( Node n );
+ bool checkCompleteFor( Node q );
/** Identify this module */
std::string identify() const { return "RewriteEngine"; }
};
diff --git a/src/theory/quantifiers/term_database.cpp b/src/theory/quantifiers/term_database.cpp
index d3a5e178f..2c6bfb7d3 100755
--- a/src/theory/quantifiers/term_database.cpp
+++ b/src/theory/quantifiers/term_database.cpp
@@ -33,14 +33,14 @@
#include "util/bitvector.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;
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
TNode TermArgTrie::existsTerm( std::vector< TNode >& reps, int argIndex ) {
if( argIndex==(int)reps.size() ){
if( d_data.empty() ){
@@ -84,15 +84,25 @@ void TermArgTrie::debugPrint( const char * c, Node n, unsigned depth ) {
}
}
-TermDb::TermDb( context::Context* c, context::UserContext* u, QuantifiersEngine* qe ) : d_quantEngine( qe ), d_inactive_map( c ), d_op_id_count( 0 ), d_typ_id_count( 0 ) {
- d_true = NodeManager::currentNM()->mkConst( true );
- d_false = NodeManager::currentNM()->mkConst( false );
- d_zero = NodeManager::currentNM()->mkConst( Rational( 0 ) );
- d_one = NodeManager::currentNM()->mkConst( Rational( 1 ) );
- if( options::ceGuidedInst() ){
- d_sygus_tdb = new TermDbSygus( c, qe );
- }else{
- d_sygus_tdb = NULL;
+TermDb::TermDb(context::Context* c, context::UserContext* u,
+ QuantifiersEngine* qe)
+ : d_quantEngine(qe),
+ d_inactive_map(c),
+ d_op_id_count(0),
+ d_typ_id_count(0),
+ d_sygus_tdb(NULL) {
+ d_consistent_ee = true;
+ d_true = NodeManager::currentNM()->mkConst(true);
+ d_false = NodeManager::currentNM()->mkConst(false);
+ d_zero = NodeManager::currentNM()->mkConst(Rational(0));
+ d_one = NodeManager::currentNM()->mkConst(Rational(1));
+ if (options::ceGuidedInst()) {
+ d_sygus_tdb = new TermDbSygus(c, qe);
+ }
+}
+TermDb::~TermDb(){
+ if(d_sygus_tdb) {
+ delete d_sygus_tdb;
}
}
@@ -129,7 +139,7 @@ Node TermDb::getMatchOperator( Node n ) {
Kind k = n.getKind();
//datatype operators may be parametric, always assume they are
if( k==SELECT || k==STORE || k==UNION || k==INTERSECTION || k==SUBSET || k==SETMINUS || k==MEMBER || k==SINGLETON ||
- k==APPLY_SELECTOR_TOTAL || k==APPLY_TESTER ){
+ k==APPLY_SELECTOR_TOTAL || k==APPLY_TESTER || k==SEP_PTO ){
//since it is parametric, use a particular one as op
TypeNode tn = n[0].getType();
Node op = n.getOperator();
@@ -175,17 +185,6 @@ void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant, bool wi
if( d_sygus_tdb ){
d_sygus_tdb->registerEvalTerm( n );
}
-
- if( options::eagerInstQuant() ){
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- if( !n.hasAttribute(InstLevelAttribute()) && n.getAttribute(InstLevelAttribute())==0 ){
- int addedLemmas = 0;
- for( unsigned i=0; i<d_op_triggers[op].size(); i++ ){
- addedLemmas += d_op_triggers[op][i]->addTerm( n );
- }
- }
- }
- }
}
}else{
setTermInactive( n );
@@ -1319,19 +1318,25 @@ bool TermDb::mayComplete( TypeNode tn ) {
void TermDb::computeVarContains( Node n, std::vector< Node >& varContains ) {
std::map< Node, bool > visited;
- computeVarContains2( n, varContains, visited );
+ computeVarContains2( n, INST_CONSTANT, varContains, visited );
+}
+
+void TermDb::computeQuantContains( Node n, std::vector< Node >& quantContains ) {
+ std::map< Node, bool > visited;
+ computeVarContains2( n, FORALL, quantContains, visited );
}
-void TermDb::computeVarContains2( Node n, std::vector< Node >& varContains, std::map< Node, bool >& visited ){
+
+void TermDb::computeVarContains2( Node n, Kind k, std::vector< Node >& varContains, std::map< Node, bool >& visited ){
if( visited.find( n )==visited.end() ){
visited[n] = true;
- if( n.getKind()==INST_CONSTANT ){
+ if( n.getKind()==k ){
if( std::find( varContains.begin(), varContains.end(), n )==varContains.end() ){
varContains.push_back( n );
}
}else{
for( unsigned i=0; i<n.getNumChildren(); i++ ){
- computeVarContains2( n[i], varContains, visited );
+ computeVarContains2( n[i], k, varContains, visited );
}
}
}
@@ -1963,7 +1968,7 @@ bool TermDb::isComm( Kind k ) {
}
bool TermDb::isBoolConnective( Kind k ) {
- return k==OR || k==AND || k==IFF || k==ITE || k==FORALL || k==NOT;
+ return k==OR || k==AND || k==IFF || k==ITE || k==FORALL || k==NOT || k==SEP_STAR;
}
void TermDb::registerTrigger( theory::inst::Trigger* tr, Node op ){
@@ -2163,6 +2168,10 @@ void TermDb::computeQuantAttributes( Node q, QAttributes& qa ){
qa.d_quant_elim_partial = true;
//don't set owner, should happen naturally
}
+ if( avar.hasAttribute(QuantIdNumAttribute()) ){
+ qa.d_qid_num = avar;
+ Trace("quant-attr") << "Attribute : id number " << qa.d_qid_num.getAttribute(QuantIdNumAttribute()) << " : " << q << std::endl;
+ }
if( avar.getKind()==REWRITE_RULE ){
Trace("quant-attr") << "Attribute : rewrite rule : " << q << std::endl;
Assert( i==0 );
@@ -2254,6 +2263,25 @@ bool TermDb::isQAttrQuantElimPartial( Node q ) {
}
}
+int TermDb::getQAttrQuantIdNum( Node q ) {
+ std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
+ if( it!=d_qattr.end() ){
+ if( !it->second.d_qid_num.isNull() ){
+ return it->second.d_qid_num.getAttribute(QuantIdNumAttribute());
+ }
+ }
+ return -1;
+}
+
+Node TermDb::getQAttrQuantIdNumNode( Node q ) {
+ std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
+ if( it==d_qattr.end() ){
+ return Node::null();
+ }else{
+ return it->second.d_qid_num;
+ }
+}
+
TermDbSygus::TermDbSygus( context::Context* c, QuantifiersEngine* qe ) : d_quantEngine( qe ){
d_true = NodeManager::currentNM()->mkConst( true );
d_false = NodeManager::currentNM()->mkConst( false );
@@ -3125,7 +3153,6 @@ void TermDbSygus::printSygusTerm( std::ostream& out, Node n, std::vector< Node >
std::string name = std::string( str.begin() + found +1, str.end() );
out << name;
}else{
- Trace("ajr-temp") << "[[print operator " << op << "]]" << std::endl;
out << op;
}
if( n.getNumChildren()>0 ){
@@ -3281,3 +3308,6 @@ void TermDbSygus::registerModelValue( Node a, Node v, std::vector< Node >& lems
}
}
+}/* CVC4::theory::quantifiers namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
diff --git a/src/theory/quantifiers/term_database.h b/src/theory/quantifiers/term_database.h
index 7ab3668eb..d4fdaa5e5 100755
--- a/src/theory/quantifiers/term_database.h
+++ b/src/theory/quantifiers/term_database.h
@@ -105,6 +105,11 @@ typedef expr::Attribute< QuantElimAttributeId, bool > QuantElimAttribute;
struct QuantElimPartialAttributeId {};
typedef expr::Attribute< QuantElimPartialAttributeId, bool > QuantElimPartialAttribute;
+/** Attribute for id number */
+struct QuantIdNumAttributeId {};
+typedef expr::Attribute< QuantIdNumAttributeId, uint64_t > QuantIdNumAttribute;
+
+
class QuantifiersEngine;
namespace inst{
@@ -145,6 +150,7 @@ public:
bool d_quant_elim;
bool d_quant_elim_partial;
Node d_ipl;
+ Node d_qid_num;
bool isRewriteRule() { return !d_rr.isNull(); }
bool isFunDef() { return !d_fundef_f.isNull(); }
};
@@ -182,23 +188,25 @@ private:
std::map< Node, std::map< TypeNode, Node > > d_par_op_map;
/** whether master equality engine is UF-inconsistent */
bool d_consistent_ee;
-public:
- TermDb( context::Context* c, context::UserContext* u, QuantifiersEngine* qe );
- ~TermDb(){}
+
+ public:
+ TermDb(context::Context* c, context::UserContext* u, QuantifiersEngine* qe);
+ ~TermDb();
/** boolean terms */
Node d_true;
Node d_false;
/** constants */
Node d_zero;
Node d_one;
-public:
+
+ public:
/** presolve (called once per user check-sat) */
void presolve();
/** reset (calculate which terms are active) */
bool reset( Theory::Effort effort );
/** identify */
std::string identify() const { return "TermDb"; }
-private:
+ private:
/** map from operators to ground terms for that operator */
std::map< Node, std::vector< Node > > d_op_map;
/** map from type nodes to terms of that type */
@@ -301,8 +309,6 @@ private:
/** map from universal quantifiers to the list of variables */
std::map< Node, std::vector< Node > > d_vars;
std::map< Node, std::map< Node, unsigned > > d_var_num;
- /** map from universal quantifiers to the list of instantiation constants */
- std::map< Node, std::vector< Node > > d_inst_constants;
/** map from universal quantifiers to their inst constant body */
std::map< Node, Node > d_inst_const_body;
/** map from universal quantifiers to their counterexample literals */
@@ -312,6 +318,8 @@ private:
/** make instantiation constants for */
void makeInstantiationConstantsFor( Node q );
public:
+ /** map from universal quantifiers to the list of instantiation constants */
+ std::map< Node, std::vector< Node > > d_inst_constants;
/** get variable number */
unsigned getVariableNum( Node q, Node v ) { return d_var_num[q][v]; }
/** get the i^th instantiation constant of q */
@@ -388,7 +396,7 @@ public:
//for triggers
private:
/** helper function for compute var contains */
- static void computeVarContains2( Node n, std::vector< Node >& varContains, std::map< Node, bool >& visited );
+ static void computeVarContains2( Node n, Kind k, std::vector< Node >& varContains, std::map< Node, bool >& visited );
/** triggers for each operator */
std::map< Node, std::vector< inst::Trigger* > > d_op_triggers;
/** helper for is instance of */
@@ -402,6 +410,8 @@ public:
static void getVarContains( Node f, std::vector< Node >& pats, std::map< Node, std::vector< Node > >& varContains );
/** get var contains for node n */
static void getVarContainsNode( Node f, Node n, std::vector< Node >& varContains );
+ /** compute quant contains */
+ static void computeQuantContains( Node n, std::vector< Node >& quantContains );
/** -1: n1 is an instance of n2, 1: n1 is an instance of n2 */
static int isInstanceOf( Node n1, Node n2 );
/** filter all nodes that have instances */
@@ -541,6 +551,10 @@ public:
bool isQAttrQuantElim( Node q );
/** is quant elim partial */
bool isQAttrQuantElimPartial( Node q );
+ /** get quant id num */
+ int getQAttrQuantIdNum( Node q );
+ /** get quant id num */
+ Node getQAttrQuantIdNumNode( Node q );
/** compute quantifier attributes */
static void computeQuantAttributes( Node q, QAttributes& qa );
};/* class TermDb */
diff --git a/src/theory/quantifiers/theory_quantifiers.cpp b/src/theory/quantifiers/theory_quantifiers.cpp
index 7ad13b3a8..e97a76ce6 100755
--- a/src/theory/quantifiers/theory_quantifiers.cpp
+++ b/src/theory/quantifiers/theory_quantifiers.cpp
@@ -88,6 +88,13 @@ void TheoryQuantifiers::presolve() {
}
}
+void TheoryQuantifiers::ppNotifyAssertions( std::vector< Node >& assertions ) {
+ Trace("quantifiers-presolve") << "TheoryQuantifiers::ppNotifyAssertions" << std::endl;
+ if( getQuantifiersEngine() ){
+ getQuantifiersEngine()->ppNotifyAssertions( assertions );
+ }
+}
+
Node TheoryQuantifiers::getValue(TNode n) {
//NodeManager* nodeManager = NodeManager::currentNM();
switch(n.getKind()) {
diff --git a/src/theory/quantifiers/theory_quantifiers.h b/src/theory/quantifiers/theory_quantifiers.h
index 6775e0536..ba5a75d86 100755
--- a/src/theory/quantifiers/theory_quantifiers.h
+++ b/src/theory/quantifiers/theory_quantifiers.h
@@ -61,6 +61,7 @@ public:
void notifyEq(TNode lhs, TNode rhs);
void preRegisterTerm(TNode n);
void presolve();
+ void ppNotifyAssertions( std::vector< Node >& assertions );
void check(Effort e);
Node getNextDecisionRequest();
Node getValue(TNode n);
diff --git a/src/theory/quantifiers/trigger.cpp b/src/theory/quantifiers/trigger.cpp
index 2faed3af0..3017238ca 100755
--- a/src/theory/quantifiers/trigger.cpp
+++ b/src/theory/quantifiers/trigger.cpp
@@ -76,12 +76,6 @@ Trigger::Trigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes )
++(qe->d_statistics.d_multi_triggers);
}
//Notice() << "Trigger : " << (*this) << " for " << f << std::endl;
- if( options::eagerInstQuant() ){
- for( int i=0; i<(int)d_nodes.size(); i++ ){
- Node op = qe->getTermDatabase()->getMatchOperator( d_nodes[i] );
- qe->getTermDatabase()->registerTrigger( this, op );
- }
- }
Trace("trigger-debug") << "Finished making trigger." << std::endl;
}
@@ -107,10 +101,6 @@ bool Trigger::getMatch( Node f, Node t, InstMatch& m ){
return ((InstMatchGenerator*)d_mg)->getMatch( f, t, m, d_quantEngine );
}
-int Trigger::addTerm( Node t ){
- return d_mg->addTerm( d_f, t, d_quantEngine );
-}
-
Node Trigger::getInstPattern(){
return NodeManager::currentNM()->mkNode( INST_PATTERN, d_nodes );
}
@@ -363,7 +353,8 @@ bool Trigger::isAtomicTrigger( Node n ){
bool Trigger::isAtomicTriggerKind( Kind k ) {
return k==APPLY_UF || k==SELECT || k==STORE ||
k==APPLY_CONSTRUCTOR || k==APPLY_SELECTOR_TOTAL || k==APPLY_TESTER ||
- k==UNION || k==INTERSECTION || k==SUBSET || k==SETMINUS || k==MEMBER || k==SINGLETON;
+ k==UNION || k==INTERSECTION || k==SUBSET || k==SETMINUS || k==MEMBER || k==SINGLETON ||
+ k==SEP_PTO;
}
bool Trigger::isRelationalTrigger( Node n ) {
diff --git a/src/theory/quantifiers/trigger.h b/src/theory/quantifiers/trigger.h
index 6d7bf1f4d..631627331 100755
--- a/src/theory/quantifiers/trigger.h
+++ b/src/theory/quantifiers/trigger.h
@@ -72,8 +72,6 @@ class Trigger {
Currently the trigger should not be a multi-trigger.
*/
bool getMatch( Node f, Node t, InstMatch& m);
- /** add ground term t, called when t is added to the TermDb */
- int addTerm( Node t );
/** return whether this is a multi-trigger */
bool isMultiTrigger() { return d_nodes.size()>1; }
/** get inst pattern list */
diff --git a/src/theory/quantifiers_engine.cpp b/src/theory/quantifiers_engine.cpp
index c08fee712..67990ef69 100644
--- a/src/theory/quantifiers_engine.cpp
+++ b/src/theory/quantifiers_engine.cpp
@@ -19,6 +19,7 @@
#include "smt/smt_statistics_registry.h"
#include "theory/arrays/theory_arrays.h"
#include "theory/datatypes/theory_datatypes.h"
+#include "theory/sep/theory_sep.h"
#include "theory/quantifiers/alpha_equivalence.h"
#include "theory/quantifiers/ambqi_builder.h"
#include "theory/quantifiers/bounded_integers.h"
@@ -112,6 +113,14 @@ QuantifiersEngine::QuantifiersEngine(context::Context* c, context::UserContext*
d_quant_rel = NULL;
}
+ if( options::quantEpr() ){
+ Assert( !options::incrementalSolving() );
+ d_qepr = new QuantEPR;
+ }else{
+ d_qepr = NULL;
+ }
+
+
d_qcf = NULL;
d_sg_gen = NULL;
d_inst_engine = NULL;
@@ -130,7 +139,7 @@ QuantifiersEngine::QuantifiersEngine(context::Context* c, context::UserContext*
d_rel_dom = NULL;
d_builder = NULL;
- d_trackInstLemmas = options::proof() && options::trackInstLemmas();
+ d_trackInstLemmas = options::cbqiNestedQE() || ( options::proof() && options::trackInstLemmas() );
d_total_inst_count_debug = 0;
//allow theory combination to go first, once initially
@@ -152,6 +161,7 @@ QuantifiersEngine::~QuantifiersEngine(){
delete d_alpha_equiv;
delete d_builder;
+ delete d_qepr;
delete d_rr_engine;
delete d_bint;
delete d_model_engine;
@@ -209,21 +219,15 @@ void QuantifiersEngine::finishInit(){
d_sg_gen = new quantifiers::ConjectureGenerator( this, c );
d_modules.push_back( d_sg_gen );
}
- //maintain invariant : either InstantiationEngine or ModelEngine must be in d_modules
if( !options::finiteModelFind() || options::fmfInstEngine() ){
d_inst_engine = new quantifiers::InstantiationEngine( this );
d_modules.push_back( d_inst_engine );
}
if( options::cbqi() ){
- if( options::cbqiSplx() ){
- d_i_cbqi = new quantifiers::InstStrategySimplex( (arith::TheoryArith*)getTheoryEngine()->theoryOf( THEORY_ARITH ), this );
- d_modules.push_back( d_i_cbqi );
- }else{
- d_i_cbqi = new quantifiers::InstStrategyCegqi( this );
- d_modules.push_back( d_i_cbqi );
- if( options::cbqiModel() ){
- needsBuilder = true;
- }
+ d_i_cbqi = new quantifiers::InstStrategyCegqi( this );
+ d_modules.push_back( d_i_cbqi );
+ if( options::cbqiModel() ){
+ needsBuilder = true;
}
}
if( options::ceGuidedInst() ){
@@ -275,7 +279,7 @@ void QuantifiersEngine::finishInit(){
d_modules.push_back( d_fs );
needsRelDom = true;
}
-
+
if( needsRelDom ){
d_rel_dom = new quantifiers::RelevantDomain( this, d_model );
d_util.push_back( d_rel_dom );
@@ -343,6 +347,26 @@ void QuantifiersEngine::presolve() {
}
}
+void QuantifiersEngine::ppNotifyAssertions( std::vector< Node >& assertions ) {
+ Trace("quant-engine-proc") << "ppNotifyAssertions in QE, #assertions = " << assertions.size() << " check epr = " << (d_qepr!=NULL) << std::endl;
+ if( ( options::instLevelInputOnly() && options::instMaxLevel()!=-1 ) || d_qepr!=NULL ){
+ for( unsigned i=0; i<assertions.size(); i++ ) {
+ if( options::instLevelInputOnly() && options::instMaxLevel()!=-1 ){
+ setInstantiationLevelAttr( assertions[i], 0 );
+ }
+ if( d_qepr!=NULL ){
+ d_qepr->registerAssertion( assertions[i] );
+ }
+ }
+ if( d_qepr!=NULL ){
+ //must handle sources of other new constants e.g. separation logic
+ //FIXME: cleanup
+ ((sep::TheorySep*)getTheoryEngine()->theoryOf( THEORY_SEP ))->initializeBounds();
+ d_qepr->finishInit();
+ }
+ }
+}
+
void QuantifiersEngine::check( Theory::Effort e ){
CodeTimer codeTimer(d_statistics.d_time);
if( !getMasterEqualityEngine()->consistent() ){
@@ -370,13 +394,6 @@ void QuantifiersEngine::check( Theory::Effort e ){
d_conflict = false;
d_hasAddedLemma = false;
bool setIncomplete = false;
- if( e==Theory::EFFORT_LAST_CALL ){
- //sources of incompleteness
- if( d_lte_part_inst && d_lte_part_inst->wasInvoked() ){
- Trace("quant-engine-debug") << "Set incomplete due to LTE partial instantiation." << std::endl;
- setIncomplete = true;
- }
- }
bool usedModelBuilder = false;
Trace("quant-engine-debug2") << "Quantifiers Engine call to check, level = " << e << ", needsCheck=" << needsCheck << std::endl;
@@ -519,20 +536,49 @@ void QuantifiersEngine::check( Theory::Effort e ){
}
}else if( quant_e==QEFFORT_MODEL ){
if( e==Theory::EFFORT_LAST_CALL ){
+ //sources of incompleteness
if( !d_recorded_inst.empty() ){
+ Trace("quant-engine-debug") << "Set incomplete due to recorded instantiations." << std::endl;
setIncomplete = true;
}
//if we have a chance not to set incomplete
if( !setIncomplete ){
setIncomplete = false;
//check if we should set the incomplete flag
- for( unsigned i=0; i<qm.size(); i++ ){
- if( !qm[i]->checkComplete() ){
- Trace("quant-engine-debug") << "Set incomplete because " << qm[i]->identify().c_str() << " was incomplete." << std::endl;
+ for( unsigned i=0; i<d_modules.size(); i++ ){
+ if( !d_modules[i]->checkComplete() ){
+ Trace("quant-engine-debug") << "Set incomplete because " << d_modules[i]->identify().c_str() << " was incomplete." << std::endl;
setIncomplete = true;
break;
}
}
+ if( !setIncomplete ){
+ //look at individual quantified formulas, one module must claim completeness for each one
+ for( unsigned i=0; i<d_model->getNumAssertedQuantifiers(); i++ ){
+ bool hasCompleteM = false;
+ Node q = d_model->getAssertedQuantifier( i );
+ QuantifiersModule * qmd = getOwner( q );
+ if( qmd!=NULL ){
+ hasCompleteM = qmd->checkCompleteFor( q );
+ }else{
+ for( unsigned j=0; j<d_modules.size(); j++ ){
+ if( d_modules[j]->checkCompleteFor( q ) ){
+ qmd = d_modules[j];
+ hasCompleteM = true;
+ break;
+ }
+ }
+ }
+ if( !hasCompleteM ){
+ Trace("quant-engine-debug") << "Set incomplete because " << q << " was not fully processed." << std::endl;
+ setIncomplete = true;
+ break;
+ }else{
+ Assert( qmd!=NULL );
+ Trace("quant-engine-debug2") << "Complete for " << q << " due to " << qmd->identify().c_str() << std::endl;
+ }
+ }
+ }
}
//if setIncomplete = false, we will answer SAT, otherwise we will run at quant_e QEFFORT_LAST_CALL
if( !setIncomplete ){
@@ -598,6 +644,7 @@ void QuantifiersEngine::notifyCombineTheories() {
}
bool QuantifiersEngine::reduceQuantifier( Node q ) {
+ //TODO: this can be unified with preregistration: AlphaEquivalence takes ownership of reducable quants
BoolMap::const_iterator it = d_quants_red.find( q );
if( it==d_quants_red.end() ){
Node lem;
@@ -704,7 +751,7 @@ void QuantifiersEngine::assertQuantifier( Node f, bool pol ){
//register the quantifier, assert it to each module
if( registerQuantifier( f ) ){
d_model->assertQuantifier( f );
- for( int i=0; i<(int)d_modules.size(); i++ ){
+ for( unsigned i=0; i<d_modules.size(); i++ ){
d_modules[i]->assertNode( f );
}
addTermToDatabase( d_term_db->getInstConstantBody( f ), true );
@@ -747,10 +794,7 @@ void QuantifiersEngine::addTermToDatabase( Node n, bool withinQuant, bool within
if( !d_presolve || !options::incrementalSolving() ){
std::set< Node > added;
getTermDatabase()->addTerm( n, added, withinQuant, withinInstClosure );
- //maybe have triggered instantiations if we are doing eager instantiation
- if( options::eagerInstQuant() ){
- flushLemmas();
- }
+
//added contains also the Node that just have been asserted in this branch
if( d_quant_rel ){
for( std::set< Node >::iterator i=added.begin(), end=added.end(); i!=end; i++ ){
@@ -840,10 +884,10 @@ void QuantifiersEngine::setInstantiationLevelAttr( Node n, Node qn, uint64_t lev
InstLevelAttribute ila;
n.setAttribute(ila,level);
Trace("inst-level-debug") << "Set instantiation level " << n << " to " << level << std::endl;
- }
- Assert( n.getNumChildren()==qn.getNumChildren() );
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- setInstantiationLevelAttr( n[i], qn[i], level );
+ Assert( n.getNumChildren()==qn.getNumChildren() );
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ setInstantiationLevelAttr( n[i], qn[i], level );
+ }
}
}
}
@@ -853,9 +897,9 @@ void QuantifiersEngine::setInstantiationLevelAttr( Node n, uint64_t level ){
InstLevelAttribute ila;
n.setAttribute(ila,level);
Trace("inst-level-debug") << "Set instantiation level " << n << " to " << level << std::endl;
- }
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- setInstantiationLevelAttr( n[i], level );
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ setInstantiationLevelAttr( n[i], level );
+ }
}
}
@@ -1089,11 +1133,12 @@ bool QuantifiersEngine::addInstantiation( Node q, std::vector< Node >& terms, bo
}
if( d_term_db->isEntailed( q[1], subs, false, true ) ){
Trace("inst-add-debug") << " --> Currently entailed." << std::endl;
+ ++(d_statistics.d_inst_duplicate_ent);
return false;
}
//Node eval = d_term_db->evaluateTerm( q[1], subs, false, true );
- //Trace("ajr-temp") << "Instantiation evaluates to : " << std::endl;
- //Trace("ajr-temp") << " " << eval << std::endl;
+ //Trace("inst-add-debug2") << "Instantiation evaluates to : " << std::endl;
+ //Trace("inst-add-debug2") << " " << eval << std::endl;
}
//check for term vector duplication
@@ -1109,6 +1154,9 @@ bool QuantifiersEngine::addInstantiation( Node q, std::vector< Node >& terms, bo
Assert( d_term_db->d_vars[q].size()==terms.size() );
Node body = getInstantiation( q, d_term_db->d_vars[q], terms, doVts ); //do virtual term substitution
Node orig_body = body;
+ if( options::cbqiNestedQE() && d_i_cbqi ){
+ body = d_i_cbqi->doNestedQE( q, terms, body, doVts );
+ }
body = quantifiers::QuantifiersRewriter::preprocess( body, true );
Trace("inst-debug") << "...preprocess to " << body << std::endl;
@@ -1217,6 +1265,18 @@ bool QuantifiersEngine::addSplitEquality( Node n1, Node n2, bool reqPhase, bool
return addSplit( fm );
}
+bool QuantifiersEngine::addEPRAxiom( TypeNode tn ) {
+ if( d_qepr ){
+ Assert( !options::incrementalSolving() );
+ if( d_qepr->isEPR( tn ) && !d_qepr->hasEPRAxiom( tn ) ){
+ Node lem = d_qepr->mkEPRAxiom( tn );
+ Trace("quant-epr") << "EPR lemma for " << tn << " : " << lem << std::endl;
+ getOutputChannel().lemma( lem );
+ }
+ }
+ return false;
+}
+
void QuantifiersEngine::markRelevant( Node q ) {
d_model->markRelevant( q );
}
@@ -1414,62 +1474,120 @@ void QuantifiersEngine::getInstantiations( std::map< Node, std::vector< Node > >
}
}
+void QuantifiersEngine::getInstantiations( Node q, std::vector< Node >& insts ) {
+ if( options::incrementalSolving() ){
+ std::map< Node, inst::CDInstMatchTrie* >::iterator it = d_c_inst_match_trie.find( q );
+ if( it!=d_c_inst_match_trie.end() ){
+ std::vector< Node > active_lemmas;
+ it->second->getInstantiations( insts, it->first, this, false, active_lemmas );
+ }
+ }else{
+ std::map< Node, inst::InstMatchTrie >::iterator it = d_inst_match_trie.find( q );
+ if( it!=d_inst_match_trie.end() ){
+ std::vector< Node > active_lemmas;
+ it->second.getInstantiations( insts, it->first, this, false, active_lemmas );
+ }
+ }
+}
+
+Node QuantifiersEngine::getInstantiatedConjunction( Node q ) {
+ Assert( q.getKind()==FORALL );
+ std::vector< Node > insts;
+ getInstantiations( q, insts );
+ if( insts.empty() ){
+ return NodeManager::currentNM()->mkConst(true);
+ }else{
+ Node ret;
+ if( insts.size()==1 ){
+ ret = insts[0];
+ }else{
+ ret = NodeManager::currentNM()->mkNode( kind::AND, insts );
+ }
+ //have to remove q, TODO: avoid this in a better way
+ TNode tq = q;
+ TNode tt = d_term_db->d_true;
+ ret = ret.substitute( tq, tt );
+ return ret;
+ }
+}
+
QuantifiersEngine::Statistics::Statistics()
: d_time("theory::QuantifiersEngine::time"),
+ d_qcf_time("theory::QuantifiersEngine::time_qcf"),
+ d_ematching_time("theory::QuantifiersEngine::time_ematching"),
d_num_quant("QuantifiersEngine::Num_Quantifiers", 0),
d_instantiation_rounds("QuantifiersEngine::Rounds_Instantiation_Full", 0),
d_instantiation_rounds_lc("QuantifiersEngine::Rounds_Instantiation_Last_Call", 0),
d_instantiations("QuantifiersEngine::Instantiations_Total", 0),
d_inst_duplicate("QuantifiersEngine::Duplicate_Inst", 0),
d_inst_duplicate_eq("QuantifiersEngine::Duplicate_Inst_Eq", 0),
+ d_inst_duplicate_ent("QuantifiersEngine::Duplicate_Inst_Entailed", 0),
d_triggers("QuantifiersEngine::Triggers", 0),
d_simple_triggers("QuantifiersEngine::Triggers_Simple", 0),
d_multi_triggers("QuantifiersEngine::Triggers_Multi", 0),
d_multi_trigger_instantiations("QuantifiersEngine::Multi_Trigger_Instantiations", 0),
d_red_alpha_equiv("QuantifiersEngine::Reductions_Alpha_Equivalence", 0),
- d_red_lte_partial_inst("QuantifiersEngine::Reductions_Lte_Partial_Inst", 0),
d_instantiations_user_patterns("QuantifiersEngine::Instantiations_User_Patterns", 0),
d_instantiations_auto_gen("QuantifiersEngine::Instantiations_Auto_Gen", 0),
d_instantiations_guess("QuantifiersEngine::Instantiations_Guess", 0),
- d_instantiations_cbqi_arith("QuantifiersEngine::Instantiations_Cbqi_Arith", 0)
+ d_instantiations_qcf("QuantifiersEngine::Instantiations_Qcf_Conflict", 0),
+ d_instantiations_qcf_prop("QuantifiersEngine::Instantiations_Qcf_Prop", 0),
+ d_instantiations_fmf_exh("QuantifiersEngine::Instantiations_Fmf_Exh", 0),
+ d_instantiations_fmf_mbqi("QuantifiersEngine::Instantiations_Fmf_Mbqi", 0),
+ d_instantiations_cbqi("QuantifiersEngine::Instantiations_Cbqi", 0),
+ d_instantiations_rr("QuantifiersEngine::Instantiations_Rewrite_Rules", 0)
{
smtStatisticsRegistry()->registerStat(&d_time);
+ smtStatisticsRegistry()->registerStat(&d_qcf_time);
+ smtStatisticsRegistry()->registerStat(&d_ematching_time);
smtStatisticsRegistry()->registerStat(&d_num_quant);
smtStatisticsRegistry()->registerStat(&d_instantiation_rounds);
smtStatisticsRegistry()->registerStat(&d_instantiation_rounds_lc);
smtStatisticsRegistry()->registerStat(&d_instantiations);
smtStatisticsRegistry()->registerStat(&d_inst_duplicate);
smtStatisticsRegistry()->registerStat(&d_inst_duplicate_eq);
+ smtStatisticsRegistry()->registerStat(&d_inst_duplicate_ent);
smtStatisticsRegistry()->registerStat(&d_triggers);
smtStatisticsRegistry()->registerStat(&d_simple_triggers);
smtStatisticsRegistry()->registerStat(&d_multi_triggers);
smtStatisticsRegistry()->registerStat(&d_multi_trigger_instantiations);
smtStatisticsRegistry()->registerStat(&d_red_alpha_equiv);
- smtStatisticsRegistry()->registerStat(&d_red_lte_partial_inst);
smtStatisticsRegistry()->registerStat(&d_instantiations_user_patterns);
smtStatisticsRegistry()->registerStat(&d_instantiations_auto_gen);
smtStatisticsRegistry()->registerStat(&d_instantiations_guess);
- smtStatisticsRegistry()->registerStat(&d_instantiations_cbqi_arith);
+ smtStatisticsRegistry()->registerStat(&d_instantiations_qcf);
+ smtStatisticsRegistry()->registerStat(&d_instantiations_qcf_prop);
+ smtStatisticsRegistry()->registerStat(&d_instantiations_fmf_exh);
+ smtStatisticsRegistry()->registerStat(&d_instantiations_fmf_mbqi);
+ smtStatisticsRegistry()->registerStat(&d_instantiations_cbqi);
+ smtStatisticsRegistry()->registerStat(&d_instantiations_rr);
}
QuantifiersEngine::Statistics::~Statistics(){
smtStatisticsRegistry()->unregisterStat(&d_time);
+ smtStatisticsRegistry()->unregisterStat(&d_qcf_time);
+ smtStatisticsRegistry()->unregisterStat(&d_ematching_time);
smtStatisticsRegistry()->unregisterStat(&d_num_quant);
smtStatisticsRegistry()->unregisterStat(&d_instantiation_rounds);
smtStatisticsRegistry()->unregisterStat(&d_instantiation_rounds_lc);
smtStatisticsRegistry()->unregisterStat(&d_instantiations);
smtStatisticsRegistry()->unregisterStat(&d_inst_duplicate);
smtStatisticsRegistry()->unregisterStat(&d_inst_duplicate_eq);
+ smtStatisticsRegistry()->unregisterStat(&d_inst_duplicate_ent);
smtStatisticsRegistry()->unregisterStat(&d_triggers);
smtStatisticsRegistry()->unregisterStat(&d_simple_triggers);
smtStatisticsRegistry()->unregisterStat(&d_multi_triggers);
smtStatisticsRegistry()->unregisterStat(&d_multi_trigger_instantiations);
smtStatisticsRegistry()->unregisterStat(&d_red_alpha_equiv);
- smtStatisticsRegistry()->unregisterStat(&d_red_lte_partial_inst);
smtStatisticsRegistry()->unregisterStat(&d_instantiations_user_patterns);
smtStatisticsRegistry()->unregisterStat(&d_instantiations_auto_gen);
smtStatisticsRegistry()->unregisterStat(&d_instantiations_guess);
- smtStatisticsRegistry()->unregisterStat(&d_instantiations_cbqi_arith);
+ smtStatisticsRegistry()->unregisterStat(&d_instantiations_qcf);
+ smtStatisticsRegistry()->unregisterStat(&d_instantiations_qcf_prop);
+ smtStatisticsRegistry()->unregisterStat(&d_instantiations_fmf_exh);
+ smtStatisticsRegistry()->unregisterStat(&d_instantiations_fmf_mbqi);
+ smtStatisticsRegistry()->unregisterStat(&d_instantiations_cbqi);
+ smtStatisticsRegistry()->unregisterStat(&d_instantiations_rr);
}
eq::EqualityEngine* QuantifiersEngine::getMasterEqualityEngine(){
diff --git a/src/theory/quantifiers_engine.h b/src/theory/quantifiers_engine.h
index 08ca0564b..232d1d889 100644
--- a/src/theory/quantifiers_engine.h
+++ b/src/theory/quantifiers_engine.h
@@ -85,6 +85,7 @@ class EqualityQueryQuantifiersEngine;
class QuantifiersEngine {
friend class quantifiers::InstantiationEngine;
+ friend class quantifiers::InstStrategyCbqi;
friend class quantifiers::InstStrategyCegqi;
friend class quantifiers::ModelEngine;
friend class quantifiers::RewriteEngine;
@@ -113,6 +114,9 @@ private:
quantifiers::AlphaEquivalence * d_alpha_equiv;
/** model builder */
quantifiers::QModelBuilder* d_builder;
+ /** utility for effectively propositional logic */
+ QuantEPR * d_qepr;
+private:
/** instantiation engine */
quantifiers::InstantiationEngine* d_inst_engine;
/** model engine */
@@ -228,6 +232,8 @@ public:
QuantRelevance* getQuantifierRelevance() { return d_quant_rel; }
/** get the model builder */
quantifiers::QModelBuilder* getModelBuilder() { return d_builder; }
+ /** get utility for EPR */
+ QuantEPR* getQuantEPR() { return d_qepr; }
public: //modules
/** get instantiation engine */
quantifiers::InstantiationEngine* getInstantiationEngine() { return d_inst_engine; }
@@ -273,6 +279,8 @@ public:
void finishInit();
/** presolve */
void presolve();
+ /** notify preprocessed assertion */
+ void ppNotifyAssertions( std::vector< Node >& assertions );
/** check at level */
void check( Theory::Effort e );
/** notify that theories were combined */
@@ -325,6 +333,8 @@ public:
bool addSplit( Node n, bool reqPhase = false, bool reqPhasePol = true );
/** add split equality */
bool addSplitEquality( Node n1, Node n2, bool reqPhase = false, bool reqPhasePol = true );
+ /** add EPR axiom */
+ bool addEPRAxiom( TypeNode tn );
/** mark relevant quantified formula, this will indicate it should be checked before the others */
void markRelevant( Node q );
/** has added lemma */
@@ -365,7 +375,10 @@ public:
/** print solution for synthesis conjectures */
void printSynthSolution( std::ostream& out );
/** get instantiations */
+ void getInstantiations( Node q, std::vector< Node >& insts );
void getInstantiations( std::map< Node, std::vector< Node > >& insts );
+ /** get instantiated conjunction */
+ Node getInstantiatedConjunction( Node q );
/** get unsat core lemmas */
bool getUnsatCoreLemmas( std::vector< Node >& active_lemmas );
bool getUnsatCoreLemmas( std::vector< Node >& active_lemmas, std::map< Node, Node >& weak_imp );
@@ -375,22 +388,29 @@ public:
class Statistics {
public:
TimerStat d_time;
+ TimerStat d_qcf_time;
+ TimerStat d_ematching_time;
IntStat d_num_quant;
IntStat d_instantiation_rounds;
IntStat d_instantiation_rounds_lc;
IntStat d_instantiations;
IntStat d_inst_duplicate;
IntStat d_inst_duplicate_eq;
+ IntStat d_inst_duplicate_ent;
IntStat d_triggers;
IntStat d_simple_triggers;
IntStat d_multi_triggers;
IntStat d_multi_trigger_instantiations;
IntStat d_red_alpha_equiv;
- IntStat d_red_lte_partial_inst;
IntStat d_instantiations_user_patterns;
IntStat d_instantiations_auto_gen;
IntStat d_instantiations_guess;
- IntStat d_instantiations_cbqi_arith;
+ IntStat d_instantiations_qcf;
+ IntStat d_instantiations_qcf_prop;
+ IntStat d_instantiations_fmf_exh;
+ IntStat d_instantiations_fmf_mbqi;
+ IntStat d_instantiations_cbqi;
+ IntStat d_instantiations_rr;
Statistics();
~Statistics();
};/* class QuantifiersEngine::Statistics */
diff --git a/src/theory/sep/theory_sep.cpp b/src/theory/sep/theory_sep.cpp
index dcba4c379..42c6d1219 100644
--- a/src/theory/sep/theory_sep.cpp
+++ b/src/theory/sep/theory_sep.cpp
@@ -26,6 +26,7 @@
#include "smt/logic_exception.h"
#include "theory/quantifiers_engine.h"
#include "theory/quantifiers/term_database.h"
+#include "options/quantifiers_options.h"
using namespace std;
@@ -35,6 +36,7 @@ namespace sep {
TheorySep::TheorySep(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo) :
Theory(THEORY_SEP, c, u, out, valuation, logicInfo),
+ d_lemmas_produced_c(u),
d_notify(*this),
d_equalityEngine(d_notify, c, "theory::sep::TheorySep", true),
d_conflict(c, false),
@@ -45,7 +47,8 @@ TheorySep::TheorySep(context::Context* c, context::UserContext* u, OutputChannel
{
d_true = NodeManager::currentNM()->mkConst<bool>(true);
d_false = NodeManager::currentNM()->mkConst<bool>(false);
-
+ d_bounds_init = false;
+
// The kinds we are treating as function application in congruence
d_equalityEngine.addFunctionKind(kind::SEP_PTO);
//d_equalityEngine.addFunctionKind(kind::SEP_STAR);
@@ -79,47 +82,9 @@ Node TheorySep::mkAnd( std::vector< TNode >& assumptions ) {
Node TheorySep::ppRewrite(TNode term) {
Trace("sep-pp") << "ppRewrite : " << term << std::endl;
-/*
- Node s_atom = term.getKind()==kind::NOT ? term[0] : term;
- if( s_atom.getKind()==kind::SEP_PTO || s_atom.getKind()==kind::SEP_STAR || s_atom.getKind()==kind::SEP_WAND || s_atom.getKind()==kind::SEP_EMP ){
- //get the reference type (will compute d_type_references)
- int card = 0;
- TypeNode tn = getReferenceType( s_atom, card );
- Trace("sep-pp") << " reference type is " << tn << ", card is " << card << std::endl;
- }
-*/
return term;
}
-//must process assertions at preprocess so that quantified assertions are processed properly
-void TheorySep::processAssertions( std::vector< Node >& assertions ) {
- d_pp_nils.clear();
- std::map< Node, bool > visited;
- for( unsigned i=0; i<assertions.size(); i++ ){
- processAssertion( assertions[i], visited );
- }
-}
-
-void TheorySep::processAssertion( Node n, std::map< Node, bool >& visited ) {
- if( visited.find( n )==visited.end() ){
- visited[n] = true;
- if( n.getKind()==kind::SEP_NIL ){
- if( std::find( d_pp_nils.begin(), d_pp_nils.end(), n )==d_pp_nils.end() ){
- d_pp_nils.push_back( n );
- }
- }else if( n.getKind()==kind::SEP_PTO || n.getKind()==kind::SEP_STAR || n.getKind()==kind::SEP_WAND || n.getKind()==kind::SEP_EMP ){
- //get the reference type (will compute d_type_references)
- int card = 0;
- TypeNode tn = getReferenceType( n, card );
- Trace("sep-pp") << " reference type is " << tn << ", card is " << card << std::endl;
- }else{
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- processAssertion( n[i], visited );
- }
- }
- }
-}
-
Theory::PPAssertStatus TheorySep::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
return PP_ASSERT_STATUS_UNSOLVED;
@@ -164,43 +129,6 @@ void TheorySep::explain(TNode literal, std::vector<TNode>& assumptions) {
}
}
-void TheorySep::preRegisterTermRec(TNode t, std::map< TNode, bool >& visited ) {
- if( visited.find( t )==visited.end() ){
- visited[t] = true;
- Trace("sep-prereg-debug") << "Preregister : " << t << std::endl;
- if( t.getKind()==kind::SEP_NIL ){
- Trace("sep-prereg") << "Preregister nil : " << t << std::endl;
- //per type, all nil variable references are equal
- TypeNode tn = t.getType();
- std::map< TypeNode, Node >::iterator it = d_nil_ref.find( tn );
- if( it==d_nil_ref.end() ){
- Trace("sep-prereg") << "...set as reference." << std::endl;
- setNilRef( tn, t );
- }else{
- Node nr = it->second;
- Trace("sep-prereg") << "...reference is " << nr << "." << std::endl;
- if( t!=nr ){
- if( d_reduce.find( t )==d_reduce.end() ){
- d_reduce.insert( t );
- Node lem = NodeManager::currentNM()->mkNode( tn.isBoolean() ? kind::IFF : kind::EQUAL, t, nr );
- Trace("sep-lemma") << "Sep::Lemma: nil ref eq : " << lem << std::endl;
- d_out->lemma( lem );
- }
- }
- }
- }else{
- for( unsigned i=0; i<t.getNumChildren(); i++ ){
- preRegisterTermRec( t[i], visited );
- }
- }
- }
-}
-
-void TheorySep::preRegisterTerm(TNode term){
- std::map< TNode, bool > visited;
- preRegisterTermRec( term, visited );
-}
-
void TheorySep::propagate(Effort e){
@@ -272,14 +200,12 @@ void TheorySep::computeCareGraph() {
/////////////////////////////////////////////////////////////////////////////
-void TheorySep::collectModelInfo( TheoryModel* m, bool fullModel )
-{
+void TheorySep::collectModelInfo( TheoryModel* m, bool fullModel ){
// Send the equality engine information to the model
m->assertEqualityEngine( &d_equalityEngine );
-
}
-void TheorySep::postProcessModel(TheoryModel* m) {
+void TheorySep::postProcessModel( TheoryModel* m ){
Trace("sep-model") << "Printing model for TheorySep..." << std::endl;
std::vector< Node > sep_children;
@@ -291,11 +217,9 @@ void TheorySep::postProcessModel(TheoryModel* m) {
Assert( d_loc_to_data_type.find( it->first )!=d_loc_to_data_type.end() );
Trace("sep-model") << "Model for heap, type = " << it->first << " with data type " << d_loc_to_data_type[it->first] << " : " << std::endl;
TypeEnumerator te_range( d_loc_to_data_type[it->first] );
- //m->d_comment_str << "Model for heap, type = " << it->first << " : " << std::endl;
computeLabelModel( it->second, d_tmodel );
if( d_label_model[it->second].d_heap_locs_model.empty() ){
Trace("sep-model") << " [empty]" << std::endl;
- //m->d_comment_str << " [empty]" << std::endl;
}else{
for( unsigned j=0; j<d_label_model[it->second].d_heap_locs_model.size(); j++ ){
Assert( d_label_model[it->second].d_heap_locs_model[j].getKind()==kind::SINGLETON );
@@ -304,20 +228,17 @@ void TheorySep::postProcessModel(TheoryModel* m) {
Assert( l.isConst() );
pto_children.push_back( l );
Trace("sep-model") << " " << l << " -> ";
- //m->d_comment_str << " " << l << " -> ";
if( d_pto_model[l].isNull() ){
Trace("sep-model") << "_";
//m->d_comment_str << "_";
pto_children.push_back( *te_range );
}else{
Trace("sep-model") << d_pto_model[l];
- //m->d_comment_str << d_pto_model[l];
Node vpto = d_valuation.getModel()->getRepresentative( d_pto_model[l] );
Assert( vpto.isConst() );
pto_children.push_back( vpto );
}
Trace("sep-model") << std::endl;
- //m->d_comment_str << std::endl;
sep_children.push_back( NodeManager::currentNM()->mkNode( kind::SEP_PTO, pto_children ) );
}
}
@@ -326,8 +247,6 @@ void TheorySep::postProcessModel(TheoryModel* m) {
m_neq = NodeManager::currentNM()->mkNode( nil.getType().isBoolean() ? kind::IFF : kind::EQUAL, nil, vnil );
Trace("sep-model") << "sep.nil = " << vnil << std::endl;
Trace("sep-model") << std::endl;
- //m->d_comment_str << "sep.nil = " << vnil << std::endl;
- //m->d_comment_str << std::endl;
if( sep_children.empty() ){
TypeEnumerator te_domain( it->first );
m_heap = NodeManager::currentNM()->mkNode( kind::SEP_EMP, *te_domain );
@@ -337,8 +256,6 @@ void TheorySep::postProcessModel(TheoryModel* m) {
m_heap = NodeManager::currentNM()->mkNode( kind::SEP_STAR, sep_children );
}
m->setHeapModel( m_heap, m_neq );
- //m->d_comment_str << m->d_sep_heap << std::endl;
- //m->d_comment_str << m->d_sep_nil_eq << std::endl;
}
Trace("sep-model") << "Finished printing model for TheorySep." << std::endl;
}
@@ -351,13 +268,6 @@ void TheorySep::postProcessModel(TheoryModel* m) {
void TheorySep::presolve() {
Trace("sep-pp") << "Presolving" << std::endl;
//TODO: cleanup if incremental?
-
- //we must preregister all instances of sep.nil to ensure they are made equal
- for( unsigned i=0; i<d_pp_nils.size(); i++ ){
- std::map< TNode, bool > visited;
- preRegisterTermRec( d_pp_nils[i], visited );
- }
- d_pp_nils.clear();
}
@@ -401,9 +311,8 @@ void TheorySep::check(Effort e) {
Trace("sep-lemma-debug") << "Reducing unlabelled assertion " << atom << std::endl;
d_reduce.insert( fact );
//introduce top-level label, add iff
- int card;
- TypeNode refType = getReferenceType( s_atom, card );
- Trace("sep-lemma-debug") << "...reference type is : " << refType << ", card is " << card << std::endl;
+ TypeNode refType = getReferenceType( s_atom );
+ Trace("sep-lemma-debug") << "...reference type is : " << refType << std::endl;
Node b_lbl = getBaseLabel( refType );
Node s_atom_new = NodeManager::currentNM()->mkNode( kind::SEP_LABEL, s_atom, b_lbl );
Node lem;
@@ -428,44 +337,9 @@ void TheorySep::check(Effort e) {
if( s_atom.getKind()==kind::SEP_STAR || s_atom.getKind()==kind::SEP_WAND ){
std::vector< Node > children;
std::vector< Node > c_lems;
- int card;
- TypeNode tn = getReferenceType( s_atom, card );
+ TypeNode tn = getReferenceType( s_atom );
Assert( d_reference_bound.find( tn )!=d_reference_bound.end() );
c_lems.push_back( NodeManager::currentNM()->mkNode( kind::SUBSET, s_lbl, d_reference_bound[tn] ) );
- if( options::sepPreciseBound() ){
- //more precise bound
- Trace("sep-bound") << "Propagate Bound(" << s_lbl << ") = ";
- Assert( d_lbl_reference_bound.find( s_lbl )!=d_lbl_reference_bound.end() );
- for( unsigned j=0; j<d_lbl_reference_bound[s_lbl].size(); j++ ){
- Trace("sep-bound") << d_lbl_reference_bound[s_lbl][j] << " ";
- }
- Trace("sep-bound") << std::endl << " to children of " << s_atom << std::endl;
- //int rb_start = 0;
- for( unsigned j=0; j<s_atom.getNumChildren(); j++ ){
- int ccard = 0;
- getReferenceType( s_atom, ccard, j );
- Node c_lbl = getLabel( s_atom, j, s_lbl );
- Trace("sep-bound") << " for " << c_lbl << ", card = " << ccard << " : ";
- std::vector< Node > bound_loc;
- bound_loc.insert( bound_loc.end(), d_references[s_atom][j].begin(), d_references[s_atom][j].end() );
-/* //this is unsound
- for( int k=0; k<ccard; k++ ){
- Assert( rb_start<(int)d_lbl_reference_bound[s_lbl].size() );
- d_lbl_reference_bound[c_lbl].push_back( d_lbl_reference_bound[s_lbl][rb_start] );
- Trace("sep-bound") << d_lbl_reference_bound[s_lbl][rb_start] << " ";
- bound_loc.push_back( d_lbl_reference_bound[s_lbl][rb_start] );
- rb_start++;
- }
-*/
- //carry all locations for now
- bound_loc.insert( bound_loc.end(), d_lbl_reference_bound[s_lbl].begin(), d_lbl_reference_bound[s_lbl].end() );
- Trace("sep-bound") << std::endl;
- Node bound_v = mkUnion( tn, bound_loc );
- Trace("sep-bound") << " ...bound value : " << bound_v << std::endl;
- children.push_back( NodeManager::currentNM()->mkNode( kind::SUBSET, c_lbl, bound_v ) );
- }
- Trace("sep-bound") << "Done propagate Bound(" << s_lbl << ")" << std::endl;
- }
std::vector< Node > labels;
getLabelChildren( s_atom, s_lbl, children, labels );
Node empSet = NodeManager::currentNM()->mkConst(EmptySet(s_lbl.getType().toType()));
@@ -568,13 +442,9 @@ void TheorySep::check(Effort e) {
Trace("sep-assert") << "Done asserting " << atom << " to EE." << std::endl;
}else if( s_atom.getKind()==kind::SEP_PTO ){
Node pto_lbl = NodeManager::currentNM()->mkNode( kind::SINGLETON, s_atom[0] );
- if( polarity && s_lbl!=pto_lbl ){
- //also propagate equality
- Node eq = s_lbl.eqNode( pto_lbl );
- Trace("sep-assert") << "Asserting implied equality " << eq << " to EE..." << std::endl;
- d_equalityEngine.assertEquality(eq, true, fact);
- Trace("sep-assert") << "Done asserting implied equality " << eq << " to EE." << std::endl;
- }
+ Assert( s_lbl==pto_lbl );
+ Trace("sep-assert") << "Asserting " << s_atom << std::endl;
+ d_equalityEngine.assertPredicate(s_atom, polarity, fact);
//associate the equivalence class of the lhs with this pto
Node r = getRepresentative( s_lbl );
HeapAssertInfo * ei = getOrMakeEqcInfo( r, true );
@@ -595,6 +465,7 @@ void TheorySep::check(Effort e) {
d_tmodel.clear();
d_pto_model.clear();
Trace("sep-process") << "---Locations---" << std::endl;
+ std::map< Node, int > min_id;
for( std::map< TypeNode, std::vector< Node > >::iterator itt = d_type_references_all.begin(); itt != d_type_references_all.end(); ++itt ){
for( unsigned k=0; k<itt->second.size(); k++ ){
Node t = itt->second[k];
@@ -602,7 +473,19 @@ void TheorySep::check(Effort e) {
if( d_valuation.getModel()->hasTerm( t ) ){
Node v = d_valuation.getModel()->getRepresentative( t );
Trace("sep-process") << v << std::endl;
- d_tmodel[v] = t;
+ //take minimal id
+ std::map< Node, unsigned >::iterator itrc = d_type_ref_card_id.find( t );
+ int tid = itrc==d_type_ref_card_id.end() ? -1 : (int)itrc->second;
+ bool set_term_model;
+ if( d_tmodel.find( v )==d_tmodel.end() ){
+ set_term_model = true;
+ }else{
+ set_term_model = min_id[v]>tid;
+ }
+ if( set_term_model ){
+ d_tmodel[v] = t;
+ min_id[v] = tid;
+ }
}else{
Trace("sep-process") << "?" << std::endl;
}
@@ -737,8 +620,7 @@ void TheorySep::check(Effort e) {
//add refinement lemma
if( d_label_map[s_atom].find( s_lbl )!=d_label_map[s_atom].end() ){
needAddLemma = true;
- int card;
- TypeNode tn = getReferenceType( s_atom, card );
+ TypeNode tn = getReferenceType( s_atom );
tn = NodeManager::currentNM()->mkSetType(tn);
//tn = NodeManager::currentNM()->mkSetType(NodeManager::currentNM()->mkRefType(tn));
Node o_b_lbl_mval = d_label_model[s_lbl].getValue( tn );
@@ -885,17 +767,62 @@ TheorySep::HeapAssertInfo * TheorySep::getOrMakeEqcInfo( Node n, bool doMake ) {
}
}
-TypeNode TheorySep::getReferenceType( Node atom, int& card, int index ) {
- Trace("sep-type") << "getReference type " << atom << " " << index << std::endl;
+//for now, assume all constraints are for the same heap type (ensured by logic exceptions thrown in computeReferenceType2)
+TypeNode TheorySep::getReferenceType( Node n ) {
+ Assert( !d_type_ref.isNull() );
+ return d_type_ref;
+}
+
+TypeNode TheorySep::getDataType( Node n ) {
+ Assert( !d_type_data.isNull() );
+ return d_type_data;
+}
+
+//must process assertions at preprocess so that quantified assertions are processed properly
+void TheorySep::ppNotifyAssertions( std::vector< Node >& assertions ) {
+ std::map< Node, bool > visited;
+ for( unsigned i=0; i<assertions.size(); i++ ){
+ Trace("sep-pp") << "Process assertion : " << assertions[i] << std::endl;
+ processAssertion( assertions[i], visited );
+ }
+ //if data type is unconstrained, assume a fresh uninterpreted sort
+ if( !d_type_ref.isNull() ){
+ if( d_type_data.isNull() ){
+ d_type_data = NodeManager::currentNM()->mkSort("_sep_U");
+ Trace("sep-type") << "Sep: assume data type " << d_type_data << std::endl;
+ d_loc_to_data_type[d_type_ref] = d_type_data;
+ }
+ }
+}
+
+void TheorySep::processAssertion( Node n, std::map< Node, bool >& visited ) {
+ if( visited.find( n )==visited.end() ){
+ visited[n] = true;
+ Trace("sep-pp-debug") << "process assertion : " << n << std::endl;
+ if( n.getKind()==kind::SEP_PTO || n.getKind()==kind::SEP_STAR || n.getKind()==kind::SEP_WAND || n.getKind()==kind::SEP_EMP ){
+ //get the reference type (will compute d_type_references)
+ int card = 0;
+ TypeNode tn = computeReferenceType( n, card );
+ Trace("sep-pp") << " reference type is " << tn << ", card is " << card << std::endl;
+ }else{
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ processAssertion( n[i], visited );
+ }
+ }
+ }
+}
+
+TypeNode TheorySep::computeReferenceType( Node atom, int& card, int index ) {
+ Trace("sep-pp-debug") << "getReference type " << atom << " " << index << std::endl;
Assert( atom.getKind()==kind::SEP_PTO || atom.getKind()==kind::SEP_STAR || atom.getKind()==kind::SEP_WAND || atom.getKind()==kind::SEP_EMP || index!=-1 );
std::map< int, TypeNode >::iterator it = d_reference_type[atom].find( index );
if( it==d_reference_type[atom].end() ){
card = 0;
- TypeNode tn;
+ TypeNode tn;
if( index==-1 && ( atom.getKind()==kind::SEP_STAR || atom.getKind()==kind::SEP_WAND ) ){
for( unsigned i=0; i<atom.getNumChildren(); i++ ){
int cardc = 0;
- TypeNode ctn = getReferenceType( atom, cardc, i );
+ TypeNode ctn = computeReferenceType( atom, cardc, i );
if( !ctn.isNull() ){
tn = ctn;
}
@@ -910,7 +837,7 @@ TypeNode TheorySep::getReferenceType( Node atom, int& card, int index ) {
Node n = index==-1 ? atom : atom[index];
//will compute d_references as well
std::map< Node, int > visited;
- tn = getReferenceType2( atom, card, index, n, visited );
+ tn = computeReferenceType2( atom, card, index, n, visited );
}
if( tn.isNull() && index==-1 ){
tn = NodeManager::currentNM()->booleanType();
@@ -940,9 +867,9 @@ TypeNode TheorySep::getReferenceType( Node atom, int& card, int index ) {
}
}
-TypeNode TheorySep::getReferenceType2( Node atom, int& card, int index, Node n, std::map< Node, int >& visited ) {
+TypeNode TheorySep::computeReferenceType2( Node atom, int& card, int index, Node n, std::map< Node, int >& visited ) {
if( visited.find( n )==visited.end() ){
- Trace("sep-type-debug") << "visit : " << n << " : " << atom << " " << index << std::endl;
+ Trace("sep-pp-debug") << "visit : " << n << " : " << atom << " " << index << std::endl;
visited[n] = -1;
if( n.getKind()==kind::SEP_PTO ){
//TODO: when THEORY_SETS supports mixed Int/Real sets
@@ -951,44 +878,34 @@ TypeNode TheorySep::getReferenceType2( Node atom, int& card, int index, Node n,
TypeNode tn1 = n[0].getType();
TypeNode tn2 = n[1].getType();
if( quantifiers::TermDb::hasBoundVarAttr( n[0] ) ){
- d_reference_bound_invalid[tn1] = true;
+ if( options::quantEpr() && n[0].getKind()==kind::BOUND_VARIABLE ){
+ // still valid : bound on heap models will include Herbrand universe of n[0].getType()
+ d_reference_bound_fv[tn1] = true;
+ }else{
+ d_reference_bound_invalid[tn1] = true;
+ Trace("sep-bound") << "reference cannot be bound (due to quantified pto)." << std::endl;
+ }
}else{
if( std::find( d_references[atom][index].begin(), d_references[atom][index].end(), n[0] )==d_references[atom][index].end() ){
d_references[atom][index].push_back( n[0] );
}
}
- std::map< TypeNode, TypeNode >::iterator itt = d_loc_to_data_type.find( tn1 );
- if( itt==d_loc_to_data_type.end() ){
- if( !d_loc_to_data_type.empty() ){
- TypeNode te1 = d_loc_to_data_type.begin()->first;
- std::stringstream ss;
- ss << "ERROR: specifying heap constraints for two different types : " << tn1 << " -> " << tn2 << " and " << te1 << " -> " << d_loc_to_data_type[te1] << std::endl;
- throw LogicException(ss.str());
- Assert( false );
- }
- Trace("sep-type") << "Sep: assume location type " << tn1 << " is associated with data type " << tn2 << " (from " << atom << ")" << std::endl;
- d_loc_to_data_type[tn1] = tn2;
- }else{
- if( itt->second!=tn2 ){
- std::stringstream ss;
- ss << "ERROR: location type " << tn1 << " is already associated with data type " << itt->second << ", offending atom is " << atom << " with data type " << tn2 << std::endl;
- throw LogicException(ss.str());
- Assert( false );
- }
- }
+ registerRefDataTypes( tn1, tn2, atom );
card = 1;
visited[n] = card;
return tn1;
- //return n[1].getType();
}else if( n.getKind()==kind::SEP_EMP ){
+ TypeNode tn = n[0].getType();
+ TypeNode tnd;
+ registerRefDataTypes( tn, tnd, atom );
card = 1;
visited[n] = card;
- return n[0].getType();
+ return tn;
}else if( n.getKind()==kind::SEP_STAR || n.getKind()==kind::SEP_WAND ){
Assert( n!=atom );
//get the references
card = 0;
- TypeNode tn = getReferenceType( n, card );
+ TypeNode tn = computeReferenceType( n, card );
for( unsigned j=0; j<d_references[n][-1].size(); j++ ){
if( std::find( d_references[atom][index].begin(), d_references[atom][index].end(), d_references[n][-1][j] )==d_references[atom][index].end() ){
d_references[atom][index].push_back( d_references[n][-1][j] );
@@ -996,12 +913,17 @@ TypeNode TheorySep::getReferenceType2( Node atom, int& card, int index, Node n,
}
visited[n] = card;
return tn;
+ }else if( n.getKind()==kind::SEP_NIL ){
+ TypeNode tn = n.getType();
+ TypeNode tnd;
+ registerRefDataTypes( tn, tnd, n );
+ return tn;
}else{
card = 0;
TypeNode otn;
for( unsigned i=0; i<n.getNumChildren(); i++ ){
int cardc = 0;
- TypeNode tn = getReferenceType2( atom, cardc, index, n[i], visited );
+ TypeNode tn = computeReferenceType2( atom, cardc, index, n[i], visited );
if( !tn.isNull() ){
otn = tn;
}
@@ -1016,27 +938,108 @@ TypeNode TheorySep::getReferenceType2( Node atom, int& card, int index, Node n,
return TypeNode::null();
}
}
-/*
-int TheorySep::getCardinality( Node n, std::vector< Node >& refs ) {
- std::map< Node, int > visited;
- return getCardinality2( n, refs, visited );
+void TheorySep::registerRefDataTypes( TypeNode tn1, TypeNode tn2, Node atom ){
+ //separation logic is effectively enabled when we find at least one spatial constraint occurs in the input
+ if( options::incrementalSolving() ){
+ std::stringstream ss;
+ ss << "ERROR: cannot use separation logic in incremental mode." << std::endl;
+ throw LogicException(ss.str());
+ }
+ std::map< TypeNode, TypeNode >::iterator itt = d_loc_to_data_type.find( tn1 );
+ if( itt==d_loc_to_data_type.end() ){
+ if( !d_loc_to_data_type.empty() ){
+ TypeNode te1 = d_loc_to_data_type.begin()->first;
+ std::stringstream ss;
+ ss << "ERROR: specifying heap constraints for two different types : " << tn1 << " -> " << tn2 << " and " << te1 << " -> " << d_loc_to_data_type[te1] << std::endl;
+ throw LogicException(ss.str());
+ Assert( false );
+ }
+ if( tn2.isNull() ){
+ Trace("sep-type") << "Sep: assume location type " << tn1 << " (from " << atom << ")" << std::endl;
+ }else{
+ Trace("sep-type") << "Sep: assume location type " << tn1 << " is associated with data type " << tn2 << " (from " << atom << ")" << std::endl;
+ }
+ d_loc_to_data_type[tn1] = tn2;
+ //for now, we only allow heap constraints of one type
+ d_type_ref = tn1;
+ d_type_data = tn2;
+ }else{
+ if( !tn2.isNull() ){
+ if( itt->second!=tn2 ){
+ if( itt->second.isNull() ){
+ Trace("sep-type") << "Sep: assume location type " << tn1 << " is associated with data type " << tn2 << " (from " << atom << ")" << std::endl;
+ //now we know data type
+ d_loc_to_data_type[tn1] = tn2;
+ d_type_data = tn2;
+ }else{
+ std::stringstream ss;
+ ss << "ERROR: location type " << tn1 << " is already associated with data type " << itt->second << ", offending atom is " << atom << " with data type " << tn2 << std::endl;
+ throw LogicException(ss.str());
+ Assert( false );
+ }
+ }
+ }
+ }
}
-int TheorySep::getCardinality2( Node n, std::vector< Node >& refs, std::map< Node, int >& visited ) {
- std::map< Node, int >::iterator it = visited.find( n );
- if( it!=visited.end() ){
- return it->second;
- }else{
-
-
+void TheorySep::initializeBounds() {
+ if( !d_bounds_init ){
+ Trace("sep-bound") << "Initialize sep bounds..." << std::endl;
+ d_bounds_init = true;
+ for( std::map< TypeNode, TypeNode >::iterator it = d_loc_to_data_type.begin(); it != d_loc_to_data_type.end(); ++it ){
+ TypeNode tn = it->first;
+ Trace("sep-bound") << "Initialize bounds for " << tn << "..." << std::endl;
+ QuantEPR * qepr = getLogicInfo().isQuantified() ? getQuantifiersEngine()->getQuantEPR() : NULL;
+ //if pto had free variable reference
+ if( d_reference_bound_invalid.find( tn )==d_reference_bound_invalid.end() ){
+ if( d_reference_bound_fv.find( tn )!=d_reference_bound_fv.end() ){
+ //include Herbrand universe of tn
+ if( qepr && qepr->isEPR( tn ) ){
+ for( unsigned j=0; j<qepr->d_consts[tn].size(); j++ ){
+ Node k = qepr->d_consts[tn][j];
+ if( std::find( d_type_references[tn].begin(), d_type_references[tn].end(), k )==d_type_references[tn].end() ){
+ d_type_references[tn].push_back( k );
+ }
+ }
+ }else{
+ d_reference_bound_invalid[tn] = true;
+ Trace("sep-bound") << "reference cannot be bound (due to non-EPR variable)." << std::endl;
+ }
+ }
+ }
+ unsigned n_emp = 0;
+ if( d_reference_bound_invalid.find( tn )==d_reference_bound_invalid.end() ){
+ n_emp = d_card_max[tn]>d_card_max[TypeNode::null()] ? d_card_max[tn] : d_card_max[TypeNode::null()];
+ }else if( d_type_references[tn].empty() ){
+ //must include at least one constant
+ n_emp = 1;
+ }
+ Trace("sep-bound") << "Constructing " << n_emp << " cardinality constants." << std::endl;
+ for( unsigned r=0; r<n_emp; r++ ){
+ Node e = NodeManager::currentNM()->mkSkolem( "e", tn, "cardinality bound element for seplog" );
+ d_type_references_card[tn].push_back( e );
+ d_type_ref_card_id[e] = r;
+ //must include this constant back into EPR handling
+ if( qepr && qepr->isEPR( tn ) ){
+ qepr->addEPRConstant( tn, e );
+ }
+ }
+ //EPR must include nil ref
+ if( qepr && qepr->isEPR( tn ) ){
+ Node nr = getNilRef( tn );
+ if( !qepr->isEPRConstant( tn, nr ) ){
+ qepr->addEPRConstant( tn, nr );
+ }
+ }
+ }
}
}
-*/
Node TheorySep::getBaseLabel( TypeNode tn ) {
std::map< TypeNode, Node >::iterator it = d_base_label.find( tn );
if( it==d_base_label.end() ){
+ initializeBounds();
Trace("sep") << "Make base label for " << tn << std::endl;
std::stringstream ss;
ss << "__Lb";
@@ -1050,35 +1053,62 @@ Node TheorySep::getBaseLabel( TypeNode tn ) {
ss2 << "__Lu";
d_reference_bound[tn] = NodeManager::currentNM()->mkSkolem( ss2.str(), ltn, "" );
d_type_references_all[tn].insert( d_type_references_all[tn].end(), d_type_references[tn].begin(), d_type_references[tn].end() );
+
+ //check whether monotonic (elements can be added to tn without effecting satisfiability)
+ bool tn_is_monotonic = true;
+ if( tn.isSort() ){
+ //TODO: use monotonicity inference
+ tn_is_monotonic = !getLogicInfo().isQuantified();
+ }else{
+ tn_is_monotonic = tn.getCardinality().isInfinite();
+ }
//add a reference type for maximum occurrences of empty in a constraint
- unsigned n_emp = d_card_max[tn]>d_card_max[TypeNode::null()] ? d_card_max[tn] : d_card_max[TypeNode::null()];
- for( unsigned r=0; r<n_emp; r++ ){
- Node e = NodeManager::currentNM()->mkSkolem( "e", tn, "cardinality bound element for seplog" );
- //d_type_references_all[tn].push_back( NodeManager::currentNM()->mkSkolem( "e", NodeManager::currentNM()->mkRefType(tn) ) );
- if( options::sepDisequalC() ){
+ if( options::sepDisequalC() && tn_is_monotonic ){
+ for( unsigned r=0; r<d_type_references_card[tn].size(); r++ ){
+ Node e = d_type_references_card[tn][r];
//ensure that it is distinct from all other references so far
for( unsigned j=0; j<d_type_references_all[tn].size(); j++ ){
Node eq = NodeManager::currentNM()->mkNode( e.getType().isBoolean() ? kind::IFF : kind::EQUAL, e, d_type_references_all[tn][j] );
d_out->lemma( eq.negate() );
}
+ d_type_references_all[tn].push_back( e );
}
- d_type_references_all[tn].push_back( e );
- d_lbl_reference_bound[d_base_label[tn]].push_back( e );
+ }else{
+ //break symmetries TODO
+
+ d_type_references_all[tn].insert( d_type_references_all[tn].end(), d_type_references_card[tn].begin(), d_type_references_card[tn].end() );
}
- //construct bound
- d_reference_bound_max[tn] = mkUnion( tn, d_type_references_all[tn] );
- Trace("sep-bound") << "overall bound for " << d_base_label[tn] << " : " << d_reference_bound_max[tn] << std::endl;
+ Assert( !d_type_references_all[tn].empty() );
+
+ if( d_reference_bound_invalid.find( tn )==d_reference_bound_invalid.end() ){
+ //construct bound
+ d_reference_bound_max[tn] = mkUnion( tn, d_type_references_all[tn] );
+ Trace("sep-bound") << "overall bound for " << d_base_label[tn] << " : " << d_reference_bound_max[tn] << std::endl;
- if( d_reference_bound_invalid.find( tn )==d_reference_bound_invalid.end() ){
Node slem = NodeManager::currentNM()->mkNode( kind::SUBSET, d_reference_bound[tn], d_reference_bound_max[tn] );
Trace("sep-lemma") << "Sep::Lemma: reference bound for " << tn << " : " << slem << std::endl;
d_out->lemma( slem );
- }else{
- Trace("sep-bound") << "reference cannot be bound (possibly due to quantified pto)." << std::endl;
+ //slem = NodeManager::currentNM()->mkNode( kind::SUBSET, d_base_label[tn], d_reference_bound_max[tn] );
+ //Trace("sep-lemma") << "Sep::Lemma: base reference bound for " << tn << " : " << slem << std::endl;
+ //d_out->lemma( slem );
+
+ //symmetry breaking
+ std::map< unsigned, Node > lit_mem_map;
+ for( unsigned i=0; i<d_type_references_card[tn].size(); i++ ){
+ lit_mem_map[i] = NodeManager::currentNM()->mkNode( kind::MEMBER, d_type_references_card[tn][i], d_reference_bound[tn]);
+ }
+ for( unsigned i=0; i<(d_type_references_card[tn].size()-1); i++ ){
+ std::vector< Node > children;
+ for( unsigned j=(i+1); j<d_type_references_card[tn].size(); j++ ){
+ children.push_back( lit_mem_map[j].negate() );
+ }
+ Assert( !children.empty() );
+ Node sym_lem = children.size()==1 ? children[0] : NodeManager::currentNM()->mkNode( kind::AND, children );
+ sym_lem = NodeManager::currentNM()->mkNode( kind::IMPLIES, lit_mem_map[i].negate(), sym_lem );
+ Trace("sep-lemma") << "Sep::Lemma: symmetry breaking lemma : " << sym_lem << std::endl;
+ d_out->lemma( sym_lem );
+ }
}
- //slem = NodeManager::currentNM()->mkNode( kind::SUBSET, d_base_label[tn], d_reference_bound_max[tn] );
- //Trace("sep-lemma") << "Sep::Lemma: base reference bound for " << tn << " : " << slem << std::endl;
- //d_out->lemma( slem );
//assert that nil ref is not in base label
Node nr = getNilRef( tn );
@@ -1095,7 +1125,7 @@ Node TheorySep::getBaseLabel( TypeNode tn ) {
Node TheorySep::getNilRef( TypeNode tn ) {
std::map< TypeNode, Node >::iterator it = d_nil_ref.find( tn );
if( it==d_nil_ref.end() ){
- Node nil = NodeManager::currentNM()->mkSepNil( tn );
+ Node nil = NodeManager::currentNM()->mkUniqueVar( tn, kind::SEP_NIL );
setNilRef( tn, nil );
return nil;
}else{
@@ -1132,7 +1162,7 @@ Node TheorySep::getLabel( Node atom, int child, Node lbl ) {
std::map< int, Node >::iterator it = d_label_map[atom][lbl].find( child );
if( it==d_label_map[atom][lbl].end() ){
int card;
- TypeNode refType = getReferenceType( atom, card );
+ TypeNode refType = computeReferenceType( atom, card );
std::stringstream ss;
ss << "__Lc" << child;
TypeNode ltn = NodeManager::currentNM()->mkSetType(refType);
@@ -1372,7 +1402,6 @@ void TheorySep::computeLabelModel( Node lbl, std::map< Node, Node >& tmodel ) {
Assert( false );
}
}
- //end hack
for( unsigned j=0; j<d_label_model[lbl].d_heap_locs_model.size(); j++ ){
Node u = d_label_model[lbl].d_heap_locs_model[j];
Assert( u.getKind()==kind::SINGLETON );
@@ -1386,7 +1415,8 @@ void TheorySep::computeLabelModel( Node lbl, std::map< Node, Node >& tmodel ) {
//TypeNode tn = u.getType().getRefConstituentType();
TypeNode tn = u.getType();
Trace("sep-process") << "WARNING: could not find symbolic term in model for " << u << ", cref type " << tn << std::endl;
- Assert( d_type_references_all.find( tn )!=d_type_references_all.end() && !d_type_references_all[tn].empty() );
+ Assert( d_type_references_all.find( tn )!=d_type_references_all.end() );
+ Assert( !d_type_references_all[tn].empty() );
tt = d_type_references_all[tn][0];
}else{
tt = itm->second;
@@ -1489,7 +1519,11 @@ void TheorySep::addPto( HeapAssertInfo * ei, Node ei_n, Node p, bool polarity )
Assert( areEqual( pb[1], p[1] ) );
std::vector< Node > exp;
if( pb[1]!=p[1] ){
+ //if( pb[1].getKind()==kind::SINGLETON && p[1].getKind()==kind::SINGLETON ){
+ // exp.push_back( pb[1][0].eqNode( p[1][0] ) );
+ //}else{
exp.push_back( pb[1].eqNode( p[1] ) );
+ //}
}
exp.push_back( pb );
exp.push_back( p.negate() );
@@ -1497,10 +1531,12 @@ void TheorySep::addPto( HeapAssertInfo * ei, Node ei_n, Node p, bool polarity )
if( pb[0][1]!=p[0][1] ){
conc.push_back( pb[0][1].eqNode( p[0][1] ).negate() );
}
- if( pb[1]!=p[1] ){
- conc.push_back( pb[1].eqNode( p[1] ).negate() );
- }
+ //if( pb[1]!=p[1] ){
+ // conc.push_back( pb[1].eqNode( p[1] ).negate() );
+ //}
Node n_conc = conc.empty() ? d_false : ( conc.size()==1 ? conc[0] : NodeManager::currentNM()->mkNode( kind::OR, conc ) );
+ Trace("sep-pto") << "Conclusion is " << n_conc << std::endl;
+ // propagation for (pto x y) ^ ~(pto z w) ^ x = z => y != w
sendLemma( exp, n_conc, "PTO_NEG_PROP" );
}
}else{
@@ -1525,6 +1561,7 @@ void TheorySep::mergePto( Node p1, Node p2 ) {
}
exp.push_back( p1 );
exp.push_back( p2 );
+ //enforces injectiveness of pto : (pto x y) ^ (pto y w) ^ x = y => y = w
sendLemma( exp, p1[0][1].eqNode( p2[0][1] ), "PTO_PROP" );
}
}
@@ -1598,8 +1635,11 @@ void TheorySep::doPendingFacts() {
}
int index = d_pending_lem[i];
Node lem = NodeManager::currentNM()->mkNode( kind::IMPLIES, d_pending_exp[index], d_pending[index] );
- d_out->lemma( lem );
- Trace("sep-pending") << "Sep : Lemma : " << lem << std::endl;
+ if( d_lemmas_produced_c.find( lem )==d_lemmas_produced_c.end() ){
+ d_lemmas_produced_c.insert( lem );
+ d_out->lemma( lem );
+ Trace("sep-pending") << "Sep : Lemma : " << lem << std::endl;
+ }
}
}
d_pending_exp.clear();
diff --git a/src/theory/sep/theory_sep.h b/src/theory/sep/theory_sep.h
index 29e7a008c..982fc3c70 100644
--- a/src/theory/sep/theory_sep.h
+++ b/src/theory/sep/theory_sep.h
@@ -44,6 +44,8 @@ class TheorySep : public Theory {
/////////////////////////////////////////////////////////////////////////////
private:
+ /** all lemmas sent */
+ NodeSet d_lemmas_produced_c;
/** True node for predicates = true */
Node d_true;
@@ -51,7 +53,8 @@ class TheorySep : public Theory {
/** True node for predicates = false */
Node d_false;
- std::vector< Node > d_pp_nils;
+ //whether bounds have been initialized
+ bool d_bounds_init;
Node mkAnd( std::vector< TNode >& assumptions );
@@ -75,7 +78,7 @@ class TheorySep : public Theory {
PPAssertStatus ppAssert(TNode in, SubstitutionMap& outSubstitutions);
Node ppRewrite(TNode atom);
- void processAssertions( std::vector< Node >& assertions );
+ void ppNotifyAssertions( std::vector< Node >& assertions );
/////////////////////////////////////////////////////////////////////////////
// T-PROPAGATION / REGISTRATION
/////////////////////////////////////////////////////////////////////////////
@@ -88,10 +91,8 @@ class TheorySep : public Theory {
/** Explain why this literal is true by adding assumptions */
void explain(TNode literal, std::vector<TNode>& assumptions);
- void preRegisterTermRec(TNode t, std::map< TNode, bool >& visited );
public:
- void preRegisterTerm(TNode t);
void propagate(Effort e);
Node explain(TNode n);
@@ -208,6 +209,9 @@ class TheorySep : public Theory {
NodeList d_infer_exp;
NodeList d_spatial_assertions;
+ //data,ref type (globally fixed)
+ TypeNode d_type_ref;
+ TypeNode d_type_data;
//currently fix one data type for each location type, throw error if using more than one
std::map< TypeNode, TypeNode > d_loc_to_data_type;
//information about types
@@ -217,11 +221,12 @@ class TheorySep : public Theory {
std::map< TypeNode, Node > d_reference_bound;
std::map< TypeNode, Node > d_reference_bound_max;
std::map< TypeNode, bool > d_reference_bound_invalid;
+ std::map< TypeNode, bool > d_reference_bound_fv;
std::map< TypeNode, std::vector< Node > > d_type_references;
+ std::map< TypeNode, std::vector< Node > > d_type_references_card;
+ std::map< Node, unsigned > d_type_ref_card_id;
std::map< TypeNode, std::vector< Node > > d_type_references_all;
std::map< TypeNode, unsigned > d_card_max;
- //bounds for labels
- std::map< Node, std::vector< Node > > d_lbl_reference_bound;
//for empty argument
std::map< TypeNode, Node > d_emp_arg;
//map from ( atom, label, child index ) -> label
@@ -242,9 +247,14 @@ class TheorySep : public Theory {
std::map< Node, HeapAssertInfo * > d_eqc_info;
HeapAssertInfo * getOrMakeEqcInfo( Node n, bool doMake = false );
+ //get global reference/data type
+ TypeNode getReferenceType( Node n );
+ TypeNode getDataType( Node n );
//calculate the element type of the heap for spatial assertions
- TypeNode getReferenceType( Node atom, int& card, int index = -1 );
- TypeNode getReferenceType2( Node atom, int& card, int index, Node n, std::map< Node, int >& visited);
+ TypeNode computeReferenceType( Node atom, int& card, int index = -1 );
+ TypeNode computeReferenceType2( Node atom, int& card, int index, Node n, std::map< Node, int >& visited);
+ void registerRefDataTypes( TypeNode tn1, TypeNode tn2, Node atom );
+ //get location/data type
//get the base label for the spatial assertion
Node getBaseLabel( TypeNode tn );
Node getNilRef( TypeNode tn );
@@ -291,6 +301,7 @@ public:
return &d_equalityEngine;
}
+ void initializeBounds();
};/* class TheorySep */
}/* CVC4::theory::sep namespace */
diff --git a/src/theory/sets/normal_form.h b/src/theory/sets/normal_form.h
index 6da7e9f8f..c1f05ae85 100644
--- a/src/theory/sets/normal_form.h
+++ b/src/theory/sets/normal_form.h
@@ -24,58 +24,64 @@ namespace theory {
namespace sets {
class NormalForm {
-public:
-
- template<bool ref_count>
- static Node elementsToSet(std::set<NodeTemplate<ref_count> > elements, TypeNode setType)
- {
+ public:
+ template <bool ref_count>
+ static Node elementsToSet(const std::set<NodeTemplate<ref_count> >& elements,
+ TypeNode setType) {
+ typedef typename std::set<NodeTemplate<ref_count> >::const_iterator
+ ElementsIterator;
NodeManager* nm = NodeManager::currentNM();
-
- if(elements.size() == 0) {
+ if (elements.size() == 0) {
return nm->mkConst(EmptySet(nm->toType(setType)));
} else {
- typeof(elements.begin()) it = elements.begin();
+ ElementsIterator it = elements.begin();
Node cur = nm->mkNode(kind::SINGLETON, *it);
- while( ++it != elements.end() ) {
- cur = nm->mkNode(kind::UNION, cur,
- nm->mkNode(kind::SINGLETON, *it));
+ while (++it != elements.end()) {
+ cur = nm->mkNode(kind::UNION, cur, nm->mkNode(kind::SINGLETON, *it));
}
return cur;
}
}
static bool checkNormalConstant(TNode n) {
- Debug("sets-checknormal") << "[sets-checknormal] checkNormal " << n << " :" << std::endl;
- if(n.getKind() == kind::EMPTYSET) {
+ Debug("sets-checknormal") << "[sets-checknormal] checkNormal " << n << " :"
+ << std::endl;
+ if (n.getKind() == kind::EMPTYSET) {
return true;
- } else if(n.getKind() == kind::SINGLETON) {
+ } else if (n.getKind() == kind::SINGLETON) {
return n[0].isConst();
- } else if(n.getKind() == kind::UNION) {
-
- // assuming (union ... (union {SmallestNodeID} {BiggerNodeId}) ... {BiggestNodeId})
+ } else if (n.getKind() == kind::UNION) {
+ // assuming (union ... (union {SmallestNodeID} {BiggerNodeId}) ...
+ // {BiggestNodeId})
// store BiggestNodeId in prvs
- if(n[1].getKind() != kind::SINGLETON) return false;
- if( !n[1][0].isConst() ) return false;
- Debug("sets-checknormal") << "[sets-checknormal] frst element = " << n[1][0] << " " << n[1][0].getId() << std::endl;
+ if (n[1].getKind() != kind::SINGLETON) return false;
+ if (!n[1][0].isConst()) return false;
+ Debug("sets-checknormal")
+ << "[sets-checknormal] frst element = " << n[1][0] << " "
+ << n[1][0].getId() << std::endl;
TNode prvs = n[1][0];
n = n[0];
// check intermediate nodes
- while(n.getKind() == kind::UNION) {
- if(n[1].getKind() != kind::SINGLETON) return false;
- if( !n[1].isConst() ) return false;
- Debug("sets-checknormal") << "[sets-checknormal] element = " << n[1][0] << " " << n[1][0].getId() << std::endl;
- if( n[1][0] >= prvs ) return false;
- TNode prvs = n[1][0];
- n = n[0];
+ while (n.getKind() == kind::UNION) {
+ if (n[1].getKind() != kind::SINGLETON) return false;
+ if (!n[1].isConst()) return false;
+ Debug("sets-checknormal")
+ << "[sets-checknormal] element = " << n[1][0] << " "
+ << n[1][0].getId() << std::endl;
+ if (n[1][0] >= prvs) return false;
+ TNode prvs = n[1][0];
+ n = n[0];
}
// check SmallestNodeID is smallest
- if(n.getKind() != kind::SINGLETON) return false;
- if( !n[0].isConst() ) return false;
- Debug("sets-checknormal") << "[sets-checknormal] lst element = " << n[0] << " " << n[0].getId() << std::endl;
- if( n[0] >= prvs ) return false;
+ if (n.getKind() != kind::SINGLETON) return false;
+ if (!n[0].isConst()) return false;
+ Debug("sets-checknormal")
+ << "[sets-checknormal] lst element = " << n[0] << " "
+ << n[0].getId() << std::endl;
+ if (n[0] >= prvs) return false;
// we made it
return true;
@@ -88,10 +94,10 @@ public:
static std::set<Node> getElementsFromNormalConstant(TNode n) {
Assert(n.isConst());
std::set<Node> ret;
- if(n.getKind() == kind::EMPTYSET) {
+ if (n.getKind() == kind::EMPTYSET) {
return ret;
}
- while(n.getKind() == kind::UNION) {
+ while (n.getKind() == kind::UNION) {
Assert(n[1].getKind() == kind::SINGLETON);
ret.insert(ret.begin(), n[1][0]);
n = n[0];
@@ -100,9 +106,7 @@ public:
ret.insert(n[0]);
return ret;
}
-
};
-
}
}
}
diff --git a/src/theory/sets/scrutinize.h b/src/theory/sets/scrutinize.h
index 2ada4a3ce..88f6001b9 100644
--- a/src/theory/sets/scrutinize.h
+++ b/src/theory/sets/scrutinize.h
@@ -17,8 +17,6 @@
#pragma once
-#include <boost/foreach.hpp>
-
#include "theory/sets/theory_sets.h"
#include "theory/sets/theory_sets_private.h"
@@ -55,7 +53,8 @@ public:
}
}
bool checkPassed = true;
- BOOST_FOREACH(TNode term, terms) {
+ for (std::set<Node>::const_iterator it = terms.begin(); it != terms.end(); it++){
+ TNode term = *it;
if( term.getType().isSet() ) {
checkPassed &= d_theory->checkModel(settermElementsMap, term);
}
@@ -72,4 +71,3 @@ public:
}/* CVC4::theory::sets namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
-
diff --git a/src/theory/sets/theory_sets_private.cpp b/src/theory/sets/theory_sets_private.cpp
index aec2c119c..e996cb215 100644
--- a/src/theory/sets/theory_sets_private.cpp
+++ b/src/theory/sets/theory_sets_private.cpp
@@ -218,7 +218,7 @@ void TheorySetsPrivate::assertMemebership(TNode fact, TNode reason, bool learnt)
if(x.getType().isSet()) {
if(polarity) {
const CDTNodeList* l = d_termInfoManager->getNonMembers(S);
- for(typeof(l->begin()) it = l->begin(); it != l->end(); ++it) {
+ for(CDTNodeList::iterator it = l->begin(); it != l->end(); ++it) {
TNode n = *it;
learnLiteral( /* atom = */ EQUAL(x, n),
/* polarity = */ false,
@@ -226,7 +226,7 @@ void TheorySetsPrivate::assertMemebership(TNode fact, TNode reason, bool learnt)
}
} else {
const CDTNodeList* l = d_termInfoManager->getMembers(S);
- for(typeof(l->begin()) it = l->begin(); it != l->end(); ++it) {
+ for(CDTNodeList::iterator it = l->begin(); it != l->end(); ++it) {
TNode n = *it;
learnLiteral( /* atom = */ EQUAL(x, n),
/* polarity = */ false,
@@ -255,7 +255,7 @@ void TheorySetsPrivate::assertMemebership(TNode fact, TNode reason, bool learnt)
Debug("sets-prop") << "[sets-prop] Propagating 'up' for "
<< x << element_of_str << S << std::endl;
const CDTNodeList* parentList = d_termInfoManager->getParents(S);
- for(typeof(parentList->begin()) k = parentList->begin();
+ for(CDTNodeList::const_iterator k = parentList->begin();
k != parentList->end(); ++k) {
doSettermPropagation(x, *k);
if(d_conflict) return;
@@ -475,9 +475,15 @@ void TheorySetsPrivate::dumpAssertionsHumanified() const
context::CDList<Assertion>::const_iterator it = d_external.facts_begin(), it_end = d_external.facts_end();
- std::map<TNode, std::set<TNode> > equalities;
- std::set< pair<TNode, TNode> > disequalities;
- std::map<TNode, std::pair<std::set<TNode>, std::set<TNode> > > members;
+ typedef std::set<TNode> TNodeSet;
+
+ typedef std::map<TNode, TNodeSet > EqualityMap;
+ EqualityMap equalities;
+
+ typedef std::set< std::pair<TNode, TNode> > TNodePairSet;
+ TNodePairSet disequalities;
+ typedef std::map<TNode, std::pair<TNodeSet, TNodeSet > > MemberMap;
+ MemberMap members;
static std::map<TNode, int> numbering;
static int number = 0;
@@ -504,10 +510,11 @@ void TheorySetsPrivate::dumpAssertionsHumanified() const
(polarity ? members[right].first : members[right].second).insert(left);
}
}
-#define FORIT(it, container) for(typeof((container).begin()) it=(container).begin(); (it) != (container).end(); ++(it))
- FORIT(kt, equalities) {
+ for(EqualityMap::const_iterator kt =equalities.begin(); kt != equalities.end(); ++kt) {
Trace(tag) << " Eq class of t" << numbering[(*kt).first] << ": " << std::endl;
- FORIT(jt, (*kt).second) {
+
+ const TNodeSet& kt_second = (*kt).second;
+ for(TNodeSet::const_iterator jt=kt_second.begin(); jt != kt_second.end(); ++jt) {
TNode S = (*jt);
if( S.getKind() != kind::UNION && S.getKind() != kind::INTERSECTION && S.getKind() != kind::SETMINUS) {
Trace(tag) << " " << *jt << ((*jt).getType().isSet() ? "\n": " ");
@@ -529,11 +536,17 @@ void TheorySetsPrivate::dumpAssertionsHumanified() const
}
Trace(tag) << std::endl;
}
- FORIT(kt, disequalities) Trace(tag) << "NOT(t"<<numbering[(*kt).first]<<" = t" <<numbering[(*kt).second] <<")"<< std::endl;
- FORIT(kt, members) {
- if( (*kt).second.first.size() > 0) {
- Trace(tag) << "IN t" << numbering[(*kt).first] << ": ";
- FORIT(jt, (*kt).second.first) {
+ for(TNodePairSet::const_iterator kt=disequalities.begin(); kt != disequalities.end(); ++kt){
+ Trace(tag) << "NOT(t"<<numbering[(*kt).first]<<" = t" <<numbering[(*kt).second] <<")"<< std::endl;
+ }
+ for(MemberMap::const_iterator kt=members.begin(); kt != members.end(); ++kt) {
+ const TNode& kt_key = (*kt).first;
+ const TNodeSet& kt_in_set = (*kt).second.first;
+ const TNodeSet& kt_out_set = (*kt).second.first;
+ if( kt_in_set.size() > 0) {
+ Trace(tag) << "IN t" << numbering[kt_key] << ": ";
+ //FORIT(jt, (*kt).second.first)
+ for(TNodeSet::const_iterator jt=kt_in_set.begin(); jt != kt_in_set.end(); ++jt) {
TNode x = (*jt);
if(x.isConst() || numbering.find(d_equalityEngine.getRepresentative(x)) == numbering.end()) {
Trace(tag) << x << ", ";
@@ -543,9 +556,9 @@ void TheorySetsPrivate::dumpAssertionsHumanified() const
}
Trace(tag) << std::endl;
}
- if( (*kt).second.second.size() > 0) {
- Trace(tag) << "NOT IN t" << numbering[(*kt).first] << ": ";
- FORIT(jt, (*kt).second.second) {
+ if( kt_out_set.size() > 0) {
+ Trace(tag) << "NOT IN t" << numbering[kt_key] << ": ";
+ for(TNodeSet::const_iterator jt=kt_out_set.begin(); jt != kt_out_set.end(); ++jt){
TNode x = (*jt);
if(x.isConst() || numbering.find(d_equalityEngine.getRepresentative(x)) == numbering.end()) {
Trace(tag) << x << ", ";
@@ -557,7 +570,6 @@ void TheorySetsPrivate::dumpAssertionsHumanified() const
}
}
Trace(tag) << std::endl;
-#undef FORIT
}
void TheorySetsPrivate::computeCareGraph() {
@@ -871,14 +883,15 @@ Node TheorySetsPrivate::elementsToShape(Elements elements, TypeNode setType) con
return cur;
}
}
-Node TheorySetsPrivate::elementsToShape(set<Node> elements, TypeNode setType) const
+
+Node TheorySetsPrivate::elementsToShape(std::set<Node> elements, TypeNode setType) const
{
NodeManager* nm = NodeManager::currentNM();
if(elements.size() == 0) {
return nm->mkConst<EmptySet>(EmptySet(nm->toType(setType)));
} else {
- typeof(elements.begin()) it = elements.begin();
+ std::set<Node>::const_iterator it = elements.begin();
Node cur = SINGLETON(*it);
while( ++it != elements.end() ) {
cur = nm->mkNode(kind::UNION, cur, SINGLETON(*it));
@@ -892,13 +905,13 @@ void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel)
Trace("sets-model") << "[sets-model] collectModelInfo(..., fullModel="
<< (fullModel ? "true)" : "false)") << std::endl;
- set<Node> terms;
+ std::set<Node> terms;
NodeManager* nm = NodeManager::currentNM();
// // this is for processCard -- commenting out for now
// if(Debug.isOn("sets-card")) {
- // for(typeof(d_cardTerms.begin()) it = d_cardTerms.begin();
+ // for(CDNodeSet::const_iterator it = d_cardTerms.begin();
// it != d_cardTerms.end(); ++it) {
// Debug("sets-card") << "[sets-card] " << *it << " = "
// << d_external.d_valuation.getModelValue(*it)
@@ -915,7 +928,8 @@ void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel)
//processCard2 begin
if(Debug.isOn("sets-card")) {
- for(typeof(d_V.begin()) it = d_V.begin(); it != d_V.end(); ++it) {
+ print_graph(true);
+ for(CDNodeSet::const_iterator it = d_V.begin(); it != d_V.end(); ++it) {
Node n = nm->mkNode(kind::CARD, *it);
Debug("sets-card") << "[sets-card] " << n << " = ";
// if(d_external.d_sharedTerms.find(n) == d_external.d_sharedTerms.end()) continue;
@@ -1005,7 +1019,7 @@ void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel)
//processCard2 begin
leaves.clear();
- for(typeof(d_V.begin()) it = d_V.begin(); it != d_V.end(); ++it)
+ for(CDNodeSet::const_iterator it = d_V.begin(); it != d_V.end(); ++it)
if(d_E.find(*it) == d_E.end())
leaves.insert(*it);
d_statistics.d_numLeaves.setData(leaves.size());
@@ -1102,7 +1116,7 @@ Node mkAnd(const std::vector<TNode>& conjunctions) {
if (t.getKind() == kind::AND) {
for(TNode::iterator child_it = t.begin();
child_it != t.end(); ++child_it) {
- Assert((*child_it).getKind() != kind::AND);
+ // Assert((*child_it).getKind() != kind::AND);
all.insert(*child_it);
}
}
@@ -1311,15 +1325,20 @@ Node TheorySetsPrivate::getLemma() {
Assert(n.getKind() == kind::EQUAL && n[0].getType().isSet());
TypeNode elementType = n[0].getType().getSetElementType();
- Node x = NodeManager::currentNM()->mkSkolem("sde_", elementType);
- Node l1 = MEMBER(x, n[0]), l2 = MEMBER(x, n[1]);
-
- if(n[0].getKind() == kind::EMPTYSET) {
- lemma = OR(n, l2);
- } else if(n[1].getKind() == kind::EMPTYSET) {
- lemma = OR(n, l1);
- } else {
- lemma = OR(n, AND(l1, NOT(l2)), AND(NOT(l1), l2));
+ // { x } != { y } => x != y
+ if( n[0].getKind()==kind::SINGLETON && n[1].getKind()==kind::SINGLETON ){
+ lemma = OR(n, NodeManager::currentNM()->mkNode( elementType.isBoolean() ? kind::IFF : kind::EQUAL, n[0][0], n[1][0] ).negate() );
+ }else{
+ Node x = NodeManager::currentNM()->mkSkolem("sde_", elementType);
+ Node l1 = MEMBER(x, n[0]), l2 = MEMBER(x, n[1]);
+
+ if(n[0].getKind() == kind::EMPTYSET) {
+ lemma = OR(n, l2);
+ } else if(n[1].getKind() == kind::EMPTYSET) {
+ lemma = OR(n, l1);
+ } else {
+ lemma = OR(n, AND(l1, NOT(l2)), AND(NOT(l1), l2));
+ }
}
}
@@ -1412,7 +1431,7 @@ void TheorySetsPrivate::propagate(Theory::Effort effort) {
}
const CDNodeSet& terms = (d_termInfoManager->d_terms);
- for(typeof(terms.key_begin()) it = terms.key_begin(); it != terms.key_end(); ++it) {
+ for(CDNodeSet::key_iterator it = terms.key_begin(); it != terms.key_end(); ++it) {
Node node = (*it);
Kind k = node.getKind();
if(k == kind::UNION && node[0].getKind() == kind::SINGLETON ) {
@@ -1496,7 +1515,11 @@ Node TheorySetsPrivate::explain(TNode literal)
Unhandled();
}
- return mkAnd(assumptions);
+ if(assumptions.size()) {
+ return mkAnd(assumptions);
+ } else {
+ return d_trueNode;
+ }
}
bool TheorySetsPrivate::lemma(Node n, SetsLemmaTag t)
@@ -1568,14 +1591,14 @@ void TheorySetsPrivate::preRegisterTerm(TNode node)
void TheorySetsPrivate::presolve() {
- for(typeof(d_termInfoManager->d_terms.begin()) it = d_termInfoManager->d_terms.begin();
+ for(CDNodeSet::const_iterator it = d_termInfoManager->d_terms.begin();
it != d_termInfoManager->d_terms.end(); ++it) {
d_relTerms.insert(*it);
}
if(Trace.isOn("sets-relterms")) {
Trace("sets-relterms") << "[sets-relterms] ";
- for(typeof(d_relTerms.begin()) it = d_relTerms.begin();
+ for(CDNodeSet::const_iterator it = d_relTerms.begin();
it != d_relTerms.end(); ++it ) {
Trace("sets-relterms") << (*it) << ", ";
}
@@ -1672,18 +1695,18 @@ void TheorySetsPrivate::TermInfoManager::mergeLists
}
}
-TheorySetsPrivate::TermInfoManager::TermInfoManager
-(TheorySetsPrivate& theory, context::Context* satContext, eq::EqualityEngine* eq):
- d_theory(theory),
- d_context(satContext),
- d_eqEngine(eq),
- d_terms(satContext),
- d_info()
-{ }
+TheorySetsPrivate::TermInfoManager::TermInfoManager(
+ TheorySetsPrivate& theory, context::Context* satContext,
+ eq::EqualityEngine* eq)
+ : d_theory(theory),
+ d_context(satContext),
+ d_eqEngine(eq),
+ d_terms(satContext),
+ d_info() {}
TheorySetsPrivate::TermInfoManager::~TermInfoManager() {
- for( typeof(d_info.begin()) it = d_info.begin();
- it != d_info.end(); ++it) {
+ for (SetsTermInfoMap::iterator it = d_info.begin(); it != d_info.end();
+ ++it) {
delete (*it).second;
}
}
@@ -1744,14 +1767,14 @@ void TheorySetsPrivate::TermInfoManager::addTerm(TNode n) {
d_theory.registerCard(CARD(n));
}
- typeof(d_info.begin()) ita = d_info.find(d_eqEngine->getRepresentative(n[i]));
+ SetsTermInfoMap::iterator ita = d_info.find(d_eqEngine->getRepresentative(n[i]));
Assert(ita != d_info.end());
CDTNodeList* l = (*ita).second->elementsNotInThisSet;
- for(typeof(l->begin()) it = l->begin(); it != l->end(); ++it) {
+ for(CDTNodeList::const_iterator it = l->begin(); it != l->end(); ++it) {
d_theory.d_settermPropagationQueue.push_back( std::make_pair( (*it), n ) );
}
l = (*ita).second->elementsInThisSet;
- for(typeof(l->begin()) it = l->begin(); it != l->end(); ++it) {
+ for(CDTNodeList::const_iterator it = l->begin(); it != l->end(); ++it) {
d_theory.d_settermPropagationQueue.push_back( std::make_pair( (*it), n ) );
}
}
@@ -1782,7 +1805,7 @@ void TheorySetsPrivate::TermInfoManager::pushToSettermPropagationQueue
// propagation : parents
const CDTNodeList* parentList = getParents(S);
- for(typeof(parentList->begin()) k = parentList->begin();
+ for(CDTNodeList::const_iterator k = parentList->begin();
k != parentList->end(); ++k) {
d_theory.d_settermPropagationQueue.push_back(std::make_pair(x, *k));
}// propagation : parents
@@ -1850,8 +1873,8 @@ void TheorySetsPrivate::TermInfoManager::mergeTerms(TNode a, TNode b) {
<< ", b: " << d_eqEngine->getRepresentative(b)
<< std::endl;
- typeof(d_info.begin()) ita = d_info.find(a);
- typeof(d_info.begin()) itb = d_info.find(b);
+ SetsTermInfoMap::iterator ita = d_info.find(a);
+ SetsTermInfoMap::iterator itb = d_info.find(b);
Assert(ita != d_info.end());
Assert(itb != d_info.end());
@@ -1879,29 +1902,33 @@ void TheorySetsPrivate::TermInfoManager::mergeTerms(TNode a, TNode b) {
d_theory.d_modelCache.clear();
}
-Node TheorySetsPrivate::TermInfoManager::getModelValue(TNode n)
-{
- if(d_terms.find(n) == d_terms.end()) {
+Node TheorySetsPrivate::TermInfoManager::getModelValue(TNode n) {
+ if (d_terms.find(n) == d_terms.end()) {
return Node();
}
Assert(n.getType().isSet());
- set<Node> elements, elements_const;
+ std::set<Node> elements;
+ std::set<Node> elements_const;
Node S = d_eqEngine->getRepresentative(n);
- typeof(d_theory.d_modelCache.begin()) it = d_theory.d_modelCache.find(S);
- if(it != d_theory.d_modelCache.end()) {
+ context::CDHashMap<Node, Node, NodeHashFunction>::const_iterator it =
+ d_theory.d_modelCache.find(S);
+ if (it != d_theory.d_modelCache.end()) {
return (*it).second;
}
const CDTNodeList* l = getMembers(S);
- for(typeof(l->begin()) it = l->begin(); it != l->end(); ++it) {
+ for (CDTNodeList::const_iterator it = l->begin(); it != l->end(); ++it) {
TNode n = *it;
elements.insert(d_eqEngine->getRepresentative(n));
}
- BOOST_FOREACH(TNode e, elements) {
- if(e.isConst()) {
+ for(std::set<Node>::iterator it = elements.begin(); it != elements.end(); it++) {
+ TNode e = *it;
+ if (e.isConst()) {
elements_const.insert(e);
} else {
Node eModelValue = d_theory.d_external.d_valuation.getModelValue(e);
- if( eModelValue.isNull() ) return eModelValue;
+ if (eModelValue.isNull()) {
+ return eModelValue;
+ }
elements_const.insert(eModelValue);
}
}
@@ -1910,9 +1937,6 @@ Node TheorySetsPrivate::TermInfoManager::getModelValue(TNode n)
return v;
}
-
-
-
/********************** Cardinality ***************************/
/********************** Cardinality ***************************/
/********************** Cardinality ***************************/
@@ -1927,7 +1951,7 @@ void TheorySetsPrivate::enableCard()
cardCreateEmptysetSkolem(t);
}
- for(typeof(d_termInfoManager->d_terms.begin()) it = d_termInfoManager->d_terms.begin();
+ for(CDNodeSet::const_iterator it = d_termInfoManager->d_terms.begin();
it != d_termInfoManager->d_terms.end(); ++it) {
Node n = (*it);
if(n.getKind() == kind::SINGLETON) {
@@ -1944,7 +1968,7 @@ void TheorySetsPrivate::registerCard(TNode node) {
// introduce cardinality of any set-term containing this term
NodeManager* nm = NodeManager::currentNM();
const CDTNodeList* parentList = d_termInfoManager->getParents(node[0]);
- for(typeof(parentList->begin()) it = parentList->begin();
+ for(CDTNodeList::const_iterator it = parentList->begin();
it != parentList->end(); ++it) {
registerCard(nm->mkNode(kind::CARD, *it));
}
@@ -1971,9 +1995,10 @@ void TheorySetsPrivate::buildGraph() {
edgesFd.clear();
edgesBk.clear();
disjoint.clear();
-
- for(typeof(d_processedCardPairs.begin()) it = d_processedCardPairs.begin();
- it != d_processedCardPairs.end(); ++it) {
+
+ for (std::map<std::pair<Node, Node>, bool>::const_iterator it =
+ d_processedCardPairs.begin();
+ it != d_processedCardPairs.end(); ++it) {
Node s = (it->first).first;
Assert(Rewriter::rewrite(s) == s);
Node t = (it->first).second;
@@ -1988,7 +2013,7 @@ void TheorySetsPrivate::buildGraph() {
tMs = Rewriter::rewrite(tMs);
edgesFd[s].insert(sNt);
- edgesFd[s].insert(sMt);
+ edgesFd[s].insert(sMt);
edgesBk[sNt].insert(s);
edgesBk[sMt].insert(s);
@@ -2000,7 +2025,7 @@ void TheorySetsPrivate::buildGraph() {
if(hasUnion) {
Node sUt = nm->mkNode(kind::UNION, s, t);
sUt = Rewriter::rewrite(sUt);
-
+
edgesFd[sUt].insert(sNt);
edgesFd[sUt].insert(sMt);
edgesFd[sUt].insert(tMs);
@@ -2017,32 +2042,34 @@ void TheorySetsPrivate::buildGraph() {
disjoint.insert(make_pair(sMt, tMs));
}
- if(Debug.isOn("sets-card-graph")) {
+ if (Debug.isOn("sets-card-graph")) {
Debug("sets-card-graph") << "[sets-card-graph] Fd:" << std::endl;
- for(typeof(edgesFd.begin()) it = edgesFd.begin();
- it != edgesFd.end(); ++it) {
- Debug("sets-card-graph") << "[sets-card-graph] " << (it->first) << std::endl;
- for(typeof( (it->second).begin()) jt = (it->second).begin();
- jt != (it->second).end(); ++jt) {
- Debug("sets-card-graph") << "[sets-card-graph] " << (*jt) << std::endl;
+ for (std::map<TNode, std::set<TNode> >::const_iterator it = edgesFd.begin();
+ it != edgesFd.end(); ++it) {
+ Debug("sets-card-graph") << "[sets-card-graph] " << (it->first)
+ << std::endl;
+ for (std::set<TNode>::const_iterator jt = (it->second).begin();
+ jt != (it->second).end(); ++jt) {
+ Debug("sets-card-graph") << "[sets-card-graph] " << (*jt)
+ << std::endl;
}
}
Debug("sets-card-graph") << "[sets-card-graph] Bk:" << std::endl;
- for(typeof(edgesBk.begin()) it = edgesBk.begin();
- it != edgesBk.end(); ++it) {
- Debug("sets-card-graph") << "[sets-card-graph] " << (it->first) << std::endl;
- for(typeof( (it->second).begin()) jt = (it->second).begin();
- jt != (it->second).end(); ++jt) {
- Debug("sets-card-graph") << "[sets-card-graph] " << (*jt) << std::endl;
+ for (std::map<TNode, std::set<TNode> >::const_iterator it = edgesBk.begin();
+ it != edgesBk.end(); ++it) {
+ Debug("sets-card-graph") << "[sets-card-graph] " << (it->first)
+ << std::endl;
+ for (std::set<TNode>::const_iterator jt = (it->second).begin();
+ jt != (it->second).end(); ++jt) {
+ Debug("sets-card-graph") << "[sets-card-graph] " << (*jt)
+ << std::endl;
}
}
}
-
-
leaves.clear();
-
- for(typeof(d_processedCardTerms.begin()) it = d_processedCardTerms.begin();
+
+ for(CDNodeSet::const_iterator it = d_processedCardTerms.begin();
it != d_processedCardTerms.end(); ++it) {
Node n = (*it)[0];
if( edgesFd.find(n) == edgesFd.end() ) {
@@ -2247,7 +2274,7 @@ std::set<TNode> TheorySetsPrivate::get_leaves(Node vertex1, Node vertex2, Node v
Node TheorySetsPrivate::eqemptySoFar() {
std::vector<Node> V;
- for(typeof(d_V.begin()) it = d_V.begin(); it != d_V.end(); ++it) {
+ for(CDNodeSet::const_iterator it = d_V.begin(); it != d_V.end(); ++it) {
Node rep = d_equalityEngine.getRepresentative(*it);
if(rep.getKind() == kind::EMPTYSET) {
V.push_back(EQUAL(rep, (*it)));
@@ -2391,11 +2418,12 @@ void TheorySetsPrivate::merge_nodes(std::set<TNode> leaves1, std::set<TNode> lea
}
-void TheorySetsPrivate::print_graph() {
+void TheorySetsPrivate::print_graph(bool printmodel) {
+ NodeManager* nm = NodeManager::currentNM();
std::string tag = "sets-graph";
if(Trace.isOn("sets-graph")) {
Trace(tag) << "[sets-graph] Graph : " << std::endl;
- for(typeof(d_V.begin()) it = d_V.begin(); it != d_V.end(); ++it) {
+ for(CDNodeSet::const_iterator it = d_V.begin(); it != d_V.end(); ++it) {
TNode v = *it;
// BOOST_FOREACH(TNode v, d_V) {
Trace(tag) << "[" << tag << "] " << v << " : ";
@@ -2414,15 +2442,40 @@ void TheorySetsPrivate::print_graph() {
if(Trace.isOn("sets-graph-dot")) {
std::ostringstream oss;
oss << "digraph G { ";
- for(typeof(d_V.begin()) it = d_V.begin(); it != d_V.end(); ++it) {
+ for(CDNodeSet::const_iterator it = d_V.begin(); it != d_V.end(); ++it) {
TNode v = *it;
+
+ std::ostringstream v_oss;
+ v_oss << v;
+ if(printmodel)
+ {
+ Node n = nm->mkNode(kind::CARD, v);
+ if((Rewriter::rewrite(n)).isConst()) {
+ v_oss << " " << (Rewriter::rewrite(n));
+ } else {
+ v_oss << " " << d_external.d_valuation.getModelValue(n);
+ }
+ }
+
if(d_E.find(v) != d_E.end()) {
BOOST_FOREACH(TNode w, d_E[v].get()) {
+
+ std::ostringstream w_oss;
+ w_oss << w;
+ if(printmodel) {
+ Node n = nm->mkNode(kind::CARD, w);
+ if((Rewriter::rewrite(n)).isConst()) {
+ w_oss << " " << (Rewriter::rewrite(n));
+ } else {
+ w_oss << " " << d_external.d_valuation.getModelValue(n);
+ }
+ }
+
//oss << v.getId() << " -> " << w.getId() << "; ";
- oss << "\"" << v << "\" -> \"" << w << "\"; ";
+ oss << "\"" << v_oss.str() << "\" -> \"" << w_oss.str() << "\"; ";
}
} else {
- oss << "\"" << v << "\";";
+ oss << "\"" << v_oss.str() << "\";";
}
}
oss << "}";
@@ -2448,7 +2501,7 @@ void TheorySetsPrivate::guessLeavesEmptyLemmas() {
// Guess leaf nodes being empty or non-empty
NodeManager* nm = NodeManager::currentNM();
leaves.clear();
- for(typeof(d_V.begin()) it = d_V.begin(); it != d_V.end(); ++it) {
+ for(CDNodeSet::const_iterator it = d_V.begin(); it != d_V.end(); ++it) {
TNode v = *it;
if(d_E.find(v) == d_E.end()) {
leaves.insert(v);
@@ -2465,7 +2518,7 @@ void TheorySetsPrivate::guessLeavesEmptyLemmas() {
numLeavesCurrentlyNonEmpty = 0,
numLemmaAlreadyExisted = 0;
- for(typeof(leaves.begin()) it = leaves.begin(); it != leaves.end(); ++it) {
+ for(std::set<TNode>::iterator it = leaves.begin(); it != leaves.end(); ++it) {
bool generateLemma = true;
Node emptySet = nm->mkConst<EmptySet>(EmptySet(nm->toType((*it).getType())));
@@ -2526,8 +2579,16 @@ void TheorySetsPrivate::processCard2(Theory::Effort level) {
NodeManager* nm = NodeManager::currentNM();
+ if(options::setsGuessEmpty() == 0) {
+ Trace("sets-guess-empty") << "[sets-guess-empty] Generating lemmas before introduce." << std::endl;
+ guessLeavesEmptyLemmas();
+ if(d_newLemmaGenerated) {
+ return;
+ }
+ }
+
// Introduce
- for(typeof(d_cardTerms.begin()) it = d_cardTerms.begin();
+ for(CDNodeSet::const_iterator it = d_cardTerms.begin();
it != d_cardTerms.end(); ++it) {
for(eq::EqClassIterator j(d_equalityEngine.getRepresentative((*it)[0]), &d_equalityEngine);
@@ -2710,14 +2771,14 @@ void TheorySetsPrivate::processCard2(Theory::Effort level) {
// merge_nodes(get_leaves(np.first), get_leaves(np.second), EQUAL(np.first, np.second));
merge_nodes(get_leaves(np.first), get_leaves(np.second), eqSoFar());
}
-
+
if(d_newLemmaGenerated) {
Trace("sets-card") << "[sets-card] New merge done. Returning." << std::endl;
return;
}
leaves.clear();
- for(typeof(d_V.begin()) it = d_V.begin(); it != d_V.end(); ++it) {
+ for(CDNodeSet::const_iterator it = d_V.begin(); it != d_V.end(); ++it) {
TNode v = *it;
if(d_E.find(v) == d_E.end()) {
leaves.insert(v);
@@ -2737,23 +2798,28 @@ void TheorySetsPrivate::processCard2(Theory::Effort level) {
}
}
+ typedef std::set<TNode>::const_iterator TNodeSetIterator;
+
// Elements being either equal or disequal [Members Arrangement rule]
- Trace("sets-card") << "[sets-card] Processing elements equality/disequal to each other" << std::endl;
- for(typeof(leaves.begin()) it = leaves.begin();
- it != leaves.end(); ++it) {
- if(!d_equalityEngine.hasTerm(*it)) continue;
+ Trace("sets-card")
+ << "[sets-card] Processing elements equality/disequal to each other"
+ << std::endl;
+ for (TNodeSetIterator it = leaves.begin(); it != leaves.end(); ++it) {
+ if (!d_equalityEngine.hasTerm(*it)) continue;
Node n = d_equalityEngine.getRepresentative(*it);
Assert(n.getKind() == kind::EMPTYSET || leaves.find(n) != leaves.end());
- if(n != *it) continue;
+ if (n != *it) continue;
const CDTNodeList* l = d_termInfoManager->getMembers(*it);
std::set<TNode> elems;
- for(typeof(l->begin()) l_it = l->begin(); l_it != l->end(); ++l_it) {
+ for (CDTNodeList::const_iterator l_it = l->begin(); l_it != l->end(); ++l_it) {
elems.insert(d_equalityEngine.getRepresentative(*l_it));
}
- for(typeof(elems.begin()) e1_it = elems.begin(); e1_it != elems.end(); ++e1_it) {
- for(typeof(elems.begin()) e2_it = elems.begin(); e2_it != elems.end(); ++e2_it) {
- if(*e1_it == *e2_it) continue;
- if(!d_equalityEngine.areDisequal(*e1_it, *e2_it, false)) {
+ for (TNodeSetIterator e1_it = elems.begin(); e1_it != elems.end();
+ ++e1_it) {
+ for (TNodeSetIterator e2_it = elems.begin(); e2_it != elems.end();
+ ++e2_it) {
+ if (*e1_it == *e2_it) continue;
+ if (!d_equalityEngine.areDisequal(*e1_it, *e2_it, false)) {
Node lem = nm->mkNode(kind::EQUAL, *e1_it, *e2_it);
lem = nm->mkNode(kind::OR, lem, nm->mkNode(kind::NOT, lem));
lemma(lem, SETS_LEMMA_GRAPH);
@@ -2769,8 +2835,7 @@ void TheorySetsPrivate::processCard2(Theory::Effort level) {
// Assert Lower bound
Trace("sets-card") << "[sets-card] Processing assert lower bound" << std::endl;
- for(typeof(leaves.begin()) it = leaves.begin();
- it != leaves.end(); ++it) {
+ for(TNodeSetIterator it = leaves.begin(); it != leaves.end(); ++it) {
Trace("sets-cardlower") << "[sets-cardlower] Card Lower: " << *it << std::endl;
Assert(d_equalityEngine.hasTerm(*it));
Node n = d_equalityEngine.getRepresentative(*it);
@@ -2783,21 +2848,21 @@ void TheorySetsPrivate::processCard2(Theory::Effort level) {
// if(n != *it) continue;
const CDTNodeList* l = d_termInfoManager->getMembers(n);
std::set<TNode> elems;
- for(typeof(l->begin()) l_it = l->begin(); l_it != l->end(); ++l_it) {
+ for(CDTNodeList::const_iterator l_it = l->begin(); l_it != l->end(); ++l_it) {
elems.insert(d_equalityEngine.getRepresentative(*l_it));
}
if(elems.size() == 0) continue;
NodeBuilder<> nb(kind::OR);
nb << ( nm->mkNode(kind::LEQ, nm->mkConst(Rational(elems.size())), nm->mkNode(kind::CARD, *it)) );
if(elems.size() > 1) {
- for(typeof(elems.begin()) e1_it = elems.begin(); e1_it != elems.end(); ++e1_it) {
- for(typeof(elems.begin()) e2_it = elems.begin(); e2_it != elems.end(); ++e2_it) {
+ for(TNodeSetIterator e1_it = elems.begin(); e1_it != elems.end(); ++e1_it) {
+ for(TNodeSetIterator e2_it = elems.begin(); e2_it != elems.end(); ++e2_it) {
if(*e1_it == *e2_it) continue;
nb << (nm->mkNode(kind::EQUAL, *e1_it, *e2_it));
}
}
}
- for(typeof(elems.begin()) e_it = elems.begin(); e_it != elems.end(); ++e_it) {
+ for(TNodeSetIterator e_it = elems.begin(); e_it != elems.end(); ++e_it) {
nb << nm->mkNode(kind::NOT, nm->mkNode(kind::MEMBER, *e_it, *it));
}
Node lem = Node(nb);
diff --git a/src/theory/sets/theory_sets_private.h b/src/theory/sets/theory_sets_private.h
index 217432670..3ed608b90 100644
--- a/src/theory/sets/theory_sets_private.h
+++ b/src/theory/sets/theory_sets_private.h
@@ -146,7 +146,8 @@ private:
public:
CDNodeSet d_terms;
private:
- std::hash_map<TNode, TheorySetsTermInfo*, TNodeHashFunction> d_info;
+ typedef std::hash_map<TNode, TheorySetsTermInfo*, TNodeHashFunction> SetsTermInfoMap;
+ SetsTermInfoMap d_info;
void mergeLists(CDTNodeList* la, const CDTNodeList* lb) const;
void pushToSettermPropagationQueue(TNode x, TNode S, bool polarity);
@@ -252,7 +253,7 @@ private:
bool d_cardEnabled;
void enableCard();
void cardCreateEmptysetSkolem(TypeNode t);
-
+
CDNodeSet d_cardTerms;
std::set<TypeNode> d_typesAdded;
CDNodeSet d_processedCardTerms;
@@ -282,7 +283,7 @@ private:
std::set<TNode> get_leaves(Node vertex1, Node vertex2);
std::set<TNode> get_leaves(Node vertex1, Node vertex2, Node vertex3);
std::set<TNode> non_empty(std::set<TNode> vertices);
- void print_graph();
+ void print_graph(bool printmodel=false);
context::CDQueue < std::pair<TNode, TNode> > d_graphMergesPending;
context::CDList<Node> d_allSetEqualitiesSoFar;
Node eqSoFar();
diff --git a/src/theory/sets/theory_sets_type_enumerator.h b/src/theory/sets/theory_sets_type_enumerator.h
index 40863b0f2..f2d6bae68 100644
--- a/src/theory/sets/theory_sets_type_enumerator.h
+++ b/src/theory/sets/theory_sets_type_enumerator.h
@@ -153,14 +153,16 @@ public:
}
while (d_constituentVec.size() < d_index) {
- TypeEnumerator *d_newEnumerator = new TypeEnumerator(*d_constituentVec.back());
- ++(*d_newEnumerator);
- if( (*d_newEnumerator).isFinished() ) {
+ TypeEnumerator* newEnumerator =
+ new TypeEnumerator(*d_constituentVec.back());
+ ++(*newEnumerator);
+ if (newEnumerator->isFinished()) {
Trace("set-type-enum") << "operator++ finished!" << std::endl;
+ delete newEnumerator;
d_finished = true;
return *this;
}
- d_constituentVec.push_back(d_newEnumerator);
+ d_constituentVec.push_back(newEnumerator);
}
Trace("set-type-enum") << "operator++ returning, **this = " << **this << std::endl;
diff --git a/src/theory/shared_terms_database.cpp b/src/theory/shared_terms_database.cpp
index 0dc6cc7a1..b78109dfb 100644
--- a/src/theory/shared_terms_database.cpp
+++ b/src/theory/shared_terms_database.cpp
@@ -37,7 +37,7 @@ SharedTermsDatabase::SharedTermsDatabase(TheoryEngine* theoryEngine, context::Co
smtStatisticsRegistry()->registerStat(&d_statSharedTerms);
}
-SharedTermsDatabase::~SharedTermsDatabase() throw(AssertionException)
+SharedTermsDatabase::~SharedTermsDatabase()
{
smtStatisticsRegistry()->unregisterStat(&d_statSharedTerms);
}
diff --git a/src/theory/shared_terms_database.h b/src/theory/shared_terms_database.h
index c108122ef..cc8959165 100644
--- a/src/theory/shared_terms_database.h
+++ b/src/theory/shared_terms_database.h
@@ -149,7 +149,7 @@ private:
public:
SharedTermsDatabase(TheoryEngine* theoryEngine, context::Context* context);
- ~SharedTermsDatabase() throw(AssertionException);
+ ~SharedTermsDatabase();
/**
* Asserts the equality to the shared terms database,
diff --git a/src/theory/strings/theory_strings.cpp b/src/theory/strings/theory_strings.cpp
index 7caa1cbb1..3ef6df3fc 100644
--- a/src/theory/strings/theory_strings.cpp
+++ b/src/theory/strings/theory_strings.cpp
@@ -331,6 +331,92 @@ bool TheoryStrings::getCurrentSubstitution( int effort, std::vector< Node >& var
return true;
}
+int TheoryStrings::getReduction( int effort, Node n, Node& nr ) {
+ //determine the effort level to process the extf at
+ // 0 - at assertion time, 1+ - after no other reduction is applicable
+ Assert( d_extf_info_tmp.find( n )!=d_extf_info_tmp.end() );
+ if( d_extf_info_tmp[n].d_model_active ){
+ int r_effort = -1;
+ int pol = d_extf_info_tmp[n].d_pol;
+ if( n.getKind()==kind::STRING_STRCTN ){
+ if( pol==1 ){
+ r_effort = 1;
+ }else if( pol==-1 ){
+ if( effort==2 ){
+ Node x = n[0];
+ Node s = n[1];
+ std::vector< Node > lexp;
+ Node lenx = getLength( x, lexp );
+ Node lens = getLength( s, lexp );
+ if( areEqual( lenx, lens ) ){
+ Trace("strings-extf-debug") << " resolve extf : " << n << " based on equal lengths disequality." << std::endl;
+ //we can reduce to disequality when lengths are equal
+ if( !areDisequal( x, s ) ){
+ lexp.push_back( lenx.eqNode(lens) );
+ lexp.push_back( n.negate() );
+ Node xneqs = x.eqNode(s).negate();
+ sendInference( lexp, xneqs, "NEG-CTN-EQL", true );
+ }
+ return 1;
+ }else if( !areDisequal( lenx, lens ) ){
+ //split on their lenths
+ sendSplit( lenx, lens, "NEG-CTN-SP" );
+ }else{
+ r_effort = 2;
+ }
+ }
+ }
+ }else{
+ if( options::stringLazyPreproc() ){
+ if( n.getKind()==kind::STRING_SUBSTR ){
+ r_effort = 1;
+ }else if( n.getKind()!=kind::STRING_IN_REGEXP ){
+ r_effort = 2;
+ }
+ }
+ }
+ if( effort==r_effort ){
+ Node c_n = pol==-1 ? n.negate() : n;
+ if( d_preproc_cache.find( c_n )==d_preproc_cache.end() ){
+ d_preproc_cache[ c_n ] = true;
+ Trace("strings-process-debug") << "Process reduction for " << n << ", pol = " << pol << std::endl;
+ if( n.getKind()==kind::STRING_STRCTN && pol==1 ){
+ Node x = n[0];
+ Node s = n[1];
+ //positive contains reduces to a equality
+ Node sk1 = mkSkolemCached( x, s, sk_id_ctn_pre, "sc1" );
+ Node sk2 = mkSkolemCached( x, s, sk_id_ctn_post, "sc2" );
+ Node eq = Rewriter::rewrite( x.eqNode( mkConcat( sk1, s, sk2 ) ) );
+ std::vector< Node > exp_vec;
+ exp_vec.push_back( n );
+ sendInference( d_empty_vec, exp_vec, eq, "POS-CTN", true );
+ //we've reduced this n
+ Trace("strings-extf-debug") << " resolve extf : " << n << " based on positive contain reduction." << std::endl;
+ return 1;
+ }else{
+ // for STRING_SUBSTR, STRING_STRCTN with pol=-1,
+ // STRING_STRIDOF, STRING_ITOS, STRING_U16TOS, STRING_U32TOS, STRING_STOI, STRING_STOU16, STRING_STOU32, STRING_STRREPL
+ std::vector< Node > new_nodes;
+ Node res = d_preproc.simplify( n, new_nodes );
+ Assert( res!=n );
+ new_nodes.push_back( NodeManager::currentNM()->mkNode( res.getType().isBoolean() ? kind::IFF : kind::EQUAL, res, n ) );
+ Node nnlem = new_nodes.size()==1 ? new_nodes[0] : NodeManager::currentNM()->mkNode( kind::AND, new_nodes );
+ nnlem = Rewriter::rewrite( nnlem );
+ Trace("strings-red-lemma") << "Reduction_" << effort << " lemma : " << nnlem << std::endl;
+ Trace("strings-red-lemma") << "...from " << n << std::endl;
+ sendInference( d_empty_vec, nnlem, "Reduction", true );
+ //we've reduced this n
+ Trace("strings-extf-debug") << " resolve extf : " << n << " based on reduction." << std::endl;
+ return 1;
+ }
+ }else{
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
/////////////////////////////////////////////////////////////////////////////
// NOTIFICATIONS
/////////////////////////////////////////////////////////////////////////////
@@ -404,15 +490,13 @@ void TheoryStrings::collectModelInfo( TheoryModel* m, bool fullModel ) {
for( unsigned j=0; j<col[i].size(); j++ ) {
Trace("strings-model") << col[i][j] << " ";
//check if col[i][j] has only variables
- EqcInfo* ei = getOrMakeEqcInfo( col[i][j], false );
- Node cst = ei ? ei->d_const_term : Node::null();
- if( cst.isNull() ){
+ if( !col[i][j].isConst() ){
Assert( d_normal_forms.find( col[i][j] )!=d_normal_forms.end() );
if( d_normal_forms[col[i][j]].size()==1 ){//&& d_normal_forms[col[i][j]][0]==col[i][j] ){
pure_eq.push_back( col[i][j] );
}
}else{
- processed[col[i][j]] = cst;
+ processed[col[i][j]] = col[i][j];
}
}
Trace("strings-model") << "have length " << lts_values[i] << std::endl;
@@ -692,104 +776,29 @@ bool TheoryStrings::needsCheckLastEffort() {
}
void TheoryStrings::checkExtfReductions( int effort ) {
+ //standardize this?
+ //std::vector< Node > nred;
+ //d_extt->doReductions( effort, nred, false );
+
std::vector< Node > extf;
d_extt->getActive( extf );
+ Trace("strings-process") << "checking " << extf.size() << " active extf" << std::endl;
for( unsigned i=0; i<extf.size(); i++ ){
Node n = extf[i];
- if( d_extf_info_tmp[n].d_model_active ){
- Assert( d_extf_info_tmp.find( n )!=d_extf_info_tmp.end() );
- if( checkExtfReduction( n, d_extf_info_tmp[n].d_pol, effort ) ){
- d_extt->markReduced( n );
- }
- if( hasProcessed() ){
+ Trace("strings-process") << "Check " << n << ", active in model=" << d_extf_info_tmp[n].d_model_active << std::endl;
+ Node nr;
+ int ret = getReduction( effort, n, nr );
+ Assert( nr.isNull() );
+ if( ret!=0 ){
+ d_extt->markReduced( extf[i] );
+ if( options::stringOpt1() && hasProcessed() ){
return;
}
}
}
}
-bool TheoryStrings::checkExtfReduction( Node atom, int pol, int effort ) {
- //determine the effort level to process the extf at
- // 0 - at assertion time, 1+ - after no other reduction is applicable
- int r_effort = -1;
- if( atom.getKind()==kind::STRING_STRCTN ){
- if( pol==1 ){
- r_effort = 1;
- }else{
- Assert( pol==-1 );
- if( effort==2 ){
- Node x = atom[0];
- Node s = atom[1];
- std::vector< Node > lexp;
- Node lenx = getLength( x, lexp );
- Node lens = getLength( s, lexp );
- if( areEqual( lenx, lens ) ){
- Trace("strings-extf-debug") << " resolve extf : " << atom << " based on equal lengths disequality." << std::endl;
- //we can reduce to disequality when lengths are equal
- if( !areDisequal( x, s ) ){
- lexp.push_back( lenx.eqNode(lens) );
- lexp.push_back( atom.negate() );
- Node xneqs = x.eqNode(s).negate();
- sendInference( lexp, xneqs, "NEG-CTN-EQL", true );
- }
- return true;
- }else if( !areDisequal( lenx, lens ) ){
- //split on their lenths
- sendSplit( lenx, lens, "NEG-CTN-SP" );
- }else{
- r_effort = 2;
- }
- }
- }
- }else{
- if( options::stringLazyPreproc() ){
- if( atom.getKind()==kind::STRING_SUBSTR ){
- r_effort = 1;
- }else if( atom.getKind()!=kind::STRING_IN_REGEXP ){
- r_effort = 2;
- }
- }
- }
- if( effort==r_effort ){
- Node c_atom = pol==-1 ? atom.negate() : atom;
- if( d_preproc_cache.find( c_atom )==d_preproc_cache.end() ){
- d_preproc_cache[ c_atom ] = true;
- Trace("strings-process-debug") << "Process reduction for " << atom << ", pol = " << pol << std::endl;
- if( atom.getKind()==kind::STRING_STRCTN && pol==1 ){
- Node x = atom[0];
- Node s = atom[1];
- //positive contains reduces to a equality
- Node sk1 = mkSkolemCached( x, s, sk_id_ctn_pre, "sc1" );
- Node sk2 = mkSkolemCached( x, s, sk_id_ctn_post, "sc2" );
- Node eq = Rewriter::rewrite( x.eqNode( mkConcat( sk1, s, sk2 ) ) );
- std::vector< Node > exp_vec;
- exp_vec.push_back( atom );
- sendInference( d_empty_vec, exp_vec, eq, "POS-CTN", true );
- //we've reduced this atom
- Trace("strings-extf-debug") << " resolve extf : " << atom << " based on positive contain reduction." << std::endl;
- return true;
- }else{
- // for STRING_SUBSTR, STRING_STRCTN with pol=-1,
- // STRING_STRIDOF, STRING_ITOS, STRING_U16TOS, STRING_U32TOS, STRING_STOI, STRING_STOU16, STRING_STOU32, STRING_STRREPL
- std::vector< Node > new_nodes;
- Node res = d_preproc.simplify( atom, new_nodes );
- Assert( res!=atom );
- new_nodes.push_back( NodeManager::currentNM()->mkNode( res.getType().isBoolean() ? kind::IFF : kind::EQUAL, res, atom ) );
- Node nnlem = new_nodes.size()==1 ? new_nodes[0] : NodeManager::currentNM()->mkNode( kind::AND, new_nodes );
- nnlem = Rewriter::rewrite( nnlem );
- Trace("strings-red-lemma") << "Reduction_" << effort << " lemma : " << nnlem << std::endl;
- Trace("strings-red-lemma") << "...from " << atom << std::endl;
- sendInference( d_empty_vec, nnlem, "Reduction", true );
- //we've reduced this atom
- Trace("strings-extf-debug") << " resolve extf : " << atom << " based on reduction." << std::endl;
- return true;
- }
- }
- }
- return false;
-}
-
-TheoryStrings::EqcInfo::EqcInfo( context::Context* c ) : d_const_term(c), d_length_term(c), d_cardinality_lem_k(c), d_normalized_length(c) {
+TheoryStrings::EqcInfo::EqcInfo( context::Context* c ) : d_length_term(c), d_cardinality_lem_k(c), d_normalized_length(c) {
}
@@ -827,10 +836,6 @@ void TheoryStrings::conflict(TNode a, TNode b){
/** called when a new equivalance class is created */
void TheoryStrings::eqNotifyNewClass(TNode t){
- if( t.getKind() == kind::CONST_STRING ){
- EqcInfo * ei =getOrMakeEqcInfo( t, true );
- ei->d_const_term = t;
- }
if( t.getKind() == kind::STRING_LENGTH ){
Trace("strings-debug") << "New length eqc : " << t << std::endl;
Node r = d_equalityEngine.getRepresentative(t[0]);
@@ -838,6 +843,8 @@ void TheoryStrings::eqNotifyNewClass(TNode t){
ei->d_length_term = t[0];
//we care about the length of this string
registerTerm( t[0], 1 );
+ }else{
+ //d_extt->registerTerm( t );
}
}
@@ -847,9 +854,6 @@ void TheoryStrings::eqNotifyPreMerge(TNode t1, TNode t2){
if( e2 ){
EqcInfo * e1 = getOrMakeEqcInfo( t1 );
//add information from e2 to e1
- if( !e2->d_const_term.get().isNull() ){
- e1->d_const_term.set( e2->d_const_term );
- }
if( !e2->d_length_term.get().isNull() ){
e1->d_length_term.set( e2->d_length_term );
}
@@ -905,7 +909,6 @@ void TheoryStrings::addCarePairs( quantifiers::TermArgTrie * t1, quantifiers::Te
}
for (unsigned c = 0; c < currentPairs.size(); ++ c) {
Trace("strings-cg-pair") << "TheoryStrings::computeCareGraph(): pair : " << currentPairs[c].first << " " << currentPairs[c].second << std::endl;
- Trace("ajr-temp") << currentPairs[c].first << ", " << currentPairs[c].second << std::endl;
addCarePair(currentPairs[c].first, currentPairs[c].second);
}
}
@@ -988,7 +991,6 @@ void TheoryStrings::assertPendingFact(Node atom, bool polarity, Node exp) {
d_equalityEngine.assertPredicate( atom, polarity, exp );
//process extf
if( atom.getKind()==kind::STRING_IN_REGEXP ){
- d_extt->registerTerm( atom );
if( polarity && atom[1].getKind()==kind::REGEXP_RANGE ){
if( d_extf_infer_cache_u.find( atom )==d_extf_infer_cache_u.end() ){
d_extf_infer_cache_u.insert( atom );
@@ -1000,6 +1002,8 @@ void TheoryStrings::assertPendingFact(Node atom, bool polarity, Node exp) {
}
}
}
+ //register the atom here, since it may not create a new equivalence class
+ //d_extt->registerTerm( atom );
}
Trace("strings-pending-debug") << " Now collect terms" << std::endl;
//collect extended function terms in the atom
@@ -1293,7 +1297,8 @@ void TheoryStrings::checkExtfEval( int effort ) {
std::vector< Node > terms;
std::vector< Node > sterms;
std::vector< std::vector< Node > > exp;
- d_extt->getInferences( effort, terms, sterms, exp );
+ d_extt->getActive( terms );
+ d_extt->getSubstitutedTerms( effort, terms, sterms, exp );
for( unsigned i=0; i<terms.size(); i++ ){
Node n = terms[i];
Node sn = sterms[i];
@@ -2955,7 +2960,7 @@ void TheoryStrings::processDeq( Node ni, Node nj ) {
}
}else{
Node sk = mkSkolemCached( nconst_k, firstChar, sk_id_dc_spt, "dc_spt", 2 );
- Node skr = mkSkolemCached( nconst_k, firstChar, sk_id_dc_spt_rem, "dc_spt_rem", -1 );
+ Node skr = mkSkolemCached( nconst_k, firstChar, sk_id_dc_spt_rem, "dc_spt_rem" );
Node eq1 = nconst_k.eqNode( NodeManager::currentNM()->mkNode( kind::STRING_CONCAT, sk, skr ) );
eq1 = Rewriter::rewrite( eq1 );
Node eq2 = nconst_k.eqNode( NodeManager::currentNM()->mkNode( kind::STRING_CONCAT, firstChar, skr ) );
@@ -3876,16 +3881,6 @@ Node TheoryStrings::ppRewrite(TNode atom) {
return atom;
}
-void TheoryStrings::collectExtendedFuncTerms( Node n, std::map< Node, bool >& visited ) {
- if( visited.find( n )==visited.end() ){
- visited[n] = true;
- d_extt->registerTerm( n );
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- collectExtendedFuncTerms( n[i], visited );
- }
- }
-}
-
// Stats
TheoryStrings::Statistics::Statistics():
d_splits("TheoryStrings::NumOfSplitOnDemands", 0),
@@ -4868,6 +4863,16 @@ Node TheoryStrings::getNormalSymRegExp(Node r, std::vector<Node> &nf_exp) {
return ret;
}
+void TheoryStrings::collectExtendedFuncTerms( Node n, std::map< Node, bool >& visited ) {
+ if( visited.find( n )==visited.end() ){
+ visited[n] = true;
+ d_extt->registerTerm( n );
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ collectExtendedFuncTerms( n[i], visited );
+ }
+ }
+}
+
}/* CVC4::theory::strings namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/strings/theory_strings.h b/src/theory/strings/theory_strings.h
index fe72bd8e7..fd984bd58 100644
--- a/src/theory/strings/theory_strings.h
+++ b/src/theory/strings/theory_strings.h
@@ -72,6 +72,7 @@ public:
Node explain( TNode literal );
eq::EqualityEngine * getEqualityEngine() { return &d_equalityEngine; }
bool getCurrentSubstitution( int effort, std::vector< Node >& vars, std::vector< Node >& subs, std::map< Node, std::vector< Node > >& exp );
+ int getReduction( int effort, Node n, Node& nr );
// NotifyClass for equality engine
class NotifyClass : public eq::EqualityEngineNotify {
@@ -237,7 +238,6 @@ private:
EqcInfo( context::Context* c );
~EqcInfo(){}
//constant in this eqc
- context::CDO< Node > d_const_term;
context::CDO< Node > d_length_term;
context::CDO< unsigned > d_cardinality_lem_k;
// 1 = added length lemma
@@ -274,8 +274,6 @@ private:
int d_pol;
//explanation
std::vector< Node > d_exp;
- //reps -> list of variables
- //std::map< Node, std::vector< Node > > d_rep_vars;
//false if it is reduced in the model
bool d_model_active;
};
@@ -321,7 +319,6 @@ private:
Node getSymbolicDefinition( Node n, std::vector< Node >& exp );
//check extf reduction
void checkExtfReductions( int effort );
- bool checkExtfReduction( Node atom, int pol, int effort );
//flat forms check
void checkFlatForms();
Node checkCycles( Node eqc, std::vector< Node >& curr, std::vector< Node >& exp );
@@ -523,6 +520,7 @@ public:
~Statistics();
};/* class TheoryStrings::Statistics */
Statistics d_statistics;
+
};/* class TheoryStrings */
}/* CVC4::theory::strings namespace */
diff --git a/src/theory/strings/theory_strings_rewriter.cpp b/src/theory/strings/theory_strings_rewriter.cpp
index 92b18eed0..2ee367cfc 100644
--- a/src/theory/strings/theory_strings_rewriter.cpp
+++ b/src/theory/strings/theory_strings_rewriter.cpp
@@ -741,6 +741,7 @@ bool TheoryStringsRewriter::testConstStringInRegExp( CVC4::String &s, unsigned i
return ( s2 == r[0].getConst<String>() );
} else {
Assert( false, "RegExp contains variables" );
+ return false;
}
}
case kind::REGEXP_CONCAT: {
diff --git a/src/theory/theory.cpp b/src/theory/theory.cpp
index 7fa74df6a..9e71a1ddf 100644
--- a/src/theory/theory.cpp
+++ b/src/theory/theory.cpp
@@ -314,15 +314,18 @@ EntailmentCheckSideEffects::~EntailmentCheckSideEffects() {
ExtTheory::ExtTheory( Theory * p ) : d_parent( p ),
-d_ext_func_terms( p->getSatContext() ), d_has_extf( p->getSatContext() ){
-
+d_ext_func_terms( p->getSatContext() ), d_ci_inactive( p->getUserContext() ),
+d_lemmas( p->getUserContext() ), d_pp_lemmas( p->getUserContext() ), d_has_extf( p->getSatContext() ){
+ d_true = NodeManager::currentNM()->mkConst( true );
}
+//gets all leaf terms in n
void ExtTheory::collectVars( Node n, std::vector< Node >& vars, std::map< Node, bool >& visited ) {
if( !n.isConst() ){
if( visited.find( n )==visited.end() ){
visited[n] = true;
- if( n.getNumChildren()>0 ){
+ //treat terms not belonging to this theory as leaf
+ if( n.getNumChildren()>0 ){//&& Theory::theoryOf(n)==d_parent->getId() ){
for( unsigned i=0; i<n.getNumChildren(); i++ ){
collectVars( n[i], vars, visited );
}
@@ -334,17 +337,17 @@ void ExtTheory::collectVars( Node n, std::vector< Node >& vars, std::map< Node,
}
//do inferences
-void ExtTheory::getInferences( int effort, std::vector< Node >& terms, std::vector< Node >& sterms, std::vector< std::vector< Node > >& exp ) {
- //all variables we need to find a substitution for
- std::vector< Node > vars;
- std::vector< Node > sub;
- std::map< Node, std::vector< Node > > expc;
- Trace("extt-debug") << "Checking " << d_ext_func_terms.size() << " extended functions." << std::endl;
- for( NodeBoolMap::iterator it = d_ext_func_terms.begin(); it != d_ext_func_terms.end(); ++it ){
- //if not already reduced
- if( (*it).second ){
- Node n = (*it).first;
- terms.push_back( n );
+void ExtTheory::getSubstitutedTerms( int effort, std::vector< Node >& terms, std::vector< Node >& sterms, std::vector< std::vector< Node > >& exp ) {
+ Trace("extt-debug") << "Currently " << d_ext_func_terms.size() << " extended functions." << std::endl;
+ Trace("extt-debug") << "..." << terms.size() << " to reduce." << std::endl;
+ if( !terms.empty() ){
+ //all variables we need to find a substitution for
+ std::vector< Node > vars;
+ std::vector< Node > sub;
+ std::map< Node, std::vector< Node > > expc;
+ for( unsigned i=0; i<terms.size(); i++ ){
+ //do substitution, rewrite
+ Node n = terms[i];
std::map< Node, ExtfInfo >::iterator iti = d_extf_info.find( n );
Assert( iti!=d_extf_info.end() );
for( unsigned i=0; i<iti->second.d_vars.size(); i++ ){
@@ -353,13 +356,11 @@ void ExtTheory::getInferences( int effort, std::vector< Node >& terms, std::vect
}
}
}
- }
- Trace("extt-debug") << "..." << terms.size() << " unreduced." << std::endl;
- if( !terms.empty() ){
- //get the current substitution
+ //get the current substitution for all variables
if( d_parent->getCurrentSubstitution( effort, vars, sub, expc ) ){
+ Assert( vars.size()==sub.size() );
for( unsigned i=0; i<terms.size(); i++ ){
- //do substitution, rewrite
+ //do substitution
Node n = terms[i];
Node ns = n.substitute( vars.begin(), vars.end(), sub.begin(), sub.end() );
std::vector< Node > expn;
@@ -392,13 +393,134 @@ void ExtTheory::getInferences( int effort, std::vector< Node >& terms, std::vect
}
}
+bool ExtTheory::doInferencesInternal( int effort, std::vector< Node >& terms, std::vector< Node >& nred, bool batch, bool isRed ) {
+ if( batch ){
+ bool addedLemma = false;
+ if( isRed ){
+ for( unsigned i=0; i<terms.size(); i++ ){
+ Node n = terms[i];
+ Node nr;
+ //TODO: reduction with substitution?
+ int ret = d_parent->getReduction( effort, n, nr );
+ if( ret==0 ){
+ nred.push_back( n );
+ }else{
+ if( !nr.isNull() && n!=nr ){
+ Node lem = NodeManager::currentNM()->mkNode( n.getType().isBoolean() ? kind::IFF : kind::EQUAL, n, nr );
+ if( sendLemma( lem, true ) ){
+ Trace("extt-lemma") << "ExtTheory : Reduction lemma : " << lem << std::endl;
+ addedLemma = true;
+ }
+ }
+ markReduced( terms[i], ret<0 );
+ }
+ }
+ }else{
+ std::vector< Node > sterms;
+ std::vector< std::vector< Node > > exp;
+ getSubstitutedTerms( effort, terms, sterms, exp );
+ for( unsigned i=0; i<terms.size(); i++ ){
+ bool processed = false;
+ if( sterms[i]!=terms[i] ){
+ Node sr = Rewriter::rewrite( sterms[i] );
+ if( sr.isConst() ){
+ processed = true;
+ markReduced( terms[i] );
+ Node eq = terms[i].eqNode( sr );
+ Node expn = exp[i].size()>1 ? NodeManager::currentNM()->mkNode( kind::AND, exp[i] ) : ( exp[i].size()==1 ? exp[i][0] : d_true );
+ Trace("extt-debug") << "ExtTheory::doInferences : infer : " << eq << " by " << expn << std::endl;
+ Node lem = NodeManager::currentNM()->mkNode( kind::IMPLIES, expn, eq );
+ Trace("extt-debug") << "...send lemma " << lem << std::endl;
+ if( sendLemma( lem ) ){
+ Trace("extt-lemma") << "ExtTheory : Constant rewrite lemma : " << lem << std::endl;
+ addedLemma = true;
+ }
+ }
+ }
+ if( !processed ){
+ nred.push_back( terms[i] );
+ }
+ }
+ }
+ return addedLemma;
+ }else{
+ std::vector< Node > nnred;
+ if( terms.empty() ){
+ for( NodeBoolMap::iterator it = d_ext_func_terms.begin(); it != d_ext_func_terms.end(); ++it ){
+ if( (*it).second && !isContextIndependentInactive( (*it).first ) ){
+ std::vector< Node > nterms;
+ nterms.push_back( (*it).first );
+ if( doInferencesInternal( effort, nterms, nnred, true, isRed ) ){
+ return true;
+ }
+ }
+ }
+ }else{
+ for( unsigned i=0; i<terms.size(); i++ ){
+ std::vector< Node > nterms;
+ nterms.push_back( terms[i] );
+ if( doInferencesInternal( effort, nterms, nnred, true, isRed ) ){
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
+
+bool ExtTheory::sendLemma( Node lem, bool preprocess ) {
+ if( preprocess ){
+ if( d_pp_lemmas.find( lem )==d_pp_lemmas.end() ){
+ d_pp_lemmas.insert( lem );
+ d_parent->getOutputChannel().lemma( lem, false, true );
+ return true;
+ }
+ }else{
+ if( d_lemmas.find( lem )==d_lemmas.end() ){
+ d_lemmas.insert( lem );
+ d_parent->getOutputChannel().lemma( lem );
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ExtTheory::doInferences( int effort, std::vector< Node >& terms, std::vector< Node >& nred, bool batch ) {
+ if( !terms.empty() ){
+ return doInferencesInternal( effort, terms, nred, batch, false );
+ }else{
+ return false;
+ }
+}
+
+bool ExtTheory::doInferences( int effort, std::vector< Node >& nred, bool batch ) {
+ std::vector< Node > terms;
+ getActive( terms );
+ return doInferencesInternal( effort, terms, nred, batch, false );
+}
+
+bool ExtTheory::doReductions( int effort, std::vector< Node >& terms, std::vector< Node >& nred, bool batch ) {
+ if( !terms.empty() ){
+ return doInferencesInternal( effort, terms, nred, batch, true );
+ }else{
+ return false;
+ }
+}
+
+bool ExtTheory::doReductions( int effort, std::vector< Node >& nred, bool batch ) {
+ std::vector< Node > terms;
+ getActive( terms );
+ return doInferencesInternal( effort, terms, nred, batch, true );
+}
+
+
//register term
void ExtTheory::registerTerm( Node n ) {
if( d_extf_kind.find( n.getKind() )!=d_extf_kind.end() ){
if( d_ext_func_terms.find( n )==d_ext_func_terms.end() ){
Trace("extt-debug") << "Found extended function : " << n << " in " << d_parent->getId() << std::endl;
d_ext_func_terms[n] = true;
- d_has_extf = true;
+ d_has_extf = n;
std::map< Node, bool > visited;
collectVars( n, d_extf_info[n].d_vars, visited );
}
@@ -406,9 +528,22 @@ void ExtTheory::registerTerm( Node n ) {
}
//mark reduced
-void ExtTheory::markReduced( Node n ) {
+void ExtTheory::markReduced( Node n, bool contextDepend ) {
d_ext_func_terms[n] = false;
- //TODO update has_extf
+ if( !contextDepend ){
+ d_ci_inactive.insert( n );
+ }
+
+ //update has_extf
+ if( d_has_extf.get()==n ){
+ for( NodeBoolMap::iterator it = d_ext_func_terms.begin(); it != d_ext_func_terms.end(); ++it ){
+ //if not already reduced
+ if( (*it).second && !isContextIndependentInactive( (*it).first ) ){
+ d_has_extf = (*it).first;
+ }
+ }
+
+ }
}
//mark congruent
@@ -424,11 +559,19 @@ void ExtTheory::markCongruent( Node a, Node b ) {
}
}
+bool ExtTheory::isContextIndependentInactive( Node n ) {
+ return d_ci_inactive.find( n )!=d_ci_inactive.end();
+}
+
+bool ExtTheory::hasActiveTerm() {
+ return !d_has_extf.get().isNull();
+}
+
//is active
bool ExtTheory::isActive( Node n ) {
NodeBoolMap::const_iterator it = d_ext_func_terms.find( n );
if( it!=d_ext_func_terms.end() ){
- return (*it).second;
+ return (*it).second && !isContextIndependentInactive( n );
}else{
return false;
}
@@ -437,7 +580,7 @@ bool ExtTheory::isActive( Node n ) {
void ExtTheory::getActive( std::vector< Node >& active ) {
for( NodeBoolMap::iterator it = d_ext_func_terms.begin(); it != d_ext_func_terms.end(); ++it ){
//if not already reduced
- if( (*it).second ){
+ if( (*it).second && !isContextIndependentInactive( (*it).first ) ){
active.push_back( (*it).first );
}
}
@@ -446,7 +589,7 @@ void ExtTheory::getActive( std::vector< Node >& active ) {
void ExtTheory::getActive( std::vector< Node >& active, Kind k ) {
for( NodeBoolMap::iterator it = d_ext_func_terms.begin(); it != d_ext_func_terms.end(); ++it ){
//if not already reduced
- if( (*it).second && (*it).first.getKind()==k ){
+ if( (*it).first.getKind()==k && (*it).second && !isContextIndependentInactive( (*it).first ) ){
active.push_back( (*it).first );
}
}
diff --git a/src/theory/theory.h b/src/theory/theory.h
index ede06fd2d..5d64c6446 100644
--- a/src/theory/theory.h
+++ b/src/theory/theory.h
@@ -24,6 +24,7 @@
#include <string>
#include "context/cdlist.h"
+#include "context/cdhashset.h"
#include "context/cdo.h"
#include "context/context.h"
#include "expr/node.h"
@@ -642,6 +643,12 @@ public:
* Don't preprocess subterm of this term
*/
virtual bool ppDontRewriteSubterm(TNode atom) { return false; }
+
+ /** notify preprocessed assertions
+ * Called on new assertions after preprocessing before they are asserted to theory engine.
+ * Should not modify assertions.
+ */
+ virtual void ppNotifyAssertions( std::vector< Node >& assertions ) {}
/**
* A Theory is called with presolve exactly one time per user
@@ -885,8 +892,11 @@ public:
*/
virtual std::pair<bool, Node> entailmentCheck(TNode lit, const EntailmentCheckParameters* params = NULL, EntailmentCheckSideEffects* out = NULL);
- /* equality engine */
+ /* equality engine TODO: use? */
virtual eq::EqualityEngine * getEqualityEngine() { return NULL; }
+
+ /* get extended theory */
+ virtual ExtTheory * getExtTheory() { return d_extt; }
/* get current substitution at an effort
* input : vars
@@ -894,6 +904,13 @@ public:
* where ( exp[vars[i]] => vars[i] = subs[i] ) holds for all i
*/
virtual bool getCurrentSubstitution( int effort, std::vector< Node >& vars, std::vector< Node >& subs, std::map< Node, std::vector< Node > >& exp ) { return false; }
+
+ /* get reduction for node
+ if return value is not 0, then n is reduced.
+ if return value <0 then n is reduced SAT-context-independently (e.g. by a lemma that persists at this user-context level).
+ if nr is non-null, then ( n = nr ) should be added as a lemma by caller, and return value should be <0.
+ */
+ virtual int getReduction( int effort, Node n, Node& nr ) { return 0; }
/**
* Turn on proof-production mode.
@@ -968,15 +985,23 @@ public:
class ExtTheory {
friend class Theory;
typedef context::CDHashMap<Node, bool, NodeHashFunction> NodeBoolMap;
+ typedef context::CDHashSet<Node, NodeHashFunction> NodeSet;
protected:
Theory * d_parent;
+ Node d_true;
//extended string terms, map to whether they are active
NodeBoolMap d_ext_func_terms;
- //any non-reduced extended functions exist
- context::CDO< bool > d_has_extf;
+ //set of terms from d_ext_func_terms that are SAT-context-independently inactive
+ // (e.g. term t when a reduction lemma of the form t = t' was added)
+ NodeSet d_ci_inactive;
+ //cache of all lemmas sent
+ NodeSet d_lemmas;
+ NodeSet d_pp_lemmas;
+ //watched term for checking if any non-reduced extended functions exist
+ context::CDO< Node > d_has_extf;
//extf kind
std::map< Kind, bool > d_extf_kind;
- //information for extf
+ //information for each term in d_ext_func_terms
class ExtfInfo {
public:
//all variables in this term
@@ -985,25 +1010,49 @@ protected:
std::map< Node, ExtfInfo > d_extf_info;
//collect variables
void collectVars( Node n, std::vector< Node >& vars, std::map< Node, bool >& visited );
+ // is context dependent inactive
+ bool isContextIndependentInactive( Node n );
+ //do inferences internal
+ bool doInferencesInternal( int effort, std::vector< Node >& terms, std::vector< Node >& nred, bool batch, bool isRed );
+ //send lemma
+ bool sendLemma( Node lem, bool preprocess = false );
public:
ExtTheory( Theory * p );
virtual ~ExtTheory(){}
//add extf kind
void addFunctionKind( Kind k ) { d_extf_kind[k] = true; }
- //do inferences
- // input : effort
- // output : terms, sterms, exp, where ( exp[i] => terms[i] = sterms[i] ) for all i
- void getInferences( int effort, std::vector< Node >& terms, std::vector< Node >& sterms, std::vector< std::vector< Node > >& exp );
//register term
+ // adds n to d_ext_func_terms if addFunctionKind( n.getKind() ) was called
void registerTerm( Node n );
- //mark reduced
- void markReduced( Node n );
- //mark congruent
+ // set n as reduced/inactive
+ // if contextDepend = false, then n remains inactive in the duration of this user-context level
+ void markReduced( Node n, bool contextDepend = true );
+ // mark that a and b are congruent terms: set b inactive, set a to inactive if b was inactive
void markCongruent( Node a, Node b );
- //is active
+
+ //getSubstitutedTerms
+ // input : effort, terms
+ // output : sterms, exp, where ( exp[i] => terms[i] = sterms[i] ) for all i
+ void getSubstitutedTerms( int effort, std::vector< Node >& terms, std::vector< Node >& sterms, std::vector< std::vector< Node > >& exp );
+ //doInferences
+ // * input : effort, terms, batch (whether to send one lemma or lemmas for all terms)
+ // * sends rewriting lemmas of the form ( exp => t = c ) where t is in terms and c is a constant, c = rewrite( t*sigma ) where exp |= sigma
+ // * output : nred (the terms that are still active)
+ // * return : true iff lemma is sent
+ bool doInferences( int effort, std::vector< Node >& terms, std::vector< Node >& nred, bool batch=true );
+ bool doInferences( int effort, std::vector< Node >& nred, bool batch=true );
+ //doReductions
+ // same as doInferences, but will send reduction lemmas of the form ( t = t' ) where t is in terms, t' is equivalent, reduced term
+ bool doReductions( int effort, std::vector< Node >& terms, std::vector< Node >& nred, bool batch=true );
+ bool doReductions( int effort, std::vector< Node >& nred, bool batch=true );
+
+ //has active term
+ bool hasActiveTerm();
+ //is n active
bool isActive( Node n );
- //get active
+ //get the set of active terms from d_ext_func_terms
void getActive( std::vector< Node >& active );
+ //get the set of active terms from d_ext_func_terms of kind k
void getActive( std::vector< Node >& active, Kind k );
};
diff --git a/src/theory/theory_engine.cpp b/src/theory/theory_engine.cpp
index 94281156f..a14534efe 100644
--- a/src/theory/theory_engine.cpp
+++ b/src/theory/theory_engine.cpp
@@ -1123,6 +1123,15 @@ Node TheoryEngine::preprocess(TNode assertion) {
return d_ppCache[assertion];
}
+void TheoryEngine::notifyPreprocessedAssertions( std::vector< Node >& assertions ){
+ // call all the theories
+ for(TheoryId theoryId = theory::THEORY_FIRST; theoryId < theory::THEORY_LAST; ++theoryId) {
+ if(d_theoryTable[theoryId]) {
+ theoryOf(theoryId)->ppNotifyAssertions( assertions );
+ }
+ }
+}
+
bool TheoryEngine::markPropagation(TNode assertion, TNode originalAssertion, theory::TheoryId toTheoryId, theory::TheoryId fromTheoryId) {
// What and where we are asserting
@@ -1444,6 +1453,15 @@ void TheoryEngine::getInstantiations( std::map< Node, std::vector< Node > >& ins
}
}
+Node TheoryEngine::getInstantiatedConjunction( Node q ) {
+ if( d_quantEngine ){
+ return d_quantEngine->getInstantiatedConjunction( q );
+ }else{
+ Assert( false );
+ return Node::null();
+ }
+}
+
static Node mkExplanation(const std::vector<NodeTheoryPair>& explanation) {
diff --git a/src/theory/theory_engine.h b/src/theory/theory_engine.h
index 9316066a5..4366f8d3a 100644
--- a/src/theory/theory_engine.h
+++ b/src/theory/theory_engine.h
@@ -35,7 +35,6 @@
#include "theory/atom_requests.h"
#include "theory/bv/bv_to_bool.h"
#include "theory/interrupted.h"
-#include "theory/quantifiers/quant_conflict_find.h"
#include "theory/rewriter.h"
#include "theory/shared_terms_database.h"
#include "theory/sort_inference.h"
@@ -605,6 +604,12 @@ public:
*/
Node preprocess(TNode node);
+
+ /**
+ * Notify (preprocessed) assertions
+ */
+ void notifyPreprocessedAssertions( std::vector< Node >& assertions );
+
/**
* Return whether or not we are incomplete (in the current context).
*/
@@ -784,6 +789,12 @@ public:
* Get instantiations
*/
void getInstantiations( std::map< Node, std::vector< Node > >& insts );
+
+ /**
+ * Get instantiated conjunction, returns q[t1] ^ ... ^ q[tn] where t1...tn are current set of instantiations for q.
+ * Can be used for quantifier elimination when satisfiable and q[t1] ^ ... ^ q[tn] |= q
+ */
+ Node getInstantiatedConjunction( Node q );
/**
* Forwards an entailment check according to the given theoryOfMode.
diff --git a/src/theory/theory_model.h b/src/theory/theory_model.h
index 7157433f9..c30d1eabc 100644
--- a/src/theory/theory_model.h
+++ b/src/theory/theory_model.h
@@ -53,7 +53,7 @@ public:
Node d_true;
Node d_false;
mutable std::hash_map<Node, Node, NodeHashFunction> d_modelCache;
-public:
+public:
/** comment stream to include in printing */
std::stringstream d_comment_str;
/** get comments */
diff --git a/src/theory/uf/equality_engine.cpp b/src/theory/uf/equality_engine.cpp
index 09d348584..5d929a708 100644
--- a/src/theory/uf/equality_engine.cpp
+++ b/src/theory/uf/equality_engine.cpp
@@ -97,7 +97,7 @@ void EqualityEngine::init() {
d_freshMergeReasonType = eq::NUMBER_OF_MERGE_REASONS;
}
-EqualityEngine::~EqualityEngine() throw(AssertionException) {
+EqualityEngine::~EqualityEngine() {
free(d_triggerDatabase);
}
@@ -987,7 +987,14 @@ void EqualityEngine::explainEquality(TNode t1, TNode t2, bool polarity, std::vec
}
if (eqp) {
- if(eqp->d_children.size() == 1) {
+ if (eqp->d_children.size() == 0) {
+ // Corner case where this is actually a disequality between two constants
+ Debug("pf::ee") << "Encountered a constant disequality (not a transitivity proof): "
+ << eqp->d_node << std::endl;
+ Assert(eqp->d_node[0][0].isConst());
+ Assert(eqp->d_node[0][1].isConst());
+ eqp->d_id = MERGED_THROUGH_CONSTANTS;
+ } else if (eqp->d_children.size() == 1) {
// The transitivity proof has just one child. Simplify.
EqProof* temp = eqp->d_children[0];
eqp->d_children.clear();
diff --git a/src/theory/uf/equality_engine.h b/src/theory/uf/equality_engine.h
index 843e7ce7f..18e83bd1a 100644
--- a/src/theory/uf/equality_engine.h
+++ b/src/theory/uf/equality_engine.h
@@ -186,7 +186,7 @@ public:
/**
* Just a destructor.
*/
- virtual ~EqualityEngine() throw(AssertionException);
+ virtual ~EqualityEngine();
/**
* Set the master equality engine for this one. Master engine will get copies of all
diff --git a/src/theory/uf/theory_uf_strong_solver.cpp b/src/theory/uf/theory_uf_strong_solver.cpp
index cda94e1c4..4713c7dcf 100644
--- a/src/theory/uf/theory_uf_strong_solver.cpp
+++ b/src/theory/uf/theory_uf_strong_solver.cpp
@@ -1645,34 +1645,37 @@ Node SortModel::getCardinalityLiteral( int c ) {
StrongSolverTheoryUF::StrongSolverTheoryUF(context::Context* c,
context::UserContext* u,
- OutputChannel& out,
- TheoryUF* th)
- : d_out( &out )
- , d_th( th )
- , d_conflict( c, false )
- , d_rep_model()
- , d_aloc_com_card( u, 0 )
- , d_com_card_assertions( c )
- , d_min_pos_com_card( c, -1 )
- , d_card_assertions_eqv_lemma( u )
- , d_min_pos_tn_master_card( c, -1 )
- , d_rel_eqc( c )
-{
- if( options::ufssDiseqPropagation() ){
- d_deq_prop = new DisequalityPropagator( th->getQuantifiersEngine(), this );
- }else{
- d_deq_prop = NULL;
+ OutputChannel& out, TheoryUF* th)
+ : d_out(&out),
+ d_th(th),
+ d_conflict(c, false),
+ d_rep_model(),
+ d_aloc_com_card(u, 0),
+ d_com_card_assertions(c),
+ d_min_pos_com_card(c, -1),
+ d_card_assertions_eqv_lemma(u),
+ d_min_pos_tn_master_card(c, -1),
+ d_rel_eqc(c),
+ d_deq_prop(NULL),
+ d_sym_break(NULL) {
+ if (options::ufssDiseqPropagation()) {
+ d_deq_prop = new DisequalityPropagator(th->getQuantifiersEngine(), this);
+ }
+ if (options::ufssSymBreak()) {
+ d_sym_break = new SubsortSymmetryBreaker(th->getQuantifiersEngine(), c);
+ }
+}
+
+StrongSolverTheoryUF::~StrongSolverTheoryUF() {
+ for (std::map<TypeNode, SortModel*>::iterator it = d_rep_model.begin();
+ it != d_rep_model.end(); ++it) {
+ delete it->second;
}
- if( options::ufssSymBreak() ){
- d_sym_break = new SubsortSymmetryBreaker( th->getQuantifiersEngine(), c );
- }else{
- d_sym_break = NULL;
+ if (d_sym_break) {
+ delete d_sym_break;
}
-}
-
-StrongSolverTheoryUF::~StrongSolverTheoryUF() {
- for( std::map< TypeNode, SortModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
- delete it->second;
+ if (d_deq_prop) {
+ delete d_deq_prop;
}
}
diff --git a/src/theory/uf/theory_uf_strong_solver.h b/src/theory/uf/theory_uf_strong_solver.h
index 4e4dbef83..40026522d 100644
--- a/src/theory/uf/theory_uf_strong_solver.h
+++ b/src/theory/uf/theory_uf_strong_solver.h
@@ -365,55 +365,10 @@ public:
/** get number of regions (for debugging) */
int getNumRegions();
}; /** class SortModel */
-private:
- /** The output channel for the strong solver. */
- OutputChannel* d_out;
- /** theory uf pointer */
- TheoryUF* d_th;
- /** Are we in conflict */
- context::CDO<bool> d_conflict;
- /** rep model structure, one for each type */
- std::map< TypeNode, SortModel* > d_rep_model;
- /** get sort model */
- SortModel* getSortModel( Node n );
-private:
- /** allocated combined cardinality */
- context::CDO< int > d_aloc_com_card;
- /** combined cardinality constraints */
- std::map< int, Node > d_com_card_literal;
- /** combined cardinality assertions (indexed by cardinality literals ) */
- NodeBoolMap d_com_card_assertions;
- /** minimum positive combined cardinality */
- context::CDO< int > d_min_pos_com_card;
- /** cardinality literals for which we have added */
- NodeBoolMap d_card_assertions_eqv_lemma;
- /** the master monotone type (if ufssFairnessMonotone enabled) */
- TypeNode d_tn_mono_master;
- std::map< TypeNode, bool > d_tn_mono_slave;
- context::CDO< int > d_min_pos_tn_master_card;
- /** initialize */
- void initializeCombinedCardinality();
- /** allocateCombinedCardinality */
- void allocateCombinedCardinality();
- /** check */
- void checkCombinedCardinality();
-private:
- /** relevant eqc */
- NodeBoolMap d_rel_eqc;
- /** ensure eqc */
- void ensureEqc( SortModel* c, Node a );
- /** ensure eqc for all subterms of n */
- void ensureEqcRec( Node n );
-public:
- /** has eqc */
- bool hasEqc( Node a );
-private:
- /** disequality propagator */
- DisequalityPropagator* d_deq_prop;
- /** symmetry breaking techniques */
- SubsortSymmetryBreaker* d_sym_break;
+
public:
- StrongSolverTheoryUF(context::Context* c, context::UserContext* u, OutputChannel& out, TheoryUF* th);
+ StrongSolverTheoryUF(context::Context* c, context::UserContext* u,
+ OutputChannel& out, TheoryUF* th);
~StrongSolverTheoryUF();
/** get theory */
TheoryUF* getTheory() { return d_th; }
@@ -437,7 +392,6 @@ public:
void assertNode( Node n, bool isDecision );
/** are disequal */
bool areDisequal( Node a, Node b );
-public:
/** check */
void check( Theory::Effort level );
/** presolve */
@@ -448,18 +402,14 @@ public:
Node getNextDecisionRequest();
/** preregister a term */
void preRegisterTerm( TNode n );
- /** preregister a quantifier */
- //void registerQuantifier( Node f );
/** notify restart */
void notifyRestart();
-public:
/** identify */
std::string identify() const { return std::string("StrongSolverTheoryUF"); }
//print debug
void debugPrint( const char* c );
/** debug a model */
bool debugModel( TheoryModel* m );
-public:
/** get is in conflict */
bool isConflict() { return d_conflict; }
/** get cardinality for node */
@@ -468,9 +418,11 @@ public:
int getCardinality( TypeNode tn );
/** minimize */
bool minimize( TheoryModel* m = NULL );
+ /** has eqc */
+ bool hasEqc(Node a);
class Statistics {
- public:
+ public:
IntStat d_clique_conflicts;
IntStat d_clique_lemmas;
IntStat d_split_lemmas;
@@ -483,7 +435,50 @@ public:
};
/** statistics class */
Statistics d_statistics;
-};/* class StrongSolverTheoryUF */
+
+ private:
+ /** get sort model */
+ SortModel* getSortModel(Node n);
+ /** initialize */
+ void initializeCombinedCardinality();
+ /** allocateCombinedCardinality */
+ void allocateCombinedCardinality();
+ /** check */
+ void checkCombinedCardinality();
+ /** ensure eqc */
+ void ensureEqc(SortModel* c, Node a);
+ /** ensure eqc for all subterms of n */
+ void ensureEqcRec(Node n);
+
+ /** The output channel for the strong solver. */
+ OutputChannel* d_out;
+ /** theory uf pointer */
+ TheoryUF* d_th;
+ /** Are we in conflict */
+ context::CDO<bool> d_conflict;
+ /** rep model structure, one for each type */
+ std::map<TypeNode, SortModel*> d_rep_model;
+ /** allocated combined cardinality */
+ context::CDO<int> d_aloc_com_card;
+ /** combined cardinality constraints */
+ std::map<int, Node> d_com_card_literal;
+ /** combined cardinality assertions (indexed by cardinality literals ) */
+ NodeBoolMap d_com_card_assertions;
+ /** minimum positive combined cardinality */
+ context::CDO<int> d_min_pos_com_card;
+ /** cardinality literals for which we have added */
+ NodeBoolMap d_card_assertions_eqv_lemma;
+ /** the master monotone type (if ufssFairnessMonotone enabled) */
+ TypeNode d_tn_mono_master;
+ std::map<TypeNode, bool> d_tn_mono_slave;
+ context::CDO<int> d_min_pos_tn_master_card;
+ /** relevant eqc */
+ NodeBoolMap d_rel_eqc;
+ /** disequality propagator */
+ DisequalityPropagator* d_deq_prop;
+ /** symmetry breaking techniques */
+ SubsortSymmetryBreaker* d_sym_break;
+}; /* class StrongSolverTheoryUF */
class DisequalityPropagator {
public:
diff --git a/src/theory/uf/theory_uf_type_rules.h b/src/theory/uf/theory_uf_type_rules.h
index ab42aaf15..5d97dda38 100644
--- a/src/theory/uf/theory_uf_type_rules.h
+++ b/src/theory/uf/theory_uf_type_rules.h
@@ -24,27 +24,31 @@ namespace theory {
namespace uf {
class UfTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
TNode f = n.getOperator();
TypeNode fType = f.getType(check);
- if( !fType.isFunction() ) {
- throw TypeCheckingExceptionPrivate(n, "operator does not have function type");
+ if (!fType.isFunction()) {
+ throw TypeCheckingExceptionPrivate(
+ n, "operator does not have function type");
}
- if( check ) {
+ if (check) {
if (n.getNumChildren() != fType.getNumChildren() - 1) {
- throw TypeCheckingExceptionPrivate(n, "number of arguments does not match the function type");
+ throw TypeCheckingExceptionPrivate(
+ n, "number of arguments does not match the function type");
}
TNode::iterator argument_it = n.begin();
TNode::iterator argument_it_end = n.end();
TypeNode::iterator argument_type_it = fType.begin();
- for(; argument_it != argument_it_end; ++argument_it, ++argument_type_it) {
+ for (; argument_it != argument_it_end;
+ ++argument_it, ++argument_type_it) {
TypeNode currentArgument = (*argument_it).getType();
TypeNode currentArgumentType = *argument_type_it;
- if(!currentArgument.isComparableTo(currentArgumentType)) {
+ if (!currentArgument.isComparableTo(currentArgumentType)) {
std::stringstream ss;
- ss << "argument type is not a subtype of the function's argument type:\n"
+ ss << "argument type is not a subtype of the function's argument "
+ << "type:\n"
<< "argument: " << *argument_it << "\n"
<< "has type: " << (*argument_it).getType() << "\n"
<< "not subtype: " << *argument_type_it;
@@ -54,80 +58,88 @@ public:
}
return fType.getRangeType();
}
-};/* class UfTypeRule */
+}; /* class UfTypeRule */
class CardinalityConstraintTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw(TypeCheckingExceptionPrivate) {
- if( check ) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
+ if (check) {
// don't care what it is, but it should be well-typed
n[0].getType(check);
TypeNode valType = n[1].getType(check);
- if( valType != nodeManager->integerType() ) {
- throw TypeCheckingExceptionPrivate(n, "cardinality constraint must be integer");
+ if (valType != nodeManager->integerType()) {
+ throw TypeCheckingExceptionPrivate(
+ n, "cardinality constraint must be integer");
}
- if( n[1].getKind()!=kind::CONST_RATIONAL ){
- throw TypeCheckingExceptionPrivate(n, "cardinality constraint must be a constant");
+ if (n[1].getKind() != kind::CONST_RATIONAL) {
+ throw TypeCheckingExceptionPrivate(
+ n, "cardinality constraint must be a constant");
}
CVC4::Rational r(INT_MAX);
- if( n[1].getConst<Rational>()>r ){
- throw TypeCheckingExceptionPrivate(n, "Exceeded INT_MAX in cardinality constraint");
+ if (n[1].getConst<Rational>() > r) {
+ throw TypeCheckingExceptionPrivate(
+ n, "Exceeded INT_MAX in cardinality constraint");
}
- if( n[1].getConst<Rational>().getNumerator().sgn()!=1 ){
- throw TypeCheckingExceptionPrivate(n, "cardinality constraint must be positive");
+ if (n[1].getConst<Rational>().getNumerator().sgn() != 1) {
+ throw TypeCheckingExceptionPrivate(
+ n, "cardinality constraint must be positive");
}
}
return nodeManager->booleanType();
}
-};/* class CardinalityConstraintTypeRule */
+}; /* class CardinalityConstraintTypeRule */
class CombinedCardinalityConstraintTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw(TypeCheckingExceptionPrivate) {
- if( check ) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
+ if (check) {
TypeNode valType = n[0].getType(check);
- if( valType != nodeManager->integerType() ) {
- throw TypeCheckingExceptionPrivate(n, "combined cardinality constraint must be integer");
+ if (valType != nodeManager->integerType()) {
+ throw TypeCheckingExceptionPrivate(
+ n, "combined cardinality constraint must be integer");
}
- if( n[0].getKind()!=kind::CONST_RATIONAL ){
- throw TypeCheckingExceptionPrivate(n, "combined cardinality constraint must be a constant");
+ if (n[0].getKind() != kind::CONST_RATIONAL) {
+ throw TypeCheckingExceptionPrivate(
+ n, "combined cardinality constraint must be a constant");
}
CVC4::Rational r(INT_MAX);
- if( n[0].getConst<Rational>()>r ){
- throw TypeCheckingExceptionPrivate(n, "Exceeded INT_MAX in combined cardinality constraint");
+ if (n[0].getConst<Rational>() > r) {
+ throw TypeCheckingExceptionPrivate(
+ n, "Exceeded INT_MAX in combined cardinality constraint");
}
- if( n[0].getConst<Rational>().getNumerator().sgn()==-1 ){
- throw TypeCheckingExceptionPrivate(n, "combined cardinality constraint must be non-negative");
+ if (n[0].getConst<Rational>().getNumerator().sgn() == -1) {
+ throw TypeCheckingExceptionPrivate(
+ n, "combined cardinality constraint must be non-negative");
}
}
return nodeManager->booleanType();
}
-};/* class CardinalityConstraintTypeRule */
+}; /* class CardinalityConstraintTypeRule */
class PartialTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw (TypeCheckingExceptionPrivate, AssertionException) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
return n.getOperator().getType().getRangeType();
}
-};/* class PartialTypeRule */
+}; /* class PartialTypeRule */
class CardinalityValueTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- throw(TypeCheckingExceptionPrivate) {
- if( check ) {
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
+ bool check) {
+ if (check) {
n[0].getType(check);
}
return nodeManager->integerType();
}
-};/* class CardinalityValueTypeRule */
+}; /* class CardinalityValueTypeRule */
-}/* CVC4::theory::uf namespace */
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
+} /* CVC4::theory::uf namespace */
+} /* CVC4::theory namespace */
+} /* CVC4 namespace */
#endif /* __CVC4__THEORY__UF__THEORY_UF_TYPE_RULES_H */
diff --git a/src/theory/unconstrained_simplifier.cpp b/src/theory/unconstrained_simplifier.cpp
index 6a33adc56..d13cc1f03 100644
--- a/src/theory/unconstrained_simplifier.cpp
+++ b/src/theory/unconstrained_simplifier.cpp
@@ -79,7 +79,7 @@ void UnconstrainedSimplifier::visitAll(TNode assertion)
d_visitedOnce[current] = parent;
if (current.getNumChildren() == 0) {
- if (current.isVar()) {
+ if (current.getKind()==kind::VARIABLE || current.getKind()==kind::SKOLEM) {
d_unconstrained.insert(current);
}
}
@@ -563,39 +563,56 @@ void UnconstrainedSimplifier::processUnconstrained()
}
break;
- // Bit-vector comparisons: replace with new Boolean variable, but have to also conjoin with a side condition
- // as there is always one case when the comparison is forced to be false
+ // Bit-vector comparisons: replace with new Boolean variable, but have
+ // to also conjoin with a side condition as there is always one case
+ // when the comparison is forced to be false
case kind::BITVECTOR_ULT:
- strict = true;
case kind::BITVECTOR_UGE:
- goto bvineq;
-
case kind::BITVECTOR_UGT:
- strict = true;
case kind::BITVECTOR_ULE:
- swap = true;
- goto bvineq;
-
case kind::BITVECTOR_SLT:
- strict = true;
case kind::BITVECTOR_SGE:
- isSigned = true;
- goto bvineq;
-
case kind::BITVECTOR_SGT:
- strict = true;
- case kind::BITVECTOR_SLE:
- isSigned = true;
- swap = true;
-
- bvineq: {
+ case kind::BITVECTOR_SLE: {
+ // Tuples over (signed, swap, strict).
+ switch (parent.getKind()) {
+ case kind::BITVECTOR_UGE:
+ break;
+ case kind::BITVECTOR_ULT:
+ strict = true;
+ break;
+ case kind::BITVECTOR_ULE:
+ swap = true;
+ break;
+ case kind::BITVECTOR_UGT:
+ swap = true;
+ strict = true;
+ break;
+ case kind::BITVECTOR_SGE:
+ isSigned = true;
+ break;
+ case kind::BITVECTOR_SLT:
+ isSigned = true;
+ strict = true;
+ break;
+ case kind::BITVECTOR_SLE:
+ isSigned = true;
+ swap = true;
+ break;
+ case kind::BITVECTOR_SGT:
+ isSigned = true;
+ swap = true;
+ strict = true;
+ break;
+ default:
+ Unreachable();
+ }
TNode other;
bool left = false;
if (parent[0] == current) {
other = parent[1];
left = true;
- }
- else {
+ } else {
Assert(parent[1] == current);
other = parent[0];
}
@@ -608,14 +625,14 @@ void UnconstrainedSimplifier::processUnconstrained()
}
currentSub = newUnconstrainedVar(parent.getType(), currentSub);
current = parent;
- }
- else {
+ } else {
currentSub = Node();
}
- }
- else {
+ } else {
unsigned size = current.getType().getBitVectorSize();
- BitVector bv = isSigned ? BitVector(size, Integer(1).multiplyByPow2(size - 1)) : BitVector(size, unsigned(0));
+ BitVector bv =
+ isSigned ? BitVector(size, Integer(1).multiplyByPow2(size - 1))
+ : BitVector(size, unsigned(0));
if (swap == left) {
bv = ~bv;
}
@@ -625,14 +642,14 @@ void UnconstrainedSimplifier::processUnconstrained()
currentSub = newUnconstrainedVar(parent.getType(), currentSub);
current = parent;
NodeManager* nm = NodeManager::currentNM();
- Node test = Rewriter::rewrite(other.eqNode(nm->mkConst<BitVector>(bv)));
+ Node test =
+ Rewriter::rewrite(other.eqNode(nm->mkConst<BitVector>(bv)));
if (test == nm->mkConst<bool>(false)) {
break;
}
if (strict) {
currentSub = currentSub.andNode(test.notNode());
- }
- else {
+ } else {
currentSub = currentSub.orNode(test);
}
// Delay adding this substitution - see comment at end of function
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback