Node ts = builtin::BuiltinProofRuleChecker::applySubstitution(
t, children, ids, ida);
Node eqq = t.eqNode(ts);
+ // should have the same conclusion, if not, then tcpg does not agree with
+ // the substitution.
if (eq != eqq)
{
- pfn = nullptr;
- }
- // should give a proof, if not, then tcpg does not agree with the
- // substitution.
- if (pfn == nullptr)
- {
- warning() << "resort to TRUST_SUBS" << std::endl
- << eq << std::endl
- << eqq << std::endl
- << "from " << children << " applied to " << t << std::endl;
- cdp->addStep(eqq, PfRule::TRUST_SUBS, {}, {eqq});
+ // this can happen in very rare cases where e.g. x -> a; f(x) -> b
+ // and t*{x -> a} = t*{x -> a}*{f(x) -> b} != t*{x -> a, f(x) -> b}
+ if (ida == MethodId::SBA_SEQUENTIAL && vsList.size() > 1)
+ {
+ Trace("smt-proof-pp-debug")
+ << "resort to sequential reconstruction" << std::endl;
+ // just do the naive sequential reconstruction,
+ // (SUBS F1 ... Fn t) ---> (TRANS (SUBS F1 t) ... (SUBS Fn tn))
+ Node curr = t;
+ std::vector<Node> transChildren;
+ for (size_t i = 0, nvs = vsList.size(); i < nvs; i++)
+ {
+ size_t ii = nvs - 1 - i;
+ TNode var = vsList[ii];
+ TNode subs = ssList[ii];
+ Node next = curr.substitute(var, subs);
+ if (next != curr)
+ {
+ Node eqo = curr.eqNode(next);
+ transChildren.push_back(eqo);
+ // ensure the proof for the substitution exists
+ addProofForSubsStep(var, subs, fromList[ii], cdp);
+ // do the single step SUBS on curr with the default arguments
+ cdp->addStep(eqo, PfRule::SUBS, {var.eqNode(subs)}, {curr});
+ curr = next;
+ }
+ }
+ Assert(curr == ts);
+ cdp->addStep(eqq, PfRule::TRANS, transChildren, {});
+ }
+ else
+ {
+ Trace("smt-proof-pp-debug")
+ << "resort to TRUST_SUBS" << std::endl
+ << eq << std::endl
+ << eqq << std::endl
+ << "from " << children << " applied to " << t << std::endl;
+ cdp->addStep(eqq, PfRule::TRUST_SUBS, {}, {eqq});
+ }
}
else
{