case PfRule::STRING_SEQ_UNIT_INJ: return "STRING_SEQ_UNIT_INJ";
case PfRule::STRING_TRUST: return "STRING_TRUST";
//================================================= Arith rules
- case PfRule::ARITH_SCALE_SUM_UPPER_BOUNDS: return "ARITH_SCALE_SUM_UPPER_BOUNDS";
+ case PfRule::MACRO_ARITH_SCALE_SUM_UB:
+ return "ARITH_SCALE_SUM_UPPER_BOUNDS";
+ case PfRule::ARITH_SUM_UB: return "ARITH_SUM_UB";
case PfRule::ARITH_TRICHOTOMY: return "ARITH_TRICHOTOMY";
case PfRule::INT_TIGHT_LB: return "INT_TIGHT_LB";
case PfRule::INT_TIGHT_UB: return "INT_TIGHT_UB";
// t1 is the sum of the scaled polynomials (k_1 * poly_1 + ... + k_n *
// poly_n) t2 is the sum of the scaled constants (k_1 * const_1 + ... + k_n
// * const_n)
- ARITH_SCALE_SUM_UPPER_BOUNDS,
-
+ MACRO_ARITH_SCALE_SUM_UB,
// ======== Sum Upper Bounds
// Children: (P1, ... , Pn)
// where each Pi has form (><i, Li, Ri)
// otherwise no update
Trace("final-pf-hole") << "hole: " << id << " : " << eq << std::endl;
}
+ else if (id == PfRule::MACRO_ARITH_SCALE_SUM_UB)
+ {
+ Debug("macro::arith") << "Expand MACRO_ARITH_SCALE_SUM_UB" << std::endl;
+ if (Debug.isOn("macro::arith"))
+ {
+ for (const auto& child : children)
+ {
+ Debug("macro::arith") << " child: " << child << std::endl;
+ }
+ Debug("macro::arith") << " args: " << args << std::endl;
+ }
+ Assert(args.size() == children.size());
+ NodeManager* nm = NodeManager::currentNM();
+ ProofStepBuffer steps{d_pnm->getChecker()};
+
+ // Scale all children, accumulating
+ std::vector<Node> scaledRels;
+ for (size_t i = 0; i < children.size(); ++i)
+ {
+ TNode child = children[i];
+ TNode scalar = args[i];
+ bool isPos = scalar.getConst<Rational>() > 0;
+ Node scalarCmp =
+ nm->mkNode(isPos ? GT : LT, scalar, nm->mkConst(Rational(0)));
+ // (= scalarCmp true)
+ Node scalarCmpOrTrue = steps.tryStep(PfRule::EVALUATE, {}, {scalarCmp});
+ Assert(!scalarCmpOrTrue.isNull());
+ // scalarCmp
+ steps.addStep(PfRule::TRUE_ELIM, {scalarCmpOrTrue}, {}, scalarCmp);
+ // (and scalarCmp relation)
+ Node scalarCmpAndRel =
+ steps.tryStep(PfRule::AND_INTRO, {scalarCmp, child}, {});
+ Assert(!scalarCmpAndRel.isNull());
+ // (=> (and scalarCmp relation) scaled)
+ Node impl =
+ steps.tryStep(isPos ? PfRule::ARITH_MULT_POS : PfRule::ARITH_MULT_NEG,
+ {},
+ {scalar, child});
+ Assert(!impl.isNull());
+ // scaled
+ Node scaled =
+ steps.tryStep(PfRule::MODUS_PONENS, {scalarCmpAndRel, impl}, {});
+ Assert(!scaled.isNull());
+ scaledRels.emplace_back(scaled);
+ }
+
+ Node sumBounds = steps.tryStep(PfRule::ARITH_SUM_UB, scaledRels, {});
+ cdp->addSteps(steps);
+ Debug("macro::arith") << "Expansion done. Proved: " << sumBounds
+ << std::endl;
+ return sumBounds;
+ }
// TRUST, PREPROCESS, THEORY_LEMMA, THEORY_PREPROCESS?
const auto isZeroPf = d_pnm->mkAssume(isZero);
const auto nm = NodeManager::currentNM();
const auto sumPf = d_pnm->mkNode(
- PfRule::ARITH_SCALE_SUM_UPPER_BOUNDS,
+ PfRule::MACRO_ARITH_SCALE_SUM_UB,
{isZeroPf, pf},
// Trick for getting correct, opposing signs.
{nm->mkConst(Rational(-1 * cSign)), nm->mkConst(Rational(cSign))});
auto ltPf = d_database->d_pnm->mkNode(
PfRule::MACRO_SR_PRED_TRANSFORM, {nGeqPf}, {ltNode});
auto sumPf = d_database->d_pnm->mkNode(
- PfRule::ARITH_SCALE_SUM_UPPER_BOUNDS,
+ PfRule::MACRO_ARITH_SCALE_SUM_UB,
{gtPf, ltPf},
{nm->mkConst<Rational>(-1), nm->mkConst<Rational>(1)});
auto botPf = d_database->d_pnm->mkNode(
}
// Apply the scaled-sum rule.
- std::shared_ptr<ProofNode> sumPf =
- pnm->mkNode(PfRule::ARITH_SCALE_SUM_UPPER_BOUNDS,
- farkasChildren,
- farkasCoeffs);
+ std::shared_ptr<ProofNode> sumPf = pnm->mkNode(
+ PfRule::MACRO_ARITH_SCALE_SUM_UB, farkasChildren, farkasCoeffs);
// Provable rewrite the result
auto botPf = pnm->mkNode(
int sndSign = negateSecond ? -1 : 1;
auto bot_pf =
d_pnm->mkNode(PfRule::MACRO_SR_PRED_TRANSFORM,
- {d_pnm->mkNode(PfRule::ARITH_SCALE_SUM_UPPER_BOUNDS,
+ {d_pnm->mkNode(PfRule::MACRO_ARITH_SCALE_SUM_UB,
{pf_neg_la, pf_neg_lb},
{nm->mkConst<Rational>(-1 * sndSign),
nm->mkConst<Rational>(sndSign)})},
void ArithProofRuleChecker::registerTo(ProofChecker* pc)
{
- pc->registerChecker(PfRule::ARITH_SCALE_SUM_UPPER_BOUNDS, this);
+ pc->registerChecker(PfRule::MACRO_ARITH_SCALE_SUM_UB, this);
pc->registerChecker(PfRule::ARITH_SUM_UB, this);
pc->registerChecker(PfRule::ARITH_TRICHOTOMY, this);
pc->registerChecker(PfRule::INT_TIGHT_UB, this);
rightSum.constructNode());
return r;
}
- case PfRule::ARITH_SCALE_SUM_UPPER_BOUNDS:
+ case PfRule::MACRO_ARITH_SCALE_SUM_UB:
{
+ //================================================= Arithmetic rules
+ // ======== Adding Inequalities
+ // Note: an ArithLiteral is a term of the form (>< poly const)
+ // where
+ // >< is >=, >, ==, <, <=, or not(== ...).
+ // poly is a polynomial
+ // const is a rational constant
+
// Children: (P1:l1, ..., Pn:ln)
// where each li is an ArithLiteral
// not(= ...) is dis-allowed!
//
// Arguments: (k1, ..., kn), non-zero reals
// ---------------------
- // Conclusion: (>< (* k t1) (* k t2))
+ // Conclusion: (>< t1 t2)
// where >< is the fusion of the combination of the ><i, (flipping each
// it its ki is negative). >< is always one of <, <= NB: this implies
// that lower bounds must have negative ki,
// and upper bounds must have positive ki.
- // t1 is the sum of the polynomials.
- // t2 is the sum of the constants.
+ // t1 is the sum of the scaled polynomials (k_1 * poly_1 + ... + k_n *
+ // poly_n) t2 is the sum of the scaled constants (k_1 * const_1 + ... +
+ // k_n * const_n)
Assert(children.size() == args.size());
if (children.size() < 2)
{
}
}
leftSum << nm->mkNode(
- Kind::MULT, children[i][0], nm->mkConst<Rational>(scalar));
+ Kind::MULT, nm->mkConst<Rational>(scalar), children[i][0]);
rightSum << nm->mkNode(
- Kind::MULT, children[i][1], nm->mkConst<Rational>(scalar));
+ Kind::MULT, nm->mkConst<Rational>(scalar), children[i][1]);
}
Node r = nm->mkNode(strict ? Kind::LT : Kind::LEQ,
leftSum.constructNode(),
Pf pfLt =
d_pnm->mkNode(PfRule::MACRO_SR_PRED_TRANSFORM, {pfNotGeq}, {lt});
Pf pfSum =
- d_pnm->mkNode(PfRule::ARITH_SCALE_SUM_UPPER_BOUNDS,
+ d_pnm->mkNode(PfRule::MACRO_ARITH_SCALE_SUM_UB,
{pfGt, pfLt},
{nm->mkConst<Rational>(-1), nm->mkConst<Rational>(1)});
Pf pfBot = d_pnm->mkNode(
[nm](const Rational& r) { return nm->mkConst<Rational>(r); });
// Prove bottom.
- auto sumPf = d_pnm->mkNode(PfRule::ARITH_SCALE_SUM_UPPER_BOUNDS,
- conflictPfs,
- farkasCoefficients);
+ auto sumPf = d_pnm->mkNode(
+ PfRule::MACRO_ARITH_SCALE_SUM_UB, conflictPfs, farkasCoefficients);
auto botPf = d_pnm->mkNode(
PfRule::MACRO_SR_PRED_TRANSFORM, {sumPf}, {nm->mkConst(false)});