Branch data Line data Source code
1 : : /******************************************************************************
2 : : * This file is part of the cvc5 project.
3 : : *
4 : : * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
5 : : * in the top-level source directory and their institutional affiliations.
6 : : * All rights reserved. See the file COPYING in the top-level source
7 : : * directory for licensing information.
8 : : * ****************************************************************************
9 : : *
10 : : * Common functions for dealing with proof nodes.
11 : : */
12 : :
13 : : #include "theory/arith/arith_proof_utilities.h"
14 : :
15 : : #include "proof/proof_node_manager.h"
16 : : #include "util/rational.h"
17 : :
18 : : namespace cvc5::internal {
19 : : namespace theory {
20 : : namespace arith {
21 : :
22 : 663581 : std::vector<Node> getMacroSumUbCoeff(NodeManager* nm,
23 : : const std::vector<Pf>& pfs,
24 : : const std::vector<Node>& coeffs)
25 : : {
26 [ - + ][ - + ]: 663581 : Assert(pfs.size() == coeffs.size());
[ - - ]
27 : :
28 : 663581 : std::vector<Node> premises;
29 [ + + ]: 2480620 : for (const Pf& p : pfs)
30 : : {
31 : 1817039 : premises.push_back(p->getResult());
32 : : }
33 : 1327162 : return getMacroSumUbCoeff(nm, premises, coeffs);
34 : 663581 : }
35 : 663631 : std::vector<Node> getMacroSumUbCoeff(NodeManager* nm,
36 : : const std::vector<Node>& premises,
37 : : const std::vector<Node>& coeffs)
38 : : {
39 [ - + ][ - + ]: 663631 : Assert(premises.size() == coeffs.size());
[ - - ]
40 : :
41 : 663631 : std::vector<Node> ret;
42 : 663631 : TypeNode itype = nm->integerType();
43 : 663631 : TypeNode rtype = nm->realType();
44 : : // For each coefficient, we must use a real if the lhs or rhs of the relation
45 : : // is a real, or if the coefficient is not integral.
46 [ + + ]: 2480770 : for (size_t i = 0, ncoeff = coeffs.size(); i < ncoeff; i++)
47 : : {
48 [ - + ][ - + ]: 1817139 : Assert(coeffs[i].isConst());
[ - - ]
49 : 1817139 : Node res = premises[i];
50 : 1817139 : Assert(res.getType().isBoolean() && res.getNumChildren() == 2);
51 : 1817139 : const Rational& r = coeffs[i].getConst<Rational>();
52 : 3548661 : bool isReal = !r.isIntegral() || res[0].getType().isReal()
53 : 3548661 : || res[1].getType().isReal();
54 [ + + ]: 1817139 : ret.push_back(nm->mkConstRealOrInt(isReal ? rtype : itype, r));
55 : 1817139 : }
56 : 1327262 : return ret;
57 : 663631 : }
58 : :
59 : 31127 : Node expandMacroSumUb(NodeManager* nm,
60 : : const std::vector<Node>& children,
61 : : const std::vector<Node>& args,
62 : : CDProof* cdp)
63 : : {
64 [ - + ]: 31127 : if (TraceIsOn("macro::arith"))
65 : : {
66 [ - - ]: 0 : Trace("macro::arith") << "Expand MACRO_ARITH_SCALE_SUM_UB" << std::endl;
67 [ - - ]: 0 : for (const auto& child : children)
68 : : {
69 [ - - ]: 0 : Trace("macro::arith") << " child: " << child << std::endl;
70 : : }
71 [ - - ]: 0 : Trace("macro::arith") << " args: " << args << std::endl;
72 : : }
73 [ - + ][ - + ]: 31127 : Assert(args.size() == children.size());
[ - - ]
74 : 31127 : ProofStepBuffer steps{cdp->getManager()->getChecker()};
75 : :
76 : : // Scale all children, accumulating
77 : 31127 : std::vector<Node> scaledRels;
78 : 31127 : Node one = nm->mkConstInt(Rational(1));
79 [ + + ]: 182539 : for (size_t i = 0; i < children.size(); ++i)
80 : : {
81 : 151412 : TNode child = children[i];
82 : 151412 : TNode scalar = args[i];
83 [ + + ]: 151412 : if (scalar.getConst<Rational>() == 1)
84 : : {
85 : : // if scaled by one, just take original
86 : 63464 : scaledRels.push_back(child);
87 : 63464 : continue;
88 : : }
89 : 87948 : bool isPos = scalar.getConst<Rational>() > 0;
90 : : Node scalarCmp =
91 : : nm->mkNode(isPos ? Kind::GT : Kind::LT,
92 : : scalar,
93 [ + + ]: 175896 : nm->mkConstRealOrInt(scalar.getType(), Rational(0)));
94 : : // (= scalarCmp true)
95 : 351792 : Node scalarCmpOrTrue = steps.tryStep(ProofRule::EVALUATE, {}, {scalarCmp});
96 [ - + ][ - + ]: 87948 : Assert(!scalarCmpOrTrue.isNull());
[ - - ]
97 : : // scalarCmp
98 : 175896 : steps.addStep(ProofRule::TRUE_ELIM, {scalarCmpOrTrue}, {}, scalarCmp);
99 : : // (and scalarCmp relation)
100 : : Node scalarCmpAndRel =
101 : 439740 : steps.tryStep(ProofRule::AND_INTRO, {scalarCmp, child}, {});
102 [ - + ][ - + ]: 87948 : Assert(!scalarCmpAndRel.isNull());
[ - - ]
103 : : // (=> (and scalarCmp relation) scaled)
104 : 175896 : Node impl = steps.tryStep(
105 : : isPos ? ProofRule::ARITH_MULT_POS : ProofRule::ARITH_MULT_NEG,
106 : : {},
107 [ + + ]: 263844 : {scalar, child});
108 [ - + ][ - + ]: 87948 : Assert(!impl.isNull());
[ - - ]
109 : : // scaled
110 : : Node scaled =
111 : 439740 : steps.tryStep(ProofRule::MODUS_PONENS, {scalarCmpAndRel, impl}, {});
112 [ - + ][ - + ]: 87948 : Assert(!scaled.isNull());
[ - - ]
113 : 87948 : scaledRels.emplace_back(scaled);
114 [ + + ][ + + ]: 214876 : }
115 : :
116 : 62254 : Node sumBounds = steps.tryStep(ProofRule::ARITH_SUM_UB, scaledRels, {});
117 : 31127 : cdp->addSteps(steps);
118 [ + - ]: 31127 : Trace("macro::arith") << "Expansion done. Proved: " << sumBounds << std::endl;
119 : 62254 : return sumBounds;
120 : 31127 : }
121 : :
122 : 5023908 : std::shared_ptr<ProofNode> ensurePredTransform(ProofNodeManager* pnm,
123 : : std::shared_ptr<ProofNode>& pf,
124 : : const Node& pred)
125 : : {
126 [ + + ]: 5023908 : if (pf->getResult() == pred)
127 : : {
128 : 881022 : return pf;
129 : : }
130 : : // give the predicate as the expected result, which is important for
131 : : // performance (does not require proof checking).
132 : 12428658 : return pnm->mkNode(ProofRule::MACRO_SR_PRED_TRANSFORM, {pf}, {pred}, pred);
133 : : }
134 : :
135 : : } // namespace arith
136 : : } // namespace theory
137 : : } // namespace cvc5::internal
|