Fixes cvc5/cvc5-projects#492.
if (ret.getKind() == kind::EQUAL && !ret[0].getType().isBoolean())
{
// For example, (= x y) ---> (and (>= x y) (<= x y))
- TrustNode trn = te->ppRewriteEquality(ret);
+ std::vector<SkolemLemma> lems;
+ TrustNode trn = te->ppRewrite(ret, lems);
+ Assert(lems.empty());
// can make proof producing by using proof generator from trn
if (!trn.isNull() && trn.getNode() != ret)
{
// the quantifiers rewriter involves constructing new bound variables that are
// not guaranteed to be consistent on each call.
THEORY_REWRITE,
+ // ======== Theory Preprocess
+ // Children: none
+ // Arguments: (F, tid)
+ // ----------------------------------------
+ // Conclusion: F
+ // where F is an equality of the form t = Theory::ppRewrite(t) for the theory
+ // with identifier tid. Notice this is a "trusted" rule.
+ THEORY_PREPROCESS,
+ // ======== Theory Preprocess
+ // Children: none
+ // Arguments: (F, tid)
+ // ----------------------------------------
+ // Conclusion: F
+ // where F was added as a new assertion by theory preprocessing from the
+ // theory with identifier tid.
+ THEORY_PREPROCESS_LEMMA,
// The remaining rules in this section have the signature of a "trusted rule":
//
// Children: ?
PREPROCESS,
// where F was added as a new assertion by some preprocessing pass.
PREPROCESS_LEMMA,
- // where F is an equality of the form t = Theory::ppRewrite(t) for some
- // theory. Notice this is a "trusted" rule.
- THEORY_PREPROCESS,
- // where F was added as a new assertion by theory preprocessing.
- THEORY_PREPROCESS_LEMMA,
// where F is an equality of the form t = t' where t was replaced by t'
// based on theory expand definitions.
THEORY_EXPAND_DEF,
return solveStatus;
}
-TrustNode TheoryEngine::ppRewriteEquality(TNode eq)
+TrustNode TheoryEngine::ppRewrite(TNode term,
+ std::vector<theory::SkolemLemma>& lems)
{
- Assert(eq.getKind() == kind::EQUAL);
- std::vector<SkolemLemma> lems;
- TrustNode trn = theoryOf(eq)->ppRewrite(eq, lems);
- // should never introduce a skolem to eliminate an equality
Assert(lems.empty());
+ TheoryId tid = d_env.theoryOf(term);
+ TrustNode trn = d_theoryTable[tid]->ppRewrite(term, lems);
+ // should never introduce a skolem to eliminate an equality
+ Assert(lems.empty() || term.getKind() != kind::EQUAL);
+ if (!isProofEnabled())
+ {
+ return trn;
+ }
+ Assert(d_lazyProof != nullptr);
+ // if proofs are enabled, must ensure we have proofs for all the skolem lemmas
+ for (SkolemLemma& skl : lems)
+ {
+ TrustNode tskl = skl.d_lemma;
+ Assert(tskl.getKind() == TrustNodeKind::LEMMA);
+ if (tskl.getGenerator() == nullptr)
+ {
+ Node proven = tskl.getProven();
+ Node tidn = builtin::BuiltinProofRuleChecker::mkTheoryIdNode(tid);
+ d_lazyProof->addStep(
+ proven, PfRule::THEORY_PREPROCESS_LEMMA, {}, {proven, tidn});
+ skl.d_lemma = TrustNode::mkTrustLemma(proven, d_lazyProof.get());
+ }
+ }
+ // notice that we don't ensure proofs are processed for the returned (rewrite)
+ // trust node, this is the responsibility of the caller, i.e. theory
+ // preprocessor.
return trn;
}
return TrustNode::mkTrustPropExp(conclusion, expNode, nullptr);
}
-bool TheoryEngine::isProofEnabled() const { return d_pnm != nullptr; }
+bool TheoryEngine::isProofEnabled() const
+{
+ return d_env.isTheoryProofProducing();
+}
void TheoryEngine::checkTheoryAssertionsWithModel(bool hardFailure) {
bool hasFailure = false;
}
/**
- * Preprocess rewrite equality, called by the preprocessor to rewrite
- * equalities appearing in the input.
+ * Preprocess rewrite, called:
+ * (1) on equalities by the preprocessor to rewrite equalities appearing in
+ * the input,
+ * (2) on non-equalities by the theory preprocessor.
+ *
+ * Calls the ppRewrite of the theory of term and adds the associated skolem
+ * lemmas to lems, for details see Theory::ppRewrite.
*/
- TrustNode ppRewriteEquality(TNode eq);
+ TrustNode ppRewrite(TNode term, std::vector<theory::SkolemLemma>& lems);
/** Notify (preprocessed) assertions. */
void notifyPreprocessedAssertions(const std::vector<Node>& assertions);
return term;
}
// call ppRewrite for the given theory
- TrustNode trn = d_engine.theoryOf(term)->ppRewrite(term, lems);
+ std::vector<SkolemLemma> newLems;
+ TrustNode trn = d_engine.ppRewrite(term, newLems);
Trace("tpp-debug2") << "preprocessWithProof returned " << trn
- << ", #lems = " << lems.size() << std::endl;
+ << ", #lems = " << newLems.size() << std::endl;
+ lems.insert(lems.end(), newLems.begin(), newLems.end());
if (trn.isNull())
{
// no change, return
regress0/proofs/proj-issue342-eager-checking-no-proof-checking.smt2
regress0/proofs/proj-issue430-coverings-double-negation.smt2
regress0/proofs/proj-issue462-sat-proof-option.smt2
+ regress0/proofs/proj-issue492-skolem-lemma-pf.smt2
regress0/proofs/qgu-fuzz-1-bool-sat.smt2
regress0/proofs/qgu-fuzz-2-bool-chainres-checking.smt2
regress0/proofs/qgu-fuzz-3-chainres-checking.smt2
--- /dev/null
+(set-logic ALL)
+(set-info :status sat)
+(set-option :produce-proofs true)
+(assert (exists ((x (Set (_ BitVec 16)))) (set.member (set.choose (set.inter x x)) (set.inter x x))))
+(check-sat)