Branch data Line data Source code
1 : : /****************************************************************************** 2 : : * Top contributors (to current version): 3 : : * Andrew Reynolds, Mathias Preiner 4 : : * 5 : : * This file is part of the cvc5 project. 6 : : * 7 : : * Copyright (c) 2009-2025 by the authors listed in the file AUTHORS 8 : : * in the top-level source directory and their institutional affiliations. 9 : : * All rights reserved. See the file COPYING in the top-level source 10 : : * directory for licensing information. 11 : : * **************************************************************************** 12 : : * 13 : : * The StaticRewrite preprocessing pass. 14 : : */ 15 : : 16 : : #include "preprocessing/passes/static_rewrite.h" 17 : : 18 : : #include "options/smt_options.h" 19 : : #include "preprocessing/assertion_pipeline.h" 20 : : #include "preprocessing/preprocessing_pass_context.h" 21 : : #include "theory/theory_engine.h" 22 : : 23 : : using namespace cvc5::internal::theory; 24 : : 25 : : namespace cvc5::internal { 26 : : namespace preprocessing { 27 : : namespace passes { 28 : : 29 : 51946 : StaticRewrite::StaticRewrite(PreprocessingPassContext* preprocContext) 30 : 51946 : : PreprocessingPass(preprocContext, "static-rewrite") 31 : : { 32 [ + + ]: 51946 : if (options().smt.produceProofs) 33 : : { 34 : 41268 : d_tpg.reset(new TConvProofGenerator(d_env, 35 : 20634 : userContext(), 36 : : TConvPolicy::FIXPOINT, 37 : : TConvCachePolicy::NEVER, 38 : 20634 : "StaticRewrite::tpg")); 39 : : } 40 : 51946 : } 41 : : 42 : 37402 : PreprocessingPassResult StaticRewrite::applyInternal( 43 : : AssertionPipeline* assertions) 44 : : { 45 : : // apply ppRewrite to all equalities in assertions 46 [ + + ]: 606345 : for (std::size_t i = 0, size = assertions->size(); i < size; ++i) 47 : : { 48 : 569053 : Node assertion = (*assertions)[i]; 49 : 569053 : TrustNode trn = rewriteAssertion(assertion); 50 [ + + ]: 569049 : if (!trn.isNull()) 51 : : { 52 : : // replace based on the trust node 53 : 7439 : assertions->replaceTrusted(i, trn); 54 [ + + ]: 7439 : if (assertions->isInConflict()) 55 : : { 56 : 106 : return PreprocessingPassResult::CONFLICT; 57 : : } 58 : : } 59 : : } 60 : 37294 : return PreprocessingPassResult::NO_CONFLICT; 61 : : } 62 : : 63 : 569051 : TrustNode StaticRewrite::rewriteAssertion(TNode n) 64 : : { 65 : 569051 : NodeManager* nm = nodeManager(); 66 : 569051 : TheoryEngine* te = d_preprocContext->getTheoryEngine(); 67 : 1138100 : std::unordered_map<TNode, Node> visited; 68 : 1138100 : std::unordered_map<TNode, Node> rewrittenTo; 69 : 569051 : std::unordered_map<TNode, Node>::iterator it; 70 : : // to ensure all nodes are ref counted 71 : 1138100 : std::unordered_set<Node> keep; 72 : 1138100 : std::vector<TNode> visit; 73 : 1138100 : TNode cur; 74 : 569051 : visit.push_back(n); 75 : 13265100 : do 76 : : { 77 : 13834100 : cur = visit.back(); 78 : 13834100 : it = visited.find(cur); 79 : : 80 [ + + ]: 13834100 : if (it == visited.end()) 81 : : { 82 [ + + ]: 6315500 : if (cur.getNumChildren()==0) 83 : : { 84 : 1890100 : visit.pop_back(); 85 : 1890100 : visited[cur] = cur; 86 : : } 87 : : else 88 : : { 89 : 4425400 : visited[cur] = Node::null(); 90 : 4425400 : visit.insert(visit.end(), cur.begin(), cur.end()); 91 : : } 92 : : } 93 [ + + ]: 7518640 : else if (it->second.isNull()) 94 : : { 95 : 4477110 : it = rewrittenTo.find(cur); 96 [ + + ]: 4477110 : if (it != rewrittenTo.end()) 97 : : { 98 : : // rewritten form is the rewritten form of what it was rewritten to 99 [ - + ][ - + ]: 51723 : Assert(visited.find(it->second) != visited.end()); [ - - ] 100 : 51723 : visited[cur] = visited[it->second]; 101 : 51723 : visit.pop_back(); 102 : 51723 : continue; 103 : : } 104 : 8850780 : Node ret = cur; 105 : 4425390 : bool childChanged = false; 106 : 8850780 : std::vector<Node> children; 107 [ + + ]: 4425390 : if (cur.getMetaKind() == kind::metakind::PARAMETERIZED) 108 : : { 109 : 731965 : children.push_back(cur.getOperator()); 110 : : } 111 [ + + ]: 13161600 : for (const Node& cn : cur) 112 : : { 113 : 8736250 : it = visited.find(cn); 114 [ - + ][ - + ]: 8736250 : Assert(it != visited.end()); [ - - ] 115 [ - + ][ - + ]: 8736250 : Assert(!it->second.isNull()); [ - - ] 116 [ + + ][ + + ]: 8736250 : childChanged = childChanged || cn != it->second; 117 : 8736250 : children.push_back(it->second); 118 : : } 119 [ + + ]: 4425390 : if (childChanged) 120 : : { 121 : 79282 : ret = nm->mkNode(cur.getKind(), children); 122 : 79282 : keep.insert(ret); 123 : : } 124 : 4425390 : bool wasRewritten = false; 125 : : // For example, (= x y) ---> (and (>= x y) (<= x y)) 126 : 8850780 : TrustNode trn = te->ppStaticRewrite(ret); 127 : : // can make proof producing by using proof generator from trn 128 [ + + ][ + - ]: 4425390 : if (!trn.isNull() && trn.getNode() != ret) [ + + ][ + + ] [ - - ] 129 : : { 130 [ + - ]: 103446 : Trace("pp-rewrite-eq") 131 [ - + ][ - - ]: 51723 : << "Rewrite " << ret << " to " << trn.getNode() << std::endl; 132 : 51723 : wasRewritten = true; 133 : 103446 : Node retr = trn.getNode(); 134 : 51723 : keep.insert(retr); 135 : 51723 : rewrittenTo[cur] = retr; 136 : 51723 : rewrittenTo[ret] = retr; 137 : 51723 : visit.push_back(retr); 138 [ + + ]: 51723 : if (d_tpg != nullptr) 139 : : { 140 : 85306 : d_tpg->addRewriteStep(ret, 141 : 85306 : trn.getNode(), 142 : : trn.getGenerator(), 143 : : false, 144 : : TrustId::PP_STATIC_REWRITE); 145 : : } 146 : : } 147 [ + + ]: 4425390 : if (!wasRewritten) 148 : : { 149 : 4373660 : visit.pop_back(); 150 : 4373660 : visited[cur] = ret; 151 : : } 152 : : } 153 : : else 154 : : { 155 : 3041530 : visit.pop_back(); 156 : : } 157 [ + + ]: 13834100 : } while (!visit.empty()); 158 [ - + ][ - + ]: 569049 : Assert(visited.find(n) != visited.end()); [ - - ] 159 [ - + ][ - + ]: 569049 : Assert(!visited.find(n)->second.isNull()); [ - - ] 160 : 1138100 : Node ret = visited[n]; 161 [ + + ]: 569049 : if (ret == n) 162 : : { 163 : 561610 : return TrustNode::null(); 164 : : } 165 : : // use the term conversion proof generator if it exists 166 [ + + ]: 7439 : return TrustNode::mkTrustRewrite(n, ret, d_tpg.get()); 167 : : } 168 : : 169 : : } // namespace passes 170 : : } // namespace preprocessing 171 : : } // namespace cvc5::internal