diff options
author | Andrew Reynolds <andrew.j.reynolds@gmail.com> | 2021-04-23 13:31:37 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-23 18:31:37 +0000 |
commit | 86569ce68ed002aeb31d102511d3c9bd8384a7ec (patch) | |
tree | 34f8871cb8da35d48af79dfc9208b2788fb7c5d4 /src/smt | |
parent | f8af16037ecb1b9a3c322fc4ea2821497f8a2225 (diff) |
Add new substitution apply methods fixpoint, sequential, simultaneous (#6429)
This adds various methods for applying substitution as an options to MACRO_SR_* rules. It extends the proof checker and the proof post processor to eliminate based on these types.
It updates the trust substitutions utility used by non-clausal simplification to use fixed-point semantics for substitution, which is highly important for efficiency.
As a result of this PR, we are orders of magnitude faster for checking proofs for problems where non-clausal substitution infers many substitutions. It also makes our regressions noticeably faster:
Diffstat (limited to 'src/smt')
-rw-r--r-- | src/smt/proof_post_processor.cpp | 105 |
1 files changed, 61 insertions, 44 deletions
diff --git a/src/smt/proof_post_processor.cpp b/src/smt/proof_post_processor.cpp index 16b7f560b..b36b00bd5 100644 --- a/src/smt/proof_post_processor.cpp +++ b/src/smt/proof_post_processor.cpp @@ -427,19 +427,27 @@ Node ProofPostprocessCallback::expandMacros(PfRule id, { std::vector<Node> sargs; sargs.push_back(t); - MethodId sid = MethodId::SB_DEFAULT; + MethodId ids = MethodId::SB_DEFAULT; if (args.size() >= 2) { - if (builtin::BuiltinProofRuleChecker::getMethodId(args[1], sid)) + if (builtin::BuiltinProofRuleChecker::getMethodId(args[1], ids)) { sargs.push_back(args[1]); } } - ts = - builtin::BuiltinProofRuleChecker::applySubstitution(t, children, sid); + MethodId ida = MethodId::SBA_SEQUENTIAL; + if (args.size() >= 3) + { + if (builtin::BuiltinProofRuleChecker::getMethodId(args[2], ida)) + { + sargs.push_back(args[2]); + } + } + ts = builtin::BuiltinProofRuleChecker::applySubstitution( + t, children, ids, ida); Trace("smt-proof-pp-debug") << "...eq intro subs equality is " << t << " == " << ts << ", from " - << sid << std::endl; + << ids << " " << ida << std::endl; if (ts != t) { Node eq = t.eqNode(ts); @@ -459,21 +467,21 @@ Node ProofPostprocessCallback::expandMacros(PfRule id, } std::vector<Node> rargs; rargs.push_back(ts); - MethodId rid = MethodId::RW_REWRITE; - if (args.size() >= 3) + MethodId idr = MethodId::RW_REWRITE; + if (args.size() >= 4) { - if (builtin::BuiltinProofRuleChecker::getMethodId(args[2], rid)) + if (builtin::BuiltinProofRuleChecker::getMethodId(args[3], idr)) { - rargs.push_back(args[2]); + rargs.push_back(args[3]); } } builtin::BuiltinProofRuleChecker* builtinPfC = static_cast<builtin::BuiltinProofRuleChecker*>( d_pnm->getChecker()->getCheckerFor(PfRule::MACRO_SR_EQ_INTRO)); - Node tr = builtinPfC->applyRewrite(ts, rid); + Node tr = builtinPfC->applyRewrite(ts, idr); Trace("smt-proof-pp-debug") << "...eq intro rewrite equality is " << ts << " == " << tr << ", from " - << rid << std::endl; + << idr << std::endl; if (ts != tr) { Node eq = ts.eqNode(tr); @@ -797,6 +805,11 @@ Node ProofPostprocessCallback::expandMacros(PfRule id, { builtin::BuiltinProofRuleChecker::getMethodId(args[1], ids); } + MethodId ida = MethodId::SBA_SEQUENTIAL; + if (args.size() >= 3) + { + builtin::BuiltinProofRuleChecker::getMethodId(args[2], ida); + } std::vector<std::shared_ptr<CDProof>> pfs; std::vector<TNode> vsList; std::vector<TNode> ssList; @@ -834,7 +847,7 @@ Node ProofPostprocessCallback::expandMacros(PfRule id, << "...process " << var << " -> " << subs << " (" << childFrom << ", " << ids << ")" << std::endl; // apply the current substitution to the range - if (!vvec.empty()) + if (!vvec.empty() && ida == MethodId::SBA_SEQUENTIAL) { Node ss = subs.substitute(vvec.begin(), vvec.end(), svec.begin(), svec.end()); @@ -889,43 +902,47 @@ Node ProofPostprocessCallback::expandMacros(PfRule id, svec.push_back(subs); pgs.push_back(cdp); } - Node ts = t.substitute(vvec.begin(), vvec.end(), svec.begin(), svec.end()); - Node eq = t.eqNode(ts); - if (ts != t) + // should be implied by the substitution now + TConvPolicy tcpolicy = ida == MethodId::SBA_FIXPOINT ? TConvPolicy::FIXPOINT + : TConvPolicy::ONCE; + TConvProofGenerator tcpg(d_pnm, + nullptr, + tcpolicy, + TConvCachePolicy::NEVER, + "SUBS_TConvProofGenerator", + nullptr, + true); + for (unsigned j = 0, nvars = vvec.size(); j < nvars; j++) { - // should be implied by the substitution now - TConvProofGenerator tcpg(d_pnm, - nullptr, - TConvPolicy::ONCE, - TConvCachePolicy::NEVER, - "SUBS_TConvProofGenerator", - nullptr, - true); - for (unsigned j = 0, nvars = vvec.size(); j < nvars; j++) - { - // substitutions are pre-rewrites - tcpg.addRewriteStep(vvec[j], svec[j], pgs[j], true); - } - // add the proof constructed by the term conversion utility - std::shared_ptr<ProofNode> pfn = tcpg.getProofFor(eq); - // should give a proof, if not, then tcpg does not agree with the - // substitution. - Assert(pfn != nullptr); - if (pfn == nullptr) - { - cdp->addStep(eq, PfRule::TRUST_SUBS, {}, {eq}); - } - else - { - cdp->addProof(pfn); - } + // substitutions are pre-rewrites + tcpg.addRewriteStep(vvec[j], svec[j], pgs[j], true); + } + // add the proof constructed by the term conversion utility + std::shared_ptr<ProofNode> pfn = tcpg.getProofForRewriting(t); + Node eq = pfn->getResult(); + Node ts = builtin::BuiltinProofRuleChecker::applySubstitution( + t, children, ids, ida); + Node eqq = t.eqNode(ts); + if (eq != eqq) + { + pfn = nullptr; + } + // should give a proof, if not, then tcpg does not agree with the + // substitution. + Assert(pfn != nullptr); + if (pfn == nullptr) + { + AlwaysAssert(false) << "resort to TRUST_SUBS" << std::endl + << eq << std::endl + << eqq << std::endl + << "from " << children << " applied to " << t; + cdp->addStep(eqq, PfRule::TRUST_SUBS, {}, {eqq}); } else { - // should not be necessary typically - cdp->addStep(eq, PfRule::REFL, {}, {t}); + cdp->addProof(pfn); } - return eq; + return eqq; } else if (id == PfRule::REWRITE) { |