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-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 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 : SkolemManager* sm = nm->getSkolemManager(); 39 [ + + ]: 2944 : if (beneathMult) 40 : : { 41 : 2294 : NodeMap::iterator find = bcache.find(n); 42 [ + + ]: 2294 : if (find != bcache.end()) 43 : : { 44 : 2170 : return (*find).second; 45 : : } 46 : : } 47 : : else 48 : : { 49 : 650 : NodeMap::iterator find = cache.find(n); 50 [ + + ]: 650 : if (find != cache.end()) 51 : : { 52 : 462 : return (*find).second; 53 : : } 54 : : } 55 [ - + ]: 312 : if (n.isClosure()) 56 : : { 57 : : // don't traverse quantified formulas 58 : 0 : return n; 59 : : } 60 : 624 : Node ret = n; 61 [ + + ]: 312 : if (n.getNumChildren() > 0) 62 : : { 63 [ + + ][ + - ]: 238 : if (beneathMult && (n.getKind() == Kind::ADD || n.getKind() == Kind::SUB)) [ - + ][ - + ] 64 : : { 65 : : // don't do it if it rewrites to a constant 66 : 0 : Node nr = rewrite(n); 67 [ - - ]: 0 : if (nr.isConst()) 68 : : { 69 : : // return the rewritten constant 70 : 0 : ret = nr; 71 : : } 72 : : else 73 : : { 74 : : // new variable 75 : 0 : ret = sm->mkDummySkolem("__purifyNl_var", 76 : 0 : n.getType(), 77 : 0 : "Variable introduced in purifyNl pass"); 78 : 0 : Node np = purifyNlTerms(n, cache, bcache, var_eq, false); 79 : 0 : var_eq.push_back(np.eqNode(ret)); 80 [ - - ]: 0 : Trace("nl-ext-purify") << "Purify : " << ret << " -> " << np 81 : 0 : << std::endl; 82 : : } 83 : : } 84 : : else 85 : : { 86 [ + + ][ + + ]: 238 : bool beneathMultNew = beneathMult || n.getKind() == Kind::MULT; 87 : 238 : bool childChanged = false; 88 : 476 : std::vector<Node> children; 89 [ + + ]: 2832 : for (unsigned i = 0, size = n.getNumChildren(); i < size; ++i) 90 : : { 91 : 5188 : Node nc = purifyNlTerms(n[i], cache, bcache, var_eq, beneathMultNew); 92 [ + - ][ - + ]: 2594 : childChanged = childChanged || nc != n[i]; [ + - ][ - - ] 93 : 2594 : children.push_back(nc); 94 : : } 95 [ - + ]: 238 : if (childChanged) 96 : : { 97 : 0 : ret = nm->mkNode(n.getKind(), children); 98 : : } 99 : : } 100 : : } 101 [ + + ]: 312 : if (beneathMult) 102 : : { 103 : 124 : bcache[n] = ret; 104 : : } 105 : : else 106 : : { 107 : 188 : cache[n] = ret; 108 : : } 109 : 312 : return ret; 110 : : } 111 : : 112 : 50369 : NlExtPurify::NlExtPurify(PreprocessingPassContext* preprocContext) 113 : 50369 : : PreprocessingPass(preprocContext, "nl-ext-purify"){}; 114 : : 115 : 10 : PreprocessingPassResult NlExtPurify::applyInternal( 116 : : AssertionPipeline* assertionsToPreprocess) 117 : : { 118 : 20 : unordered_map<Node, Node> cache; 119 : 20 : unordered_map<Node, Node> bcache; 120 : 10 : std::vector<Node> var_eq; 121 : 10 : unsigned size = assertionsToPreprocess->size(); 122 [ + + ]: 360 : for (unsigned i = 0; i < size; ++i) 123 : : { 124 : 700 : Node a = (*assertionsToPreprocess)[i]; 125 : 700 : Node ap = purifyNlTerms(a, cache, bcache, var_eq); 126 [ - + ]: 350 : if (a != ap) 127 : : { 128 : 0 : assertionsToPreprocess->replace(i, ap); 129 [ - - ]: 0 : Trace("nl-ext-purify") 130 : 0 : << "Purify : " << a << " -> " << (*assertionsToPreprocess)[i] << "\n"; 131 : : } 132 : : } 133 [ - + ]: 10 : if (!var_eq.empty()) 134 : : { 135 [ - - ]: 0 : for (const Node& ve : var_eq) 136 : : { 137 : 0 : assertionsToPreprocess->push_back(ve); 138 : : } 139 : : } 140 : 20 : return PreprocessingPassResult::NO_CONFLICT; 141 : : } 142 : : 143 : : 144 : : } // namespace passes 145 : : } // namespace preprocessing 146 : : } // namespace cvc5::internal