CVC5_API_TRY_CATCH_BEGIN;
CVC5_API_SOLVER_CHECK_TERM(q);
//////// all checks before this line
- return Term(this, d_slv->getQuantifierElimination(q.getNode(), true, true));
+ return Term(this, d_slv->getQuantifierElimination(q.getNode(), true));
////////
CVC5_API_TRY_CATCH_END;
}
CVC5_API_TRY_CATCH_BEGIN;
CVC5_API_SOLVER_CHECK_TERM(q);
//////// all checks before this line
- return Term(this, d_slv->getQuantifierElimination(q.getNode(), false, true));
+ return Term(this, d_slv->getQuantifierElimination(q.getNode(), false));
////////
CVC5_API_TRY_CATCH_END;
}
return d_sygusSolver->getSubsolverSynthSolutions(solMap);
}
-Node SolverEngine::getQuantifierElimination(Node q, bool doFull, bool strict)
+Node SolverEngine::getQuantifierElimination(Node q, bool doFull)
{
SolverEngineScope smts(this);
finishInit();
- const LogicInfo& logic = getLogicInfo();
- if (!logic.isPure(THEORY_ARITH) && strict)
- {
- d_env->warning() << "Unexpected logic for quantifier elimination " << logic
- << endl;
- }
return d_quantElimSolver->getQuantifierElimination(
*d_asserts, q, doFull, d_isInternalSubsolver);
}
* extended command get-qe-disjunct, which can be used
* for incrementally computing the result of a
* quantifier elimination.
- *
- * The argument strict is whether to output
- * warnings, such as when an unexpected logic is used.
- *
- * throw@ Exception
*/
- Node getQuantifierElimination(Node q, bool doFull, bool strict = true);
+ Node getQuantifierElimination(Node q, bool doFull);
/**
* This method asks this SMT engine to find an interpolant with respect to
}
};
+AlphaEquivalenceTypeNode::AlphaEquivalenceTypeNode(context::Context* c)
+ : d_quant(c)
+{
+}
+
Node AlphaEquivalenceTypeNode::registerNode(
+ context::Context* c,
Node q,
Node t,
std::vector<TypeNode>& typs,
{
AlphaEquivalenceTypeNode* aetn = this;
size_t index = 0;
+ std::map<std::pair<TypeNode, size_t>,
+ std::unique_ptr<AlphaEquivalenceTypeNode>>::iterator itc;
while (index < typs.size())
{
TypeNode curr = typs[index];
Assert(typCount.find(curr) != typCount.end());
Trace("aeq-debug") << "[" << curr << " " << typCount[curr] << "] ";
std::pair<TypeNode, size_t> key(curr, typCount[curr]);
- aetn = &(aetn->d_children[key]);
+ itc = aetn->d_children.find(key);
+ if (itc == aetn->d_children.end())
+ {
+ aetn->d_children[key] = std::make_unique<AlphaEquivalenceTypeNode>(c);
+ aetn = aetn->d_children[key].get();
+ }
+ else
+ {
+ aetn = itc->second.get();
+ }
index = index + 1;
}
Trace("aeq-debug") << " : ";
- std::map<Node, Node>::iterator it = aetn->d_quant.find(t);
- if (it != aetn->d_quant.end())
+ NodeMap::iterator it = aetn->d_quant.find(t);
+ if (it != aetn->d_quant.end() && !it->second.isNull())
{
+ Trace("aeq-debug") << it->second << std::endl;
return it->second;
}
+ Trace("aeq-debug") << "(new)" << std::endl;
aetn->d_quant[t] = q;
return q;
}
+AlphaEquivalenceDb::AlphaEquivalenceDb(context::Context* c,
+ expr::TermCanonize* tc,
+ bool sortCommChildren)
+ : d_context(c),
+ d_ae_typ_trie(c),
+ d_tc(tc),
+ d_sortCommutativeOpChildren(sortCommChildren)
+{
+}
Node AlphaEquivalenceDb::addTerm(Node q)
{
Assert(q.getKind() == FORALL);
sto.d_tu = d_tc;
std::sort( typs.begin(), typs.end(), sto );
Trace("aeq-debug") << " ";
- Node ret = d_ae_typ_trie.registerNode(q, t, typs, typCount);
+ Node ret = d_ae_typ_trie.registerNode(d_context, q, t, typs, typCount);
Trace("aeq") << " ...result : " << ret << std::endl;
return ret;
}
AlphaEquivalence::AlphaEquivalence(Env& env)
: EnvObj(env),
d_termCanon(),
- d_aedb(&d_termCanon, true),
+ d_aedb(userContext(), &d_termCanon, true),
d_pnm(env.getProofNodeManager()),
d_pfAlpha(d_pnm ? new EagerProofGenerator(d_pnm) : nullptr)
{
* d_children[T1][2].d_children[T2][3].
*/
class AlphaEquivalenceTypeNode {
-public:
- /** children of this node */
- std::map<std::pair<TypeNode, size_t>, AlphaEquivalenceTypeNode> d_children;
- /**
- * map from canonized quantifier bodies to a quantified formula whose
- * canonized body is that term.
- */
- std::map<Node, Node> d_quant;
- /** register node
- *
- * This registers term q to this trie. The term t is the canonical form of
- * q, typs/typCount represent a multi-set of types of free variables in t.
- */
- Node registerNode(Node q,
- Node t,
- std::vector<TypeNode>& typs,
- std::map<TypeNode, size_t>& typCount);
+ using NodeMap = context::CDHashMap<Node, Node>;
+
+ public:
+ AlphaEquivalenceTypeNode(context::Context* c);
+ /** children of this node */
+ std::map<std::pair<TypeNode, size_t>,
+ std::unique_ptr<AlphaEquivalenceTypeNode>>
+ d_children;
+ /**
+ * map from canonized quantifier bodies to a quantified formula whose
+ * canonized body is that term.
+ */
+ NodeMap d_quant;
+ /** register node
+ *
+ * This registers term q to this trie. The term t is the canonical form of
+ * q, typs/typCount represent a multi-set of types of free variables in t.
+ */
+ Node registerNode(context::Context* c,
+ Node q,
+ Node t,
+ std::vector<TypeNode>& typs,
+ std::map<TypeNode, size_t>& typCount);
};
/**
class AlphaEquivalenceDb
{
public:
- AlphaEquivalenceDb(expr::TermCanonize* tc, bool sortCommChildren)
- : d_tc(tc), d_sortCommutativeOpChildren(sortCommChildren)
- {
- }
+ AlphaEquivalenceDb(context::Context* c,
+ expr::TermCanonize* tc,
+ bool sortCommChildren);
/** adds quantified formula q to this database
*
* This function returns a quantified formula q' that is alpha-equivalent to
* had been added to this class, or q otherwise.
*/
Node addTermToTypeTrie(Node t, Node q);
+ /** The context we depend on */
+ context::Context* d_context;
/** a trie per # of variables per type */
AlphaEquivalenceTypeNode d_ae_typ_trie;
/** pointer to the term canonize utility */
q = nm->mkNode(kind::EXISTS, q[0], q[1].negate());
std::unique_ptr<SolverEngine> smt_qe;
initializeSubsolver(smt_qe, env);
- Node qqe = smt_qe->getQuantifierElimination(q, true, false);
+ Node qqe = smt_qe->getQuantifierElimination(q, true);
if (expr::hasBoundVar(qqe))
{
Trace("cegqi-nested-qe") << " ...failed QE" << std::endl;
Trace("cegqi-qep") << "Run quantifier elimination on " << conj_se_ngsi_subs
<< std::endl;
- Node qeRes = smt_qe->getQuantifierElimination(conj_se_ngsi_subs, true, false);
+ Node qeRes = smt_qe->getQuantifierElimination(conj_se_ngsi_subs, true);
Trace("cegqi-qep") << "Result : " << qeRes << std::endl;
// create single invocation conjecture, if QE was successful
regress1/quantifiers/issue5279-nqe.smt2
regress1/quantifiers/issue5288-vts-real-int.smt2
regress1/quantifiers/issue5365-nqe.smt2
+ regress1/quantifiers/issue5373-1-qe-inc.smt2
+ regress1/quantifiers/issue5373-2.smt2
regress1/quantifiers/issue5378-witness.smt2
regress1/quantifiers/issue5469-aext.smt2
regress1/quantifiers/issue5470-aext.smt2
--- /dev/null
+; COMMAND-LINE: -i
+; EXPECT: true
+; EXPECT: true
+(set-logic ALL)
+(get-qe (exists ((q Real) (q Bool) (q Bool) (q Bool) (q Real) (q Real) (q Real)) true))
+(get-qe (exists ((q Real) (q Bool) (f Bool) (q Bool) (q Real) (q Real) (q Real)) true))
--- /dev/null
+; COMMAND-LINE: -i
+; EXPECT: sat
+; EXPECT: sat
+; EXPECT: sat
+(set-logic ALL)
+(declare-sort U 0)
+(declare-fun c (U U) U)
+(declare-fun k () U)
+(declare-fun a (U Int) Int)
+(assert (or (not (forall ((g U)) (! (or (forall ((x Int)) (! (distinct (a g x) (a k x)) :qid k!10))) :qid k!10))) (exists ((f U) (g U) (x Int)) (distinct (a (c f g) x) (a f (a g x))))))
+(check-sat)
+(check-sat-assuming ((exists ((f U) (g U) (x Int)) (distinct (a (c f g) x) (a f (a g x))))))
+(check-sat-assuming ((exists ((f U) (g U) (x Int)) (distinct (a (c f g) x) (a f (a g x))))))