Branch data Line data Source code
1 : : /****************************************************************************** 2 : : * Top contributors (to current version): 3 : : * Haniel Barbosa, 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 NlExtPurify preprocessing pass. 14 : : * 15 : : * Purifies non-linear terms. 16 : : */ 17 : : 18 : : #include "preprocessing/passes/nl_ext_purify.h" 19 : : 20 : : #include "expr/skolem_manager.h" 21 : : #include "preprocessing/assertion_pipeline.h" 22 : : #include "theory/rewriter.h" 23 : : 24 : : namespace cvc5::internal { 25 : : namespace preprocessing { 26 : : namespace passes { 27 : : 28 : : using namespace std; 29 : : using namespace cvc5::internal::theory; 30 : : 31 : 2944 : Node NlExtPurify::purifyNlTerms(TNode n, 32 : : NodeMap& cache, 33 : : NodeMap& bcache, 34 : : std::vector<Node>& var_eq, 35 : : bool beneathMult) 36 : : { 37 : 2944 : NodeManager* nm = nodeManager(); 38 [ + + ]: 2944 : if (beneathMult) 39 : : { 40 : 2294 : NodeMap::iterator find = bcache.find(n); 41 [ + + ]: 2294 : if (find != bcache.end()) 42 : : { 43 : 2170 : return (*find).second; 44 : : } 45 : : } 46 : : else 47 : : { 48 : 650 : NodeMap::iterator find = cache.find(n); 49 [ + + ]: 650 : if (find != cache.end()) 50 : : { 51 : 462 : return (*find).second; 52 : : } 53 : : } 54 [ - + ]: 312 : if (n.isClosure()) 55 : : { 56 : : // don't traverse quantified formulas 57 : 0 : return n; 58 : : } 59 : 312 : Node ret = n; 60 [ + + ]: 312 : if (n.getNumChildren() > 0) 61 : : { 62 [ + + ][ + - ]: 238 : if (beneathMult && (n.getKind() == Kind::ADD || n.getKind() == Kind::SUB)) [ - + ][ - + ] 63 : : { 64 : : // don't do it if it rewrites to a constant 65 : 0 : Node nr = rewrite(n); 66 [ - - ]: 0 : if (nr.isConst()) 67 : : { 68 : : // return the rewritten constant 69 : 0 : ret = nr; 70 : : } 71 : : else 72 : : { 73 : : // new variable 74 : 0 : ret = NodeManager::mkDummySkolem("__purifyNl_var", n.getType()); 75 : 0 : Node np = purifyNlTerms(n, cache, bcache, var_eq, false); 76 : 0 : var_eq.push_back(np.eqNode(ret)); 77 [ - - ]: 0 : Trace("nl-ext-purify") << "Purify : " << ret << " -> " << np 78 : 0 : << std::endl; 79 : 0 : } 80 : 0 : } 81 : : else 82 : : { 83 [ + + ][ + + ]: 238 : bool beneathMultNew = beneathMult || n.getKind() == Kind::MULT; 84 : 238 : bool childChanged = false; 85 : 238 : std::vector<Node> children; 86 [ + + ]: 2832 : for (unsigned i = 0, size = n.getNumChildren(); i < size; ++i) 87 : : { 88 : 2594 : Node nc = purifyNlTerms(n[i], cache, bcache, var_eq, beneathMultNew); 89 [ + - ][ - + ]: 2594 : childChanged = childChanged || nc != n[i]; [ + - ][ - - ] 90 : 2594 : children.push_back(nc); 91 : 2594 : } 92 [ - + ]: 238 : if (childChanged) 93 : : { 94 : 0 : ret = nm->mkNode(n.getKind(), children); 95 : : } 96 : 238 : } 97 : : } 98 [ + + ]: 312 : if (beneathMult) 99 : : { 100 : 124 : bcache[n] = ret; 101 : : } 102 : : else 103 : : { 104 : 188 : cache[n] = ret; 105 : : } 106 : 312 : return ret; 107 : 312 : } 108 : : 109 : 50585 : NlExtPurify::NlExtPurify(PreprocessingPassContext* preprocContext) 110 : 50585 : : PreprocessingPass(preprocContext, "nl-ext-purify"){}; 111 : : 112 : 10 : PreprocessingPassResult NlExtPurify::applyInternal( 113 : : AssertionPipeline* assertionsToPreprocess) 114 : : { 115 : 10 : unordered_map<Node, Node> cache; 116 : 10 : unordered_map<Node, Node> bcache; 117 : 10 : std::vector<Node> var_eq; 118 : 10 : unsigned size = assertionsToPreprocess->size(); 119 [ + + ]: 360 : for (unsigned i = 0; i < size; ++i) 120 : : { 121 : 350 : Node a = (*assertionsToPreprocess)[i]; 122 : 350 : Node ap = purifyNlTerms(a, cache, bcache, var_eq); 123 [ - + ]: 350 : if (a != ap) 124 : : { 125 : 0 : assertionsToPreprocess->replace( 126 : : i, ap, nullptr, TrustId::PREPROCESS_NL_EXT_PURIFY); 127 [ - - ]: 0 : Trace("nl-ext-purify") 128 : 0 : << "Purify : " << a << " -> " << (*assertionsToPreprocess)[i] << "\n"; 129 : : } 130 : 350 : } 131 [ - + ]: 10 : if (!var_eq.empty()) 132 : : { 133 [ - - ]: 0 : for (const Node& ve : var_eq) 134 : : { 135 : 0 : assertionsToPreprocess->push_back( 136 : : ve, false, nullptr, TrustId::PREPROCESS_NL_EXT_PURIFY_LEMMA); 137 : : } 138 : : } 139 : 10 : return PreprocessingPassResult::NO_CONFLICT; 140 : 10 : } 141 : : 142 : : 143 : : } // namespace passes 144 : : } // namespace preprocessing 145 : : } // namespace cvc5::internal