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 : : * Implementation of expand definitions for an SMT engine. 11 : : */ 12 : : 13 : : #include "smt/expand_definitions.h" 14 : : 15 : : #include <stack> 16 : : #include <utility> 17 : : 18 : : #include "preprocessing/assertion_pipeline.h" 19 : : #include "smt/env.h" 20 : : #include "theory/rewriter.h" 21 : : #include "theory/theory.h" 22 : : #include "util/resource_manager.h" 23 : : 24 : : using namespace cvc5::internal::preprocessing; 25 : : using namespace cvc5::internal::theory; 26 : : using namespace cvc5::internal::kind; 27 : : 28 : : namespace cvc5::internal { 29 : : namespace smt { 30 : : 31 : 43383 : ExpandDefs::ExpandDefs(Env& env) : EnvObj(env) {} 32 : : 33 : 74478 : ExpandDefs::~ExpandDefs() {} 34 : : 35 : 14003 : Node ExpandDefs::expandDefinitions(TNode n) 36 : : { 37 : 14003 : return expandDefinitions(n, d_cache); 38 : : } 39 : : 40 : 38613 : Node ExpandDefs::expandDefinitions(TNode n, 41 : : std::unordered_map<Node, Node>& cache) 42 : : { 43 : 38613 : const TNode orig = n; 44 : 38613 : std::stack<std::tuple<Node, Node, bool>> worklist; 45 : 38613 : std::stack<Node> result; 46 : 38613 : worklist.push(std::make_tuple(Node(n), Node(n), false)); 47 : : // The worklist is made of triples, each is input / original node then the 48 : : // output / rewritten node and finally a flag tracking whether the children 49 : : // have been explored (i.e. if this is a downward or upward pass). 50 : : 51 : 38613 : ResourceManager* rm = d_env.getResourceManager(); 52 : 38613 : Rewriter* rr = d_env.getRewriter(); 53 : : do 54 : : { 55 : 665521 : rm->spendResource(Resource::PreprocessStep); 56 : : 57 : : // n is the input / original 58 : : // node is the output / result 59 : 665521 : Node node; 60 : : bool childrenPushed; 61 : 665521 : std::tie(n, node, childrenPushed) = worklist.top(); 62 : 665521 : worklist.pop(); 63 : : 64 : : // Working downwards 65 [ + + ]: 665521 : if (!childrenPushed) 66 : : { 67 : : // we can short circuit (variable) leaves and closures, whose bodies 68 : : // are not preprocessed 69 [ + + ][ + + ]: 460717 : if (n.isVar() || n.isClosure()) [ + + ] 70 : : { 71 : : // don't bother putting in the cache 72 : 153946 : result.push(n); 73 : 255913 : continue; 74 : : } 75 : : 76 : : // maybe it's in the cache 77 : 306771 : std::unordered_map<Node, Node>::iterator cacheHit = cache.find(n); 78 [ + + ]: 306771 : if (cacheHit != cache.end()) 79 : : { 80 : 101967 : TNode ret = (*cacheHit).second; 81 [ + + ]: 101967 : result.push(ret.isNull() ? n : ret); 82 : 101967 : continue; 83 : 101967 : } 84 : : // ensure rewritten 85 : 204804 : Node nr = rewrite(n); 86 : : // now get the appropriate theory 87 : 204804 : theory::TheoryId tid = d_env.theoryOf(nr); 88 : 204804 : theory::TheoryRewriter* tr = rr->getTheoryRewriter(tid); 89 : : 90 [ - + ][ - + ]: 204804 : Assert(tr != nullptr); [ - - ] 91 [ + - ]: 409608 : Trace("expand") << "Expand definition on " << nr << " (from " << n << ")" 92 : 204804 : << std::endl; 93 : 204804 : Node nre = tr->expandDefinition(nr); 94 [ + - ]: 204804 : Trace("expand") << "...returns " << nre << std::endl; 95 [ + + ]: 204804 : node = nre.isNull() ? nr : nre; 96 : : // the partial functions can fall through, in which case we still 97 : : // consider their children 98 : 204804 : worklist.push(std::make_tuple( 99 : 409608 : Node(n), node, true)); // Original and rewritten result 100 : : 101 [ + + ]: 626908 : for (const Node& nc : node) 102 : : { 103 : : // Rewrite the children of the result only 104 : 422104 : worklist.push(std::make_tuple(nc, nc, false)); 105 : 422104 : } 106 : 204804 : } 107 : : else 108 : : { 109 : : // Working upwards 110 : : // Reconstruct the node from it's (now rewritten) children on the stack 111 : : 112 [ + - ]: 204804 : Trace("expand") << "cons : " << node << std::endl; 113 [ + + ]: 204804 : if (node.getNumChildren() > 0) 114 : : { 115 : 181224 : NodeBuilder nb(nodeManager(), node.getKind()); 116 [ + + ]: 181224 : if (node.getMetaKind() == metakind::PARAMETERIZED) 117 : : { 118 [ + - ][ - + ]: 8341 : Trace("expand") << "op : " << node.getOperator() << std::endl; [ - - ] 119 : 8341 : nb << node.getOperator(); 120 : : } 121 [ + + ]: 603328 : for (size_t i = 0, nchild = node.getNumChildren(); i < nchild; ++i) 122 : : { 123 [ - + ][ - + ]: 422104 : Assert(!result.empty()); [ - - ] 124 : 422104 : Node expanded = result.top(); 125 : 422104 : result.pop(); 126 [ + - ]: 422104 : Trace("expand") << "exchld : " << expanded << std::endl; 127 : 422104 : nb << expanded; 128 : 422104 : } 129 : 181224 : node = nb; 130 : 181224 : } 131 : : // Only cache once all subterms are expanded 132 [ + + ]: 204804 : cache[n] = n == node ? Node::null() : node; 133 : 204804 : result.push(node); 134 : : } 135 [ + + ][ + + ]: 1331042 : } while (!worklist.empty()); 136 : : 137 [ - + ][ - + ]: 38613 : AlwaysAssert(result.size() == 1); [ - - ] 138 : : 139 : 77226 : return result.top(); 140 : 38613 : } 141 : : 142 : : } // namespace smt 143 : : } // namespace cvc5::internal