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-2024 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 : 50591 : StaticRewrite::StaticRewrite(PreprocessingPassContext* preprocContext) 30 : 50591 : : PreprocessingPass(preprocContext, "static-rewrite") 31 : : { 32 [ + + ]: 50591 : if (options().smt.produceProofs) 33 : : { 34 : 39086 : d_tpg.reset(new TConvProofGenerator(d_env, 35 : 19543 : userContext(), 36 : : TConvPolicy::FIXPOINT, 37 : : TConvCachePolicy::NEVER, 38 : 19543 : "StaticRewrite::tpg")); 39 : : } 40 : 50591 : } 41 : : 42 : 36520 : PreprocessingPassResult StaticRewrite::applyInternal( 43 : : AssertionPipeline* assertions) 44 : : { 45 : : // apply ppRewrite to all equalities in assertions 46 [ + + ]: 595465 : for (std::size_t i = 0, size = assertions->size(); i < size; ++i) 47 : : { 48 : 559015 : Node assertion = (*assertions)[i]; 49 : 559015 : TrustNode trn = rewriteAssertion(assertion); 50 [ + + ]: 559011 : if (!trn.isNull()) 51 : : { 52 : : // replace based on the trust node 53 : 6244 : assertions->replaceTrusted(i, trn); 54 [ + + ]: 6244 : if (assertions->isInConflict()) 55 : : { 56 : 66 : return PreprocessingPassResult::CONFLICT; 57 : : } 58 : : } 59 : : } 60 : 36452 : return PreprocessingPassResult::NO_CONFLICT; 61 : : } 62 : : 63 : 559013 : TrustNode StaticRewrite::rewriteAssertion(TNode n) 64 : : { 65 : 559013 : NodeManager* nm = nodeManager(); 66 : 559013 : TheoryEngine* te = d_preprocContext->getTheoryEngine(); 67 : 1118030 : std::unordered_map<TNode, Node> visited; 68 : 1118030 : std::unordered_map<TNode, Node> rewrittenTo; 69 : 559013 : std::unordered_map<TNode, Node>::iterator it; 70 : : // to ensure all nodes are ref counted 71 : 1118030 : std::unordered_set<Node> keep; 72 : 1118030 : std::vector<TNode> visit; 73 : 1118030 : TNode cur; 74 : 559013 : visit.push_back(n); 75 : 12909700 : do 76 : : { 77 : 13468700 : cur = visit.back(); 78 : 13468700 : it = visited.find(cur); 79 : : 80 [ + + ]: 13468700 : if (it == visited.end()) 81 : : { 82 [ + + ]: 6173210 : if (cur.getNumChildren()==0) 83 : : { 84 : 1855320 : visit.pop_back(); 85 : 1855320 : visited[cur] = cur; 86 : : } 87 : : else 88 : : { 89 : 4317900 : visited[cur] = Node::null(); 90 : 4317900 : visit.insert(visit.end(), cur.begin(), cur.end()); 91 : : } 92 : : } 93 [ + + ]: 7295500 : else if (it->second.isNull()) 94 : : { 95 : 4359540 : it = rewrittenTo.find(cur); 96 [ + + ]: 4359540 : if (it != rewrittenTo.end()) 97 : : { 98 : : // rewritten form is the rewritten form of what it was rewritten to 99 [ - + ][ - + ]: 41651 : Assert(visited.find(it->second) != visited.end()); [ - - ] 100 : 41651 : visited[cur] = visited[it->second]; 101 : 41651 : visit.pop_back(); 102 : 41651 : continue; 103 : : } 104 : 8635790 : Node ret = cur; 105 : 4317890 : bool childChanged = false; 106 : 8635790 : std::vector<Node> children; 107 [ + + ]: 4317890 : if (cur.getMetaKind() == kind::metakind::PARAMETERIZED) 108 : : { 109 : 714104 : children.push_back(cur.getOperator()); 110 : : } 111 [ + + ]: 12826400 : for (const Node& cn : cur) 112 : : { 113 : 8508500 : it = visited.find(cn); 114 [ - + ][ - + ]: 8508500 : Assert(it != visited.end()); [ - - ] 115 [ - + ][ - + ]: 8508500 : Assert(!it->second.isNull()); [ - - ] 116 [ + + ][ + + ]: 8508500 : childChanged = childChanged || cn != it->second; 117 : 8508500 : children.push_back(it->second); 118 : : } 119 [ + + ]: 4317890 : if (childChanged) 120 : : { 121 : 58343 : ret = nm->mkNode(cur.getKind(), children); 122 : 58343 : keep.insert(ret); 123 : : } 124 : 4317890 : bool wasRewritten = false; 125 : : // For example, (= x y) ---> (and (>= x y) (<= x y)) 126 : 8635790 : TrustNode trn = te->ppStaticRewrite(ret); 127 : : // can make proof producing by using proof generator from trn 128 [ + + ][ + - ]: 4317890 : if (!trn.isNull() && trn.getNode() != ret) [ + + ][ + + ] [ - - ] 129 : : { 130 [ + - ]: 83302 : Trace("pp-rewrite-eq") 131 [ - + ][ - - ]: 41651 : << "Rewrite " << ret << " to " << trn.getNode() << std::endl; 132 : 41651 : wasRewritten = true; 133 : 83302 : Node retr = trn.getNode(); 134 : 41651 : keep.insert(retr); 135 : 41651 : rewrittenTo[cur] = retr; 136 : 41651 : rewrittenTo[ret] = retr; 137 : 41651 : visit.push_back(retr); 138 [ + + ]: 41651 : if (d_tpg != nullptr) 139 : : { 140 : 65252 : d_tpg->addRewriteStep(ret, 141 : 65252 : trn.getNode(), 142 : : trn.getGenerator(), 143 : : false, 144 : : TrustId::PP_STATIC_REWRITE); 145 : : } 146 : : } 147 [ + + ]: 4317890 : if (!wasRewritten) 148 : : { 149 : 4276240 : visit.pop_back(); 150 : 4276240 : visited[cur] = ret; 151 : : } 152 : : } 153 : : else 154 : : { 155 : 2935950 : visit.pop_back(); 156 : : } 157 [ + + ]: 13468700 : } while (!visit.empty()); 158 [ - + ][ - + ]: 559011 : Assert(visited.find(n) != visited.end()); [ - - ] 159 [ - + ][ - + ]: 559011 : Assert(!visited.find(n)->second.isNull()); [ - - ] 160 : 1118020 : Node ret = visited[n]; 161 [ + + ]: 559011 : if (ret == n) 162 : : { 163 : 552767 : return TrustNode::null(); 164 : : } 165 : : // use the term conversion proof generator if it exists 166 [ + + ]: 6244 : return TrustNode::mkTrustRewrite(n, ret, d_tpg.get()); 167 : : } 168 : : 169 : : } // namespace passes 170 : : } // namespace preprocessing 171 : : } // namespace cvc5::internal