#include "theory/arith/theory_arith.h"
+#include "expr/proof_rule.h"
#include "options/smt_options.h"
#include "smt/smt_statistics_registry.h"
#include "theory/arith/arith_rewriter.h"
d_internal(
new TheoryArithPrivate(*this, c, u, out, valuation, logicInfo, pnm)),
d_ppRewriteTimer("theory::arith::ppRewriteTimer"),
+ d_ppPfGen(pnm, c, "Arith::ppRewrite"),
d_astate(*d_internal, c, u, valuation),
d_inferenceManager(*this, d_astate, pnm),
d_nonlinearExtension(nullptr),
Debug("arith::preprocess")
<< "arith::preprocess() : returning " << rewritten << endl;
// don't need to rewrite terms since rewritten is not a non-standard op
- return TrustNode::mkTrustRewrite(atom, rewritten, nullptr);
+ if (proofsEnabled())
+ {
+ return d_ppPfGen.mkTrustedRewrite(
+ atom,
+ rewritten,
+ d_pnm->mkNode(PfRule::INT_TRUST, {}, {atom.eqNode(rewritten)}));
+ }
+ else
+ {
+ return TrustNode::mkTrustRewrite(atom, rewritten, nullptr);
+ }
}
}
return ppRewriteTerms(atom);
#include "expr/node_builder.h"
#include "expr/proof_generator.h"
#include "expr/proof_node_manager.h"
+#include "expr/proof_rule.h"
#include "expr/skolem_manager.h"
#include "options/arith_options.h"
#include "options/smt_options.h" // for incrementalSolving()
ArithVar canBranch = nextIntegerViolatation(false);
if(canBranch != ARITHVAR_SENTINEL){
++d_statistics.d_panicBranches;
- Node branch = branchIntegerVariable(canBranch);
- Assert(branch.getKind() == kind::OR);
- Node rwbranch = Rewriter::rewrite(branch[0]);
+ TrustNode branch = branchIntegerVariable(canBranch);
+ Assert(branch.getNode().getKind() == kind::OR);
+ Node rwbranch = Rewriter::rewrite(branch.getNode()[0]);
if(!isSatLiteral(rwbranch)){
- d_approxCuts.push_back(branch);
+ d_approxCuts.push_back(branch.getNode());
return true;
}
}
}
if(!emmittedConflictOrSplit) {
- Node possibleLemma = roundRobinBranch();
- if(!possibleLemma.isNull()){
+ TrustNode possibleLemma = roundRobinBranch();
+ if (!possibleLemma.getNode().isNull())
+ {
++(d_statistics.d_externalBranchAndBounds);
d_cutCount = d_cutCount + 1;
emmittedConflictOrSplit = true;
Debug("arith::lemma") << "rrbranch lemma"
<< possibleLemma << endl;
- outputLemma(possibleLemma);
-
+ outputTrustedLemma(possibleLemma);
}
}
bool TheoryArithPrivate::foundNonlinear() const { return d_foundNl; }
-Node TheoryArithPrivate::branchIntegerVariable(ArithVar x) const {
+TrustNode TheoryArithPrivate::branchIntegerVariable(ArithVar x) const
+{
const DeltaRational& d = d_partialModel.getAssignment(x);
Assert(!d.isIntegral());
const Rational& r = d.getNoninfinitesimalPart();
TNode var = d_partialModel.asNode(x);
Integer floor_d = d.floor();
- Node lem;
+ TrustNode lem = TrustNode::null();
NodeManager* nm = NodeManager::currentNM();
if (options::brabTest())
{
nm->mkNode(kind::LEQ, var, mkRationalNode(nearest - 1)));
Node lb = Rewriter::rewrite(
nm->mkNode(kind::GEQ, var, mkRationalNode(nearest + 1)));
- lem = nm->mkNode(kind::OR, ub, lb);
- Node eq = Rewriter::rewrite(
- nm->mkNode(kind::EQUAL, var, mkRationalNode(nearest)));
+ Node right = nm->mkNode(kind::OR, ub, lb);
+ Node rawEq = nm->mkNode(kind::EQUAL, var, mkRationalNode(nearest));
+ Node eq = Rewriter::rewrite(rawEq);
// Also preprocess it before we send it out. This is important since
// arithmetic may prefer eliminating equalities.
+ TrustNode teq;
if (Theory::theoryOf(eq) == THEORY_ARITH)
{
- TrustNode teq = d_containing.ppRewrite(eq);
+ teq = d_containing.ppRewrite(eq);
eq = teq.isNull() ? eq : teq.getNode();
}
Node literal = d_containing.getValuation().ensureLiteral(eq);
+ Trace("integers") << "eq: " << eq << "\nto: " << literal << endl;
d_containing.getOutputChannel().requirePhase(literal, true);
- lem = nm->mkNode(kind::OR, literal, lem);
+ Node l = nm->mkNode(kind::OR, literal, right);
+ Trace("integers") << "l: " << l << endl;
+ if (proofsEnabled())
+ {
+ Node less = nm->mkNode(kind::LT, var, mkRationalNode(nearest));
+ Node greater = nm->mkNode(kind::GT, var, mkRationalNode(nearest));
+ // TODO (project #37): justify. Thread proofs through *ensureLiteral*.
+ Debug("integers::pf") << "less: " << less << endl;
+ Debug("integers::pf") << "greater: " << greater << endl;
+ Debug("integers::pf") << "literal: " << literal << endl;
+ Debug("integers::pf") << "eq: " << eq << endl;
+ Debug("integers::pf") << "rawEq: " << rawEq << endl;
+ Pf pfNotLit = d_pnm->mkAssume(literal.negate());
+ // rewrite notLiteral to notRawEq, using teq.
+ Pf pfNotRawEq =
+ literal == rawEq
+ ? pfNotLit
+ : d_pnm->mkNode(
+ PfRule::MACRO_SR_PRED_TRANSFORM,
+ {pfNotLit, teq.getGenerator()->getProofFor(teq.getProven())},
+ {rawEq.negate()});
+ Pf pfBot =
+ d_pnm->mkNode(PfRule::CONTRA,
+ {d_pnm->mkNode(PfRule::ARITH_TRICHOTOMY,
+ {d_pnm->mkAssume(less.negate()), pfNotRawEq},
+ {greater}),
+ d_pnm->mkAssume(greater.negate())},
+ {});
+ std::vector<Node> assumptions = {
+ literal.negate(), less.negate(), greater.negate()};
+ // Proof of (not (and (not (= v i)) (not (< v i)) (not (> v i))))
+ Pf pfNotAnd = d_pnm->mkScope(pfBot, assumptions);
+ Pf pfL = d_pnm->mkNode(PfRule::MACRO_SR_PRED_TRANSFORM,
+ {d_pnm->mkNode(PfRule::NOT_AND, {pfNotAnd}, {})},
+ {l});
+ lem = d_pfGen->mkTrustNode(l, pfL);
+ }
+ else
+ {
+ lem = TrustNode::mkTrustLemma(l, nullptr);
+ }
}
else
{
Node ub =
Rewriter::rewrite(nm->mkNode(kind::LEQ, var, mkRationalNode(floor_d)));
Node lb = ub.notNode();
- lem = nm->mkNode(kind::OR, ub, lb);
+ if (proofsEnabled())
+ {
+ lem = d_pfGen->mkTrustNode(
+ nm->mkNode(kind::OR, ub, lb), PfRule::SPLIT, {}, {ub});
+ }
+ else
+ {
+ lem = TrustNode::mkTrustLemma(nm->mkNode(kind::OR, ub, lb), nullptr);
+ }
}
Trace("integers") << "integers: branch & bound: " << lem << endl;
- if(isSatLiteral(lem[0])) {
- Debug("integers") << " " << lem[0] << " == " << getSatValue(lem[0]) << endl;
- } else {
- Debug("integers") << " " << lem[0] << " is not assigned a SAT literal" << endl;
- }
- if(isSatLiteral(lem[1])) {
- Debug("integers") << " " << lem[1] << " == " << getSatValue(lem[1]) << endl;
- } else {
- Debug("integers") << " " << lem[1] << " is not assigned a SAT literal" << endl;
+ if (Debug.isOn("integers"))
+ {
+ Node l = lem.getNode();
+ if (isSatLiteral(l[0]))
+ {
+ Debug("integers") << " " << l[0] << " == " << getSatValue(l[0])
+ << endl;
+ }
+ else
+ {
+ Debug("integers") << " " << l[0] << " is not assigned a SAT literal"
+ << endl;
+ }
+ if (isSatLiteral(l[1]))
+ {
+ Debug("integers") << " " << l[1] << " == " << getSatValue(l[1])
+ << endl;
+ }
+ else
+ {
+ Debug("integers") << " " << l[1] << " is not assigned a SAT literal"
+ << endl;
+ }
}
return lem;
}
}
/** Returns true if the roundRobinBranching() issues a lemma. */
-Node TheoryArithPrivate::roundRobinBranch(){
+TrustNode TheoryArithPrivate::roundRobinBranch()
+{
if(hasIntegerModel()){
- return Node::null();
+ return TrustNode::null();
}else{
ArithVar v = d_nextIntegerCheckVar;