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